diff --git a/addons/web/__openerp__.py b/addons/web/__openerp__.py index 26ee5613dc5..417fea91434 100644 --- a/addons/web/__openerp__.py +++ b/addons/web/__openerp__.py @@ -36,19 +36,6 @@ "static/lib/underscore/underscore.string.js", "static/lib/backbone/backbone.js", - "static/lib/visualsearch/lib/js/visualsearch.js", - "static/lib/visualsearch/lib/js/utils/backbone_extensions.js", - "static/lib/visualsearch/lib/js/utils/hotkeys.js", - "static/lib/visualsearch/lib/js/utils/inflector.js", - "static/lib/visualsearch/lib/js/utils/jquery_extensions.js", - "static/lib/visualsearch/lib/js/utils/search_parser.js", - "static/lib/visualsearch/lib/js/models/search_facets.js", - "static/lib/visualsearch/lib/js/models/search_query.js", - "static/lib/visualsearch/lib/js/templates/templates.js", - "static/lib/visualsearch/lib/js/views/search_facet.js", - "static/lib/visualsearch/lib/js/views/search_input.js", - "static/lib/visualsearch/lib/js/views/search_box.js", - "static/lib/labjs/LAB.src.js", "static/lib/py.js/lib/py.js", "static/src/js/boot.js", @@ -74,9 +61,6 @@ "static/lib/jquery.ui.timepicker/css/jquery-ui-timepicker-addon.css", "static/lib/jquery.ui.notify/css/ui.notify.css", "static/lib/jquery.tipsy/tipsy.css", - "static/lib/visualsearch/lib/css/reset.css", - "static/lib/visualsearch/lib/css/workspace.css", - "static/lib/visualsearch/lib/css/icons.css", # "static/src/css/base_old.css", "static/src/css/base.css", "static/src/css/data_export.css", diff --git a/addons/web/controllers/main.py b/addons/web/controllers/main.py index 12ef0b53524..6eb8ed94909 100644 --- a/addons/web/controllers/main.py +++ b/addons/web/controllers/main.py @@ -1287,25 +1287,6 @@ class SearchView(View): del filter['domain'] return filters - @openerpweb.jsonrequest - def save_filter(self, req, model, name, context_to_save, domain): - Model = req.session.model("ir.filters") - ctx = common.nonliterals.CompoundContext(context_to_save) - ctx.session = req.session - ctx = ctx.evaluate() - domain = common.nonliterals.CompoundDomain(domain) - domain.session = req.session - domain = domain.evaluate() - uid = req.session._uid - context = req.session.eval_context(req.context) - to_return = Model.create_or_replace({"context": ctx, - "domain": domain, - "model_id": model, - "name": name, - "user_id": uid - }, context) - return to_return - @openerpweb.jsonrequest def add_to_dashboard(self, req, menu_id, action_id, context_to_save, domain, view_mode, name=''): ctx = common.nonliterals.CompoundContext(context_to_save) diff --git a/addons/web/i18n/ar.po b/addons/web/i18n/ar.po index aaaf641a89f..20e52deeaa7 100644 --- a/addons/web/i18n/ar.po +++ b/addons/web/i18n/ar.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:14+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:05+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web/static/src/js/chrome.js:172 diff --git a/addons/web/i18n/bn.po b/addons/web/i18n/bn.po index eae0f05e782..557f352f2ac 100644 --- a/addons/web/i18n/bn.po +++ b/addons/web/i18n/bn.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:05+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web/static/src/js/chrome.js:172 diff --git a/addons/web/i18n/bs.po b/addons/web/i18n/bs.po index 6546059aecb..0107413ed9a 100644 --- a/addons/web/i18n/bs.po +++ b/addons/web/i18n/bs.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:05+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web/static/src/js/chrome.js:172 diff --git a/addons/web/i18n/cs.po b/addons/web/i18n/cs.po index dc678816427..2a1fd3f719e 100644 --- a/addons/web/i18n/cs.po +++ b/addons/web/i18n/cs.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:05+0000\n" +"X-Generator: Launchpad (build 15238)\n" "X-Poedit-Language: Czech\n" #. openerp-web diff --git a/addons/web/i18n/da.po b/addons/web/i18n/da.po index afb2589dccf..806f42608e3 100644 --- a/addons/web/i18n/da.po +++ b/addons/web/i18n/da.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:05+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web/static/src/js/chrome.js:172 diff --git a/addons/web/i18n/de.po b/addons/web/i18n/de.po index 29ea7c05e30..2bc64f7a215 100644 --- a/addons/web/i18n/de.po +++ b/addons/web/i18n/de.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:05+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web/static/src/js/chrome.js:172 diff --git a/addons/web/i18n/en_AU.po b/addons/web/i18n/en_AU.po index d31291bc628..130cd3a95e2 100644 --- a/addons/web/i18n/en_AU.po +++ b/addons/web/i18n/en_AU.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web/static/src/js/chrome.js:172 diff --git a/addons/web/i18n/en_GB.po b/addons/web/i18n/en_GB.po index 47d997179c3..013f04cbff5 100644 --- a/addons/web/i18n/en_GB.po +++ b/addons/web/i18n/en_GB.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web/static/src/js/chrome.js:172 diff --git a/addons/web/i18n/es.po b/addons/web/i18n/es.po index 24e9ef305e2..f8176f1e633 100644 --- a/addons/web/i18n/es.po +++ b/addons/web/i18n/es.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web/static/src/js/chrome.js:172 diff --git a/addons/web/i18n/es_CL.po b/addons/web/i18n/es_CL.po index abff2b42e94..14c8a0f5d16 100644 --- a/addons/web/i18n/es_CL.po +++ b/addons/web/i18n/es_CL.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web/static/src/js/chrome.js:172 diff --git a/addons/web/i18n/es_CR.po b/addons/web/i18n/es_CR.po index 2ee7971a071..51fffec5203 100644 --- a/addons/web/i18n/es_CR.po +++ b/addons/web/i18n/es_CR.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" "Language: es\n" #. openerp-web diff --git a/addons/web/i18n/es_EC.po b/addons/web/i18n/es_EC.po index a7cd0b13f88..45c2aa069d3 100644 --- a/addons/web/i18n/es_EC.po +++ b/addons/web/i18n/es_EC.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web/static/src/js/chrome.js:172 diff --git a/addons/web/i18n/et.po b/addons/web/i18n/et.po index 3d08eed59f8..10061e5becc 100644 --- a/addons/web/i18n/et.po +++ b/addons/web/i18n/et.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:05+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web/static/src/js/chrome.js:172 diff --git a/addons/web/i18n/eu.po b/addons/web/i18n/eu.po index 122489d30d2..62282e4d7cf 100644 --- a/addons/web/i18n/eu.po +++ b/addons/web/i18n/eu.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:14+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:05+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web/static/src/js/chrome.js:172 diff --git a/addons/web/i18n/fi.po b/addons/web/i18n/fi.po index 67e287e1c71..242cbc5240a 100644 --- a/addons/web/i18n/fi.po +++ b/addons/web/i18n/fi.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:05+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web/static/src/js/chrome.js:172 diff --git a/addons/web/i18n/fr.po b/addons/web/i18n/fr.po index 0c8d94df9f1..95f5c0e55b8 100644 --- a/addons/web/i18n/fr.po +++ b/addons/web/i18n/fr.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:05+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web/static/src/js/chrome.js:172 diff --git a/addons/web/i18n/gl.po b/addons/web/i18n/gl.po index f7110bceb47..494a263e8f7 100644 --- a/addons/web/i18n/gl.po +++ b/addons/web/i18n/gl.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:05+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web/static/src/js/chrome.js:172 diff --git a/addons/web/i18n/gu.po b/addons/web/i18n/gu.po index bb351af1a58..9cd7d671097 100644 --- a/addons/web/i18n/gu.po +++ b/addons/web/i18n/gu.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:05+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web/static/src/js/chrome.js:172 diff --git a/addons/web/i18n/hr.po b/addons/web/i18n/hr.po index 7ffba0383d7..9bb4a2a69ab 100644 --- a/addons/web/i18n/hr.po +++ b/addons/web/i18n/hr.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web/static/src/js/chrome.js:172 diff --git a/addons/web/i18n/id.po b/addons/web/i18n/id.po index 8c3ed7497fa..23eedfb8945 100644 --- a/addons/web/i18n/id.po +++ b/addons/web/i18n/id.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:05+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web/static/src/js/chrome.js:172 diff --git a/addons/web/i18n/it.po b/addons/web/i18n/it.po index c9f1fa6f5a1..37dadfaf5a0 100644 --- a/addons/web/i18n/it.po +++ b/addons/web/i18n/it.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web/static/src/js/chrome.js:172 diff --git a/addons/web/i18n/ja.po b/addons/web/i18n/ja.po index 62245bc937b..2d58e13acf1 100644 --- a/addons/web/i18n/ja.po +++ b/addons/web/i18n/ja.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web/static/src/js/chrome.js:172 diff --git a/addons/web/i18n/ka.po b/addons/web/i18n/ka.po index 3cae4c721b8..06ffda4e002 100644 --- a/addons/web/i18n/ka.po +++ b/addons/web/i18n/ka.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:05+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web/static/src/js/chrome.js:172 diff --git a/addons/web/i18n/mk.po b/addons/web/i18n/mk.po index 9b88370cfeb..4bf26b7aac4 100644 --- a/addons/web/i18n/mk.po +++ b/addons/web/i18n/mk.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web/static/src/js/chrome.js:172 diff --git a/addons/web/i18n/mn.po b/addons/web/i18n/mn.po index 64bf98ceed9..cf65b27d8bf 100644 --- a/addons/web/i18n/mn.po +++ b/addons/web/i18n/mn.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web/static/src/js/chrome.js:172 diff --git a/addons/web/i18n/nb.po b/addons/web/i18n/nb.po index a46724e15ac..145288312ba 100644 --- a/addons/web/i18n/nb.po +++ b/addons/web/i18n/nb.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web/static/src/js/chrome.js:172 diff --git a/addons/web/i18n/nl.po b/addons/web/i18n/nl.po index 73e96b454ce..78163c12d2c 100644 --- a/addons/web/i18n/nl.po +++ b/addons/web/i18n/nl.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:05+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web/static/src/js/chrome.js:172 diff --git a/addons/web/i18n/nl_BE.po b/addons/web/i18n/nl_BE.po index 243838b2b40..de7fc18891c 100644 --- a/addons/web/i18n/nl_BE.po +++ b/addons/web/i18n/nl_BE.po @@ -8,14 +8,14 @@ msgstr "" "Project-Id-Version: openerp-web\n" "Report-Msgid-Bugs-To: FULL NAME \n" "POT-Creation-Date: 2012-02-14 15:27+0100\n" -"PO-Revision-Date: 2011-10-07 12:50+0000\n" -"Last-Translator: Niels Huylebroeck \n" +"PO-Revision-Date: 2012-05-15 14:32+0000\n" +"Last-Translator: Els Van Vossel (Agaplan) \n" "Language-Team: Dutch (Belgium) \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-16 05:10+0000\n" +"X-Generator: Launchpad (build 15247)\n" #. openerp-web #: addons/web/static/src/js/chrome.js:172 @@ -27,60 +27,60 @@ msgstr "" #: addons/web/static/src/js/view_form.js:424 #: addons/web/static/src/js/view_form.js:1239 msgid "Ok" -msgstr "Ok" +msgstr "OK" #. openerp-web #: addons/web/static/src/js/chrome.js:180 msgid "Send OpenERP Enterprise Report" -msgstr "" +msgstr "OpenERP-Entrepriserapport versturen" #. openerp-web #: addons/web/static/src/js/chrome.js:194 msgid "Dont send" -msgstr "" +msgstr "Niet versturen" #. openerp-web #: addons/web/static/src/js/chrome.js:256 #, python-format msgid "Loading (%d)" -msgstr "" +msgstr "Laden (%d)" #. openerp-web #: addons/web/static/src/js/chrome.js:288 msgid "Invalid database name" -msgstr "" +msgstr "Ongeldige databasenaam" #. openerp-web #: addons/web/static/src/js/chrome.js:483 msgid "Backed" -msgstr "" +msgstr "Back-up klaar" #. openerp-web #: addons/web/static/src/js/chrome.js:484 msgid "Database backed up successfully" -msgstr "" +msgstr "Databaseback-up geslaagd" #. openerp-web #: addons/web/static/src/js/chrome.js:527 msgid "Restored" -msgstr "" +msgstr "Teruggezet" #. openerp-web #: addons/web/static/src/js/chrome.js:527 msgid "Database restored successfully" -msgstr "" +msgstr "Database met succes teruggezet" #. openerp-web #: addons/web/static/src/js/chrome.js:708 #: addons/web/static/src/xml/base.xml:359 msgid "About" -msgstr "" +msgstr "Info" #. openerp-web #: addons/web/static/src/js/chrome.js:787 #: addons/web/static/src/xml/base.xml:356 msgid "Preferences" -msgstr "" +msgstr "Voorkeuren" #. openerp-web #: addons/web/static/src/js/chrome.js:790 @@ -102,7 +102,7 @@ msgstr "Annuleren" #. openerp-web #: addons/web/static/src/js/chrome.js:791 msgid "Change password" -msgstr "" +msgstr "Wachtwoord wijzigen" #. openerp-web #: addons/web/static/src/js/chrome.js:792 @@ -119,24 +119,24 @@ msgstr "Opslaan" #: addons/web/static/src/xml/base.xml:226 #: addons/web/static/src/xml/base.xml:1729 msgid "Change Password" -msgstr "" +msgstr "Wachtwoord wijzigen" #. openerp-web #: addons/web/static/src/js/chrome.js:1096 #: addons/web/static/src/js/chrome.js:1100 msgid "OpenERP - Unsupported/Community Version" -msgstr "" +msgstr "OpenERP - Niet-ondersteunde/Communityversie" #. openerp-web #: addons/web/static/src/js/chrome.js:1131 #: addons/web/static/src/js/chrome.js:1135 msgid "Client Error" -msgstr "" +msgstr "Clientfout" #. openerp-web #: addons/web/static/src/js/data_export.js:6 msgid "Export Data" -msgstr "" +msgstr "Gegevens exporteren" #. openerp-web #: addons/web/static/src/js/data_export.js:19 @@ -154,37 +154,37 @@ msgstr "Sluiten" #. openerp-web #: addons/web/static/src/js/data_export.js:20 msgid "Export To File" -msgstr "" +msgstr "Naar bestand exporteren" #. openerp-web #: addons/web/static/src/js/data_export.js:125 msgid "Please enter save field list name" -msgstr "" +msgstr "Geef eerst de naam van de lijst" #. openerp-web #: addons/web/static/src/js/data_export.js:360 msgid "Please select fields to save export list..." -msgstr "" +msgstr "Kies velden voor de lijst" #. openerp-web #: addons/web/static/src/js/data_export.js:373 msgid "Please select fields to export..." -msgstr "" +msgstr "Kies te exporteren velden" #. openerp-web #: addons/web/static/src/js/data_import.js:34 msgid "Import Data" -msgstr "" +msgstr "Gegevens importeren" #. openerp-web #: addons/web/static/src/js/data_import.js:70 msgid "Import File" -msgstr "" +msgstr "Bestand importeren" #. openerp-web #: addons/web/static/src/js/data_import.js:105 msgid "External ID" -msgstr "" +msgstr "Externe id" #. openerp-web #: addons/web/static/src/js/formats.js:300 @@ -192,14 +192,14 @@ msgstr "" #: addons/web/static/src/js/formats.js:322 #: addons/web/static/src/js/view_page.js:251 msgid "Download" -msgstr "" +msgstr "Downloaden" #. openerp-web #: addons/web/static/src/js/formats.js:305 #: addons/web/static/src/js/formats.js:327 #, python-format msgid "Download \"%s\"" -msgstr "" +msgstr "Download \"%s\"" #. openerp-web #: addons/web/static/src/js/search.js:191 @@ -216,70 +216,70 @@ msgstr "" #: addons/web/static/src/js/search.js:291 #: addons/web/static/src/js/search.js:296 msgid "OK" -msgstr "" +msgstr "OK" #. openerp-web #: addons/web/static/src/js/search.js:286 #: addons/web/static/src/xml/base.xml:1292 #: addons/web/static/src/js/search.js:291 msgid "Add to Dashboard" -msgstr "" +msgstr "Aan dashboard toevoegen" #. openerp-web #: addons/web/static/src/js/search.js:415 #: addons/web/static/src/js/search.js:420 msgid "Invalid Search" -msgstr "" +msgstr "Ongeldige zoekopdracht" #. openerp-web #: addons/web/static/src/js/search.js:415 #: addons/web/static/src/js/search.js:420 msgid "triggered from search view" -msgstr "" +msgstr "geactiveerd door zoekweergave" #. openerp-web #: addons/web/static/src/js/search.js:503 #: addons/web/static/src/js/search.js:508 #, python-format msgid "Incorrect value for field %(fieldname)s: [%(value)s] is %(message)s" -msgstr "" +msgstr "Onjuiste waarde voor veld %(fieldname)s: [%(value)s] is %(message)s" #. openerp-web #: addons/web/static/src/js/search.js:839 #: addons/web/static/src/js/search.js:844 msgid "not a valid integer" -msgstr "" +msgstr "geen geldig geheel getal" #. openerp-web #: addons/web/static/src/js/search.js:853 #: addons/web/static/src/js/search.js:858 msgid "not a valid number" -msgstr "" +msgstr "geen geldig getal" #. openerp-web #: addons/web/static/src/js/search.js:931 #: addons/web/static/src/xml/base.xml:968 #: addons/web/static/src/js/search.js:936 msgid "Yes" -msgstr "" +msgstr "Ja" #. openerp-web #: addons/web/static/src/js/search.js:932 #: addons/web/static/src/js/search.js:937 msgid "No" -msgstr "" +msgstr "Nee" #. openerp-web #: addons/web/static/src/js/search.js:1290 #: addons/web/static/src/js/search.js:1295 msgid "contains" -msgstr "" +msgstr "bevat" #. openerp-web #: addons/web/static/src/js/search.js:1291 #: addons/web/static/src/js/search.js:1296 msgid "doesn't contain" -msgstr "" +msgstr "bevat niet" #. openerp-web #: addons/web/static/src/js/search.js:1292 @@ -293,7 +293,7 @@ msgstr "" #: addons/web/static/src/js/search.js:1349 #: addons/web/static/src/js/search.js:1370 msgid "is equal to" -msgstr "" +msgstr "is gelijk aan" #. openerp-web #: addons/web/static/src/js/search.js:1293 @@ -307,7 +307,7 @@ msgstr "" #: addons/web/static/src/js/search.js:1350 #: addons/web/static/src/js/search.js:1371 msgid "is not equal to" -msgstr "" +msgstr "is niet gelijk aan" #. openerp-web #: addons/web/static/src/js/search.js:1294 @@ -321,7 +321,7 @@ msgstr "" #: addons/web/static/src/js/search.js:1351 #: addons/web/static/src/js/search.js:1372 msgid "greater than" -msgstr "" +msgstr "is groter dan" #. openerp-web #: addons/web/static/src/js/search.js:1295 @@ -335,7 +335,7 @@ msgstr "" #: addons/web/static/src/js/search.js:1352 #: addons/web/static/src/js/search.js:1373 msgid "less than" -msgstr "" +msgstr "is kleiner dan" #. openerp-web #: addons/web/static/src/js/search.js:1296 @@ -349,7 +349,7 @@ msgstr "" #: addons/web/static/src/js/search.js:1353 #: addons/web/static/src/js/search.js:1374 msgid "greater or equal than" -msgstr "" +msgstr "is groter of gelijk aan" #. openerp-web #: addons/web/static/src/js/search.js:1297 @@ -363,7 +363,7 @@ msgstr "" #: addons/web/static/src/js/search.js:1354 #: addons/web/static/src/js/search.js:1375 msgid "less or equal than" -msgstr "" +msgstr "is kleiner dan of gelijk aan" #. openerp-web #: addons/web/static/src/js/search.js:1360 @@ -371,31 +371,31 @@ msgstr "" #: addons/web/static/src/js/search.js:1365 #: addons/web/static/src/js/search.js:1388 msgid "is" -msgstr "" +msgstr "is gelijk aan" #. openerp-web #: addons/web/static/src/js/search.js:1384 #: addons/web/static/src/js/search.js:1389 msgid "is not" -msgstr "" +msgstr "is niet gelijk aan" #. openerp-web #: addons/web/static/src/js/search.js:1396 #: addons/web/static/src/js/search.js:1401 msgid "is true" -msgstr "" +msgstr "is waar" #. openerp-web #: addons/web/static/src/js/search.js:1397 #: addons/web/static/src/js/search.js:1402 msgid "is false" -msgstr "" +msgstr "is onwaar" #. openerp-web #: addons/web/static/src/js/view_editor.js:20 #, python-format msgid "Manage Views (%s)" -msgstr "" +msgstr "Weergaven beheren (%s)" #. openerp-web #: addons/web/static/src/js/view_editor.js:46 @@ -411,7 +411,7 @@ msgstr "Creër" #: addons/web/static/src/xml/base.xml:483 #: addons/web/static/src/xml/base.xml:755 msgid "Edit" -msgstr "" +msgstr "Bewerken" #. openerp-web #: addons/web/static/src/js/view_editor.js:48 @@ -423,18 +423,18 @@ msgstr "Verwijderen" #: addons/web/static/src/js/view_editor.js:71 #, python-format msgid "Create a view (%s)" -msgstr "" +msgstr "Een weergave maken (%s)" #. openerp-web #: addons/web/static/src/js/view_editor.js:168 msgid "Do you really want to remove this view?" -msgstr "" +msgstr "Wilt u deze weergave echt verwijderen?" #. openerp-web #: addons/web/static/src/js/view_editor.js:364 #, python-format msgid "View Editor %d - %s" -msgstr "" +msgstr "Bekijk editor %d - %s" #. openerp-web #: addons/web/static/src/js/view_editor.js:367 @@ -449,7 +449,7 @@ msgstr "" #. openerp-web #: addons/web/static/src/js/view_editor.js:381 msgid "Preview" -msgstr "" +msgstr "Voorbeeld" #. openerp-web #: addons/web/static/src/js/view_editor.js:501 diff --git a/addons/web/i18n/pl.po b/addons/web/i18n/pl.po index 85205cf4900..149c6f8315e 100644 --- a/addons/web/i18n/pl.po +++ b/addons/web/i18n/pl.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web/static/src/js/chrome.js:172 diff --git a/addons/web/i18n/pt.po b/addons/web/i18n/pt.po index 11e05a77e98..f725c4df967 100644 --- a/addons/web/i18n/pt.po +++ b/addons/web/i18n/pt.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web/static/src/js/chrome.js:172 diff --git a/addons/web/i18n/pt_BR.po b/addons/web/i18n/pt_BR.po index 0c3d5cf4feb..33f36eb0176 100644 --- a/addons/web/i18n/pt_BR.po +++ b/addons/web/i18n/pt_BR.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web/static/src/js/chrome.js:172 diff --git a/addons/web/i18n/ro.po b/addons/web/i18n/ro.po index a792820c5f5..60f04134fad 100644 --- a/addons/web/i18n/ro.po +++ b/addons/web/i18n/ro.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web/static/src/js/chrome.js:172 diff --git a/addons/web/i18n/ru.po b/addons/web/i18n/ru.po index 680f116b193..1b1db25f32f 100644 --- a/addons/web/i18n/ru.po +++ b/addons/web/i18n/ru.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web/static/src/js/chrome.js:172 diff --git a/addons/web/i18n/sk.po b/addons/web/i18n/sk.po index 3f7c371e979..943d09013bf 100644 --- a/addons/web/i18n/sk.po +++ b/addons/web/i18n/sk.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web/static/src/js/chrome.js:172 diff --git a/addons/web/i18n/sl.po b/addons/web/i18n/sl.po index fddddddee42..cd4b9263120 100644 --- a/addons/web/i18n/sl.po +++ b/addons/web/i18n/sl.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web/static/src/js/chrome.js:172 diff --git a/addons/web/i18n/sq.po b/addons/web/i18n/sq.po index 32d80d49e06..2013a7b67b5 100644 --- a/addons/web/i18n/sq.po +++ b/addons/web/i18n/sq.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:14+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:05+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web/static/src/js/chrome.js:172 diff --git a/addons/web/i18n/sr@latin.po b/addons/web/i18n/sr@latin.po index 15da636a061..4b59d431040 100644 --- a/addons/web/i18n/sr@latin.po +++ b/addons/web/i18n/sr@latin.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web/static/src/js/chrome.js:172 diff --git a/addons/web/i18n/sv.po b/addons/web/i18n/sv.po index 69ad4844a98..80d34385f44 100644 --- a/addons/web/i18n/sv.po +++ b/addons/web/i18n/sv.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web/static/src/js/chrome.js:172 @@ -235,7 +235,7 @@ msgstr "Felaktig sökning" #: addons/web/static/src/js/search.js:415 #: addons/web/static/src/js/search.js:420 msgid "triggered from search view" -msgstr "" +msgstr "aktiverad från sökvyn" #. openerp-web #: addons/web/static/src/js/search.js:503 @@ -590,7 +590,7 @@ msgstr "Skapa: " #: addons/web/static/src/xml/base.xml:1646 #: addons/web/static/src/js/view_form.js:2680 msgid "Add" -msgstr "Tillägg" +msgstr "Lägg till" #. openerp-web #: addons/web/static/src/js/view_form.js:2721 @@ -653,7 +653,7 @@ msgstr "Träd" #: addons/web/static/src/js/views.js:565 #: addons/web/static/src/xml/base.xml:480 msgid "Fields View Get" -msgstr "" +msgstr "Fält för visningsvy" #. openerp-web #: addons/web/static/src/js/views.js:573 @@ -676,7 +676,7 @@ msgstr "Hantera vyer" #. openerp-web #: addons/web/static/src/js/views.js:611 msgid "Could not find current view declaration" -msgstr "" +msgstr "Aktuell visningsvydeklaration saknas" #. openerp-web #: addons/web/static/src/js/views.js:805 @@ -686,7 +686,7 @@ msgstr "Översätt" #. openerp-web #: addons/web/static/src/js/views.js:807 msgid "Technical translation" -msgstr "" +msgstr "Teknisk översättning" #. openerp-web #: addons/web/static/src/js/views.js:811 @@ -1350,6 +1350,10 @@ msgid "" " You can export all data or only the fields that can be " "reimported after modification." msgstr "" +"Den här guiden kommer att exportera alla data som matchar de aktuella " +"sökkriterierna till en CSV-fil.\n" +" Du kan exportera alla data eller endast de fält som kan " +"återimporteras efter modifiering." #. openerp-web #: addons/web/static/src/xml/base.xml:1618 @@ -1432,6 +1436,9 @@ 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 "" +"Välj en CSV-fil som ska importeras. Om du behöver ett prov av filen för att " +"importera,\n" +" kan du först exportera en, ange då \"Importkompatibel\"-alternativet." #. openerp-web #: addons/web/static/src/xml/base.xml:1747 @@ -1489,6 +1496,7 @@ msgid "" "For use if CSV files have titles on multiple lines, skips more than a single " "line during import" msgstr "" +"Använd då CSV-filer flera titelrader som skall hoppas över vid import" #. openerp-web #: addons/web/static/src/xml/base.xml:1803 diff --git a/addons/web/i18n/tr.po b/addons/web/i18n/tr.po index da3f6f8aef1..b0fd76dd0df 100644 --- a/addons/web/i18n/tr.po +++ b/addons/web/i18n/tr.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web/static/src/js/chrome.js:172 diff --git a/addons/web/i18n/uk.po b/addons/web/i18n/uk.po index e7acacde7fb..5b8a50310e6 100644 --- a/addons/web/i18n/uk.po +++ b/addons/web/i18n/uk.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web/static/src/js/chrome.js:172 diff --git a/addons/web/i18n/zh_CN.po b/addons/web/i18n/zh_CN.po index 1948b12ba76..997d2de0803 100644 --- a/addons/web/i18n/zh_CN.po +++ b/addons/web/i18n/zh_CN.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web/static/src/js/chrome.js:172 diff --git a/addons/web/i18n/zh_TW.po b/addons/web/i18n/zh_TW.po index 51984398f8d..f89fffe15b2 100644 --- a/addons/web/i18n/zh_TW.po +++ b/addons/web/i18n/zh_TW.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web/static/src/js/chrome.js:172 diff --git a/addons/web/static/lib/qweb/qweb2.js b/addons/web/static/lib/qweb/qweb2.js index d4f7781e88b..c9b065ee69f 100644 --- a/addons/web/static/lib/qweb/qweb2.js +++ b/addons/web/static/lib/qweb/qweb2.js @@ -4,7 +4,7 @@ // TODO: t-set + t-value + children node == scoped variable ? var QWeb2 = { expressions_cache: {}, - RESERVED_WORDS: 'true,false,NaN,null,undefined,debugger,console,in,instanceof,new,function,return,this,typeof,eval,Math,RegExp,Array,Object,Date'.split(','), + RESERVED_WORDS: 'true,false,NaN,null,undefined,debugger,console,in,instanceof,new,function,return,this,typeof,eval,void,Math,RegExp,Array,Object,Date'.split(','), ACTIONS_PRECEDENCE: 'foreach,if,call,set,esc,escf,raw,rawf,js,debug,log'.split(','), WORD_REPLACEMENT: { 'and': '&&', diff --git a/addons/web/static/lib/visualsearch/LICENSE b/addons/web/static/lib/visualsearch/LICENSE deleted file mode 100755 index fe0ea1154c4..00000000000 --- a/addons/web/static/lib/visualsearch/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ -Copyright (c) 2011 Samuel Clay, @samuelclay, DocumentCloud - -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation -files (the "Software"), to deal in the Software without -restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/addons/web/static/lib/visualsearch/README b/addons/web/static/lib/visualsearch/README deleted file mode 100755 index c059a9824d6..00000000000 --- a/addons/web/static/lib/visualsearch/README +++ /dev/null @@ -1,16 +0,0 @@ - __ ___ _ _____ _ _ - \ \ / (_) | |/ ____| | | (_) - \ \ / / _ ___ _ _ __ _| | (___ ___ __ _ _ __ ___| |__ _ ___ - \ \/ / | / __| | | |/ _` | |\___ \ / _ \/ _` | '__/ __| '_ \ | / __| - \ / | \__ \ |_| | (_| | |____) | __/ (_| | | | (__| | | |_| \__ \ - \/ |_|___/\__,_|\__,_|_|_____/ \___|\__,_|_| \___|_| |_(_) |___/ - _/ | - |__/ - -VisualSearch.js enhances ordinary search boxes with the ability to autocomplete -faceted search queries. Specify the facets for completion, along with the -completable values for any facet. You can retrieve the search query as a -structured object, so you don't have to parse the query string yourself. - -For documentation, pre-packed downloads, demos, and tests, see: -http://documentcloud.github.com/visualsearch \ No newline at end of file diff --git a/addons/web/static/lib/visualsearch/Rakefile b/addons/web/static/lib/visualsearch/Rakefile deleted file mode 100755 index 192a50b944e..00000000000 --- a/addons/web/static/lib/visualsearch/Rakefile +++ /dev/null @@ -1,37 +0,0 @@ -require 'rubygems' -require 'jammit' -require 'fileutils' - -desc "Use Jammit to compile the multiple versions of Visual Search" -task :build do - $VS_MIN = false - Jammit.package!({ - :config_path => "assets.yml", - :output_folder => "build" - }) - - $VS_MIN = true - Jammit.package!({ - :config_path => "assets.yml", - :output_folder => "build-min" - }) - - # Move the JSTs back to lib to accomodate the demo page. - FileUtils.mv("build/visualsearch_templates.js", "lib/js/templates/templates.js") - - # Fix image url paths. - ['build', 'build-min'].each do |build| - File.open("#{build}/visualsearch.css", 'r+') do |file| - css = file.read - css.gsub!(/url\((.*?)images\/embed\/icons/, 'url(../images/embed/icons') - file.rewind - file.write(css) - file.truncate(css.length) - end - end -end - -desc "Build the docco documentation" -task :docs do - sh "docco lib/js/*.js lib/js/**/*.js" -end diff --git a/addons/web/static/lib/visualsearch/assets.yml b/addons/web/static/lib/visualsearch/assets.yml deleted file mode 100755 index 357c37c74aa..00000000000 --- a/addons/web/static/lib/visualsearch/assets.yml +++ /dev/null @@ -1,28 +0,0 @@ -embed_assets: datauri -javascript_compressor: closure -template_function: _.template -gzip_assets: <% if $VS_MIN %>on<% else %>off<% end %> -compress_assets: <% if $VS_MIN %>on<% else %>off<% end %> - -javascripts: - dependencies: - - vendor/jquery-*.js - - vendor/jquery.ui.core.js - - vendor/jquery.ui.widget.js - - vendor/jquery.ui.position.js - - vendor/jquery.ui.*.js - - vendor/underscore-*.js - - vendor/backbone-*.js - visualsearch: - - lib/js/visualsearch.js - - lib/js/views/*.js - - lib/js/utils/*.js - - lib/js/models/*.js - - lib/js/templates/*.jst - <% unless $VS_MIN %>visualsearch_templates: - - lib/js/templates/*.jst - <% end %> - -stylesheets: - visualsearch: - - lib/css/*.css \ No newline at end of file diff --git a/addons/web/static/lib/visualsearch/build/visualsearch-datauri.css b/addons/web/static/lib/visualsearch/build/visualsearch-datauri.css deleted file mode 100755 index 3e3edd0063f..00000000000 --- a/addons/web/static/lib/visualsearch/build/visualsearch-datauri.css +++ /dev/null @@ -1,310 +0,0 @@ -.VS-search .VS-icon { - background-repeat: no-repeat; - background-position: center center; - vertical-align: middle; - width: 16px; height: 16px; -} - .VS-search .VS-icon-cancel { - width: 11px; height: 11px; - background-position: center 0; - background-image: url("data:image/png;charset=utf-8;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAAWCAYAAAAW5GZjAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAb9JREFUeNqUUr1qAkEQ3j0khQp6kihaeGgEEa18gTQR0iRY+BaBSMDGwidIEUKqFL6BopgqBAJ5AMFGjUU0d4WHEvwJarvZ77gRIzGYgb1hZr+Z75vZ40IIzqTNZrPj8Xicn0wmmcViEXS73aaqqq+BQODG6/W+A8MBNk3zfDAY3C6Xy0O2ZS6X6zMSiVwHg8FHLjtq7Xb7RQKj7BeTzVCgJ5PJU2U0GhUk7REuMpkMi8fjFggeMeecrVYrFRId0CgTAgDDMFg4HLbA8IjJgHNgGEr0er0fQIphUmZAwdSUADUB4RFDsz3oSMF6CLzZkQqgGebz+Z75dDqNdTqdp13bgDmdTj2VSp0oWHg0Gr2UNH2Z/9o+yMv7K4/HY/C/XhDUfr//jl7QQVT9fp/V63VWqVRYt9tliUSCZbPZg1wux9Lp9PqFeK1Wu9A0DdXz7YM87i0FrVZLs4Fi1wmFQh/NZjOmVKvVgq7rR/QflMtlixGedjwcDlUpMQ9tbzalkAAB2/R297mNW+sT2wUbUnA//V/nYrH4QOBNABUQuFQq3TNMuc82sDVrz41G42yvPeODAwZQ0QzwiJEnzLcAAwBJ6WXlwoBgZAAAAABJRU5ErkJggg=="); - cursor: pointer; - } - .VS-search .VS-icon-cancel:hover { - background-position: center -11px; - } - .VS-search .VS-icon-search { - width: 12px; height: 12px; - background-image: url("data:image/png;charset=utf-8;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAUZJREFUeNpUUM2qgmAQzS8NiUgLzTIXLZQW1QuI9AY9QPSW9gQ9QiriwpJQEBVrVWT2d7p2L9xZzDdzZs7M+YYqy/J8Ptu2vd/v4zgeDAaqqk4mE47jar9GnU6nzWbjOA5FUa/Xq0Jns9l8Pud5vkpp58cwAOzhcBhFkeu6GNztdg3D+Db5vo9nOp2iiWGYTqdDCMFe4LquI0aVpGmKR9M0lmUbjQY8YiBJklTb4YkoilBzOBzq9TogeMQIJEmqmlAlo9EIyXa7tSyrKAp4xEBkWUb5q2k8Hh+PR8/zwjCEgufz+aESstvtoKnVan2GgY31kBkEAfT1ej1FUZDiNIIgrFYr9H1ug3teLpfH43G/3/FBUJGu1+s8z8FZLpc0mmiabrfbf5fEumazuVgsTNO8Xq+3242qRNT+G0CMz7IMzH6//xZgAA60tj6rqzxpAAAAAElFTkSuQmCC"); - } - -/*------------------------------ RESET + DEFAULT STYLES ---------------------------------*/ - -/* -Eric Meyer's final reset.css -Source: http://meyerweb.com/eric/thoughts/2007/05/01/reset-reloaded/ -*/ -.VS-search div, .VS-search span, .VS-search a, .VS-search img, -.VS-search ul, .VS-search li, .VS-search form, .VS-search label, -.VS-interface ul, .VS-interface li, .VS-interface { - margin: 0; - padding: 0; - border: 0; - outline: 0; - font-weight: inherit; - font-style: inherit; - font-size: 100%; - font-family: inherit; - vertical-align: baseline; -} - -.VS-search :focus { - outline: 0; -} -.VS-search { - line-height: 1; - color: black; -} -.VS-search ol, .VS-search ul { - list-style: none; -} - -/* ===================== */ -/* = General and Reset = */ -/* ===================== */ - -.VS-search { - font-family: Arial, sans-serif; - color: #373737; - font-size: 12px; -} -.VS-search input { - display: block; - border: none; - -moz-box-shadow: none; - -webkit-box-shadow: none; - box-shadow: none; - outline: none; - margin: 0; padding: 4px; - background: transparent; - font-size: 16px; - line-height: 20px; - width: 100%; -} -.VS-interface, .VS-search .dialog, .VS-search input { - font-family: "Lucida Grande", "Lucida Sans Unicode", Helvetica, Arial, sans-serif !important; - line-height: 1.1em; -} - -/* ========== */ -/* = Layout = */ -/* ========== */ - -.VS-search .VS-search-box { - cursor: text; - position: relative; - background: transparent; - border: 2px solid #ccc; - border-radius: 16px; -webkit-border-radius: 16px; -moz-border-radius: 16px; - background-color: #fafafa; - -webkit-box-shadow: inset 0px 0px 3px #ccc; - -moz-box-shadow: inset 0px 0px 3px #ccc; - box-shadow: inset 0px 0px 3px #ccc; - min-height: 28px; - height: auto; -} - .VS-search .VS-search-box.VS-focus { - border-color: #acf; - -webkit-box-shadow: inset 0px 0px 3px #acf; - -moz-box-shadow: inset 0px 0px 3px #acf; - box-shadow: inset 0px 0px 3px #acf; - } - .VS-search .VS-search-inner { - position: relative; - margin: 0 20px 0 22px; - overflow: hidden; - } - .VS-search input { - width: 100px; - } - .VS-search input, - .VS-search .VS-input-width-tester { - padding: 6px 0; - float: left; - color: #808080; - font: 13px/17px Helvetica, Arial; - } - .VS-search.VS-focus input { - color: #606060; - } - .VS-search .VS-icon-search { - position: absolute; - left: 9px; top: 8px; - } - .VS-search .VS-icon-cancel { - position: absolute; - right: 9px; top: 8px; - } - -/* ================ */ -/* = Search Facet = */ -/* ================ */ - -.VS-search .search_facet { - float: left; - margin: 0; - padding: 0 0 0 14px; - position: relative; - border: 1px solid transparent; - height: 20px; - margin: 3px -3px 3px 0; -} - .VS-search .search_facet.is_selected { - margin-left: -3px; - -webkit-border-radius: 16px; - -moz-border-radius: 16px; - border-radius: 16px; - background-color: #d2e6fd; - background-image: -moz-linear-gradient(top, #d2e6fd, #b0d1f9); /* FF3.6 */ - background-image: -webkit-gradient(linear, left top, left bottom, from(#d2e6fd), to(#b0d1f9)); /* Saf4+, Chrome */ - background-image: linear-gradient(top, #d2e6fd, #b0d1f9); - border: 1px solid #6eadf5; - } - .VS-search .search_facet .category { - float: left; - text-transform: uppercase; - font-weight: bold; - font-size: 10px; - color: #808080; - padding: 8px 0 5px; - line-height: 13px; - cursor: pointer; - padding: 4px 0 0; - } - .VS-search .search_facet.is_selected .category { - margin-left: 3px; - } - .VS-search .search_facet .search_facet_input_container { - float: left; - } - .VS-search .search_facet input { - margin: 0; - padding: 0; - color: #000; - font-size: 13px; - line-height: 16px; - padding: 5px 0 5px 4px; - height: 16px; - width: auto; - z-index: 100; - position: relative; - padding-top: 1px; - padding-bottom: 2px; - padding-right: 3px; - - } - .VS-search .search_facet.is_editing input, - .VS-search .search_facet.is_selected input { - color: #000; - } - .VS-search .search_facet .search_facet_remove { - position: absolute; - left: 0; - top: 4px; - } - .VS-search .search_facet.is_selected .search_facet_remove { - opacity: 0.4; - left: 3px; - filter: alpha(opacity=40); - background-position: center -11px; - } - .VS-search .search_facet .search_facet_remove:hover { - opacity: 1; - } - .VS-search .search_facet.is_editing .category, - .VS-search .search_facet.is_selected .category { - color: #000; - } - .VS-search .search_facet.search_facet_maybe_delete .category, - .VS-search .search_facet.search_facet_maybe_delete input { - color: darkred; - } - -/* ================ */ -/* = Search Input = */ -/* ================ */ - -.VS-search .search_input { - height: 28px; - float: left; - margin-left: -1px; -} - .VS-search .search_input input { - padding: 6px 3px 6px 2px; - line-height: 10px; - height: 22px; - margin-top: -4px; - width: 10px; - z-index: 100; - min-width: 4px; - position: relative; - } - .VS-search .search_input.is_editing input { - color: #202020; - } - -/* ================ */ -/* = Autocomplete = */ -/* ================ */ - -.VS-interface.ui-autocomplete { - position: absolute; - border: 1px solid #C0C0C0; - border-top: 1px solid #D9D9D9; - background-color: #F6F6F6; - cursor: pointer; - z-index: 10000; - padding: 0; - margin: 0; - width: auto; - min-width: 80px; - max-width: 220px; - max-height: 240px; - overflow-y: auto; - overflow-x: hidden; - font-size: 13px; - top: 5px; - opacity: 0.97; - box-shadow: 3px 4px 5px -2px rgba(0, 0, 0, 0.5); -webkit-box-shadow: 3px 4px 5px -2px rgba(0, 0, 0, 0.5); -moz-box-shadow: 3px 4px 5px -2px rgba(0, 0, 0, 0.5); -} - .VS-interface.ui-autocomplete .ui-autocomplete-category { - text-transform: capitalize; - font-size: 11px; - padding: 4px 4px 4px; - border-top: 1px solid #A2A2A2; - border-bottom: 1px solid #A2A2A2; - background-color: #B7B7B7; - text-shadow: 0 -1px 0 #999; - font-weight: bold; - color: white; - cursor: default; - } - .VS-interface.ui-autocomplete .ui-menu-item { - float: none; - } - .VS-interface.ui-autocomplete .ui-menu-item a { - color: #000; - outline: none; - display: block; - padding: 3px 4px 5px; - border-radius: none; - line-height: 1; - background-color: #F8F8F8; - background-image: -moz-linear-gradient(top, #F8F8F8, #F3F3F3); /* FF3.6 */ - background-image: -webkit-gradient(linear, left top, left bottom, from(#F8F8F8), to(#F3F3F3)); /* Saf4+, Chrome */ - background-image: linear-gradient(top, #F8F8F8, #F3F3F3); - border-top: 1px solid #FAFAFA; - border-bottom: 1px solid #f0f0f0; - } - .VS-interface.ui-autocomplete .ui-menu-item a:active { - outline: none; - } - .VS-interface.ui-autocomplete .ui-menu-item .ui-state-hover { - background-color: #6483F7; - background-image: -moz-linear-gradient(top, #648bF5, #2465f3); /* FF3.6 */ - background-image: -webkit-gradient(linear, left top, left bottom, from(#648bF5), to(#2465f3)); /* Saf4+, Chrome */ - background-image: linear-gradient(top, #648bF5, #2465f3); - border-top: 1px solid #5b83ec; - border-bottom: 1px solid #1459e9; - border-left: none; - border-right: none; - color: white; - margin: 0; - } - .VS-interface.ui-autocomplete .ui-corner-all { - border-radius: 0; - } - .VS-interface.ui-autocomplete li { - list-style: none; - width: auto; - } diff --git a/addons/web/static/lib/visualsearch/build/visualsearch.css b/addons/web/static/lib/visualsearch/build/visualsearch.css deleted file mode 100755 index 079ff122300..00000000000 --- a/addons/web/static/lib/visualsearch/build/visualsearch.css +++ /dev/null @@ -1,310 +0,0 @@ -.VS-search .VS-icon { - background-repeat: no-repeat; - background-position: center center; - vertical-align: middle; - width: 16px; height: 16px; -} - .VS-search .VS-icon-cancel { - width: 11px; height: 11px; - background-position: center 0; - background-image: url(../images/embed/icons/cancel_search.png?1311104738); - cursor: pointer; - } - .VS-search .VS-icon-cancel:hover { - background-position: center -11px; - } - .VS-search .VS-icon-search { - width: 12px; height: 12px; - background-image: url(../images/embed/icons/search_glyph.png?1311104738); - } - -/*------------------------------ RESET + DEFAULT STYLES ---------------------------------*/ - -/* -Eric Meyer's final reset.css -Source: http://meyerweb.com/eric/thoughts/2007/05/01/reset-reloaded/ -*/ -.VS-search div, .VS-search span, .VS-search a, .VS-search img, -.VS-search ul, .VS-search li, .VS-search form, .VS-search label, -.VS-interface ul, .VS-interface li, .VS-interface { - margin: 0; - padding: 0; - border: 0; - outline: 0; - font-weight: inherit; - font-style: inherit; - font-size: 100%; - font-family: inherit; - vertical-align: baseline; -} - -.VS-search :focus { - outline: 0; -} -.VS-search { - line-height: 1; - color: black; -} -.VS-search ol, .VS-search ul { - list-style: none; -} - -/* ===================== */ -/* = General and Reset = */ -/* ===================== */ - -.VS-search { - font-family: Arial, sans-serif; - color: #373737; - font-size: 12px; -} -.VS-search input { - display: block; - border: none; - -moz-box-shadow: none; - -webkit-box-shadow: none; - box-shadow: none; - outline: none; - margin: 0; padding: 4px; - background: transparent; - font-size: 16px; - line-height: 20px; - width: 100%; -} -.VS-interface, .VS-search .dialog, .VS-search input { - font-family: "Lucida Grande", "Lucida Sans Unicode", Helvetica, Arial, sans-serif !important; - line-height: 1.1em; -} - -/* ========== */ -/* = Layout = */ -/* ========== */ - -.VS-search .VS-search-box { - cursor: text; - position: relative; - background: transparent; - border: 2px solid #ccc; - border-radius: 16px; -webkit-border-radius: 16px; -moz-border-radius: 16px; - background-color: #fafafa; - -webkit-box-shadow: inset 0px 0px 3px #ccc; - -moz-box-shadow: inset 0px 0px 3px #ccc; - box-shadow: inset 0px 0px 3px #ccc; - min-height: 28px; - height: auto; -} - .VS-search .VS-search-box.VS-focus { - border-color: #acf; - -webkit-box-shadow: inset 0px 0px 3px #acf; - -moz-box-shadow: inset 0px 0px 3px #acf; - box-shadow: inset 0px 0px 3px #acf; - } - .VS-search .VS-search-inner { - position: relative; - margin: 0 20px 0 22px; - overflow: hidden; - } - .VS-search input { - width: 100px; - } - .VS-search input, - .VS-search .VS-input-width-tester { - padding: 6px 0; - float: left; - color: #808080; - font: 13px/17px Helvetica, Arial; - } - .VS-search.VS-focus input { - color: #606060; - } - .VS-search .VS-icon-search { - position: absolute; - left: 9px; top: 8px; - } - .VS-search .VS-icon-cancel { - position: absolute; - right: 9px; top: 8px; - } - -/* ================ */ -/* = Search Facet = */ -/* ================ */ - -.VS-search .search_facet { - float: left; - margin: 0; - padding: 0 0 0 14px; - position: relative; - border: 1px solid transparent; - height: 20px; - margin: 3px -3px 3px 0; -} - .VS-search .search_facet.is_selected { - margin-left: -3px; - -webkit-border-radius: 16px; - -moz-border-radius: 16px; - border-radius: 16px; - background-color: #d2e6fd; - background-image: -moz-linear-gradient(top, #d2e6fd, #b0d1f9); /* FF3.6 */ - background-image: -webkit-gradient(linear, left top, left bottom, from(#d2e6fd), to(#b0d1f9)); /* Saf4+, Chrome */ - background-image: linear-gradient(top, #d2e6fd, #b0d1f9); - border: 1px solid #6eadf5; - } - .VS-search .search_facet .category { - float: left; - text-transform: uppercase; - font-weight: bold; - font-size: 10px; - color: #808080; - padding: 8px 0 5px; - line-height: 13px; - cursor: pointer; - padding: 4px 0 0; - } - .VS-search .search_facet.is_selected .category { - margin-left: 3px; - } - .VS-search .search_facet .search_facet_input_container { - float: left; - } - .VS-search .search_facet input { - margin: 0; - padding: 0; - color: #000; - font-size: 13px; - line-height: 16px; - padding: 5px 0 5px 4px; - height: 16px; - width: auto; - z-index: 100; - position: relative; - padding-top: 1px; - padding-bottom: 2px; - padding-right: 3px; - - } - .VS-search .search_facet.is_editing input, - .VS-search .search_facet.is_selected input { - color: #000; - } - .VS-search .search_facet .search_facet_remove { - position: absolute; - left: 0; - top: 4px; - } - .VS-search .search_facet.is_selected .search_facet_remove { - opacity: 0.4; - left: 3px; - filter: alpha(opacity=40); - background-position: center -11px; - } - .VS-search .search_facet .search_facet_remove:hover { - opacity: 1; - } - .VS-search .search_facet.is_editing .category, - .VS-search .search_facet.is_selected .category { - color: #000; - } - .VS-search .search_facet.search_facet_maybe_delete .category, - .VS-search .search_facet.search_facet_maybe_delete input { - color: darkred; - } - -/* ================ */ -/* = Search Input = */ -/* ================ */ - -.VS-search .search_input { - height: 28px; - float: left; - margin-left: -1px; -} - .VS-search .search_input input { - padding: 6px 3px 6px 2px; - line-height: 10px; - height: 22px; - margin-top: -4px; - width: 10px; - z-index: 100; - min-width: 4px; - position: relative; - } - .VS-search .search_input.is_editing input { - color: #202020; - } - -/* ================ */ -/* = Autocomplete = */ -/* ================ */ - -.VS-interface.ui-autocomplete { - position: absolute; - border: 1px solid #C0C0C0; - border-top: 1px solid #D9D9D9; - background-color: #F6F6F6; - cursor: pointer; - z-index: 10000; - padding: 0; - margin: 0; - width: auto; - min-width: 80px; - max-width: 220px; - max-height: 240px; - overflow-y: auto; - overflow-x: hidden; - font-size: 13px; - top: 5px; - opacity: 0.97; - box-shadow: 3px 4px 5px -2px rgba(0, 0, 0, 0.5); -webkit-box-shadow: 3px 4px 5px -2px rgba(0, 0, 0, 0.5); -moz-box-shadow: 3px 4px 5px -2px rgba(0, 0, 0, 0.5); -} - .VS-interface.ui-autocomplete .ui-autocomplete-category { - text-transform: capitalize; - font-size: 11px; - padding: 4px 4px 4px; - border-top: 1px solid #A2A2A2; - border-bottom: 1px solid #A2A2A2; - background-color: #B7B7B7; - text-shadow: 0 -1px 0 #999; - font-weight: bold; - color: white; - cursor: default; - } - .VS-interface.ui-autocomplete .ui-menu-item { - float: none; - } - .VS-interface.ui-autocomplete .ui-menu-item a { - color: #000; - outline: none; - display: block; - padding: 3px 4px 5px; - border-radius: none; - line-height: 1; - background-color: #F8F8F8; - background-image: -moz-linear-gradient(top, #F8F8F8, #F3F3F3); /* FF3.6 */ - background-image: -webkit-gradient(linear, left top, left bottom, from(#F8F8F8), to(#F3F3F3)); /* Saf4+, Chrome */ - background-image: linear-gradient(top, #F8F8F8, #F3F3F3); - border-top: 1px solid #FAFAFA; - border-bottom: 1px solid #f0f0f0; - } - .VS-interface.ui-autocomplete .ui-menu-item a:active { - outline: none; - } - .VS-interface.ui-autocomplete .ui-menu-item .ui-state-hover { - background-color: #6483F7; - background-image: -moz-linear-gradient(top, #648bF5, #2465f3); /* FF3.6 */ - background-image: -webkit-gradient(linear, left top, left bottom, from(#648bF5), to(#2465f3)); /* Saf4+, Chrome */ - background-image: linear-gradient(top, #648bF5, #2465f3); - border-top: 1px solid #5b83ec; - border-bottom: 1px solid #1459e9; - border-left: none; - border-right: none; - color: white; - margin: 0; - } - .VS-interface.ui-autocomplete .ui-corner-all { - border-radius: 0; - } - .VS-interface.ui-autocomplete li { - list-style: none; - width: auto; - } diff --git a/addons/web/static/lib/visualsearch/build/visualsearch.js b/addons/web/static/lib/visualsearch/build/visualsearch.js deleted file mode 100755 index 319d978db3c..00000000000 --- a/addons/web/static/lib/visualsearch/build/visualsearch.js +++ /dev/null @@ -1,1845 +0,0 @@ -// This is the annotated source code for -// [VisualSearch.js](http://documentcloud.github.com/visualsearch/), -// a rich search box for real data. -// -// The annotated source HTML is generated by -// [Docco](http://jashkenas.github.com/docco/). - -/** @license VisualSearch.js 0.2.2 - * (c) 2011 Samuel Clay, @samuelclay, DocumentCloud Inc. - * VisualSearch.js may be freely distributed under the MIT license. - * For all details and documentation: - * http://documentcloud.github.com/visualsearch - */ - -(function() { - - var $ = jQuery; // Handle namespaced jQuery - - // Setting up VisualSearch globals. These will eventually be made instance-based. - if (!window.VS) window.VS = {}; - if (!VS.app) VS.app = {}; - if (!VS.ui) VS.ui = {}; - if (!VS.model) VS.model = {}; - if (!VS.utils) VS.utils = {}; - - // Sets the version for VisualSearch to be used programatically elsewhere. - VS.VERSION = '0.2.2'; - - VS.VisualSearch = function(options) { - var defaults = { - container : '', - query : '', - unquotable : [], - callbacks : { - search : $.noop, - focus : $.noop, - blur : $.noop, - facetMatches : $.noop, - valueMatches : $.noop - } - }; - this.options = _.extend({}, defaults, options); - this.options.callbacks = _.extend({}, defaults.callbacks, options.callbacks); - - VS.app.hotkeys.initialize(); - this.searchQuery = new VS.model.SearchQuery(); - this.searchBox = new VS.ui.SearchBox({app: this}); - - if (options.container) { - var searchBox = this.searchBox.render().el; - $(this.options.container).html(searchBox); - } - this.searchBox.value(this.options.query || ''); - - // Disable page caching for browsers that incorrectly cache the visual search inputs. - // This is forced the browser to re-render the page when it is retrieved in its history. - $(window).bind('unload', function(e) {}); - - // Gives the user back a reference to the `searchBox` so they - // can use public methods. - return this; - }; - - // Entry-point used to tie all parts of VisualSearch together. It will either attach - // itself to `options.container`, or pass back the `searchBox` so it can be rendered - // at will. - VS.init = function(options) { - return new VS.VisualSearch(options); - }; - -})(); -(function() { - -var $ = jQuery; // Handle namespaced jQuery - -// The search box is responsible for managing the many facet views and input views. -VS.ui.SearchBox = Backbone.View.extend({ - - id : 'search', - - events : { - 'click .VS-cancel-search-box' : 'clearSearch', - 'mousedown .VS-search-box' : 'maybeFocusSearch', - 'dblclick .VS-search-box' : 'highlightSearch', - 'click .VS-search-box' : 'maybeTripleClick' - }, - - // Creating a new SearchBox registers handlers for re-rendering facets when necessary, - // as well as handling typing when a facet is selected. - initialize : function() { - this.app = this.options.app; - this.flags = { - allSelected : false - }; - this.facetViews = []; - this.inputViews = []; - _.bindAll(this, 'renderFacets', '_maybeDisableFacets', 'disableFacets', - 'deselectAllFacets', 'addedFacet', 'removedFacet', 'changedFacet'); - this.app.searchQuery - .bind('reset', this.renderFacets) - .bind('add', this.addedFacet) - .bind('remove', this.removedFacet) - .bind('change', this.changedFacet); - $(document).bind('keydown', this._maybeDisableFacets); - }, - - // Renders the search box, but requires placement on the page through `this.el`. - render : function() { - $(this.el).append(JST['search_box']({})); - $(document.body).setMode('no', 'search'); - - return this; - }, - - // # Querying Facets # - - // Either gets a serialized query string or sets the faceted query from a query string. - value : function(query) { - if (query == null) return this.serialize(); - return this.setQuery(query); - }, - - // Uses the VS.app.searchQuery collection to serialize the current query from the various - // facets that are in the search box. - serialize : function() { - var query = []; - var inputViewsCount = this.inputViews.length; - - this.app.searchQuery.each(_.bind(function(facet, i) { - query.push(this.inputViews[i].value()); - query.push(facet.serialize()); - }, this)); - - if (inputViewsCount) { - query.push(this.inputViews[inputViewsCount-1].value()); - } - - return _.compact(query).join(' '); - }, - - // Takes a query string and uses the SearchParser to parse and render it. Note that - // `VS.app.SearchParser` refreshes the `VS.app.searchQuery` collection, which is bound - // here to call `this.renderFacets`. - setQuery : function(query) { - this.currentQuery = query; - VS.app.SearchParser.parse(this.app, query); - }, - - // Returns the position of a facet/input view. Useful when moving between facets. - viewPosition : function(view) { - var views = view.type == 'facet' ? this.facetViews : this.inputViews; - var position = _.indexOf(views, view); - if (position == -1) position = 0; - return position; - }, - - // Used to launch a search. Hitting enter or clicking the search button. - searchEvent : function(e) { - var query = this.value(); - this.focusSearch(e); - this.value(query); - this.app.options.callbacks.search(query, this.app.searchQuery); - }, - - // # Rendering Facets # - - // Add a new facet. Facet will be focused and ready to accept a value. Can also - // specify position, in the case of adding facets from an inbetween input. - addFacet : function(category, initialQuery, position) { - category = VS.utils.inflector.trim(category); - initialQuery = VS.utils.inflector.trim(initialQuery || ''); - if (!category) return; - - var model = new VS.model.SearchFacet({ - category : category, - value : initialQuery || '', - app : this.app - }); - this.app.searchQuery.add(model, {at: position}); - }, - - // Renders a newly added facet, and selects it. - addedFacet : function (model) { - this.renderFacets(); - var facetView = _.detect(this.facetViews, function(view) { - if (view.model == model) return true; - }); - - _.defer(function() { - facetView.enableEdit(); - }); - }, - - // Changing a facet programmatically re-renders it. - changedFacet: function () { - this.renderFacets(); - }, - - // When removing a facet, potentially do something. For now, the adjacent - // remaining facet is selected, but this is handled by the facet's view, - // since its position is unknown by the time the collection triggers this - // remove callback. - removedFacet : function (facet, query, options) {}, - - // Renders each facet as a searchFacet view. - renderFacets : function() { - this.facetViews = []; - this.inputViews = []; - - this.$('.VS-search-inner').empty(); - - this.app.searchQuery.each(_.bind(function(facet, i) { - this.renderFacet(facet, i); - }, this)); - - // Add on an n+1 empty search input on the very end. - this.renderSearchInput(); - }, - - // Render a single facet, using its category and query value. - renderFacet : function(facet, position) { - var view = new VS.ui.SearchFacet({ - app : this.app, - model : facet, - order : position - }); - - // Input first, facet second. - this.renderSearchInput(); - this.facetViews.push(view); - this.$('.VS-search-inner').children().eq(position*2).after(view.render().el); - - view.calculateSize(); - _.defer(_.bind(view.calculateSize, view)); - - return view; - }, - - // Render a single input, used to create and autocomplete facets - renderSearchInput : function() { - var input = new VS.ui.SearchInput({position: this.inputViews.length, app: this.app}); - this.$('.VS-search-inner').append(input.render().el); - this.inputViews.push(input); - }, - - // # Modifying Facets # - - // Clears out the search box. Command+A + delete can trigger this, as can a cancel button. - // - // If a `clearSearch` callback was provided, the callback is invoked and - // provided with a function performs the actual removal of the data. This - // allows third-party developers to either clear data asynchronously, or - // prior to performing their custom "clear" logic. - clearSearch : function(e) { - var actualClearSearch = _.bind(function() { - this.disableFacets(); - this.value(''); - this.flags.allSelected = false; - this.searchEvent(e); - this.focusSearch(e); - }, this); - - if (this.app.options.callbacks.clearSearch) { - this.app.options.callbacks.clearSearch(actualClearSearch); - } else { - actualClearSearch(); - } - }, - - // Command+A selects all facets. - selectAllFacets : function() { - this.flags.allSelected = true; - - $(document).one('click.selectAllFacets', this.deselectAllFacets); - - _.each(this.facetViews, function(facetView, i) { - facetView.selectFacet(); - }); - _.each(this.inputViews, function(inputView, i) { - inputView.selectText(); - }); - }, - - // Used by facets and input to see if all facets are currently selected. - allSelected : function(deselect) { - if (deselect) this.flags.allSelected = false; - return this.flags.allSelected; - }, - - // After `selectAllFacets` is engaged, this method is bound to the entire document. - // This immediate disables and deselects all facets, but it also checks if the user - // has clicked on either a facet or an input, and properly selects the view. - deselectAllFacets : function(e) { - this.disableFacets(); - - if (this.$(e.target).is('.category,input')) { - var el = $(e.target).closest('.search_facet,.search_input'); - var view = _.detect(this.facetViews.concat(this.inputViews), function(v) { - return v.el == el[0]; - }); - if (view.type == 'facet') { - view.selectFacet(); - } else if (view.type == 'input') { - _.defer(function() { - view.enableEdit(true); - }); - } - } - }, - - // Disables all facets except for the passed in view. Used when switching between - // facets, so as not to have to keep state of active facets. - disableFacets : function(keepView) { - _.each(this.inputViews, function(view) { - if (view && view != keepView && - (view.modes.editing == 'is' || view.modes.selected == 'is')) { - view.disableEdit(); - } - }); - _.each(this.facetViews, function(view) { - if (view && view != keepView && - (view.modes.editing == 'is' || view.modes.selected == 'is')) { - view.disableEdit(); - view.deselectFacet(); - } - }); - - this.flags.allSelected = false; - this.removeFocus(); - $(document).unbind('click.selectAllFacets'); - }, - - // Resize all inputs to account for extra keystrokes which may be changing the facet - // width incorrectly. This is a safety check to ensure inputs are correctly sized. - resizeFacets : function(view) { - _.each(this.facetViews, function(facetView, i) { - if (!view || facetView == view) { - facetView.resize(); - } - }); - }, - - // Handles keydown events on the document. Used to complete the Cmd+A deletion, and - // blurring focus. - _maybeDisableFacets : function(e) { - if (this.flags.allSelected && VS.app.hotkeys.key(e) == 'backspace') { - e.preventDefault(); - this.clearSearch(e); - return false; - } else if (this.flags.allSelected && VS.app.hotkeys.printable(e)) { - this.clearSearch(e); - } - }, - - // # Focusing Facets # - - // Move focus between facets and inputs. Takes a direction as well as many options - // for skipping over inputs and only to facets, placement of cursor position in facet - // (i.e. at the end), and selecting the text in the input/facet. - focusNextFacet : function(currentView, direction, options) { - options = options || {}; - var viewCount = this.facetViews.length; - var viewPosition = options.viewPosition || this.viewPosition(currentView); - - if (!options.skipToFacet) { - // Correct for bouncing between matching text and facet arrays. - if (currentView.type == 'text' && direction > 0) direction -= 1; - if (currentView.type == 'facet' && direction < 0) direction += 1; - } else if (options.skipToFacet && currentView.type == 'text' && - viewCount == viewPosition && direction >= 0) { - // Special case of looping around to a facet from the last search input box. - viewPosition = 0; - direction = 0; - } - var view, next = Math.min(viewCount, viewPosition + direction); - - if (currentView.type == 'text') { - if (next >= 0 && next < viewCount) { - view = this.facetViews[next]; - } else if (next == viewCount) { - view = this.inputViews[this.inputViews.length-1]; - } - if (view && options.selectFacet && view.type == 'facet') { - view.selectFacet(); - } else if (view) { - view.enableEdit(); - view.setCursorAtEnd(direction || options.startAtEnd); - } - } else if (currentView.type == 'facet') { - if (options.skipToFacet) { - if (next >= viewCount || next < 0) { - view = _.last(this.inputViews); - view.enableEdit(); - } else { - view = this.facetViews[next]; - view.enableEdit(); - view.setCursorAtEnd(direction || options.startAtEnd); - } - } else { - view = this.inputViews[next]; - view.enableEdit(); - } - } - if (options.selectText) view.selectText(); - this.resizeFacets(); - }, - - maybeFocusSearch : function(e) { - if ($(e.target).is('.VS-search-box') || - $(e.target).is('.VS-search-inner') || - e.type == 'keydown') { - this.focusSearch(e); - } - }, - - // Bring focus to last input field. - focusSearch : function(e, selectText) { - var view = this.inputViews[this.inputViews.length-1]; - view.enableEdit(selectText); - if (!selectText) view.setCursorAtEnd(-1); - if (e.type == 'keydown') { - view.keydown(e); - view.box.trigger('keydown'); - } - _.defer(_.bind(function() { - if (!this.$('input:focus').length) { - view.enableEdit(selectText); - } - }, this)); - }, - - // Double-clicking on the search wrapper should select the existing text in - // the last search input. Also start the triple-click timer. - highlightSearch : function(e) { - if ($(e.target).is('.VS-search-box') || - $(e.target).is('.VS-search-inner') || - e.type == 'keydown') { - var lastinput = this.inputViews[this.inputViews.length-1]; - lastinput.startTripleClickTimer(); - this.focusSearch(e, true); - } - }, - - maybeTripleClick : function(e) { - var lastinput = this.inputViews[this.inputViews.length-1]; - return lastinput.maybeTripleClick(e); - }, - - // Used to show the user is focused on some input inside the search box. - addFocus : function() { - this.app.options.callbacks.focus(); - this.$('.VS-search-box').addClass('VS-focus'); - }, - - // User is no longer focused on anything in the search box. - removeFocus : function() { - this.app.options.callbacks.blur(); - var focus = _.any(this.facetViews.concat(this.inputViews), function(view) { - return view.isFocused(); - }); - if (!focus) this.$('.VS-search-box').removeClass('VS-focus'); - }, - - // Show a menu which adds pre-defined facets to the search box. This is unused for now. - showFacetCategoryMenu : function(e) { - e.preventDefault(); - e.stopPropagation(); - if (this.facetCategoryMenu && this.facetCategoryMenu.modes.open == 'is') { - return this.facetCategoryMenu.close(); - } - - var items = [ - {title: 'Account', onClick: _.bind(this.addFacet, this, 'account', '')}, - {title: 'Project', onClick: _.bind(this.addFacet, this, 'project', '')}, - {title: 'Filter', onClick: _.bind(this.addFacet, this, 'filter', '')}, - {title: 'Access', onClick: _.bind(this.addFacet, this, 'access', '')} - ]; - - var menu = this.facetCategoryMenu || (this.facetCategoryMenu = new dc.ui.Menu({ - items : items, - standalone : true - })); - - this.$('.VS-icon-search').after(menu.render().open().content); - return false; - } - -}); - -})(); - -(function() { - -var $ = jQuery; // Handle namespaced jQuery - -// This is the visual search facet that holds the category and its autocompleted -// input field. -VS.ui.SearchFacet = Backbone.View.extend({ - - type : 'facet', - - className : 'search_facet', - - events : { - 'click .category' : 'selectFacet', - 'keydown input' : 'keydown', - 'mousedown input' : 'enableEdit', - 'mouseover .VS-icon-cancel' : 'showDelete', - 'mouseout .VS-icon-cancel' : 'hideDelete', - 'click .VS-icon-cancel' : 'remove' - }, - - initialize : function(options) { - this.flags = { - canClose : false - }; - _.bindAll(this, 'set', 'keydown', 'deselectFacet', 'deferDisableEdit'); - }, - - // Rendering the facet sets up autocompletion, events on blur, and populates - // the facet's input with its starting value. - render : function() { - $(this.el).html(JST['search_facet']({ - model : this.model - })); - - this.setMode('not', 'editing'); - this.setMode('not', 'selected'); - this.box = this.$('input'); - this.box.val(this.model.get('value')); - this.box.bind('blur', this.deferDisableEdit); - // Handle paste events with `propertychange` - this.box.bind('input propertychange', this.keydown); - this.setupAutocomplete(); - - return this; - }, - - // This method is used to setup the facet's input to auto-grow. - // This is defered in the searchBox so it can be attached to the - // DOM to get the correct font-size. - calculateSize : function() { - this.box.autoGrowInput(); - this.box.unbind('updated.autogrow'); - this.box.bind('updated.autogrow', _.bind(this.moveAutocomplete, this)); - }, - - // Forces a recalculation of this facet's input field's value. Called when - // the facet is focused, removed, or otherwise modified. - resize : function(e) { - this.box.trigger('resize.autogrow', e); - }, - - // Watches the facet's input field to see if it matches the beginnings of - // words in `autocompleteValues`, which is different for every category. - // If the value, when selected from the autocompletion menu, is different - // than what it was, commit the facet and search for it. - setupAutocomplete : function() { - this.box.autocomplete({ - source : _.bind(this.autocompleteValues, this), - minLength : 0, - delay : 0, - autoFocus : true, - position : {offset : "0 5"}, - create : _.bind(function(e, ui) { - $(this.el).find('.ui-autocomplete-input').css('z-index','auto'); - }, this), - select : _.bind(function(e, ui) { - e.preventDefault(); - var originalValue = this.model.get('value'); - this.set(ui.item.value); - if (originalValue != ui.item.value || this.box.val() != ui.item.value) { - this.search(e); - } - return false; - }, this), - open : _.bind(function(e, ui) { - var box = this.box; - this.box.autocomplete('widget').find('.ui-menu-item').each(function() { - var $value = $(this); - if ($value.data('item.autocomplete')['value'] == box.val()) { - box.data('autocomplete').menu.activate(new $.Event("mouseover"), $value); - } - }); - }, this) - }); - - this.box.autocomplete('widget').addClass('VS-interface'); - }, - - // As the facet's input field grows, it may move to the next line in the - // search box. `autoGrowInput` triggers an `updated` event on the input - // field, which is bound to this method to move the autocomplete menu. - moveAutocomplete : function() { - var autocomplete = this.box.data('autocomplete'); - if (autocomplete) { - autocomplete.menu.element.position({ - my : "left top", - at : "left bottom", - of : this.box.data('autocomplete').element, - collision : "flip", - offset : "0 5" - }); - } - }, - - // When a user enters a facet and it is being edited, immediately show - // the autocomplete menu and size it to match the contents. - searchAutocomplete : function(e) { - var autocomplete = this.box.data('autocomplete'); - if (autocomplete) { - var menu = autocomplete.menu.element; - autocomplete.search(); - - // Resize the menu based on the correctly measured width of what's bigger: - // the menu's original size or the menu items' new size. - menu.outerWidth(Math.max( - menu.width('').outerWidth(), - autocomplete.element.outerWidth() - )); - } - }, - - // Closes the autocomplete menu. Called on disabling, selecting, deselecting, - // and anything else that takes focus out of the facet's input field. - closeAutocomplete : function() { - var autocomplete = this.box.data('autocomplete'); - if (autocomplete) autocomplete.close(); - }, - - // Search terms used in the autocomplete menu. These are specific to the facet, - // and only match for the facet's category. The values are then matched on the - // first letter of any word in matches, and finally sorted according to the - // value's own category. You can pass `preserveOrder` as an option in the - // `facetMatches` callback to skip any further ordering done client-side. - autocompleteValues : function(req, resp) { - var category = this.model.get('category'); - var value = this.model.get('value'); - var searchTerm = req.term; - - this.options.app.options.callbacks.valueMatches(category, searchTerm, function(matches, options) { - options = options || {}; - matches = matches || []; - - if (searchTerm && value != searchTerm) { - if (options.preserveMatches) { - return matches; - } else { - var re = VS.utils.inflector.escapeRegExp(searchTerm || ''); - var matcher = new RegExp('\\b' + re, 'i'); - matches = $.grep(matches, function(item) { - return matcher.test(item) || - matcher.test(item.value) || - matcher.test(item.label); - }); - } - } - - if (options.preserveOrder) { - resp(matches); - } else { - resp(_.sortBy(matches, function(match) { - if (match == value || match.value == value) return ''; - else return match; - })); - } - }); - - }, - - // Sets the facet's model's value. - set : function(value) { - if (!value) return; - this.model.set({'value': value}); - }, - - // Before the searchBox performs a search, we need to close the - // autocomplete menu. - search : function(e, direction) { - if (!direction) direction = 1; - this.closeAutocomplete(); - this.options.app.searchBox.searchEvent(e); - _.defer(_.bind(function() { - this.options.app.searchBox.focusNextFacet(this, direction, {viewPosition: this.options.order}); - }, this)); - }, - - // Begin editing the facet's input. This is called when the user enters - // the input either from another facet or directly clicking on it. - // - // This method tells all other facets and inputs to disable so it can have - // the sole focus. It also prepares the autocompletion menu. - enableEdit : function() { - if (this.modes.editing != 'is') { - this.setMode('is', 'editing'); - this.deselectFacet(); - if (this.box.val() == '') { - this.box.val(this.model.get('value')); - } - } - - this.flags.canClose = false; - this.options.app.searchBox.disableFacets(this); - this.options.app.searchBox.addFocus(); - _.defer(_.bind(function() { - this.options.app.searchBox.addFocus(); - }, this)); - this.resize(); - this.searchAutocomplete(); - this.box.focus(); - }, - - // When the user blurs the input, they may either be going to another input - // or off the search box entirely. If they go to another input, this facet - // will be instantly disabled, and the canClose flag will be turned back off. - // - // However, if the user clicks elsewhere on the page, this method starts a timer - // that checks if any of the other inputs are selected or are being edited. If - // not, then it can finally close itself and its autocomplete menu. - deferDisableEdit : function() { - this.flags.canClose = true; - _.delay(_.bind(function() { - if (this.flags.canClose && !this.box.is(':focus') && - this.modes.editing == 'is' && this.modes.selected != 'is') { - this.disableEdit(); - } - }, this), 250); - }, - - // Called either by other facets receiving focus or by the timer in `deferDisableEdit`, - // this method will turn off the facet, remove any text selection, and close - // the autocomplete menu. - disableEdit : function() { - var newFacetQuery = VS.utils.inflector.trim(this.box.val()); - if (newFacetQuery != this.model.get('value')) { - this.set(newFacetQuery); - } - this.flags.canClose = false; - this.box.selectRange(0, 0); - this.box.blur(); - this.setMode('not', 'editing'); - this.closeAutocomplete(); - this.options.app.searchBox.removeFocus(); - }, - - // Selects the facet, which blurs the facet's input and highlights the facet. - // If this is the only facet being selected (and not part of a select all event), - // we attach a mouse/keyboard watcher to check if the next action by the user - // should delete this facet or just deselect it. - selectFacet : function(e) { - if (e) e.preventDefault(); - var allSelected = this.options.app.searchBox.allSelected(); - if (this.modes.selected == 'is') return; - - if (this.box.is(':focus')) { - this.box.setCursorPosition(0); - this.box.blur(); - } - - this.flags.canClose = false; - this.closeAutocomplete(); - this.setMode('is', 'selected'); - this.setMode('not', 'editing'); - if (!allSelected || e) { - $(document).unbind('keydown.facet', this.keydown); - $(document).unbind('click.facet', this.deselectFacet); - _.defer(_.bind(function() { - $(document).unbind('keydown.facet').bind('keydown.facet', this.keydown); - $(document).unbind('click.facet').one('click.facet', this.deselectFacet); - }, this)); - this.options.app.searchBox.disableFacets(this); - this.options.app.searchBox.addFocus(); - } - return false; - }, - - // Turns off highlighting on the facet. Called in a variety of ways, this - // only deselects the facet if it is selected, and then cleans up the - // keyboard/mouse watchers that were created when the facet was first - // selected. - deselectFacet : function(e) { - if (e) e.preventDefault(); - if (this.modes.selected == 'is') { - this.setMode('not', 'selected'); - this.closeAutocomplete(); - this.options.app.searchBox.removeFocus(); - } - $(document).unbind('keydown.facet', this.keydown); - $(document).unbind('click.facet', this.deselectFacet); - return false; - }, - - // Is the user currently focused in this facet's input field? - isFocused : function() { - return this.box.is(':focus'); - }, - - // Hovering over the delete button styles the facet so the user knows that - // the delete button will kill the entire facet. - showDelete : function() { - $(this.el).addClass('search_facet_maybe_delete'); - }, - - // On `mouseout`, the user is no longer hovering on the delete button. - hideDelete : function() { - $(this.el).removeClass('search_facet_maybe_delete'); - }, - - // When switching between facets, depending on the direction the cursor is - // coming from, the cursor in this facet's input field should match the original - // direction. - setCursorAtEnd : function(direction) { - if (direction == -1) { - this.box.setCursorPosition(this.box.val().length); - } else { - this.box.setCursorPosition(0); - } - }, - - // Deletes the facet and sends the cursor over to the nearest input field. - remove : function(e) { - var committed = this.model.get('value'); - this.deselectFacet(); - this.disableEdit(); - this.options.app.searchQuery.remove(this.model); - if (committed) { - this.search(e, -1); - } else { - this.options.app.searchBox.renderFacets(); - this.options.app.searchBox.focusNextFacet(this, -1, {viewPosition: this.options.order}); - } - }, - - // Selects the text in the facet's input field. When the user tabs between - // facets, convention is to highlight the entire field. - selectText: function() { - this.box.selectRange(0, this.box.val().length); - }, - - // Handles all keyboard inputs when in the facet's input field. This checks - // for movement between facets and inputs, entering a new value that needs - // to be autocompleted, as well as the removal of this facet. - keydown : function(e) { - var key = VS.app.hotkeys.key(e); - - if (key == 'enter' && this.box.val()) { - this.disableEdit(); - this.search(e); - } else if (key == 'left') { - if (this.modes.selected == 'is') { - this.deselectFacet(); - this.options.app.searchBox.focusNextFacet(this, -1, {startAtEnd: -1}); - } else if (this.box.getCursorPosition() == 0 && !this.box.getSelection().length) { - this.selectFacet(); - } - } else if (key == 'right') { - if (this.modes.selected == 'is') { - e.preventDefault(); - this.deselectFacet(); - this.setCursorAtEnd(0); - this.enableEdit(); - } else if (this.box.getCursorPosition() == this.box.val().length) { - e.preventDefault(); - this.disableEdit(); - this.options.app.searchBox.focusNextFacet(this, 1); - } - } else if (VS.app.hotkeys.shift && key == 'tab') { - e.preventDefault(); - this.options.app.searchBox.focusNextFacet(this, -1, { - startAtEnd : -1, - skipToFacet : true, - selectText : true - }); - } else if (key == 'tab') { - e.preventDefault(); - this.options.app.searchBox.focusNextFacet(this, 1, { - skipToFacet : true, - selectText : true - }); - } else if (VS.app.hotkeys.command && (e.which == 97 || e.which == 65)) { - e.preventDefault(); - this.options.app.searchBox.selectAllFacets(); - return false; - } else if (VS.app.hotkeys.printable(e) && this.modes.selected == 'is') { - this.options.app.searchBox.focusNextFacet(this, -1, {startAtEnd: -1}); - this.remove(e); - } else if (key == 'backspace') { - if (this.modes.selected == 'is') { - e.preventDefault(); - this.remove(e); - } else if (this.box.getCursorPosition() == 0 && - !this.box.getSelection().length) { - e.preventDefault(); - this.selectFacet(); - } - } - - this.resize(e); - - // Handle paste events - if (e.which == null) { - this.searchAutocomplete(e); - _.defer(_.bind(this.resize, this, e)); - } - } - -}); - -})(); - -(function() { - -var $ = jQuery; // Handle namespaced jQuery - -// This is the visual search input that is responsible for creating new facets. -// There is one input placed in between all facets. -VS.ui.SearchInput = Backbone.View.extend({ - - type : 'text', - - className : 'search_input', - - events : { - 'keypress input' : 'keypress', - 'keydown input' : 'keydown', - 'click input' : 'maybeTripleClick', - 'dblclick input' : 'startTripleClickTimer' - }, - - initialize : function() { - this.app = this.options.app; - this.flags = { - canClose : false - }; - _.bindAll(this, 'removeFocus', 'addFocus', 'moveAutocomplete', 'deferDisableEdit'); - }, - - // Rendering the input sets up autocomplete, events on focusing and blurring - // the input, and the auto-grow of the input. - render : function() { - $(this.el).html(JST['search_input']({})); - - this.setMode('not', 'editing'); - this.setMode('not', 'selected'); - this.box = this.$('input'); - this.box.autoGrowInput(); - this.box.bind('updated.autogrow', this.moveAutocomplete); - this.box.bind('blur', this.deferDisableEdit); - this.box.bind('focus', this.addFocus); - this.setupAutocomplete(); - - return this; - }, - - // Watches the input and presents an autocompleted menu, taking the - // remainder of the input field and adding a separate facet for it. - // - // See `addTextFacetRemainder` for explanation on how the remainder works. - setupAutocomplete : function() { - this.box.autocomplete({ - minLength : 1, - delay : 50, - autoFocus : true, - position : {offset : "0 -1"}, - source : _.bind(this.autocompleteValues, this), - create : _.bind(function(e, ui) { - $(this.el).find('.ui-autocomplete-input').css('z-index','auto'); - }, this), - select : _.bind(function(e, ui) { - e.preventDefault(); - e.stopPropagation(); - var remainder = this.addTextFacetRemainder(ui.item.value); - var position = this.options.position + (remainder ? 1 : 0); - this.app.searchBox.addFacet(ui.item.value, '', position); - return false; - }, this) - }); - - // Renders the results grouped by the categories they belong to. - this.box.data('autocomplete')._renderMenu = function(ul, items) { - var category = ''; - _.each(items, _.bind(function(item, i) { - if (item.category && item.category != category) { - ul.append('
  • '+item.category+'
  • '); - category = item.category; - } - this._renderItem(ul, item); - }, this)); - }; - - this.box.autocomplete('widget').addClass('VS-interface'); - }, - - // Search terms used in the autocomplete menu. The values are matched on the - // first letter of any word in matches, and finally sorted according to the - // value's own category. You can pass `preserveOrder` as an option in the - // `facetMatches` callback to skip any further ordering done client-side. - autocompleteValues : function(req, resp) { - var searchTerm = req.term; - var lastWord = searchTerm.match(/\w+$/); // Autocomplete only last word. - var re = VS.utils.inflector.escapeRegExp(lastWord && lastWord[0] || ' '); - this.app.options.callbacks.facetMatches(function(prefixes, options) { - options = options || {}; - prefixes = prefixes || []; - - // Only match from the beginning of the word. - var matcher = new RegExp('^' + re, 'i'); - var matches = $.grep(prefixes, function(item) { - return item && matcher.test(item.label || item); - }); - - if (options.preserveOrder) { - resp(matches); - } else { - resp(_.sortBy(matches, function(match) { - if (match.label) return match.category + '-' + match.label; - else return match; - })); - } - }); - - }, - - // Closes the autocomplete menu. Called on disabling, selecting, deselecting, - // and anything else that takes focus out of the facet's input field. - closeAutocomplete : function() { - var autocomplete = this.box.data('autocomplete'); - if (autocomplete) autocomplete.close(); - }, - - // As the input field grows, it may move to the next line in the - // search box. `autoGrowInput` triggers an `updated` event on the input - // field, which is bound to this method to move the autocomplete menu. - moveAutocomplete : function() { - var autocomplete = this.box.data('autocomplete'); - if (autocomplete) { - autocomplete.menu.element.position({ - my : "left top", - at : "left bottom", - of : this.box.data('autocomplete').element, - collision : "none", - offset : '0 -1' - }); - } - }, - - // When a user enters a facet and it is being edited, immediately show - // the autocomplete menu and size it to match the contents. - searchAutocomplete : function(e) { - var autocomplete = this.box.data('autocomplete'); - if (autocomplete) { - var menu = autocomplete.menu.element; - autocomplete.search(); - - // Resize the menu based on the correctly measured width of what's bigger: - // the menu's original size or the menu items' new size. - menu.outerWidth(Math.max( - menu.width('').outerWidth(), - autocomplete.element.outerWidth() - )); - } - }, - - // If a user searches for "word word category", the category would be - // matched and autocompleted, and when selected, the "word word" would - // also be caught as the remainder and then added in its own facet. - addTextFacetRemainder : function(facetValue) { - var boxValue = this.box.val(); - var lastWord = boxValue.match(/\b(\w+)$/); - var matcher = new RegExp(lastWord[0], "i"); - if (lastWord && facetValue.search(matcher) == 0) { - boxValue = boxValue.replace(/\b(\w+)$/, ''); - } - boxValue = boxValue.replace('^\s+|\s+$', ''); - if (boxValue) { - this.app.searchBox.addFacet('text', boxValue, this.options.position); - } - return boxValue; - }, - - // Directly called to focus the input. This is different from `addFocus` - // because this is not called by a focus event. This instead calls a - // focus event causing the input to become focused. - enableEdit : function(selectText) { - this.addFocus(); - if (selectText) { - this.selectText(); - } - this.box.focus(); - }, - - // Event called on user focus on the input. Tells all other input and facets - // to give up focus, and starts revving the autocomplete. - addFocus : function() { - this.flags.canClose = false; - if (!this.app.searchBox.allSelected()) { - this.app.searchBox.disableFacets(this); - } - this.app.searchBox.addFocus(); - this.setMode('is', 'editing'); - this.setMode('not', 'selected'); - this.searchAutocomplete(); - }, - - // Directly called to blur the input. This is different from `removeFocus` - // because this is not called by a blur event. - disableEdit : function() { - this.box.blur(); - this.removeFocus(); - }, - - // Event called when user blur's the input, either through the keyboard tabbing - // away or the mouse clicking off. Cleans up - removeFocus : function() { - this.flags.canClose = false; - this.app.searchBox.removeFocus(); - this.setMode('not', 'editing'); - this.setMode('not', 'selected'); - this.closeAutocomplete(); - }, - - // When the user blurs the input, they may either be going to another input - // or off the search box entirely. If they go to another input, this facet - // will be instantly disabled, and the canClose flag will be turned back off. - // - // However, if the user clicks elsewhere on the page, this method starts a timer - // that checks if any of the other inputs are selected or are being edited. If - // not, then it can finally close itself and its autocomplete menu. - deferDisableEdit : function() { - this.flags.canClose = true; - _.delay(_.bind(function() { - if (this.flags.canClose && - !this.box.is(':focus') && - this.modes.editing == 'is') { - this.disableEdit(); - } - }, this), 250); - }, - - // Starts a timer that will cause a triple-click, which highlights all facets. - startTripleClickTimer : function() { - this.tripleClickTimer = setTimeout(_.bind(function() { - this.tripleClickTimer = null; - }, this), 500); - }, - - // Event on click that checks if a triple click is in play. The - // `tripleClickTimer` is counting down, ready to be engaged and intercept - // the click event to force a select all instead. - maybeTripleClick : function(e) { - if (!!this.tripleClickTimer) { - e.preventDefault(); - this.app.searchBox.selectAllFacets(); - return false; - } - }, - - // Is the user currently focused in the input field? - isFocused : function() { - return this.box.is(':focus'); - }, - - // When serializing the facets, the inputs need to also have their values represented, - // in case they contain text that is not yet faceted (but will be once the search is - // completed). - value : function() { - return this.box.val(); - }, - - // When switching between facets and inputs, depending on the direction the cursor - // is coming from, the cursor in this facet's input field should match the original - // direction. - setCursorAtEnd : function(direction) { - if (direction == -1) { - this.box.setCursorPosition(this.box.val().length); - } else { - this.box.setCursorPosition(0); - } - }, - - // Selects the entire range of text in the input. Useful when tabbing between inputs - // and facets. - selectText : function() { - this.box.selectRange(0, this.box.val().length); - if (!this.app.searchBox.allSelected()) { - this.box.focus(); - } else { - this.setMode('is', 'selected'); - } - }, - - // Before the searchBox performs a search, we need to close the - // autocomplete menu. - search : function(e, direction) { - if (!direction) direction = 0; - this.closeAutocomplete(); - this.app.searchBox.searchEvent(e); - _.defer(_.bind(function() { - this.app.searchBox.focusNextFacet(this, direction); - }, this)); - }, - - // Callback fired on key press in the search box. We search when they hit return. - keypress : function(e) { - var key = VS.app.hotkeys.key(e); - - if (key == 'enter') { - return this.search(e, 100); - } else if (VS.app.hotkeys.colon(e)) { - this.box.trigger('resize.autogrow', e); - var query = this.box.val(); - var prefixes = []; - if (this.app.options.callbacks.facetMatches) { - this.app.options.callbacks.facetMatches(function(p) { - prefixes = p; - }); - } - var labels = _.map(prefixes, function(prefix) { - if (prefix.label) return prefix.label; - else return prefix; - }); - if (_.contains(labels, query)) { - e.preventDefault(); - var remainder = this.addTextFacetRemainder(query); - var position = this.options.position + (remainder?1:0); - this.app.searchBox.addFacet(query, '', position); - return false; - } - } else if (key == 'backspace') { - if (this.box.getCursorPosition() == 0 && !this.box.getSelection().length) { - e.preventDefault(); - e.stopPropagation(); - e.stopImmediatePropagation(); - this.app.searchBox.resizeFacets(); - return false; - } - } - }, - - // Handles all keyboard inputs when in the input field. This checks - // for movement between facets and inputs, entering a new value that needs - // to be autocompleted, as well as stepping between facets with backspace. - keydown : function(e) { - var key = VS.app.hotkeys.key(e); - - if (key == 'left') { - if (this.box.getCursorPosition() == 0) { - e.preventDefault(); - this.app.searchBox.focusNextFacet(this, -1, {startAtEnd: -1}); - } - } else if (key == 'right') { - if (this.box.getCursorPosition() == this.box.val().length) { - e.preventDefault(); - this.app.searchBox.focusNextFacet(this, 1, {selectFacet: true}); - } - } else if (VS.app.hotkeys.shift && key == 'tab') { - e.preventDefault(); - this.app.searchBox.focusNextFacet(this, -1, {selectText: true}); - } else if (key == 'tab') { - e.preventDefault(); - var value = this.box.val(); - if (value.length) { - var remainder = this.addTextFacetRemainder(value); - var position = this.options.position + (remainder?1:0); - this.app.searchBox.addFacet(value, '', position); - } else { - this.app.searchBox.focusNextFacet(this, 0, { - skipToFacet: true, - selectText: true - }); - } - } else if (VS.app.hotkeys.command && - String.fromCharCode(e.which).toLowerCase() == 'a') { - e.preventDefault(); - this.app.searchBox.selectAllFacets(); - return false; - } else if (key == 'backspace' && !this.app.searchBox.allSelected()) { - if (this.box.getCursorPosition() == 0 && !this.box.getSelection().length) { - e.preventDefault(); - this.app.searchBox.focusNextFacet(this, -1, {backspace: true}); - return false; - } - } - - this.box.trigger('resize.autogrow', e); - } - -}); - -})(); - -(function(){ - - var $ = jQuery; // Handle namespaced jQuery - - // Makes the view enter a mode. Modes have both a 'mode' and a 'group', - // and are mutually exclusive with any other modes in the same group. - // Setting will update the view's modes hash, as well as set an HTML class - // of *[mode]_[group]* on the view's element. Convenient way to swap styles - // and behavior. - Backbone.View.prototype.setMode = function(mode, group) { - this.modes || (this.modes = {}); - if (this.modes[group] === mode) return; - $(this.el).setMode(mode, group); - this.modes[group] = mode; - }; - -})(); -(function() { - -var $ = jQuery; // Handle namespaced jQuery - -// DocumentCloud workspace hotkeys. To tell if a key is currently being pressed, -// just ask `VS.app.hotkeys.[key]` on `keypress`, or ask `VS.app.hotkeys.key(e)` -// on `keydown`. -// -// For the most headache-free way to use this utility, check modifier keys, -// like shift and command, with `VS.app.hotkeys.shift`, and check every other -// key with `VS.app.hotkeys.key(e) == 'key_name'`. -VS.app.hotkeys = { - - // Keys that will be mapped to the `hotkeys` namespace. - KEYS: { - '16': 'shift', - '17': 'command', - '91': 'command', - '93': 'command', - '224': 'command', - '13': 'enter', - '37': 'left', - '38': 'upArrow', - '39': 'right', - '40': 'downArrow', - '46': 'delete', - '8': 'backspace', - '9': 'tab', - '188': 'comma' - }, - - // Binds global keydown and keyup events to listen for keys that match `this.KEYS`. - initialize : function() { - _.bindAll(this, 'down', 'up', 'blur'); - $(document).bind('keydown', this.down); - $(document).bind('keyup', this.up); - $(window).bind('blur', this.blur); - }, - - // On `keydown`, turn on all keys that match. - down : function(e) { - var key = this.KEYS[e.which]; - if (key) this[key] = true; - }, - - // On `keyup`, turn off all keys that match. - up : function(e) { - var key = this.KEYS[e.which]; - if (key) this[key] = false; - }, - - // If an input is blurred, all keys need to be turned off, since they are no longer - // able to modify the document. - blur : function(e) { - for (var key in this.KEYS) this[this.KEYS[key]] = false; - }, - - // Check a key from an event and return the common english name. - key : function(e) { - return this.KEYS[e.which]; - }, - - // Colon is special, since the value is different between browsers. - colon : function(e) { - var charCode = e.which; - return charCode && String.fromCharCode(charCode) == ":"; - }, - - // Check a key from an event and match it against any known characters. - // The `keyCode` is different depending on the event type: `keydown` vs. `keypress`. - // - // These were determined by looping through every `keyCode` and `charCode` that - // resulted from `keydown` and `keypress` events and counting what was printable. - printable : function(e) { - var code = e.which; - if (e.type == 'keydown') { - if (code == 32 || // space - (code >= 48 && code <= 90) || // 0-1a-z - (code >= 96 && code <= 111) || // 0-9+-/*. - (code >= 186 && code <= 192) || // ;=,-./^ - (code >= 219 && code <= 222)) { // (\)' - return true; - } - } else { - // [space]!"#$%&'()*+,-.0-9:;<=>?@A-Z[\]^_`a-z{|} and unicode characters - if ((code >= 32 && code <= 126) || - (code >= 160 && code <= 500) || - (String.fromCharCode(code) == ":")) { - return true; - } - } - return false; - } - -}; - -})(); -(function() { - -var $ = jQuery; // Handle namespaced jQuery - -// Naive English transformations on words. Only used for a few transformations -// in VisualSearch.js. -VS.utils.inflector = { - - // Delegate to the ECMA5 String.prototype.trim function, if available. - trim : function(s) { - return s.trim ? s.trim() : s.replace(/^\s+|\s+$/g, ''); - }, - - // Escape strings that are going to be used in a regex. Escapes punctuation - // that would be incorrect in a regex. - escapeRegExp : function(s) { - return s.replace(/([.*+?^${}()|[\]\/\\])/g, '\\$1'); - } -}; - -})(); -(function() { - -var $ = jQuery; // Handle namespaced jQuery - -$.fn.extend({ - - // Makes the selector enter a mode. Modes have both a 'mode' and a 'group', - // and are mutually exclusive with any other modes in the same group. - // Setting will update the view's modes hash, as well as set an HTML class - // of *[mode]_[group]* on the view's element. Convenient way to swap styles - // and behavior. - setMode : function(state, group) { - group = group || 'mode'; - var re = new RegExp("\\w+_" + group + "(\\s|$)", 'g'); - var mode = (state === null) ? "" : state + "_" + group; - this.each(function() { - this.className = (this.className.replace(re, '')+' '+mode) - .replace(/\s\s/g, ' '); - }); - return mode; - }, - - // When attached to an input element, this will cause the width of the input - // to match its contents. This calculates the width of the contents of the input - // by measuring a hidden shadow div that should match the styling of the input. - autoGrowInput: function() { - return this.each(function() { - var $input = $(this); - var $tester = $('
    ').css({ - opacity : 0, - top : -9999, - left : -9999, - position : 'absolute', - whiteSpace : 'nowrap' - }).addClass('VS-input-width-tester').addClass('VS-interface'); - - // Watch for input value changes on all of these events. `resize` - // event is called explicitly when the input has been changed without - // a single keypress. - var events = 'keydown.autogrow keypress.autogrow ' + - 'resize.autogrow change.autogrow'; - $input.next('.VS-input-width-tester').remove(); - $input.after($tester); - $input.unbind(events).bind(events, function(e, realEvent) { - if (realEvent) e = realEvent; - var value = $input.val(); - - // Watching for the backspace key is tricky because it may not - // actually be deleting the character, but instead the key gets - // redirected to move the cursor from facet to facet. - if (VS.app.hotkeys.key(e) == 'backspace') { - var position = $input.getCursorPosition(); - if (position > 0) value = value.slice(0, position-1) + - value.slice(position, value.length); - } else if (VS.app.hotkeys.printable(e) && - !VS.app.hotkeys.command) { - value += String.fromCharCode(e.which); - } - value = value.replace(/&/g, '&') - .replace(/\s/g,' ') - .replace(//g, '>'); - - $tester.html(value); - $input.width($tester.width() + 3); - $input.trigger('updated.autogrow'); - }); - - // Sets the width of the input on initialization. - $input.trigger('resize.autogrow'); - }); - }, - - - // Cross-browser method used for calculating where the cursor is in an - // input field. - getCursorPosition: function() { - var position = 0; - var input = this.get(0); - - if (document.selection) { // IE - input.focus(); - var sel = document.selection.createRange(); - var selLen = document.selection.createRange().text.length; - sel.moveStart('character', -input.value.length); - position = sel.text.length - selLen; - } else if (input && $(input).is(':visible') && - input.selectionStart != null) { // Firefox/Safari - position = input.selectionStart; - } - - return position; - }, - - // A simple proxy for `selectRange` that sets the cursor position in an - // input field. - setCursorPosition: function(position) { - return this.each(function() { - return $(this).selectRange(position, position); - }); - }, - - // Cross-browser way to select text in an input field. - selectRange: function(start, end) { - return this.each(function() { - if (this.setSelectionRange) { // FF/Webkit - this.focus(); - this.setSelectionRange(start, end); - } else if (this.createTextRange) { // IE - var range = this.createTextRange(); - range.collapse(true); - range.moveEnd('character', end); - range.moveStart('character', start); - if (end - start >= 0) range.select(); - } - }); - }, - - // Returns an object that contains the text selection range values for - // an input field. - getSelection: function() { - var input = this[0]; - - if (input.selectionStart != null) { // FF/Webkit - var start = input.selectionStart; - var end = input.selectionEnd; - return { - start : start, - end : end, - length : end-start, - text : input.value.substr(start, end-start) - }; - } else if (document.selection) { // IE - var range = document.selection.createRange(); - if (range) { - var textRange = input.createTextRange(); - var copyRange = textRange.duplicate(); - textRange.moveToBookmark(range.getBookmark()); - copyRange.setEndPoint('EndToStart', textRange); - var start = copyRange.text.length; - var end = start + range.text.length; - return { - start : start, - end : end, - length : end-start, - text : range.text - }; - } - } - return {start: 0, end: 0, length: 0}; - } - -}); - -// Debugging in Internet Explorer. This allows you to use -// `console.log(['message', var1, var2, ...])`. Just remove the `false` and -// add your console.logs. This will automatically stringify objects using -// `JSON.stringify', so you can read what's going out. Think of this as a -// *Diet Firebug Lite Zero with Lemon*. -if ($.browser.msie && false) { - window.console = {}; - var _$ied; - window.console.log = function(msg) { - if (_.isArray(msg)) { - var message = msg[0]; - var vars = _.map(msg.slice(1), function(arg) { - return JSON.stringify(arg); - }).join(' - '); - } - if(!_$ied){ - _$ied = $('
      ').css({ - 'position': 'fixed', - 'bottom': 10, - 'left': 10, - 'zIndex': 20000, - 'width': $('body').width() - 80, - 'border': '1px solid #000', - 'padding': '10px', - 'backgroundColor': '#fff', - 'fontFamily': 'arial,helvetica,sans-serif', - 'fontSize': '11px' - }); - $('body').append(_$ied); - } - var $message = $('
    1. '+message+' - '+vars+'
    2. ').css({ - 'borderBottom': '1px solid #999999' - }); - _$ied.find('ol').append($message); - _.delay(function() { - $message.fadeOut(500); - }, 5000); - }; - -} - -})(); - -(function() { - -var $ = jQuery; // Handle namespaced jQuery - -// Used to extract keywords and facets from the free text search. -var FREETEXT_RE = '(\'[^\']+\'|"[^"]+"|[^\'"\\s]\\S*)'; -var CATEGORY_RE = FREETEXT_RE + ':\\s*'; -VS.app.SearchParser = { - - // Matches `category: "free text"`, with and without quotes. - ALL_FIELDS : new RegExp(CATEGORY_RE + FREETEXT_RE, 'g'), - - // Matches a single category without the text. Used to correctly extract facets. - CATEGORY : new RegExp(CATEGORY_RE), - - // Called to parse a query into a collection of `SearchFacet` models. - parse : function(instance, query) { - var searchFacets = this._extractAllFacets(instance, query); - instance.searchQuery.reset(searchFacets); - return searchFacets; - }, - - // Walks the query and extracts facets, categories, and free text. - _extractAllFacets : function(instance, query) { - var facets = []; - var originalQuery = query; - - while (query) { - var category, value; - originalQuery = query; - var field = this._extractNextField(query); - if (!field) { - category = 'text'; - value = this._extractSearchText(query); - query = VS.utils.inflector.trim(query.replace(value, '')); - } else if (field.indexOf(':') != -1) { - category = field.match(this.CATEGORY)[1].replace(/(^['"]|['"]$)/g, ''); - value = field.replace(this.CATEGORY, '').replace(/(^['"]|['"]$)/g, ''); - query = VS.utils.inflector.trim(query.replace(field, '')); - } else if (field.indexOf(':') == -1) { - category = 'text'; - value = field; - query = VS.utils.inflector.trim(query.replace(value, '')); - } - - if (category && value) { - var searchFacet = new VS.model.SearchFacet({ - category : category, - value : VS.utils.inflector.trim(value), - app : instance - }); - facets.push(searchFacet); - } - if (originalQuery == query) break; - } - - return facets; - }, - - // Extracts the first field found, capturing any free text that comes - // before the category. - _extractNextField : function(query) { - var textRe = new RegExp('^\\s*(\\S+)\\s+(?=' + CATEGORY_RE + FREETEXT_RE + ')'); - var textMatch = query.match(textRe); - if (textMatch && textMatch.length >= 1) { - return textMatch[1]; - } else { - return this._extractFirstField(query); - } - }, - - // If there is no free text before the facet, extract the category and value. - _extractFirstField : function(query) { - var fields = query.match(this.ALL_FIELDS); - return fields && fields.length && fields[0]; - }, - - // If the found match is not a category and facet, extract the trimmed free text. - _extractSearchText : function(query) { - query = query || ''; - var text = VS.utils.inflector.trim(query.replace(this.ALL_FIELDS, '')); - return text; - } - -}; - -})(); - -(function() { - -var $ = jQuery; // Handle namespaced jQuery - -// The model that holds individual search facets and their categories. -// Held in a collection by `VS.app.searchQuery`. -VS.model.SearchFacet = Backbone.Model.extend({ - - // Extract the category and value and serialize it in preparation for - // turning the entire searchBox into a search query that can be sent - // to the server for parsing and searching. - serialize : function() { - var category = this.quoteCategory(this.get('category')); - var value = VS.utils.inflector.trim(this.get('value')); - - if (!value) return ''; - - if (!_.contains(this.get("app").options.unquotable || [], category) && category != 'text') { - value = this.quoteValue(value); - } - - if (category != 'text') { - category = category + ': '; - } else { - category = ""; - } - return category + value; - }, - - // Wrap categories that have spaces or any kind of quote with opposite matching - // quotes to preserve the complex category during serialization. - quoteCategory : function(category) { - var hasDoubleQuote = (/"/).test(category); - var hasSingleQuote = (/'/).test(category); - var hasSpace = (/\s/).test(category); - - if (hasDoubleQuote && !hasSingleQuote) { - return "'" + category + "'"; - } else if (hasSpace || (hasSingleQuote && !hasDoubleQuote)) { - return '"' + category + '"'; - } else { - return category; - } - }, - - // Wrap values that have quotes in opposite matching quotes. If a value has - // both single and double quotes, just use the double quotes. - quoteValue : function(value) { - var hasDoubleQuote = (/"/).test(value); - var hasSingleQuote = (/'/).test(value); - - if (hasDoubleQuote && !hasSingleQuote) { - return "'" + value + "'"; - } else { - return '"' + value + '"'; - } - } - -}); - -})(); -(function() { - -var $ = jQuery; // Handle namespaced jQuery - -// Collection which holds all of the individual facets (category: value). -// Used for finding and removing specific facets. -VS.model.SearchQuery = Backbone.Collection.extend({ - - // Model holds the category and value of the facet. - model : VS.model.SearchFacet, - - // Turns all of the facets into a single serialized string. - serialize : function() { - return this.map(function(facet){ return facet.serialize(); }).join(' '); - }, - - facets : function() { - return this.map(function(facet) { - var value = {}; - value[facet.get('category')] = facet.get('value'); - return value; - }); - }, - - // Find a facet by its category. Multiple facets with the same category - // is fine, but only the first is returned. - find : function(category) { - var facet = this.detect(function(facet) { - return facet.get('category') == category; - }); - return facet && facet.get('value'); - }, - - // Counts the number of times a specific category is in the search query. - count : function(category) { - return this.select(function(facet) { - return facet.get('category') == category; - }).length; - }, - - // Returns an array of extracted values from each facet in a category. - values : function(category) { - var facets = this.select(function(facet) { - return facet.get('category') == category; - }); - return _.map(facets, function(facet) { return facet.get('value'); }); - }, - - // Checks all facets for matches of either a category or both category and value. - has : function(category, value) { - return this.any(function(facet) { - var categoryMatched = facet.get('category') == category; - if (!value) return categoryMatched; - return categoryMatched && facet.get('value') == value; - }); - }, - - // Used to temporarily hide a specific category and serialize the search query. - withoutCategory : function(category) { - return this.map(function(facet) { - if (facet.get('category') != category) return facet.serialize(); - }).join(' '); - } - -}); - -})();(function(){ -window.JST = window.JST || {}; - -window.JST['search_box'] = _.template(''); -window.JST['search_facet'] = _.template('<% if (model.has(\'category\')) { %>\n
      <%= model.get(\'category\') %>:
      \n<% } %>\n\n
      \n \n
      \n\n
      '); -window.JST['search_input'] = _.template(''); -})(); \ No newline at end of file diff --git a/addons/web/static/lib/visualsearch/demo.html b/addons/web/static/lib/visualsearch/demo.html deleted file mode 100755 index 212fb7cee28..00000000000 --- a/addons/web/static/lib/visualsearch/demo.html +++ /dev/null @@ -1,453 +0,0 @@ - - - - - - DocumentCloud's VisualSearch.js - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      - -

      VisualSearch.js

      - -

      - VisualSearch.js - enhances ordinary search boxes with the ability to autocomplete - faceted search queries. Specify the facets for completion, along with the - completable values for any facet. You can retrieve the search query as a - structured object, so you don't have to parse the query string yourself. -

      - -

      - The complete annotated source code - is also available. -

      - -

      - The project is - hosted on GitHub. - You can report bugs and discuss features on the - issues page, - on Freenode in the #documentcloud channel, - or send tweets to @documentcloud. -

      - -

      - VisualSearch.js is an open-source component of DocumentCloud. -

      -

      Demo Try searching for: account, filter, access, title, city, state, or country.

      - -
      -
       
      - - - - - -
      -
       
      - - - -
      - - - diff --git a/addons/web/static/lib/visualsearch/index.html b/addons/web/static/lib/visualsearch/index.html deleted file mode 100755 index 07cc8de20e8..00000000000 --- a/addons/web/static/lib/visualsearch/index.html +++ /dev/null @@ -1,537 +0,0 @@ - - - - - - DocumentCloud's VisualSearch.js - - - - - - - - - - - - - - - -
      - -

      VisualSearch.js

      - -

      - - Created by Samuel Clay, - @samuelclay. - -

      - -

      - VisualSearch.js - enhances ordinary search boxes with the ability to autocomplete - faceted search queries. Specify the facets for completion, along with the - completable values for any facet. You can retrieve the search query as a - structured object, so you don't have to parse the query string yourself. -

      - -

      - Here's an example of a search on DocumentCloud.org that uses facets. -

      - -

      - The project is - hosted on GitHub. - You can report bugs and discuss features on the - issues page, - on Freenode in the #documentcloud channel, - or send tweets to @documentcloud. -

      - -

      - VisualSearch.js is an open-source component of DocumentCloud. -
      - The complete annotated source code - is also available.
      -

      - -

      Table of Contents

      - - Demo | Downloads | Usage | Change Log - - -

      Demo Try searching for: account, filter, access, title, city, state, or country.

      - - - -
      -
       
      - - - -

      Downloads (Right-click, and use "Save As")

      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      0. Everything (visualsearch.zip)
      Download everything
      1. VisualSearch JavaScript (visualsearch.js)
      Production Version (0.2.2)8kb, Minified and Gzipped
      Development Version (0.2.2)45kb, Uncompressed with Comments
      2. VisualSearch Stylesheets (visualsearch.css)
      You should include both the datauri and image urls versions. See how to include both
      Production Version - datauri4kb, Minified and Gzipped
      Production Version - image urls4kb, Minified and Gzipped
      Development Version8kb, Uncompressed with Comments
      3. VisualSearch Images
      Search Glyph4kb, embedded in visualsearch-datauri.css
      Cancel Button4kb, embedded in visualsearch-datauri.css
      4. VisualSearch Dependencies (jQuery 1.4+, jQuery UI, Underscore.js, Backbone.js)
      You should only include the dependencies you don't already have.
      Production Version - All49kb, Minified and Gzipped
      Development Version - All340kb, Uncompressed with Comments
      jQuery 1.6.1238kb, Uncompressed with Comments
      jQuery UI 1.8.13:
      Core Position Widget Autocomplete
      48kb, Uncompressed with Comments
      Underscore 1.1.529kb, Uncompressed with Comments
      Backbone 0.5.041kb, Uncompressed with Comments
      - -

      Usage

      - -

      To use VisualSearch.js on your site, follow these instructions on installation, configuration, and customization.

      - -
        -
      1. Insert the JavaScript and CSS into your page:
        -
        <script src="visualsearch.js" type="text/javascript"></script>
        -<!--[if (!IE)|(gte IE 8)]><!-->
        -  <link href="visualsearch-datauri.css" media="screen" rel="stylesheet" type="text/css" />
        -<!--<![endif]-->
        -<!--[if lte IE 7]><!-->
        -  <link href="visualsearch.css" media="screen" rel="stylesheet" type="text/css" />
        -<!--<![endif]-->
        -
      2. -
      3. Initialize the Visual Search box:
        -
        <div class="visual_search"></div>
        -
        -<script type="text/javascript" charset="utf-8">
        -  $(document).ready(function() {
        -    var visualSearch = VS.init({
        -      container : $('.visual_search'),
        -      query     : '',
        -      callbacks : {
        -        search       : function(query, searchCollection) {},
        -        facetMatches : function(callback) {},
        -        valueMatches : function(facet, searchTerm, callback) {}
        -      }
        -    });
        -  });
        -</script>
        -
      4. -
      5. Customize the autocompleted facets and values: -
        callbacks : {
        -  ...
        -  // These are the facets that will be autocompleted in an empty input.
        -  facetMatches : function(callback) {
        -    callback([
        -      'account', 'filter', 'access', 'title',
        -      { label: 'city',    category: 'location' },
        -      { label: 'address', category: 'location' },
        -      { label: 'country', category: 'location' },
        -      { label: 'state',   category: 'location' },
        -    ]);
        -  }
        -  ...
        -  // These are the values that match specific categories, autocompleted
        -  // in a category's input field.  searchTerm can be used to filter the
        -  // list on the server-side, prior to providing a list to the widget.
        -  valueMatches : function(facet, searchTerm, callback) {
        -    switch (facet) {
        -    case 'account':
        -        callback([
        -          { value: '1-amanda', label: 'Amanda' },
        -          { value: '2-aron',   label: 'Aron' },
        -          { value: '3-eric',   label: 'Eric' },
        -          { value: '4-jeremy', label: 'Jeremy' },
        -          { value: '5-samuel', label: 'Samuel' },
        -          { value: '6-scott',  label: 'Scott' }
        -        ]);
        -        break;
        -      case 'filter':
        -        callback(['published', 'unpublished', 'draft']);
        -        break;
        -      case 'access':
        -        callback(['public', 'private', 'protected']);
        -        break;
        -      case 'title':
        -        callback([
        -          'Pentagon Papers',
        -          'CoffeeScript Manual',
        -          'Laboratory for Object Oriented Thinking',
        -          'A Repository Grows in Brooklyn'
        -        ]);
        -        break;
        -    }
        -  }
        -...
        -}
        -
      6. -
      7. Inspect the Visual Search box -
        // Returns the unstructured search query
        -visualSearch.searchBox.value() 
        -// "country: "South Africa" account: 5-samuel title: "Pentagon Papers""
        -
        -// Returns an array of Facet model instances
        -visualSearch.searchQuery.facets()
        -// [FacetModel<country:"South Africa">, 
        -//  FacetModel<account:5-samuel>, 
        -//  FacetModel<title:"Pentagon Papers">]
        -
        -// Set the search query with raw text
        -visualSearch.searchBox.value("Country: US State: \"New York\" Key: Value")
        -
        -
        -
      8. -
      - - -

      Change Log

      - -

      - 0.2.2 March 10th, 2012
      - If you do not want to automatically filter the value matches, you can pass an - options hash with preserveMatches: true as the second argument to the callback. - See pull request #44 for details. -

      -

      - 0.2.1 November 14th, 2011
      - The autocompleted facets and values that are provided by your callbacks facetMatches - and valueMatches can now preserve the order of items you give them. Simply pass an - options hash with preserveOrder: true as the second argument to the callback. See - the demo page for an example. -

      -

      - 0.2.0 August 10th, 2011
      - Multiple instances of VisualSearch on a single page. VS.init now returns - a reference to the instance. The search callback now contains both the - serialized search query and a reference to the search query collection (as a - Backbone.Collection), - which can be used to manipulate each facet directly. See - the source code for search_query.js for available - methods on the collection. -

      -

      - 0.1.0 June 23rd, 2011
      - Initial release of VisualSearch.js. -

      - -

      - - A DocumentCloud Project - -

      - -
      - - - diff --git a/addons/web/static/src/css/base.css b/addons/web/static/src/css/base.css index b3082126142..89b8cc1a38f 100644 --- a/addons/web/static/src/css/base.css +++ b/addons/web/static/src/css/base.css @@ -9,6 +9,17 @@ font-style: normal; } +@font-face { + font-family: "EntypoRegular"; + src: url("/web/static/src/font/entypo-webfont.eot") format("eot"); + src: url("/web/static/src/font/entypo-webfont.eot?#iefix") format("embedded-opentype"); + src: url("/web/static/src/font/entypo-webfont.woff") format("woff"); + src: url("/web/static/src/font/entypo-webfont.ttf") format("truetype"); + src: url("/web/static/src/font/entypo-webfont.svg") format("svg") active; + font-weight: normal; + font-style: normal; +} + .openerp.openerp-web-client-container { height: 100%; position: relative; @@ -45,7 +56,6 @@ } .openerp th, .openerp td { padding: 0; - line-height: 18px; text-align: left; } .openerp th { @@ -93,6 +103,11 @@ font-size: 21px; font-weight: 300 !important; } +.openerp .oe_e { + font-family: "entypoRegular" !important; + font-size: 34px; + font-weight: 300 !important; +} .openerp .oe_left { float: left; margin-right: 8px; @@ -101,12 +116,21 @@ float: right; margin-left: 8px; } +.openerp .oe_text_right { + text-align: right; +} .openerp .oe_clear { clear: both; } .openerp .oe_wait { cursor: wait; } +.openerp .oe_fade { + color: #888888; +} +.openerp .oe_bold { + font-weight: bold; +} .openerp a.button:link, .openerp a.button:visited, .openerp button, .openerp input[type='submit'] { display: inline-block; border: 1px solid #ababab; @@ -426,7 +450,6 @@ width: 100%; height: 31px; border-top: solid 1px #d3d3d3; - border-bottom: solid 1px black; background-color: #646060; background-image: -webkit-gradient(linear, left top, left bottom, from(#646060), to(#262626)); background-image: -webkit-linear-gradient(top, #646060, #262626); @@ -435,13 +458,6 @@ background-image: -o-linear-gradient(top, #646060, #262626); background-image: linear-gradient(to bottom, #646060, #262626); } -.openerp .oe_topbar .oe_systray { - float: right; -} -.openerp .oe_topbar .oe_systray > div { - float: left; - padding: 0 4px 0 4px; -} .openerp .oe_topbar .oe_topbar_item li { float: left; } @@ -500,6 +516,8 @@ background: #f0eeee; border-right: 1px solid #afafb6; text-shadow: 0 1px 1px white; + padding-bottom: 16px; + line-height: 18px; } .openerp a.oe_logo { width: 220px; @@ -577,6 +595,7 @@ background-color: none; } .openerp .oe_user_menu .oe_dropdown_options li a { + white-space: nowrap; display: block; padding: 4px 15px; clear: both; @@ -596,6 +615,72 @@ -webkit-box-shadow: none; -box-shadow: none; } +.openerp .oe_user_menu .oe_dropdown_options li hr { + border-top: 1px solid #999999; + border-bottom: 0; +} +.openerp .oe_systray > div { + float: left; + padding: 0 4px 0 4px; +} +.openerp .oe_systray { + float: right; +} +.openerp .oe_systray .oe_systray_dropdown { + position: relative; +} +.openerp .oe_systray .oe_systray_dropdown:hover .oe_systray_dropdown_options { + display: block; +} +.openerp .oe_systray .oe_systray_dropdown_options { + background: #333333; + background: rgba(37, 37, 37, 0.9); + display: none; + position: absolute; + z-index: 900; + border: 0; + margin-left: 0; + margin-right: 0; + padding: 6px 0; + border-color: #999999; + border-color: rgba(0, 0, 0, 0.2); + border-style: solid; + border-width: 0 1px 1px; + -moz-border-radius: 0 0 6px 6px; + -webkit-border-radius: 0 0 6px 6px; + border-radius: 0 0 6px 6px; + -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3); + -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3); + -box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3); + -webkit-background-clip: padding-box; + -moz-background-clip: padding-box; + background-clip: padding-box; +} +.openerp .oe_systray .oe_systray_dropdown_options li { + float: none; + display: block; + background-color: none; +} +.openerp .oe_systray .oe_systray_dropdown_options li a { + display: block; + padding: 4px 15px; + clear: both; + font-weight: normal; + line-height: 18px; + color: #eeeeee; +} +.openerp .oe_systray .oe_systray_dropdown_options li a:hover { + background-color: #292929; + background-image: -webkit-gradient(linear, left top, left bottom, from(#292929), to(#191919)); + background-image: -webkit-linear-gradient(top, #292929, #191919); + background-image: -moz-linear-gradient(top, #292929, #191919); + background-image: -ms-linear-gradient(top, #292929, #191919); + background-image: -o-linear-gradient(top, #292929, #191919); + background-image: linear-gradient(to bottom, #292929, #191919); + -moz-box-shadow: none; + -webkit-box-shadow: none; + -box-shadow: none; +} .openerp .oe_menu { float: left; padding: 0; @@ -657,16 +742,16 @@ width: 100%; display: inline-block; } -.openerp .oe_secondary_submenu li { +.openerp .oe_secondary_submenu > li { position: relative; - padding: 1px 0 1px 16px; + padding: 1px 0 1px 20px; } -.openerp .oe_secondary_submenu li a { +.openerp .oe_secondary_submenu > li a { display: block; color: #4c4c4c; padding: 2px 4px 2px 0; } -.openerp .oe_secondary_submenu li .oe_menu_label { +.openerp .oe_secondary_submenu > li .oe_menu_label { position: absolute; top: 1px; right: 1px; @@ -728,7 +813,7 @@ content: "&darr"; text-indent: -99999px; vertical-align: top; - margin-left: -8px; + margin-left: -12px; margin-top: 4px; margin-right: 4px; border-top: 4px solid transparent; @@ -739,7 +824,7 @@ } .openerp .oe_secondary_submenu .oe_menu_opened:before { margin-top: 6px; - margin-left: -12px; + margin-left: -16px; margin-right: 4px; border-left: 4px solid transparent; border-right: 4px solid transparent; @@ -844,7 +929,7 @@ color: white; text-shadow: 0 1px 2px rgba(0, 0, 0, 0.4); } -.openerp .oe_view_manager_header2 { +.openerp .oe_view_manager_header { width: 100%; border-top: 1px solid #cacaca; border-bottom: 1px solid #cacaca; @@ -859,53 +944,70 @@ -webkit-box-shadow: 0 1px 0 rgba(255, 255, 255, 0.4), 0 0 9px rgba(0, 0, 0, 0.1); -box-shadow: 0 1px 0 rgba(255, 255, 255, 0.4), 0 0 9px rgba(0, 0, 0, 0.1); } -.openerp .oe_view_manager_header2 h2 { - float: left; - font-size: 18px; - margin: 1px 0; +.openerp .oe_view_manager_header .oe_header_row { + clear: both; + text-shadow: 0 1px 1px white; } -.openerp .oe_view_manager_header2 h2 a { - color: #8a89ba; +.openerp .oe_view_manager_header .oe_header_row td { + padding: 8px; } -.openerp .oe_view_manager_header2 td { - padding: 4px 8px; +.openerp .oe_view_manager_header .oe_header_row:last-child td { + padding-top: 0; +} +.openerp .oe_view_manager_header .oe_header_row:first-child td { + padding-top: 8px; +} +.openerp .oe_view_manager_header .oe_view_manager_sidebar { + margin: 0px auto; + width: 400px; + text-align: center; +} +.openerp .oe_view_manager_header td { line-height: 26px; } -.openerp .oe_view_manager_header2 .oe_button_group { +.openerp .oe_view_manager_header h2 { + font-size: 18px; + margin: 0; + float: left; +} +.openerp .oe_view_manager_header h2 a { + color: #8a89ba; +} +.openerp .oe_view_manager_header .oe_button_group { display: inline-block; border: 1px solid #ababab; -moz-border-radius: 5px; -webkit-border-radius: 5px; border-radius: 5px; } -.openerp .oe_view_manager_header2 .oe_button_group li { +.openerp .oe_view_manager_header .oe_button_group li { float: left; border-right: 1px solid #ababab; } -.openerp .oe_view_manager_header2 .oe_button_group li:last-child { +.openerp .oe_view_manager_header .oe_button_group li:last-child { border: none; } -.openerp .oe_view_manager_header2 .oe_button_group a { +.openerp .oe_view_manager_header .oe_button_group a { color: #4c4c4c; } -.openerp .oe_view_manager_header2 .oe_button_group a:hover { +.openerp .oe_view_manager_header .oe_button_group a:hover { text-decoration: none; } -.openerp .oe_view_manager_header2 .oe_button_group .active { +.openerp .oe_view_manager_header .oe_button_group .active { background: #999999; -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3) inset; -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3) inset; -box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3) inset; } -.openerp .oe_view_manager_header2 .oe_button_group .active a { +.openerp .oe_view_manager_header .oe_button_group .active a { color: white; text-shadow: 0 1px 2px rgba(0, 0, 0, 0.4); } -.openerp .oe_view_manager_header2 .oe_view_manager_buttons { +.openerp .oe_view_manager_header .oe_view_manager_buttons { white-space: nowrap; } -.openerp .oe_view_manager_body h4 { - margin: 8px 0; +.openerp .oe_view_manager_pager { + line-height: 26px; } .openerp .oe_pager_value { float: left; @@ -950,34 +1052,46 @@ text-shadow: 0 1px 2px rgba(0, 0, 0, 0.4); } .openerp .oe_view_manager_switch li { - padding-left: 1px; text-align: center; width: 24px; height: 24px; - line-height: 24px; + line-height: 16px; +} +.openerp .oe_view_manager_switch li a { + position: relative; } .openerp .oe_view_manager_switch .oe_vm_switch_list:after, .openerp .oe_view_manager_switch .oe_vm_switch_tree:after { - content: "ö"; + padding: 2px; + content: "i"; } .openerp .oe_view_manager_switch .oe_vm_switch_graph:after { - content: "ó"; + font-family: "mnmliconsRegular" !important; + font-size: 21px; + font-weight: 300 !important; + content: "}"; + top: -2px; + position: relative; } .openerp .oe_view_manager_switch .oe_vm_switch_gantt:after { + font-family: "mnmliconsRegular" !important; + font-size: 21px; + font-weight: 300 !important; content: "y"; + top: -2px; + position: relative; } .openerp .oe_view_manager_switch .oe_vm_switch_calendar:after { - content: "b"; + content: "P"; } .openerp .oe_view_manager_switch .oe_vm_switch_kanban:after { - content: "ó"; + content: "k"; } .openerp .oe_view_manager_switch .oe_vm_switch_diagram:after { - content: "}"; + content: "f"; } .openerp .oe_form_dropdown_section { position: relative; display: inline-block; - margin-right: 4px; } .openerp .oe_dropdown_toggle:after { width: 0; @@ -1028,6 +1142,7 @@ line-height: 14px; color: #4c4c4c; text-decoration: none; + cursor: pointer; } .openerp .oe_dropdown_menu li a:hover { text-decoration: none; @@ -1046,119 +1161,164 @@ white-space: nowrap; } .openerp .oe_searchview { + cursor: text; position: relative; float: right; -} -.openerp .oe_searchview .VS-search .VS-search-box { - min-height: 0; - border-width: 1px; - padding: 0; + padding-right: 20px; width: 410px; + border: 1px solid #ababab; + background: white; + -moz-border-radius: 1em; + -webkit-border-radius: 1em; + border-radius: 1em; + -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2) inset; + -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2) inset; + -box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2) inset; } -.openerp .oe_searchview .VS-search .VS-icon { - top: 5px; +.openerp .oe_searchview.oe_focused { + border-color: #a6a6fe; + -moz-box-shadow: 0 1px 2px #a6a6fe inset; + -webkit-box-shadow: 0 1px 2px #a6a6fe inset; + -box-shadow: 0 1px 2px #a6a6fe inset; } -.openerp .oe_searchview .VS-search .VS-icon-search { - left: 5px; +.openerp .oe_searchview .oe_searchview_clear { + cursor: pointer; + position: absolute; + top: 0; + right: 22px; + width: 15px; + height: 100%; + background: url(../img/attachments-close.png) center center no-repeat; } -.openerp .oe_searchview .VS-search .VS-search-inner { - margin: 0 40px 0 17px; - font-size: 13px; +.openerp .oe_searchview .oe_searchview_unfold_drawer { + position: absolute; + top: 0; + right: 0; + height: 100%; + line-height: 2.5em; + padding: 0 7px 0 4px; + color: #cccccc; + cursor: pointer; } -.openerp .oe_searchview .VS-search .VS-search-inner input { - font-size: inherit; - line-height: inherit; - height: auto; - padding: 0; +.openerp .oe_searchview .oe_searchview_unfold_drawer:hover { + color: #999999; } -.openerp .oe_searchview .VS-search .VS-search-inner .VS-input-width-tester { - font-size: inherit; - padding: 0; +.openerp .oe_searchview .oe_searchview_unfold_drawer:before { + content: "◀"; } -.openerp .oe_searchview .VS-search .VS-search-inner .search_input { - margin-left: 0; - height: 22px; +.openerp .oe_searchview .oe_searchview_facets:before { + color: #cccccc; + font-family: "mnmliconsRegular"; + content: "r"; + font-size: 150%; + padding: 0 1px 0 3px; + display: inline; } -.openerp .oe_searchview .VS-search .VS-search-inner .search_input input, .openerp .oe_searchview .VS-search .VS-search-inner .search_input .VS-input-width-tester { - padding: 0 2px; - height: inherit; - margin: 0; +.openerp .oe_searchview .oe_searchview_facets * { + vertical-align: top; + display: inline-block; + line-height: 26px; } -.openerp .oe_searchview .VS-search .VS-search-inner .search_facet { - padding: 0; - margin: 1px 0; +.openerp .oe_searchview .oe_searchview_facets .oe_searchview_input, .openerp .oe_searchview .oe_searchview_facets .oe_searchview_facet { + height: 26px; +} +.openerp .oe_searchview .oe_searchview_facets .oe_searchview_input:focus, .openerp .oe_searchview .oe_searchview_facets .oe_searchview_facet:focus { + outline: none; +} +.openerp .oe_searchview .oe_searchview_facets .oe_searchview_input { + padding: 0 3px; +} +.openerp .oe_searchview .oe_searchview_facets .oe_searchview_facet { + position: relative; + cursor: pointer; border: 1px solid #afafb6; -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; - background: #f0f0fa; - height: 18px; + background: #8786b7; + -webkit-font-smoothing: auto; + padding-left: 1.1em; + margin: 1px 0; } -.openerp .oe_searchview .VS-search .VS-search-inner .search_facet.is_selected { +.openerp .oe_searchview .oe_searchview_facets .oe_searchview_facet:focus { border-color: #a6a6fe; -moz-box-shadow: 0 0 3px 1px #a6a6fe; -webkit-box-shadow: 0 0 3px 1px #a6a6fe; -box-shadow: 0 0 3px 1px #a6a6fe; } -.openerp .oe_searchview .VS-search .VS-search-inner .search_facet.is_selected .category { - margin-left: 0; +.openerp .oe_searchview .oe_searchview_facets .oe_searchview_facet .oe_facet_values { + background: #f0f0fa; + -moz-border-radius: 0 3px 3px 0; + -webkit-border-radius: 0 3px 3px 0; + border-radius: 0 3px 3px 0; } -.openerp .oe_searchview .VS-search .VS-search-inner .search_facet.is_selected .VS-icon-cancel { - filter: alpha(opacity=100); - opacity: 1; - background-position: center 0; +.openerp .oe_searchview .oe_searchview_facets .oe_searchview_facet .oe_facet_category, .openerp .oe_searchview .oe_searchview_facets .oe_searchview_facet .oe_facet_value { + height: 24px; + padding: 1px 0.1em; } -.openerp .oe_searchview .VS-search .VS-search-inner .search_facet .category { - padding: 0 4px 0 14px; +.openerp .oe_searchview .oe_searchview_facets .oe_searchview_facet .oe_facet_category { color: white; - background: #8786b7; text-shadow: 0 1px 1px rgba(0, 0, 0, 0.4); - font-weight: normal; - text-transform: none; - height: 18px; - line-height: 18px; - font-size: inherit; } -.openerp .oe_searchview .VS-search .VS-search-inner .search_facet .search_facet_input_container { +.openerp .oe_searchview .oe_searchview_facets .oe_searchview_facet .oe_facet_value { border-left: 1px solid #afafb6; - height: 18px; - line-height: 18px; - padding: 0 4px; - cursor: pointer; } -.openerp .oe_searchview .VS-search .VS-search-inner .search_facet .search_facet_remove { - left: 1px; - top: 3px; -} -.openerp .oe_searchview .VS-search .VS-icon-cancel { - right: 24px; -} -.openerp .oe_searchview .VS-search .oe_vs_unfold_drawer { +.openerp .oe_searchview .oe_searchview_facets .oe_searchview_facet .oe_facet_remove { position: absolute; top: 0; - right: 0; - height: 100%; - line-height: 23px; - padding: 0 7px 0 4px; - color: #cccccc; - cursor: pointer; + left: 2px; + color: white; } -.openerp .oe_searchview .VS-search .oe_vs_unfold_drawer:before { - content: "▾"; +.openerp .oe_searchview .oe_searchview_facets .oe_searchview_facet .oe_facet_remove:hover { + color: #cccccc; } .openerp .oe_searchview.oe_searchview_open_drawer .oe_searchview_drawer { display: block; } +.openerp .oe_searchview.oe_searchview_open_drawer .oe_searchview_unfold_drawer:before { + content: "▼"; +} .openerp .oe_searchview .oe_searchview_drawer { position: absolute; z-index: 1; + margin-top: 3px; top: 100%; right: 0; background-color: white; - width: 410px; + min-width: 100%; display: none; border: 1px solid #cccccc; text-align: left; + padding-bottom: 0.5em; + -moz-border-radius: 1em; + -webkit-border-radius: 1em; + border-radius: 1em; +} +.openerp .oe_searchview .oe_searchview_drawer > div { + border-top: 1px solid #cccccc; + margin: 3px 0; +} +.openerp .oe_searchview .oe_searchview_drawer > div:first-child { + border-top: none; + margin: 0; +} +.openerp .oe_searchview .oe_searchview_drawer h4, .openerp .oe_searchview .oe_searchview_drawer h4 * { + margin: 0; + cursor: pointer; +} +.openerp .oe_searchview .oe_searchview_drawer h4:before { + content: "▸ "; +} +.openerp .oe_searchview .oe_searchview_drawer button, .openerp .oe_searchview .oe_searchview_drawer .button { + border: none; + background: transparent; + padding: 0 2px; + -moz-box-shadow: none; + -webkit-box-shadow: none; + -box-shadow: none; + -moz-border-radius: 0; + -webkit-border-radius: 0; + border-radius: 0; } .openerp .oe_searchview .oe_searchview_drawer .oe_searchview_filters { display: table; @@ -1182,23 +1342,49 @@ } .openerp .oe_searchview .oe_searchview_drawer .oe_searchview_filters li { list-style: none; - padding: 3px 6px; - height: 14px; + padding: 3px 6px 3px 18px; + line-height: 14px; color: inherit; cursor: pointer; } +.openerp .oe_searchview .oe_searchview_drawer .oe_searchview_filters li.oe_selected { + background: url(/web/static/src/img/icons/gtk-apply.png) left 2px no-repeat; +} .openerp .oe_searchview .oe_searchview_drawer .oe_searchview_filters li:hover { background-color: #f0f0fa; } -.openerp .oe_searchview .oe_searchview_drawer .oe_searchview_advanced h4 { - border-top: 1px solid #cccccc; - margin: 5px 0 3px; +.openerp .oe_searchview .oe_searchview_drawer .oe_searchview_custom form { + display: none; +} +.openerp .oe_searchview .oe_searchview_drawer .oe_searchview_custom form button { + font-size: 1px; + letter-spacing: -1px; + color: transparent; +} +.openerp .oe_searchview .oe_searchview_drawer .oe_searchview_custom form button:before { + font-family: "mnmliconsRegular"; + content: "S"; + font-size: 20px; + color: #404040; +} +.openerp .oe_searchview .oe_searchview_drawer .oe_searchview_custom li { cursor: pointer; + position: relative; + line-height: 1.2em; + padding: 2px 20px 2px 25px; } -.openerp .oe_searchview .oe_searchview_drawer .oe_searchview_advanced h4:before { - content: "▸ "; +.openerp .oe_searchview .oe_searchview_drawer .oe_searchview_custom li.oe_searchview_custom_private { + background: url(/web/static/src/img/icons/terp-locked.png) 5px center no-repeat; } -.openerp .oe_searchview .oe_searchview_drawer .oe_searchview_advanced div { +.openerp .oe_searchview .oe_searchview_drawer .oe_searchview_custom li:hover { + background-color: #f0f0fa; +} +.openerp .oe_searchview .oe_searchview_drawer .oe_searchview_custom li button { + position: absolute; + top: 0; + right: 5px; +} +.openerp .oe_searchview .oe_searchview_drawer .oe_searchview_advanced form { display: none; } .openerp .oe_searchview .oe_searchview_drawer .oe_searchview_advanced button.oe_add_condition:before { @@ -1214,13 +1400,35 @@ .openerp .oe_searchview .oe_searchview_drawer .oe_searchview_advanced li { list-style: none; margin: 0; + white-space: nowrap; } -.openerp .oe_searchview .oe_searchview_drawer .oe_searchview_advanced.oe_opened h4:before { +.openerp .oe_searchview .oe_searchview_drawer .oe_opened h4:before { content: "▾ "; } -.openerp .oe_searchview .oe_searchview_drawer .oe_searchview_advanced.oe_opened div { +.openerp .oe_searchview .oe_searchview_drawer .oe_opened form { display: block; } +.openerp .oe_searchview .oe_searchview_drawer .oe_searchview_custom_delete, .openerp .oe_searchview .oe_searchview_drawer .searchview_extended_delete_prop { + font-size: 1px; + letter-spacing: -1px; + color: transparent; +} +.openerp .oe_searchview .oe_searchview_drawer .oe_searchview_custom_delete:before, .openerp .oe_searchview .oe_searchview_drawer .searchview_extended_delete_prop:before { + font-family: "mnmliconsRegular"; + content: "d"; + font-size: 20px; + color: #404040; +} +.openerp .oe_view_nocontent > img { + float: left; + margin: 1.5em; +} +.openerp .oe_view_nocontent > div { + overflow: hidden; + padding: 35px 0px 0px 0px; + max-width: 700px; + font-size: 125%; +} .openerp .oe_view_topbar { border-bottom: 1px solid #cacaca; background-color: #fcfcfc; @@ -1271,11 +1479,11 @@ } .openerp .oe_form_topbar button { font-size: 12px; - height: 24px; + height: 24px !important; line-height: 24px; vertical-align: top; padding: 0 10px; - margin: 3px 0; + margin: 3px 4px 3px 0; } .openerp .oe_form_topbar button span.i { line-height: 20px; @@ -1326,12 +1534,31 @@ font-weight: bold; color: #b33630; } +.openerp .oe_form_topbar.oe_form_topbar_hifirst button:first-child, .openerp button.oe_form_button_hi { + color: white; + background: #dc5f59; + background: -moz-linear-gradient(#dc5f59, #b33630); + background: -webkit-gradient(linear, left top, left bottom, from(#dc5f59), to(#b33630)); + background: -webkit-linear-gradient(#dc5f59, #b33630); + -moz-box-shadow: none; + -webkit-box-shadow: none; + -box-shadow: none; +} +.openerp .oe_form_topbar.oe_form_topbar_hifirst button:first-child:hover, .openerp button.oe_form_button_hi:hover { + background: #df6b66; + background: -moz-linear-gradient(#df6b66, #bf3a33); + background: -webkit-gradient(linear, left top, left bottom, from(#df6b66), to(#bf3a33)); + background: -webkit-linear-gradient(#df6b66, #bf3a33); + -moz-box-shadow: 0 0 1px rgba(0, 0, 0, 0.2); + -webkit-box-shadow: 0 0 1px rgba(0, 0, 0, 0.2); + -box-shadow: 0 0 1px rgba(0, 0, 0, 0.2); +} .openerp .oe_application .oe_form_sheetbg { background: url(/web/static/src/img/form_sheetbg.png); - padding: 8px; + padding: 8px 0; border-bottom: 1px solid #dddddd; } -.openerp .oe_application .oe_form_sheet_width { +.openerp .oe_application .oe_form_sheet_width, .openerp .oe_application .oe_form_bottom { min-width: 650px; max-width: 980px; margin: 0 auto; @@ -1345,44 +1572,30 @@ -webkit-box-shadow: 0 0 10px rgba(0, 0, 0, 0.3); -box-shadow: 0 0 10px rgba(0, 0, 0, 0.3); } -.openerp .oe_form_autolayout .oe_button { - height: 22px; -} -.openerp .oe_form_autolayout .oe_form_group_cell { +.openerp .oe_form .oe_form_group_cell { line-height: 18px; padding: 2px; - height: 25px; + height: 20px; } -.openerp .oe_form_autolayout .oe_form_group_cell > .oe_form_field_many2one, -.openerp .oe_form_autolayout .oe_form_group_cell > .oe_form_field_many2one input, -.openerp .oe_form_autolayout .oe_form_group_cell > .oe_form_field_char input, -.openerp .oe_form_autolayout .oe_form_group_cell > .oe_form_field_text textarea, -.openerp .oe_form_autolayout .oe_form_group_cell > .oe_form_field_email, -.openerp .oe_form_autolayout .oe_form_group_cell > .oe_form_field_email input, -.openerp .oe_form_autolayout .oe_form_group_cell > .oe_form_field_url, -.openerp .oe_form_autolayout .oe_form_group_cell > .oe_form_field_url input, -.openerp .oe_form_autolayout .oe_form_group_cell > .oe_form_field_float input, -.openerp .oe_form_autolayout .oe_form_group_cell > .oe_form_field_selection select, -.openerp .oe_form_autolayout .oe_form_group_cell > div > .oe_datepicker_root, -.openerp .oe_form_autolayout .oe_form_group_cell > div > .oe_datepicker_root > input.oe_datepicker_master { +.openerp .oe_form .oe_form_group_cell > .oe_form_field_many2one, +.openerp .oe_form .oe_form_group_cell > .oe_form_field_many2one input, +.openerp .oe_form .oe_form_group_cell > .oe_form_field_char input, +.openerp .oe_form .oe_form_group_cell > .oe_form_field_text textarea, +.openerp .oe_form .oe_form_group_cell > .oe_form_field_email, +.openerp .oe_form .oe_form_group_cell > .oe_form_field_email input, +.openerp .oe_form .oe_form_group_cell > .oe_form_field_url, +.openerp .oe_form .oe_form_group_cell > .oe_form_field_url input, +.openerp .oe_form .oe_form_group_cell > .oe_form_field_float input, +.openerp .oe_form .oe_form_group_cell > .oe_form_field_selection select, +.openerp .oe_form .oe_form_group_cell > div > .oe_datepicker_root, +.openerp .oe_form .oe_form_group_cell > div > .oe_datepicker_root > input.oe_datepicker_master { width: 100%; } -.openerp .oe_form_autolayout .oe_form_button.oe_button { - color: #4c4c4c; -} -.openerp .oe_form_autolayout .oe_form_button.oe_button span { - position: relative; - vertical-align: top; -} -.openerp .oe_form_autolayout .oe_form_group_cell > .oe_form_button.oe_button { - white-space: nowrap; - min-width: 100%; - width: 100%; -} -.openerp .oe_form_autolayout .oe_form_group_cell.oe_form_group_nested { +.openerp .oe_form .oe_form_group_cell.oe_form_group_nested { padding: 0; } .openerp .oe_form .oe_form_label_help[for], .openerp .oe_form .oe_form_label[for] { + font-weight: bold; white-space: nowrap; padding-right: 8px; } @@ -1420,18 +1633,28 @@ -webkit-border-radius: 3px; border-radius: 3px; background: white; - min-width: 90px; + min-width: 70px; color: #1f1f1f; } .openerp .oe_form input[readonly], .openerp .oe_form select[readonly], .openerp .oe_form textarea[readonly], .openerp .oe_form input[disabled], -.openerp .oe_form select[disabled], -.openerp .oe_form textarea[disabled] { +.openerp .oe_form select[disabled] { background: #e5e5e5 !important; color: #666666; } +.openerp .oe_form textarea[disabled] { + border: none; + border-left: 8px solid #eeeeee; + padding-left: 8px; + -moz-box-shadow: none; + -webkit-box-shadow: none; + -box-shadow: none; + -moz-border-radius: 0px; + -webkit-border-radius: 0px; + border-radius: 0px; +} .openerp .oe_form .oe_form_field_many2one input, .openerp .oe_form .oe_form_field_binary input, .openerp .oe_form .oe_form_field_binary input, @@ -1449,8 +1672,6 @@ .openerp .oe_form .oe_form_field_url button img { vertical-align: top; } -.openerp .oe_form .oe_form_field_translatable, -.openerp .oe_form .oe_form_field_many2one, .openerp .oe_form .oe_form_field_date, .openerp .oe_form .oe_form_field_datetime { white-space: nowrap; @@ -1499,6 +1720,7 @@ border: 1px solid #dd0000 !important; } .openerp .oe_form .oe_button.oe_field_button { + display: block; -webkit-border-top-left-radius: 0px; -webkit-border-bottom-left-radius: 0px; -moz-border-radius-topleft: 0px; @@ -1521,6 +1743,27 @@ right: 5px; top: 3px; } +.openerp .oe_form .oe_form_group_cell .oe_kanban_view { + position: static; +} +.openerp .oe_form .oe_form_button.oe_button { + height: 22px; + color: #4c4c4c; +} +.openerp .oe_form .oe_form_button.oe_button span { + position: relative; + vertical-align: top; +} +.openerp .oe_form .oe_form_button > img { + vertical-align: -3px; + padding: 0 2px; +} +.openerp .oe_form .oe_form_group_cell > .oe_form_button.oe_button { + display: block; + white-space: nowrap; + min-width: 100%; + width: 100%; +} .openerp .oe_form .oe-binary-file-set { overflow: hidden; position: relative; @@ -1540,12 +1783,14 @@ margin: 0; padding: 0; } +.openerp .oe_horizontal_border { + border-bottom: 1px solid black; +} .openerp .oe_horizontal_separator { font-weight: bold; - border: 0 solid #666666; - border-bottom-width: 1px; - margin: 3px 4px 3px 1px; - height: 17px; + font-size: 20px; + margin: 20px 0px 10px 0px; + color: #aaaabb; } .openerp .oe_horizontal_separator:empty { height: 5px; @@ -1622,7 +1867,7 @@ -webkit-border-radius: 3px; border-radius: 3px; background: white; - min-width: 90px; + min-width: 50px; } .openerp .oe_form .oe_form_field_progressbar.ui-progressbar span { position: absolute; @@ -1647,9 +1892,13 @@ height: auto; line-height: 16px; } +.openerp .oe-select-create-popup-view-form > .oe_formview > .oe_form_pager { + display: none; +} .openerp .oe_form .oe_form_title, .openerp .oe_form .oe_form_title input { font-size: 20px; font-weight: bold; + height: 30px; } .openerp .oe_form .oe_form_group_odd_border > tbody > tr.oe_form_group_row > td.oe_form_group_cell:nth-child(odd), .openerp .oe_form .oe_form_group_label_border > tbody > tr.oe_form_group_row > td.oe_form_group_cell_label { @@ -1662,85 +1911,58 @@ } .openerp .oe_form .oe_form_group_odd_border > tbody > tr.oe_form_group_row > td.oe_form_group_cell, .openerp .oe_form .oe_form_group_label_border > tbody > tr.oe_form_group_row > td.oe_form_group_cell { - padding: 2px 2px 2px 8px !important; + padding-left: 8px; } -.openerp .oe_listview_nocontent > img { - float: left; - margin-right: 1.5em; +.openerp .oe_form .oe_form_subtotal_footer { + float: right; } -.openerp .oe_listview_nocontent > div { - overflow: hidden; - padding: 6px; - font-size: 125%; +.openerp .oe_form .oe_form_subtotal_footer > div { + text-align: right; + padding: 3px; +} +.openerp .oe_form .oe_form_subtotal_footer label { + font-weight: normal !important; +} +.openerp .oe_form .oe_form_subtotal_footer span { + display: inline-block; + min-width: 80px; + text-align: right; +} +.openerp .oe_form .oe_form_subtotal_footer .oe_form_subtotal_footer_separator { + border-top: 1px solid #cacaca; + font-size: 120%; + font-weight: bold; +} +.openerp .oe_form .oe_form_subtotal_footer .oe_form_subtotal_footer_separator label { + font-weight: bold !important; } .openerp .oe-listview-content { width: 100%; } -.openerp .oe-listview-content thead, .openerp .oe-listview-content tfoot { - border-bottom: 1px solid #cacaca; +.openerp .oe-listview-content > thead { + border-bottom: 2px solid #cacaca; background: #eeeeee; -} -.openerp .oe-listview-content tfoot { - border-bottom: 1px solid #cacaca; - font-weight: bold; -} -.openerp .oe-listview-content tbody { - cursor: pointer; - background: white; -} -.openerp .oe-listview-content thead { vertical-align: top; } -.openerp .oe-listview-content td.oe_list_checkbox:first-child, .openerp .oe-listview-content th.oe_list_checkbox:first-child { - width: 17px; -} -.openerp .oe-listview-content td.oe_list_checkbox:first-child:after, .openerp .oe-listview-content th.oe_list_checkbox:first-child:after { - border-width: 0; -} -.openerp .oe-listview-content tbody tr:nth-child(odd) td, .openerp .oe-listview-content tbody tr:nth-child(odd) th { - background-color: #f0f0fa; - background-color: #f0f0fa; - background-image: -webkit-gradient(linear, left top, left bottom, from(#f0f0fa), to(#eeeef6)); - background-image: -webkit-linear-gradient(top, #f0f0fa, #eeeef6); - background-image: -moz-linear-gradient(top, #f0f0fa, #eeeef6); - background-image: -ms-linear-gradient(top, #f0f0fa, #eeeef6); - background-image: -o-linear-gradient(top, #f0f0fa, #eeeef6); - background-image: linear-gradient(to bottom, #f0f0fa, #eeeef6); -} -.openerp .oe-listview-content tbody tr:hover td, .openerp .oe-listview-content tbody tr:hover th { - background-color: #eeeeee; - background-image: -webkit-gradient(linear, left top, left bottom, from(#eeeeee), to(#dedede)); - background-image: -webkit-linear-gradient(top, #eeeeee, #dedede); - background-image: -moz-linear-gradient(top, #eeeeee, #dedede); - background-image: -ms-linear-gradient(top, #eeeeee, #dedede); - background-image: -o-linear-gradient(top, #eeeeee, #dedede); - background-image: linear-gradient(to bottom, #eeeeee, #dedede); -} -.openerp .oe-listview-content td, .openerp .oe-listview-content th { +.openerp .oe-listview-content > thead td, .openerp .oe-listview-content > thead th { padding: 3px 6px; line-height: 18px; } -.openerp .oe-listview-content td button, .openerp .oe-listview-content th button { - border: none; - background: transparent; - padding: 0; - -moz-box-shadow: none; - -webkit-box-shadow: none; - -box-shadow: none; +.openerp .oe-listview-content > thead th:after { + content: ""; + float: right; + margin-top: 7px; + border-width: 0 4px 4px; + border-style: solid; + border-color: black transparent; + visibility: hidden; } -.openerp .oe-listview-content .numeric { - text-align: right; - width: 82px; -} -.openerp .oe-listview-content .numeric input { - text-align: right; -} -.openerp .oe-listview-content table .sortdown:after, .openerp .oe-listview-content table .sortdown:hover:after { +.openerp .oe-listview-content > thead th.sortup:after { visibility: visible; filter: alpha(opacity=60); opacity: 0.6; } -.openerp .oe-listview-content table .sortup:after { +.openerp .oe-listview-content > thead th.sortdown:after { border-bottom: none; border-left: 4px solid transparent; border-right: 4px solid transparent; @@ -1752,58 +1974,67 @@ filter: alpha(opacity=60); opacity: 0.6; } -.openerp .oe_kanban_group_title { - margin: 1px 1px 4px; - font-size: 15px; +.openerp .oe-listview-content > tbody { + cursor: pointer; + background: white; +} +.openerp .oe-listview-content > tbody > tr { + border-top: 1px solid #dddddd; +} +.openerp .oe-listview-content > tbody > tr > td.oe-field-cell { + padding: 3px 6px; +} +.openerp .oe-listview-content > tbody > tr > td, .openerp .oe-listview-content > tbody > tr > th { + line-height: 18px; +} +.openerp .oe-listview-content > tbody > tr > td > button, .openerp .oe-listview-content > tbody > tr > th > button { + border: none; + background: transparent; + padding: 0; + -moz-box-shadow: none; + -webkit-box-shadow: none; + -box-shadow: none; +} +.openerp .oe-listview-content > tbody > tr > td.oe_list_checkbox:first-child, .openerp .oe-listview-content > tbody > tr th.oe_list_checkbox:first-child { + width: 17px; +} +.openerp .oe-listview-content > tbody > tr > td.oe_list_checkbox:first-child:after, .openerp .oe-listview-content > tbody > tr th.oe_list_checkbox:first-child:after { + border-width: 0; +} +.openerp .oe-listview-content > tbody > tr > td.oe-number { + text-align: right !important; +} +.openerp .oe-listview-content > tbody > tr:nth-child(odd) { + background-color: #f0f0fa; + background-color: #f0f0fa; + background-image: -webkit-gradient(linear, left top, left bottom, from(#f0f0fa), to(#eeeef6)); + background-image: -webkit-linear-gradient(top, #f0f0fa, #eeeef6); + background-image: -moz-linear-gradient(top, #f0f0fa, #eeeef6); + background-image: -ms-linear-gradient(top, #f0f0fa, #eeeef6); + background-image: -o-linear-gradient(top, #f0f0fa, #eeeef6); + background-image: linear-gradient(to bottom, #f0f0fa, #eeeef6); +} +.openerp .oe-listview-content > tfoot { + border-top: 2px solid #cacaca; + border-bottom: 1px solid #cacaca; + background: #eeeeee; font-weight: bold; - text-shadow: 0 1px 0 white; } -.openerp .oe_kanban_column, .openerp .oe_kanban_group_header { - width: 240px; - vertical-align: top; - padding: 6px 7px 6px 6px; - background: #f0eeee; - border-left: 1px solid #f0f8f8; - border-right: 1px solid #b9b9b9; +.openerp .oe-listview-content > tbody tr:hover td, .openerp .oe-listview-content tbody tr:hover th { + background-color: #eeeeee; + background-image: -webkit-gradient(linear, left top, left bottom, from(#eeeeee), to(#dedede)); + background-image: -webkit-linear-gradient(top, #eeeeee, #dedede); + background-image: -moz-linear-gradient(top, #eeeeee, #dedede); + background-image: -ms-linear-gradient(top, #eeeeee, #dedede); + background-image: -o-linear-gradient(top, #eeeeee, #dedede); + background-image: linear-gradient(to bottom, #eeeeee, #dedede); } -.openerp .oe_kanban_record { - position: relative; - display: block; - min-height: 50px; - margin: 6px 0; - display: block; - -moz-border-radius: 4px; - -webkit-border-radius: 4px; - border-radius: 4px; +.openerp .oe-listview-content .numeric { + text-align: right; + width: 82px; } -.openerp .oe_kanban_record:last-child { - margin-bottom: 0; -} -.openerp .oe_kanban_record .oe_kanban_title { - font-weight: bold; - margin: 2px 4px; -} -.openerp .oe_kanban_gravatar { - width: 20px; - height: 20px; - -moz-border-radius: 3px; - -webkit-border-radius: 3px; - border-radius: 3px; - -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2); - -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2); - -box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2); -} -.openerp .oe_kanban_avatar_toto { - height: 40px; - width: 40px; - border: 1px solid; - border-color: #e5e5e5 #dbdbdb #d2d2d2; - -moz-border-radius: 3px; - -webkit-border-radius: 3px; - border-radius: 3px; - -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2); - -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2); - -box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2); +.openerp .oe-listview-content .numeric input { + text-align: right; } .openerp .oe_trad_field.touched { border: 1px solid green !important; @@ -1870,6 +2101,15 @@ color: #333333; } +.kitten-mode-activated { + background-image: url(http://placekitten.com/g/1365/769); + background-size: cover; + background-attachment: fixed; +} +.kitten-mode-activated > * { + opacity: 0.7; +} + .openerp .oe_form_field_many2one td:first-child { position: relative; } diff --git a/addons/web/static/src/css/base.sass b/addons/web/static/src/css/base.sass index 412c36b3ee5..e013009f9b1 100644 --- a/addons/web/static/src/css/base.sass +++ b/addons/web/static/src/css/base.sass @@ -4,6 +4,7 @@ $section-title-color: #8786b7 $facets-border: #afafb6 $facets-border-selected: #a6a6fe +$hover-background: #f0f0fa $colour4: #8a89ba // }}} // Mixins {{{ @@ -16,6 +17,16 @@ $colour4: #8a89ba font-weight: normal font-style: normal +@font-face + font-family: 'EntypoRegular' + src: url('/web/static/src/font/entypo-webfont.eot') format('eot') + src: url('/web/static/src/font/entypo-webfont.eot?#iefix') format('embedded-opentype') + src: url('/web/static/src/font/entypo-webfont.woff') format('woff') + src: url('/web/static/src/font/entypo-webfont.ttf') format('truetype') + src: url('/web/static/src/font/entypo-webfont.svg') format('svg') active + font-weight: normal + font-style: normal + @mixin vertical-gradient($startColor: #555, $endColor: #333) background-color: $startColor background-image: -webkit-gradient(linear, left top, left bottom, from($startColor), to($endColor)) /* Saf4+, Chrome */ @@ -64,6 +75,18 @@ $colour4: #8a89ba -webkit-box-sizing: border-box box-sizing: border-box +// Transforms the (readable) text of an inline element into an mmlicons icon, +// allows for actual readable text in-code (and in readers?) with iconic looks +@mixin text-to-icon($icon-name, $color: #404040) + font-size: 1px + letter-spacing: -1px + color: transparent + &:before + font-family: "mnmliconsRegular" + content: $icon-name + font-size: 20px + color: $color + // }}} .openerp.openerp-web-client-container @@ -95,7 +118,6 @@ $colour4: #8a89ba border-right: none th, td padding: 0 - line-height: 18px text-align: left th font-weight: bold @@ -123,16 +145,27 @@ $colour4: #8a89ba font-family: "mnmliconsRegular" !important font-size: 21px font-weight: 300 !important + .oe_e + font-family: "entypoRegular" !important + font-size: 34px + font-weight: 300 !important .oe_left float: left margin-right: 8px .oe_right float: right margin-left: 8px + .oe_text_right + text-align: right .oe_clear clear: both .oe_wait cursor: wait + .oe_fade + color: #888 + //font-size: 12px + .oe_bold + font-weight: bold // }}} // Button style {{{ a.button:link, a.button:visited, button, input[type='submit'] @@ -351,15 +384,8 @@ $colour4: #8a89ba width: 100% height: 31px border-top: solid 1px #d3d3d3 - border-bottom: solid 1px black @include vertical-gradient(#646060, #262626) - .oe_systray - float: right - .oe_systray > div - float: left - padding: 0 4px 0 4px - .oe_topbar_item li float: left @@ -408,6 +434,8 @@ $colour4: #8a89ba background: #f0eeee border-right: 1px solid #afafb6 text-shadow: 0 1px 1px white + padding-bottom: 16px + line-height: 18px a.oe_logo width: 220px display: block @@ -444,6 +472,7 @@ $colour4: #8a89ba float: left .oe_dropdown position: relative + .oe_dropdown_options float: left background: #333 @@ -465,6 +494,53 @@ $colour4: #8a89ba @include radius(0 0 6px 6px) @include box-shadow(0 1px 4px rgba(0,0,0,0.3)) @include background-clip() + li + float: none + display: block + background-color: none + a + white-space: nowrap + display: block + padding: 4px 15px + clear: both + font-weight: normal + line-height: 18px + color: #eee + &:hover + @include vertical-gradient(#292929, #191919) + @include box-shadow(none) + hr + border-top: 1px solid #999 + border-bottom: 0 + // }}} + // Systray {{{ + .oe_systray > div + float: left + padding: 0 4px 0 4px + .oe_systray + float: right + + .oe_systray_dropdown + position: relative + .oe_systray_dropdown:hover .oe_systray_dropdown_options + display: block + .oe_systray_dropdown_options + background: #333 + background: rgba(37,37,37,0.9) + display: none + position: absolute + z-index: 900 + border: 0 + margin-left: 0 + margin-right: 0 + padding: 6px 0 + border-color: #999 + border-color: rgba(0, 0, 0, 0.2) + border-style: solid + border-width: 0 1px 1px + @include radius(0 0 6px 6px) + @include box-shadow(0 1px 4px rgba(0,0,0,0.3)) + @include background-clip() li float: none display: block @@ -527,9 +603,9 @@ $colour4: #8a89ba margin: 0 width: 100% display: inline-block - li + > li position: relative - padding: 1px 0 1px 16px + padding: 1px 0 1px 20px a display: block color: #4c4c4c @@ -580,7 +656,7 @@ $colour4: #8a89ba content: "&darr" text-indent: -99999px vertical-align: top - margin-left: -8px + margin-left: -12px margin-top: 4px margin-right: 4px border-top: 4px solid transparent @@ -589,7 +665,7 @@ $colour4: #8a89ba @include opacity(0.5) .oe_menu_opened:before margin-top: 6px - margin-left: -12px + margin-left: -16px margin-right: 4px border-left: 4px solid transparent border-right: 4px solid transparent @@ -669,21 +745,37 @@ $colour4: #8a89ba text-shadow: 0 1px 2px rgba(0,0,0,0.4) // }}} // ViewManager.header {{{ - .oe_view_manager_header2 + .oe_view_manager_header width: 100% border-top: 1px solid #cacaca border-bottom: 1px solid #cacaca @include vertical-gradient(#fcfcfc, #dedede) @include box-shadow((0 1px 0 rgba(255,255,255,0.4), 0 0 9px rgba(0,0,0,0.1))) + .oe_header_row + //min-height: 26px + //line-height: 26px + clear: both + text-shadow: 0 1px 1px white + td + padding: 8px + .oe_header_row:last-child + td + padding-top: 0 + .oe_header_row:first-child + td + padding-top: 8px + .oe_view_manager_sidebar + margin: 0px auto + width: 400px + text-align: center + td + line-height: 26px h2 - float: left font-size: 18px - margin: 1px 0 + margin: 0 + float: left a color: $colour4 - td - padding: 4px 8px - line-height: 26px .oe_button_group display: inline-block border: 1px solid #ababab @@ -706,12 +798,9 @@ $colour4: #8a89ba .oe_view_manager_buttons white-space: nowrap // }}} - // ViewManager.body {{{ - .oe_view_manager_body - h4 - margin: 8px 0 - // }}} // ViewManager.pager {{{ + .oe_view_manager_pager + line-height: 26px .oe_pager_value float: left margin-right: 8px @@ -746,29 +835,40 @@ $colour4: #8a89ba // ViewManager.switches {{{ .oe_view_manager_switch li - padding-left: 1px text-align: center width: 24px height: 24px - line-height: 24px + line-height: 16px + a + position: relative .oe_vm_switch_list:after, .oe_vm_switch_tree:after - content: "ö" + padding: 2px + content: "i" .oe_vm_switch_graph:after - content: "ó" - .oe_vm_switch_gantt:after - content: "y" - .oe_vm_switch_calendar:after - content: "b" - .oe_vm_switch_kanban:after - content: "ó" - .oe_vm_switch_diagram:after + font-family: "mnmliconsRegular" !important + font-size: 21px + font-weight: 300 !important content: "}" + top: -2px + position: relative + .oe_vm_switch_gantt:after + font-family: "mnmliconsRegular" !important + font-size: 21px + font-weight: 300 !important + content: "y" + top: -2px + position: relative + .oe_vm_switch_calendar:after + content: "P" + .oe_vm_switch_kanban:after + content: "k" + .oe_vm_switch_diagram:after + content: "f" // }}} // ViewManager.sidebar {{{ .oe_form_dropdown_section position: relative display: inline-block - margin-right: 4px .oe_dropdown_toggle:after width: 0 height: 0 @@ -810,6 +910,7 @@ $colour4: #8a89ba line-height: 14px color: #4c4c4c text-decoration: none + cursor: pointer &:hover text-decoration: none @include vertical-gradient(#f0f0fa, #eeeef6) @@ -819,121 +920,145 @@ $colour4: #8a89ba // }}} // SearchView xmo {{{ .oe_searchview + cursor: text position: relative float: right - .VS-search - .VS-search-box - min-height: 0 - border-width: 1px - padding: 0 - width: 410px - //border: 1px solid #ababab - //margin-top: 0 - //margin-bottom: 0 - //padding: 4px 19px - //font-size: 13px - //background: url('../img/search.png') no-repeat 5px - //background-color: white - //@include radius(13px) - //@include box-shadow(0 1px 2px rgba(0,0,0,0.2) inset) - .VS-icon - top: 5px + padding-right: 20px + width: 410px + border: 1px solid #ababab + background: white + @include radius(1em) + @include box-shadow(0 1px 2px rgba(0,0,0,0.2) inset) - .VS-icon-search - left: 5px + &.oe_focused + border-color: $facets-border-selected + @include box-shadow(0 1px 2px $facets-border-selected inset) - .VS-search-inner - margin: 0 40px 0 17px - font-size: 13px + .oe_searchview_clear + cursor: pointer + position: absolute + top: 0 + right: 22px + width: 15px + height: 100% + background: url(../img/attachments-close.png) center center no-repeat - input - font-size: inherit - line-height: inherit - height: auto - padding: 0 + .oe_searchview_unfold_drawer + position: absolute + top: 0 + right: 0 + height: 100% + line-height: 2.5em + padding: 0 7px 0 4px + color: #ccc + cursor: pointer + &:hover + color: #999 + &:before + content: "◀" - .VS-input-width-tester - font-size: inherit - padding: 0 - - .search_input - margin-left: 0 - height: 22px - input, .VS-input-width-tester - padding: 0 2px - height: inherit - margin: 0 - - .search_facet - padding: 0 - margin: 1px 0 - border: 1px solid $facets-border - @include radius(3px) - background: #f0f0fa - height: 18px - - &.is_selected - border-color: $facets-border-selected - @include box-shadow(0 0 3px 1px $facets-border-selected) - - .category - margin-left: 0 - .VS-icon-cancel - // don't change the icon on selection - @include opacity(1.0) - background-position: center 0 - - .category - padding: 0 4px 0 14px - color: white - background: #8786b7 - text-shadow: 0 1px 1px rgba(0, 0, 0, 0.4) - font-weight: normal - text-transform: none - height: 18px - line-height: 18px - font-size: inherit - - .search_facet_input_container - border-left: 1px solid $facets-border - height: 18px - line-height: 18px - padding: 0 4px - cursor: pointer - - .search_facet_remove - left: 1px - top: 3px - - .VS-icon-cancel - right: 24px - - .oe_vs_unfold_drawer - position: absolute - top: 0 - right: 0 - height: 100% - line-height: 23px - padding: 0 7px 0 4px + .oe_searchview_facets + &:before color: #ccc + font-family: "mnmliconsRegular" + content: "r" + font-size: 150% + padding: 0 1px 0 3px + display: inline + + * + vertical-align: top + display: inline-block + line-height: 26px + + .oe_searchview_input, .oe_searchview_facet + height: 26px + &:focus + outline: none + + .oe_searchview_input + padding: 0 3px + + .oe_searchview_facet + position: relative cursor: pointer - &:before - content: "▾" + border: 1px solid $facets-border + @include radius(3px) + background: #8786b7 + -webkit-font-smoothing: auto + padding-left: 1.1em + // spacing for opera, FF + margin: 1px 0 + + &:focus + border-color: $facets-border-selected + @include box-shadow(0 0 3px 1px $facets-border-selected) + + .oe_facet_values + background: #f0f0fa + @include radius(0 3px 3px 0) + + .oe_facet_category, .oe_facet_value + height: 24px + padding: 1px 0.1em + + .oe_facet_category + color: white + text-shadow: 0 1px 1px rgba(0, 0, 0, 0.4) + + .oe_facet_value + border-left: 1px solid $facets-border + + .oe_facet_remove + position: absolute + top: 0 + left: 2px + color: white + + &:hover + color: #ccc &.oe_searchview_open_drawer .oe_searchview_drawer display: block + .oe_searchview_unfold_drawer:before + content: "▼" .oe_searchview_drawer position: absolute z-index: 1 + // detach drawer from field slightly + margin-top: 3px top: 100% right: 0 background-color: white - width: 410px + min-width: 100% display: none border: 1px solid #ccc text-align: left + padding-bottom: 0.5em + @include radius(1em) + + > div + border-top: 1px solid #ccc + margin: 3px 0 + > div:first-child + border-top: none + margin: 0 + + h4, h4 * + margin: 0 + cursor: pointer + + h4:before + content: "▸ " + + button, .button + border: none + background: transparent + padding: 0 2px + @include box-shadow(none) + @include radius(0) .oe_searchview_filters display: table @@ -955,24 +1080,44 @@ $colour4: #8a89ba li list-style: none - padding: 3px 6px - height: 14px + padding: 3px 6px 3px 18px + line-height: 14px color: inherit cursor: pointer + &.oe_selected + background: url(/web/static/src/img/icons/gtk-apply.png) left 2px no-repeat + // after oe_selected so background color is not overridden &:hover - background-color: #f0f0fa + background-color: $hover-background + + + .oe_searchview_custom + form + display: none + + button + @include text-to-icon("S") + li + cursor: pointer + position: relative + line-height: 1.2em + padding: 2px 20px 2px 25px + + &.oe_searchview_custom_private + background: url(/web/static/src/img/icons/terp-locked.png) 5px center no-repeat + + &:hover + background-color: $hover-background + + button + position: absolute + top: 0 + right: 5px + .oe_searchview_advanced - h4 - border-top: 1px solid #ccc - margin: 5px 0 3px - cursor: pointer - - h4:before - content: "▸ " - - div + form display: none button.oe_add_condition:before @@ -986,14 +1131,29 @@ $colour4: #8a89ba li list-style: none margin: 0 + white-space: nowrap - &.oe_opened - h4:before - content: "▾ " - div - display: block + .oe_opened + h4:before + content: "▾ " + form + display: block + + // delete buttons + .oe_searchview_custom_delete, .searchview_extended_delete_prop + @include text-to-icon("d") // }}} - // View.topbar {{{ + // Views Common {{{ + .oe_view_nocontent + > img + float: left + margin: 1.5em + > div + // don't encroach on my arrow + overflow: hidden + padding: 35px 0px 0px 0px + max-width: 700px + font-size: 125% .oe_view_topbar border-bottom: 1px solid #cacaca @include vertical-gradient(#fcfcfc, #dedede) @@ -1030,11 +1190,11 @@ $colour4: #8a89ba line-height: 30px button font-size: 12px - height: 24px + height: 24px !important line-height: 24px vertical-align: top padding: 0 10px - margin: 3px 0 + margin: 3px 4px 3px 0 span.i line-height: 20px height: 24px @@ -1074,12 +1234,29 @@ $colour4: #8a89ba .oe_form_steps_active font-weight: bold color: #b33630 + .oe_form_topbar.oe_form_topbar_hifirst button:first-child, button.oe_form_button_hi + color: white + background: #DC5F59 + background: -moz-linear-gradient(#DC5F59, #B33630) + background: -webkit-gradient(linear, left top, left bottom, from(#DC5F59), to(#B33630)) + background: -webkit-linear-gradient(#DC5F59, #B33630) + -moz-box-shadow: none + -webkit-box-shadow: none + -box-shadow: none + .oe_form_topbar.oe_form_topbar_hifirst button:first-child:hover, button.oe_form_button_hi:hover + background: #DF6B66 + background: -moz-linear-gradient( #DF6B66, #BF3A33) + background: -webkit-gradient(linear, left top, left bottom, from( #DF6B66), to( #BF3A33)) + background: -webkit-linear-gradient( #DF6B66, #BF3A33) + -moz-box-shadow: 0 0 1px rgba(0, 0, 0, 0.2) + -webkit-box-shadow: 0 0 1px rgba(0, 0, 0, 0.2) + -box-shadow: 0 0 1px rgba(0, 0, 0, 0.2) .oe_application .oe_form_sheetbg background: url(/web/static/src/img/form_sheetbg.png) - padding: 8px + padding: 8px 0 border-bottom: 1px solid #ddd - .oe_form_sheet_width + .oe_form_sheet_width, .oe_form_bottom min-width: 650px max-width: 980px margin: 0 auto @@ -1089,30 +1266,13 @@ $colour4: #8a89ba min-height: 420px border: 1px solid #afafb6 @include box-shadow(0 0 10px rgba(0,0,0,0.3)) - //.avatar - // max-height: 52px - //.contacts - // li - // float: left - // width: 33% - // margin-bottom: 4px - // .avatar - // height: 40px - // width: 40px - // border: 1px solid - // border-color: #e5e5e5 #dbdbdb #d2d2d2 - // .data - // padding: 2px - // line-height: 18px // }}} - // FormView.autolayout {{{ - .oe_form_autolayout - .oe_button - height: 22px + // FormView.layout {{{ + .oe_form .oe_form_group_cell line-height: 18px padding: 2px - height: 25px + height: 20px .oe_form_group_cell > .oe_form_field_many2one, .oe_form_group_cell > .oe_form_field_many2one input, .oe_form_group_cell > .oe_form_field_char input, @@ -1126,21 +1286,13 @@ $colour4: #8a89ba .oe_form_group_cell > div > .oe_datepicker_root, .oe_form_group_cell > div > .oe_datepicker_root > input.oe_datepicker_master width: 100% - .oe_form_button.oe_button - color: #4c4c4c - span - position: relative - vertical-align: top - .oe_form_group_cell > .oe_form_button.oe_button - white-space: nowrap - min-width: 100% - width: 100% .oe_form_group_cell.oe_form_group_nested padding: 0 // }}} // FormView.label {{{ .oe_form .oe_form_label_help[for], .oe_form_label[for] + font-weight: bold white-space: nowrap padding-right: 8px span @@ -1177,16 +1329,21 @@ $colour4: #8a89ba -webkit-border-radius: 3px border-radius: 3px background: white - min-width: 90px + min-width: 70px color: #1f1f1f input[readonly], select[readonly], textarea[readonly], input[disabled], - select[disabled], - textarea[disabled] + select[disabled] background: #E5E5E5 !important color: #666 + textarea[disabled] + border: none + border-left: 8px solid #eee + padding-left: 8px + @include box-shadow(none) + @include radius(0px) .oe_form_field_many2one input, .oe_form_field_binary input, .oe_form_field_binary input, @@ -1202,8 +1359,6 @@ $colour4: #8a89ba .oe_form_field_email button img, .oe_form_field_url button img vertical-align: top - .oe_form_field_translatable, - .oe_form_field_many2one, .oe_form_field_date, .oe_form_field_datetime white-space: nowrap @@ -1243,10 +1398,8 @@ $colour4: #8a89ba input, select, textarea background-color: #F66 !important border: 1px solid #D00 !important - // }}} - // FormView.buttons {{{ - .oe_form .oe_button.oe_field_button + display: block -webkit-border-top-left-radius: 0px -webkit-border-bottom-left-radius: 0px -moz-border-radius-topleft: 0px @@ -1266,6 +1419,26 @@ $colour4: #8a89ba filter: alpha(opacity=50) right: 5px top: 3px + .oe_form_group_cell .oe_kanban_view + // Hack due to absolute positioning of kanban view messing with o2m + position: static + // }}} + // FormView.buttons {{{ + .oe_form + .oe_form_button.oe_button + height: 22px + color: #4c4c4c + span + position: relative + vertical-align: top + .oe_form_button > img + vertical-align: -3px + padding: 0 2px + .oe_form_group_cell > .oe_form_button.oe_button + display: block + white-space: nowrap + min-width: 100% + width: 100% // }}} // FormView.binaryfile {{{ /* http://www.quirksmode.org/dom/inputfile.html @@ -1292,12 +1465,13 @@ $colour4: #8a89ba padding: 0 // }}} // FormView.separator {{{ + .oe_horizontal_border + border-bottom: 1px solid black .oe_horizontal_separator font-weight: bold - border: 0 solid #666 - border-bottom-width: 1px - margin: 3px 4px 3px 1px - height: 17px + font-size: 20px + margin: 20px 0px 10px 0px + color: #aab .oe_horizontal_separator:empty height: 5px .oe_vertical_separator @@ -1363,7 +1537,7 @@ $colour4: #8a89ba -webkit-border-radius: 3px border-radius: 3px background: white - min-width: 90px + min-width: 50px span position: absolute @@ -1387,6 +1561,8 @@ $colour4: #8a89ba li height: auto line-height: 16px + .oe-select-create-popup-view-form > .oe_formview > .oe_form_pager + display: none // }}} // FormView.classes for openerp views {{{ @@ -1394,6 +1570,7 @@ $colour4: #8a89ba .oe_form_title, .oe_form_title input font-size: 20px font-weight: bold + height: 30px .oe_form_group_odd_border > tbody > tr.oe_form_group_row > td.oe_form_group_cell:nth-child(odd), .oe_form_group_label_border > tbody > tr.oe_form_group_row > td.oe_form_group_cell_label border-right: 1px solid #ddd @@ -1402,110 +1579,100 @@ $colour4: #8a89ba min-width: 120px .oe_form_group_odd_border > tbody > tr.oe_form_group_row > td.oe_form_group_cell, .oe_form_group_label_border > tbody > tr.oe_form_group_row > td.oe_form_group_cell - padding: 2px 2px 2px 8px !important + padding-left: 8px + .oe_form_subtotal_footer + float: right + > div + text-align: right + padding: 3px + label + font-weight: normal !important + span + display: inline-block + min-width: 80px + text-align: right + .oe_form_subtotal_footer_separator + border-top: 1px solid #cacaca + font-size: 120% + font-weight: bold + label + font-weight: bold !important // }}} // ListView {{{ - .oe_listview_nocontent - > img - float: left - margin-right: 1.5em - > div - // don't encroach on my arrow - overflow: hidden - padding: 6px - font-size: 125% .oe-listview-content width: 100% - thead, tfoot - border-bottom: 1px solid #cacaca + > thead + border-bottom: 2px solid #cacaca background: #eee - tfoot - border-bottom: 1px solid #cacaca - font-weight: bold - tbody + vertical-align: top + td, th + padding: 3px 6px + line-height: 18px + th:after + content: "" + float: right + margin-top: 7px + border-width: 0 4px 4px + border-style: solid + border-color: #000 transparent + visibility: hidden + th.sortup:after + visibility: visible + @include opacity(0.6) + th.sortdown:after + border-bottom: none + border-left: 4px solid transparent + border-right: 4px solid transparent + border-top: 4px solid #000 + visibility: visible + @include box-shadow(none) + @include opacity(0.6) + // TODO mit + //th:hover:after + // border-bottom: none + // border-left: 4px solid transparent + // border-right: 4px solid transparent + // border-top: 4px solid #000 + // visibility: visible + // @include box-shadow(none) + // @include opacity(0.6) + > tbody cursor: pointer background: white - thead - vertical-align: top - td.oe_list_checkbox:first-child, th.oe_list_checkbox:first-child - width: 17px - &:after - border-width: 0 - tbody tr:nth-child(odd) td, tbody tr:nth-child(odd) th - background-color: #f0f0fa - @include vertical-gradient(#f0f0fa, #eeeef6) - tbody tr:hover td, tbody tr:hover th + > tr + border-top: 1px solid #ddd + > td.oe-field-cell + padding: 3px 6px + > td, > th + line-height: 18px + > button + border: none + background: transparent + padding: 0 + @include box-shadow(none) + > td.oe_list_checkbox:first-child, th.oe_list_checkbox:first-child + width: 17px + &:after + border-width: 0 + > td.oe-number + text-align: right !important + > tr:nth-child(odd) + background-color: #f0f0fa + @include vertical-gradient(#f0f0fa, #eeeef6) + > tfoot + border-top: 2px solid #cacaca + border-bottom: 1px solid #cacaca + background: #eee + font-weight: bold + + > tbody tr:hover td, tbody tr:hover th @include vertical-gradient(#eee, #dedede) - td, th - padding: 3px 6px - line-height: 18px - button - border: none - background: transparent - padding: 0 - @include box-shadow(none) + .numeric text-align: right width: 82px input text-align: right - //thead th:after - //content: "" - //float: right - //margin-top: 7px - //border-width: 0 4px 4px - //border-style: solid - //border-color: #000 transparent - //visibility: hidden - table .sortdown:after, table .sortdown:hover:after - visibility: visible - @include opacity(0.6) - table .sortup:after - border-bottom: none - border-left: 4px solid transparent - border-right: 4px solid transparent - border-top: 4px solid #000 - visibility: visible - @include box-shadow(none) - @include opacity(0.6) - // }}} - // KanbanView {{{ - .oe_kanban_group_title - margin: 1px 1px 4px - font-size: 15px - font-weight: bold - text-shadow: 0 1px 0 white - .oe_kanban_column, .oe_kanban_group_header - width: 240px - vertical-align: top - padding: 6px 7px 6px 6px - background: #f0eeee - border-left: 1px solid #f0f8f8 - border-right: 1px solid #b9b9b9 - .oe_kanban_record - position: relative - display: block - min-height: 50px - margin: 6px 0 - display: block - @include radius(4px) - &:last-child - margin-bottom: 0 - .oe_kanban_title - font-weight: bold - margin: 2px 4px - .oe_kanban_gravatar - width: 20px - height: 20px - @include radius(3px) - @include box-shadow(0 1px 2px rgba(0,0,0,0.2)) - .oe_kanban_avatar_toto - height: 40px - width: 40px - border: 1px solid - border-color: #e5e5e5 #dbdbdb #d2d2d2 - @include radius(3px) - @include box-shadow(0 1px 2px rgba(0,0,0,0.2)) // }}} // Translation {{{ .oe_trad_field.touched @@ -1564,6 +1731,13 @@ $colour4: #8a89ba color: #333 // }}} +.kitten-mode-activated + background-image: url(http://placekitten.com/g/1365/769) + background-size: cover + background-attachment: fixed + >* + opacity: 0.70 + // Transitional overrides for old styles {{{ .openerp .oe_form_field_many2one diff --git a/addons/web/static/src/css/base_old.css b/addons/web/static/src/css/base_old.css index 8f333fae761..74b660f7613 100644 --- a/addons/web/static/src/css/base_old.css +++ b/addons/web/static/src/css/base_old.css @@ -880,60 +880,6 @@ label.error { text-align: left; padding: 4px 5px; } -/* Shortcuts*/ -.oe-shortcut-toggle { - height: 20px; - margin-top: 3px; - padding: 0; - width: 24px; - cursor: pointer; - display: block; - background: url(/web/static/src/img/add-shortcut.png) no-repeat center center; - float: left; -} -.oe-shortcut-remove{ - background: url(/web/static/src/img/remove-shortcut.png) no-repeat center center; -} -.oe-shortcuts { - position: absolute; - margin: 0; - padding: 6px 15px; - top: 37px; - left: 197px; - right: 0; - height: 17px; - line-height: 1.2; -} -.oe-shortcuts ul { - display: block; - overflow: hidden; - list-style: none; - white-space: nowrap; - padding: 0; - margin: 0; -} -.oe-shortcuts li { - cursor: pointer; - display: -moz-inline-stack; - display: inline-block; - display: inline; /*IE7 */ - color: #fff; - text-align: center; - border-left: 1px solid #909090; - padding: 0 4px; - font-size: 80%; - font-weight: normal; - vertical-align: top; -} - -.oe-shortcuts li:hover { - background-color: #666; -} -.oe-shortcuts li:first-child { - border-left: none; - padding-left: 0; -} - ul.oe-arrow-list { padding-left: 1.1em; margin: 0; diff --git a/addons/web/static/src/font/entypo-webfont.eot b/addons/web/static/src/font/entypo-webfont.eot new file mode 100755 index 00000000000..2c09f336d57 Binary files /dev/null and b/addons/web/static/src/font/entypo-webfont.eot differ diff --git a/addons/web/static/src/font/entypo-webfont.svg b/addons/web/static/src/font/entypo-webfont.svg new file mode 100755 index 00000000000..c24d92adb5f --- /dev/null +++ b/addons/web/static/src/font/entypo-webfont.svg @@ -0,0 +1,198 @@ + + + + +This is a custom SVG webfont generated by Font Squirrel. +Copyright : Creative Commons CC BYSA 2012 +Designer : Daniel Bruce +Foundry : Daniel Bruce +Foundry URL : wwwdanielbrucese + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/addons/web/static/src/font/entypo-webfont.ttf b/addons/web/static/src/font/entypo-webfont.ttf new file mode 100755 index 00000000000..89b7a194cc7 Binary files /dev/null and b/addons/web/static/src/font/entypo-webfont.ttf differ diff --git a/addons/web/static/src/font/entypo-webfont.woff b/addons/web/static/src/font/entypo-webfont.woff new file mode 100755 index 00000000000..3879f5b811e Binary files /dev/null and b/addons/web/static/src/font/entypo-webfont.woff differ diff --git a/addons/web/static/src/img/list_empty_arrow.png b/addons/web/static/src/img/view_empty_arrow.png similarity index 100% rename from addons/web/static/src/img/list_empty_arrow.png rename to addons/web/static/src/img/view_empty_arrow.png diff --git a/addons/web/static/src/js/chrome.js b/addons/web/static/src/js/chrome.js index f43da0431ff..a36421f2b2b 100644 --- a/addons/web/static/src/js/chrome.js +++ b/addons/web/static/src/js/chrome.js @@ -43,11 +43,15 @@ instance.web.Notification = instance.web.Widget.extend({ } }); +/** + * The very minimal function everything should call to create a dialog + * in OpenERP Web Client. + */ instance.web.dialog = function(element) { var result = element.dialog.apply(element, _.rest(_.toArray(arguments))); result.dialog("widget").addClass("openerp"); return result; -} +}; instance.web.Dialog = instance.web.Widget.extend({ dialog_title: "", @@ -162,7 +166,7 @@ instance.web.CrashManager = instance.web.CallbackEnabled.extend({ } }, on_managed_error: function(error) { - instance.web.dialog($('
      ' + QWeb.render('CrashManager.warning', {error: error}) + '
      '), { + instance.web.dialog($('
      ' + QWeb.render('CrashManager.warning', {error: error}) + '
      '), { title: "OpenERP " + _.str.capitalize(error.type), buttons: [ {text: _t("Ok"), click: function() { $(this).dialog("close"); }} @@ -181,7 +185,7 @@ instance.web.CrashManager = instance.web.CallbackEnabled.extend({ // Call the send method from server to send mail with details new instance.web.DataSet(self, 'publisher_warranty.contract').call_and_eval('send', [error.data,explanation,remark,issuename]).then(function(result){ if (result === false) { - alert('There was a communication error.') + alert('There was a communication error.'); } else { $this.dialog('close'); } @@ -269,12 +273,12 @@ instance.web.DatabaseManager = instance.web.Widget.extend({ start: function() { var self = this; var fetch_db = this.rpc("/web/database/get_list", {}).pipe( - function(result) { - self.db_list = result.db_list; + function(result) { + self.db_list = result.db_list; }, - function (_, ev) { + function (_, ev) { ev.preventDefault(); - self.db_list = null; + self.db_list = null; }); var fetch_langs = this.rpc("/web/session/get_lang_list", {}).then(function(result) { self.lang_list = result.lang_list; @@ -284,11 +288,15 @@ instance.web.DatabaseManager = instance.web.Widget.extend({ do_render: function() { var self = this; self.$element.html(QWeb.render("DatabaseManager", { widget : self })); - self.$element.find(".oe_database_manager_menu").tabs(); + self.$element.find(".oe_database_manager_menu").tabs({ + show: function(event, ui) { + $('*[autofocus]:first', ui.panel).focus(); + } + }); self.$element.find("form[name=create_db_form]").validate({ submitHandler: self.do_create }); - self.$element.find("form[name=drop_db_form]").validate({ submitHandler: self.do_drop }); - self.$element.find("form[name=backup_db_form]").validate({ submitHandler: self.do_backup }); - self.$element.find("form[name=restore_db_form]").validate({ submitHandler: self.do_restore }); + self.$element.find("form[name=drop_db_form]").validate({ submitHandler: self.do_drop }); + self.$element.find("form[name=backup_db_form]").validate({ submitHandler: self.do_backup }); + self.$element.find("form[name=restore_db_form]").validate({ submitHandler: self.do_restore }); self.$element.find("form[name=change_pwd_form]").validate({ messages: { old_pwd: "Please enter your previous password", @@ -300,7 +308,7 @@ instance.web.DatabaseManager = instance.web.Widget.extend({ }, submitHandler: self.do_change_password }); - self.$element.find("#back_to_login").click(self.do_exit); + self.$element.find("#back_to_login").click(self.do_exit); }, destroy: function () { this.$element.find('#db-create, #db-drop, #db-backup, #db-restore, #db-change-password, #back-to-login').unbind('click').end().empty(); @@ -409,12 +417,12 @@ instance.web.DatabaseManager = instance.web.Widget.extend({ self.display_error({ title: 'Access Denied', error: 'Incorrect super-administrator password' - }) + }); } else { self.display_error({ title: 'Restore Database', error: 'Could not restore the database' - }) + }); } }, complete: function() { @@ -442,6 +450,8 @@ instance.web.DatabaseManager = instance.web.Widget.extend({ instance.web.Login = instance.web.Widget.extend({ template: "Login", remember_credentials: true, + _db_list: null, + init: function(parent) { this._super(parent); this.has_local_storage = typeof(localStorage) != 'undefined'; @@ -451,7 +461,7 @@ instance.web.Login = instance.web.Widget.extend({ if (this.has_local_storage && this.remember_credentials) { this.selected_db = localStorage.getItem('last_db_login_success'); this.selected_login = localStorage.getItem('last_login_login_success'); - if (jQuery.deparam(jQuery.param.querystring()).debug != undefined) { + if (jQuery.deparam(jQuery.param.querystring()).debug !== undefined) { this.selected_password = localStorage.getItem('last_password_login_success'); } } @@ -470,23 +480,33 @@ instance.web.Login = instance.web.Widget.extend({ self.databasemanager.destroy(); self.$element.find('.oe_login_bottom').show(); self.$element.find('.oe_login_pane').show(); - self.load_db_list(); - }) + self.load_db_list(true).then(self.proxy('_db_list_loaded')); + }); }); - self.load_db_list(); + return self.load_db_list().then(self.proxy('_db_list_loaded')); }, - load_db_list: function () { - var self = this; - self.rpc("/web/database/get_list", {}, function(result) { - self.set_db_list(result.db_list); - }, function(error, event) { - if (error.data.fault_code === 'AccessDenied') { - event.preventDefault(); - } - }); + load_db_list: function (force) { + var d = $.when(), self = this; + if (_.isNull(this._db_list) || force) { + d = self.rpc("/web/database/get_list", {}, function(result) { + self._db_list = _.clone(result.db_list); + }, function(error, event) { + if (error.data.fault_code === 'AccessDenied') { + event.preventDefault(); + } + }); + } + return d; }, - set_db_list: function (list) { - this.$element.find("[name=db]").replaceWith(instance.web.qweb.render('Login.dblist', { db_list: list, selected_db: this.selected_db})) + _db_list_loaded: function () { + var list = this._db_list, + dbdiv = this.$element.find('div.oe_login_dbpane'); + this.$element.find("[name=db]").replaceWith(instance.web.qweb.render('Login.dblist', { db_list: list, selected_db: this.selected_db})); + if(list && list.length === 1) { + dbdiv.hide(); + } else { + dbdiv.show(); + } }, on_submit: function(ev) { if(ev) { @@ -513,19 +533,12 @@ instance.web.Login = instance.web.Widget.extend({ do_login: function (db, login, password) { var self = this; this.$element.removeClass('oe_login_invalid'); - this.session.on_session_invalid.add({ - callback: function () { - self.$element.addClass("oe_login_invalid"); - }, - unique: true - }); - this.session.session_authenticate(db, login, password).then(function() { - self.$element.removeClass("oe_login_invalid"); + return this.session.session_authenticate(db, login, password).pipe(function() { if (self.has_local_storage) { if(self.remember_credentials) { localStorage.setItem('last_db_login_success', db); localStorage.setItem('last_login_login_success', login); - if (jQuery.deparam(jQuery.param.querystring()).debug != undefined) { + if (jQuery.deparam(jQuery.param.querystring()).debug !== undefined) { localStorage.setItem('last_password_login_success', password); } } else { @@ -534,6 +547,10 @@ instance.web.Login = instance.web.Widget.extend({ localStorage.setItem('last_password_login_success', ''); } } + self.$(".oe_login_pane").fadeOut("slow"); + self.trigger("login"); + },function () { + self.$element.addClass("oe_login_invalid"); }); } }); @@ -544,34 +561,33 @@ instance.web.Menu = instance.web.Widget.extend({ this._super.apply(this, arguments); this.has_been_loaded = $.Deferred(); this.maximum_visible_links = 'auto'; // # of menu to show. 0 = do not crop, 'auto' = algo + this.data = {data:{children:[]}}; }, start: function() { this._super.apply(this, arguments); this.$secondary_menus = this.getParent().$element.find('.oe_secondary_menus_container'); - this.$secondary_menus.on('click', 'a[data-menu]', this.on_menu_click); - $('html').bind('click', this.do_hide_more); + return this.do_reload(); }, do_reload: function() { - var self = this; - return this.rpc("/web/menu/load", {}, this.on_loaded).then(function () { - if (self.current_menu) { - self.open_menu(self.current_menu); - } - }); + return this.rpc("/web/menu/load", {}).then(this.on_loaded); }, on_loaded: function(data) { var self = this; this.data = data; this.renderElement(); this.limit_entries(); - this.$element.on('click', 'a[data-menu]', this.on_menu_click); + this.$secondary_menus.html(QWeb.render("Menu.secondary", { widget : this })); this.$element.on('click', 'a.oe_menu_more_link', function() { self.$element.find('.oe_menu_more').toggle(); return false; }); - this.$secondary_menus.html(QWeb.render("Menu.secondary", { widget : this })); + this.$element.on('click', 'a[data-menu]', this.on_menu_click); + this.$secondary_menus.on('click', 'a[data-menu]', this.on_menu_click); // Hide second level submenus this.$secondary_menus.find('.oe_menu_toggler').siblings('.oe_secondary_submenu').hide(); + if (self.current_menu) { + self.open_menu(self.current_menu); + } this.has_been_loaded.resolve(); }, limit_entries: function() { @@ -585,6 +601,7 @@ instance.web.Menu = instance.web.Widget.extend({ $index.after($more); $more.find('.oe_menu_more').append($index.next().nextAll()); } + this.do_hide_more(); }, auto_limit_entries: function() { // TODO: auto detect overflow and bind window on resize @@ -603,6 +620,7 @@ instance.web.Menu = instance.web.Widget.extend({ open_menu: function (id) { var $clicked_menu, $sub_menu, $main_menu; $clicked_menu = this.$element.add(this.$secondary_menus).find('a[data-menu=' + id + ']'); + this.trigger('open_menu', id, $clicked_menu); if (this.$secondary_menus.has($clicked_menu).length) { $sub_menu = $clicked_menu.parents('.oe_secondary_menu'); @@ -620,6 +638,9 @@ instance.web.Menu = instance.web.Widget.extend({ this.$secondary_menus.find('.oe_secondary_menu').hide(); $sub_menu.show(); + // Hide/Show the leftbar menu depending of the presence of sub-items + this.$secondary_menus.parent('.oe_leftbar').toggle(!!$sub_menu.children().length); + // Activate current menu item and show parents this.$secondary_menus.find('.oe_active').removeClass('oe_active'); if ($main_menu !== $clicked_menu) { @@ -631,56 +652,61 @@ instance.web.Menu = instance.web.Widget.extend({ } } }, + /** + * Call open_menu with the first menu_item matching an action_id + * + * @param {Number} id the action_id to match + */ open_action: function (id) { - var menu_id, $menu = this.$element.add(this.$secondary_menus).find('a[data-action-id=' + id + ']'); - if (menu_id = $menu.data('menu')) { + var $menu = this.$element.add(this.$secondary_menus).find('a[data-action-id=' + id + ']'); + var menu_id = $menu.data('menu'); + if (menu_id) { this.open_menu(menu_id); } }, - on_menu_click: function(ev, id) { - // TODO If first level menu doesnt have action trigger first leaf - this.do_hide_more(); - id = id || 0; - var $clicked_menu, manual = false; - + /** + * Process a click on a menu item + * + * @param {Number} id the menu_id + */ + menu_click: function(id) { if (id) { - // We can manually activate a menu with it's id (for hash url mapping) - manual = true; - $clicked_menu = this.$element.find('a[data-menu=' + id + ']'); - if (!$clicked_menu.length) { - $clicked_menu = this.$secondary_menus.find('a[data-menu=' + id + ']'); + this.do_hide_more(); + // find back the menuitem in dom to get the action + var $item = this.$element.find('a[data-menu=' + id + ']'); + if (!$item.length) { + $item = this.$secondary_menus.find('a[data-menu=' + id + ']'); + } + var action_id = $item.data('action-id'); + // If first level menu doesnt have action trigger first leaf + if (!action_id) { + if(this.$element.has($item).length) { + $sub_menu = this.$secondary_menus.find('.oe_secondary_menu[data-menu-parent=' + id + ']'); + $items = $sub_menu.find('a[data-action-id]').filter('[data-action-id!=""]'); + if($items.length) { + action_id = $items.data('action-id'); + id = $items.data('menu'); + } + } } - } else { - $clicked_menu = $(ev.currentTarget); - id = $clicked_menu.data('menu'); - } - - this.trigger('menuClicked', id, $clicked_menu); - - if (id) { this.open_menu(id); this.current_menu = id; this.session.active_id = id; - var action_id = $clicked_menu.data('action-id'); if (action_id) { - this.on_action(action_id); + this.trigger('menu_click', action_id, id, $item); } } - if (ev) { - ev.stopPropagation(); - } + }, + /** + * Jquery event handler for menu click + * + * @param {Event} ev the jquery event + */ + on_menu_click: function(ev) { + this.menu_click($(ev.currentTarget).data('menu')); + ev.stopPropagation(); return false; }, - do_show_secondary: function($sub_menu, $main_menu) { - var self = this; - this.$secondary_menus.show(); - if (!arguments.length) { - return; - } - $sub_menu.show(); - }, - on_action: function(action) { - } }); instance.web.UserMenu = instance.web.Widget.extend({ @@ -701,7 +727,9 @@ instance.web.UserMenu = instance.web.Widget.extend({ }); this.$element.on('click', '.oe_dropdown_options li a[data-menu]', function() { var f = self['on_menu_' + $(this).data('menu')]; - f && f($(this)); + if (f) { + f($(this)); + } self.$element.find('.oe_dropdown_options').hide(); return false; }); @@ -712,7 +740,7 @@ instance.web.UserMenu = instance.web.Widget.extend({ title: _t("Change Password"), width : 'auto' }).open(); - this.dialog.$element.html(QWeb.render("Change_Pwd", self)); + this.dialog.$element.html(QWeb.render("UserMenu.password", self)); this.dialog.$element.find("form[name=change_password_form]").validate({ submitHandler: function (form) { self.rpc("/web/session/change_password",{ @@ -746,64 +774,20 @@ instance.web.UserMenu = instance.web.Widget.extend({ return; var func = new instance.web.Model("res.users").get_func("read"); return func(self.session.uid, ["name", "company_id"]).pipe(function(res) { - // TODO: Show company if multicompany is in use - var topbar_name = _.str.sprintf("%s (%s)", res.name, instance.connection.db, res.company_id[1]); + var topbar_name = res.name; + if(instance.connection.debug) + topbar_name = _.str.sprintf("%s (%s)", topbar_name, instance.connection.db); + if(res.company_id[0] > 1) + topbar_name = _.str.sprintf("%s (%s)", topbar_name, res.company_id[1]); self.$element.find('.oe_topbar_name').text(topbar_name); var avatar_src = _.str.sprintf('%s/web/binary/image?session_id=%s&model=res.users&field=avatar&id=%s', self.session.prefix, self.session.session_id, self.session.uid); $avatar.attr('src', avatar_src); - return self.shortcut_load(); }); }; this.update_promise = this.update_promise.pipe(fct, fct); }, on_action: function() { }, - shortcut_load :function(){ - var self = this, - sc = self.session.shortcuts, - shortcuts_ds = new instance.web.DataSet(this, 'ir.ui.view_sc'); - self.$element.find('.oe_dropdown_options a[data-menu=shortcut]').each(function() { - $(this).parent().remove(); - }); - // TODO: better way to communicate between sections. - // sc.bindings, because jquery does not bind/trigger on arrays... - if (!sc.binding) { - sc.binding = {}; - $(sc.binding).bind({ - 'add': function (e, attrs) { - shortcuts_ds.create(attrs, function (out) { - var shortcut = QWeb.render('UserMenu.shortcut', { - shortcuts : [{ - name : attrs.name, - id : out.result, - res_id : attrs.res_id - }] - }); - $(shortcut).appendTo(self.$element.find('.oe_dropdown_options')); - attrs.id = out.result; - sc.push(attrs); - }); - }, - 'remove-current': function () { - var menu_id = self.session.active_id; - var $shortcut = self.$element.find('.oe_dropdown_options li a[data-id=' + menu_id + ']'); - var shortcut_id = $shortcut.data('shortcut-id'); - $shortcut.remove(); - shortcuts_ds.unlink([shortcut_id]); - var sc_new = _.reject(sc, function(shortcut){ return shortcut_id === shortcut.id}); - sc.splice(0, sc.length); - sc.push.apply(sc, sc_new); - } - }); - } - return this.rpc('/web/session/sc_list', {}, function(shortcuts) { - sc.splice(0, sc.length); - sc.push.apply(sc, shortcuts); - - $(QWeb.render('UserMenu.shortcut', {'shortcuts': shortcuts})) - .appendTo(self.$element.find('.oe_dropdown_options')); - }); - }, on_menu_logout: function() { }, on_menu_settings: function() { @@ -830,8 +814,8 @@ instance.web.UserMenu = instance.web.Widget.extend({ title: _t("Preferences"), width: '700px', buttons: [ - {text: _t("Cancel"), click: function(){ $(this).dialog('destroy'); }}, {text: _t("Change password"), click: function(){ self.change_password(); }}, + {text: _t("Cancel"), click: function(){ $(this).dialog('destroy'); }}, {text: _t("Save"), click: function(){ var inner_viewmanager = action_manager.inner_viewmanager; inner_viewmanager.views[inner_viewmanager.active_view].controller.do_save() @@ -850,7 +834,7 @@ instance.web.UserMenu = instance.web.Widget.extend({ on_menu_about: function() { var self = this; self.rpc("/web/webclient/version_info", {}).then(function(res) { - var $help = $(QWeb.render("About-Page", {version_info: res})); + var $help = $(QWeb.render("UserMenu.about", {version_info: res})); $help.find('a.oe_activate_debug_mode').click(function (e) { e.preventDefault(); window.location = $.param.querystring( @@ -860,16 +844,6 @@ instance.web.UserMenu = instance.web.Widget.extend({ modal: true, width: 960, title: _t("About")}); }); }, - on_menu_shortcut: function($link) { - var self = this, - id = $link.data('id'); - self.session.active_id = id; - self.rpc('/web/menu/action', {'menu_id': id}, function(ir_menu_data) { - if (ir_menu_data.action.length){ - self.on_action(ir_menu_data.action[0][2]); - } - }); - } }); instance.web.WebClient = instance.web.Widget.extend({ @@ -883,75 +857,68 @@ instance.web.WebClient = instance.web.Widget.extend({ start: function() { var self = this; this.$element.addClass("openerp openerp-web-client-container"); - 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) { + if (jQuery.param !== undefined && jQuery.deparam(jQuery.param.querystring()).kitten !== undefined) { + $("body").addClass("kitten-mode-activated"); + self.$element.delegate('img.oe-record-edit-link-img', 'hover', function(e) { self.$element.toggleClass('clark-gable'); }); } this.session.session_bind().then(function() { + self.destroy_content(); + self.show_common(); if (!self.session.session_is_valid()) { self.show_login(); - } - }); - this.session.on_session_valid.add(function() { - self.show_application(); - - self.user_menu.do_update(); - self.menu.do_reload(); - if(self.action_manager) - self.action_manager.destroy(); - self.action_manager = new instance.web.ActionManager(self); - self.action_manager.appendTo(self.$element.find('.oe_application')); - self.bind_hashchange(); - var version_label = _t("OpenERP - Unsupported/Community Version"); - if (!self.session.openerp_entreprise) { - self.$element.find('.oe_footer_powered').append(_.str.sprintf(' - %s', version_label)); - document.title = version_label; + } else { + self.show_application(); } }); this.$element.on('mouseenter', '.oe_systray > div:not([data-tipsy=true])', function() { $(this).attr('data-tipsy', 'true').tipsy().trigger('mouseenter'); }); }, + show_common: function() { + var self = this; + this.crashmanager = new instance.web.CrashManager(); + instance.connection.on_rpc_error.add(this.crashmanager.on_rpc_error); + window.onerror = function (message, file, line) { + self.crashmanager.on_traceback({ + type: _t("Client Error"), + message: message, + data: {debug: file + ':' + line} + }); + }; + self.notification = new instance.web.Notification(this); + self.notification.appendTo(self.$element); + self.loading = new instance.web.Loading(self); + self.loading.appendTo(self.$element); + self.login = new instance.web.Login(self); + self.login.on("login",self,self.show_application); + self.$table = $(QWeb.render("WebClient", {})); + self.action_manager = new instance.web.ActionManager(self); + self.action_manager.appendTo(self.$table.find('.oe_application')); + }, show_login: function() { var self = this; - this.destroy_content(); - this.show_common(); - self.login = new instance.web.Login(self); self.login.appendTo(self.$element); }, show_application: function() { var self = this; - this.destroy_content(); - this.show_common(); - self.$table = $(QWeb.render("WebClient", {})); self.$element.append(self.$table); + self.login.$element.hide(); self.menu = new instance.web.Menu(self); self.menu.replace(this.$element.find('.oe_menu_placeholder')); - self.menu.on_action.add(this.proxy('on_menu_action')); + self.menu.on('menu_click', this, this.on_menu_action); self.user_menu = new instance.web.UserMenu(self); self.user_menu.replace(this.$element.find('.oe_user_menu_placeholder')); self.user_menu.on_menu_logout.add(this.proxy('on_logout')); self.user_menu.on_action.add(this.proxy('on_menu_action')); - }, - show_common: function() { - var self = this; - if (!this.crashmanager) { - this.crashmanager = new instance.web.CrashManager(); - instance.connection.on_rpc_error.add(this.crashmanager.on_rpc_error); - window.onerror = function (message, file, line) { - self.crashmanager.on_traceback({ - type: _t("Client Error"), - message: message, - data: {debug: file + ':' + line} - }); - } + self.user_menu.do_update(); + self.bind_hashchange(); + var version_label = _t("OpenERP - Unsupported/Community Version"); + if (!self.session.openerp_entreprise) { + self.$element.find('.oe_footer_powered').append(_.str.sprintf(' - %s', version_label)); + document.title = version_label; } - this.notification = new instance.web.Notification(this); - this.notification.appendTo(this.$element); - this.loading = new instance.web.Loading(this); - this.loading.appendTo(this.$element); }, destroy_content: function() { _.each(_.clone(this.getChildren()), function(el) { @@ -994,15 +961,25 @@ instance.web.WebClient = instance.web.Widget.extend({ } else { self.menu.has_been_loaded.then(function() { var first_menu_id = self.menu.$element.find("a:first").data("menu"); - if(first_menu_id) - self.menu.on_menu_click(null,first_menu_id); + if(first_menu_id) { + self.menu.menu_click(first_menu_id); + } }); } }, on_hashchange: function(event) { + var self = this; var state = event.getState(true); if (!_.isEqual(this._current_state, state)) { - this.action_manager.do_load_state(state, !!this._current_state); + if(state.action_id === undefined && state.menu_id) { + self.menu.has_been_loaded.then(function() { + self.menu.do_reload().then(function() { + self.menu.menu_click(state.menu_id) + }); + }); + } else { + this.action_manager.do_load_state(state, !!this._current_state); + } } this._current_state = state; }, @@ -1016,10 +993,10 @@ instance.web.WebClient = instance.web.Widget.extend({ }, do_action: function(action) { var self = this; - // TODO replace by client action menuclick + // TODO replace by client action menuclick if(action.menu_id) { this.do_reload().then(function () { - self.menu.on_menu_click(null, action.menu_id); + self.menu.menu_click(action.menu_id); }); } }, @@ -1035,7 +1012,7 @@ instance.web.EmbeddedClient = instance.web.Widget.extend({ template: 'EmptyComponent', init: function(parent, action_id, options) { this._super(parent); - // TODO take the xmlid of a action instead of its id + // TODO take the xmlid of a action instead of its id this.action_id = action_id; this.options = options || {}; this.am = new instance.web.ActionManager(this); @@ -1076,7 +1053,7 @@ instance.web.embed = function (origin, dbname, login, key, action, options) { }); }); -} +}; }; diff --git a/addons/web/static/src/js/corelib.js b/addons/web/static/src/js/corelib.js index b30350a9502..94c748f839c 100644 --- a/addons/web/static/src/js/corelib.js +++ b/addons/web/static/src/js/corelib.js @@ -331,6 +331,9 @@ instance.web.EventDispatcherMixin = _.extend({}, instance.web.ParentedMixin, { }, on: function(events, dest, func) { var self = this; + if (!(func instanceof Function)) { + throw new Error("Event handler must be a function."); + } events = events.split(/\s+/); _.each(events, function(eventName) { self.__edispatcherEvents.on(eventName, func, dest); @@ -709,6 +712,12 @@ instance.web.Widget = instance.web.Class.extend(instance.web.WidgetMixin, { this.$element = elem; } }, + /** + * Shortcut for $element.find() like backbone + */ + "$": function() { + return this.$element.find.apply(this.$element,arguments); + }, /** * Informs the action manager to do an action. This supposes that * the action manager can be found amongst the ancestors of the current widget. @@ -1341,6 +1350,9 @@ instance.web.JsonRPC = instance.web.CallbackEnabled.extend({ }, on_rpc_error: function(error) { }, + get_url: function (file) { + return this.prefix + file; + }, }); } diff --git a/addons/web/static/src/js/coresetup.js b/addons/web/static/src/js/coresetup.js index 8f5f150f125..4defde54a3c 100644 --- a/addons/web/static/src/js/coresetup.js +++ b/addons/web/static/src/js/coresetup.js @@ -69,7 +69,6 @@ instance.web.Session = instance.web.JsonRPC.extend( /** @lends instance.web.Sess self.module_loaded[mod] = true; }); this.context = {}; - this.shortcuts = []; this.active_id = null; return this.session_init(); }, @@ -122,6 +121,10 @@ instance.web.Session = instance.web.JsonRPC.extend( /** @lends instance.web.Sess 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) { + if (!result.uid) { + return $.Deferred().reject(); + } + _.extend(self, { session_id: result.session_id, db: result.db, @@ -285,9 +288,6 @@ instance.web.Session = instance.web.JsonRPC.extend( /** @lends instance.web.Sess } } }, - get_url: function (file) { - return this.prefix + file; - }, /** * Cooperative file download implementation, for ajaxy APIs. * @@ -580,6 +580,33 @@ $.async_when = function() { return old_async_when.apply(this, arguments); }; +/** + * Registry for all the client actions key: tag value: widget + */ +instance.web.client_actions = new instance.web.Registry(); + +/** + * Client action to reload the whole interface. + * If params has an entry 'menu_id', it opens the given menu entry. + */ +instance.web.client_actions.add("reload", "instance.web.Reload"); + +instance.web.Reload = instance.web.Widget.extend({ + init: function(parent, params) { + this._super(parent); + this.menu_id = (params && params.menu_id) || false; + }, + start: function() { + if (this.menu_id) { + // open the given menu id + var url_without_fragment = window.location.toString().split("#", 1)[0]; + window.location = url_without_fragment + "#menu_id=" + this.menu_id; + } else { + window.location.reload(); + } + } +}); + }; // vim:et fdc=0 fdl=0 foldnestmax=3 fdm=syntax: diff --git a/addons/web/static/src/js/data.js b/addons/web/static/src/js/data.js index 2dc66aaa135..fdb15d598af 100644 --- a/addons/web/static/src/js/data.js +++ b/addons/web/static/src/js/data.js @@ -1079,44 +1079,44 @@ instance.web.ProxyDataSet = instance.web.DataSetSearch.extend({ this.create_function = null; this.write_function = null; this.read_function = null; + this.default_get_function = null; + this.unlink_function = null; }, - read_ids: function () { + read_ids: function (ids, fields, options) { if (this.read_function) { - return this.read_function.apply(null, arguments); + return this.read_function(ids, fields, options, this._super); } else { return this._super.apply(this, arguments); } }, default_get: function(fields, options) { - return this._super(fields, options).then(this.on_default_get); + if (this.default_get_function) { + return this.default_get_function(fields, options, this._super); + } else { + return this._super.apply(this, arguments); + } }, - on_default_get: function(result) {}, create: function(data, callback, error_callback) { - this.on_create(data); if (this.create_function) { - return this.create_function(data, callback, error_callback); + return this.create_function(data, this._super).then(callback, error_callback); } else { - console.warn("trying to create a record using default proxy dataset behavior"); - return $.async_when({"result": undefined}).then(callback); + return this._super.apply(this, arguments); } }, - on_create: function(data) {}, - write: function (id, data, options, callback) { - this.on_write(id, data); + write: function (id, data, options, callback, error_callback) { if (this.write_function) { - return this.write_function(id, data, options, callback); + return this.write_function(id, data, options, this._super).then(callback, error_callback); } else { - console.warn("trying to write a record using default proxy dataset behavior"); - return $.async_when({"result": true}).then(callback); + return this._super.apply(this, arguments); } }, - on_write: function(id, data) {}, unlink: function(ids, callback, error_callback) { - this.on_unlink(ids); - console.warn("trying to unlink a record using default proxy dataset behavior"); - return $.async_when({"result": true}).then(callback); + if (this.unlink_function) { + return this.unlink_function(ids, this._super).then(callback, error_callback); + } else { + return this._super.apply(this, arguments); + } }, - on_unlink: function(ids) {} }); instance.web.CompoundContext = instance.web.Class.extend({ diff --git a/addons/web/static/src/js/formats.js b/addons/web/static/src/js/formats.js index 640ba4d5a93..2b527686ddd 100644 --- a/addons/web/static/src/js/formats.js +++ b/addons/web/static/src/js/formats.js @@ -111,7 +111,7 @@ instance.web.format_value = function (value, descriptor, value_if_empty) { return value_if_empty === undefined ? '' : value_if_empty; } var l10n = _t.database.parameters; - switch (descriptor.type || (descriptor.field && descriptor.field.type)) { + switch (descriptor.widget || descriptor.type || (descriptor.field && descriptor.field.type)) { case 'id': return value.toString(); case 'integer': @@ -171,7 +171,7 @@ instance.web.parse_value = function (value, descriptor, value_if_empty) { case "": return value_if_empty === undefined ? false : value_if_empty; } - switch (descriptor.type || (descriptor.field && descriptor.field.type)) { + switch (descriptor.widget || descriptor.type || (descriptor.field && descriptor.field.type)) { case 'integer': var tmp; do { diff --git a/addons/web/static/src/js/search.js b/addons/web/static/src/js/search.js index c2df866b5c6..c70cf2ab470 100644 --- a/addons/web/static/src/js/search.js +++ b/addons/web/static/src/js/search.js @@ -6,67 +6,269 @@ _.mixin({ sum: function (obj) { return _.reduce(obj, function (a, b) { return a + b; }, 0); } }); -// Have SearchBox optionally use callback function to produce inputs and facets -// (views) set on callbacks.make_facet and callbacks.make_input keys when -// initializing VisualSearch -var SearchBox_renderFacet = function (facet, position) { - var view = new (this.app.options.callbacks['make_facet'] || VS.ui.SearchFacet)({ - app : this.app, - model : facet, - order : position - }); +/** @namespace */ +var my = instance.web.search = {}; - // Input first, facet second. - this.renderSearchInput(); - this.facetViews.push(view); - this.$('.VS-search-inner').children().eq(position*2).after(view.render().el); +var B = Backbone; +my.FacetValue = B.Model.extend({ - view.calculateSize(); - _.defer(_.bind(view.calculateSize, view)); - - return view; - }; // warning: will not match -// Ensure we're replacing the function we think -if (SearchBox_renderFacet.toString() !== VS.ui.SearchBox.prototype.renderFacet.toString().replace(/(VS\.ui\.SearchFacet)/, "(this.app.options.callbacks['make_facet'] || $1)")) { - throw new Error( - "Trying to replace wrong version of VS.ui.SearchBox#renderFacet. " - + "Please fix replacement."); -} -var SearchBox_renderSearchInput = function () { - var input = new (this.app.options.callbacks['make_input'] || VS.ui.SearchInput)({position: this.inputViews.length, app: this.app}); - this.$('.VS-search-inner').append(input.render().el); - this.inputViews.push(input); - }; -// Ensure we're replacing the function we think -if (SearchBox_renderSearchInput.toString() !== VS.ui.SearchBox.prototype.renderSearchInput.toString().replace(/(VS\.ui\.SearchInput)/, "(this.app.options.callbacks['make_input'] || $1)")) { - throw new Error( - "Trying to replace wrong version of VS.ui.SearchBox#renderSearchInput. " - + "Please fix replacement."); -} -var SearchBox_searchEvent = function (e) { - var query = null; - this.renderFacets(); - this.focusSearch(e); - this.app.options.callbacks.search(query, this.app.searchQuery); - }; -if (SearchBox_searchEvent.toString() !== VS.ui.SearchBox.prototype.searchEvent.toString().replace( - /this\.value\(\);\n[ ]{4}this\.focusSearch\(e\);\n[ ]{4}this\.value\(query\)/, - 'null;\n this.renderFacets();\n this.focusSearch(e)')) { - throw new Error( - "Trying to replace wrong version of VS.ui.SearchBox#searchEvent. " - + "Please fix replacement."); -} -_.extend(VS.ui.SearchBox.prototype, { - renderFacet: SearchBox_renderFacet, - renderSearchInput: SearchBox_renderSearchInput, - searchEvent: SearchBox_searchEvent }); -_.extend(VS.model.SearchFacet.prototype, { - value: function () { - if (this.has('json')) { - return this.get('json'); +my.FacetValues = B.Collection.extend({ + model: my.FacetValue +}); +my.Facet = B.Model.extend({ + initialize: function (attrs) { + var values = attrs.values; + delete attrs.values; + + B.Model.prototype.initialize.apply(this, arguments); + + this.values = new my.FacetValues(values || []); + this.values.on('add remove change reset', function () { + this.trigger('change', this); + }, this); + }, + get: function (key) { + if (key !== 'values') { + return B.Model.prototype.get.call(this, key); } - return this.get('value'); + return this.values.toJSON(); + }, + set: function (key, value) { + if (key !== 'values') { + return B.Model.prototype.set.call(this, key, value); + } + this.values.reset(value); + }, + toJSON: function () { + var out = {}; + var attrs = this.attributes; + for(var att in attrs) { + if (!attrs.hasOwnProperty(att) || att === 'field') { + continue; + } + out[att] = attrs[att]; + } + out.values = this.values.toJSON(); + return out; + } +}); +my.SearchQuery = B.Collection.extend({ + model: my.Facet, + initialize: function () { + B.Collection.prototype.initialize.apply( + this, arguments); + this.on('change', function (facet) { + if(!facet.values.isEmpty()) { return; } + + this.remove(facet); + }, this); + }, + add: function (values, options) { + options || (options = {}); + if (!(values instanceof Array)) { + values = [values]; + } + + _(values).each(function (value) { + var model = this._prepareModel(value, options); + var previous = this.detect(function (facet) { + return facet.get('category') === model.get('category') + && facet.get('field') === model.get('field'); + }); + if (previous) { + previous.values.add(model.get('values')); + return; + } + B.Collection.prototype.add.call(this, model, options); + }, this); + return this; + }, + toggle: function (value, options) { + options || (options = {}); + + var facet = this.detect(function (facet) { + return facet.get('category') === value.category + && facet.get('field') === value.field; + }); + if (!facet) { + return this.add(value, options); + } + + var changed = false; + _(value.values).each(function (val) { + var already_value = facet.values.detect(function (v) { + return v.get('value') === val.value + && v.get('label') === val.label; + }); + // toggle value + if (already_value) { + facet.values.remove(already_value, {silent: true}); + } else { + facet.values.add(val, {silent: true}); + } + changed = true; + }); + // "Commit" changes to values array as a single call, so observers of + // change event don't get misled by intermediate incomplete toggling + // states + facet.trigger('change', facet); + return this; + } +}); + +function assert(condition, message) { + if(!condition) { + throw new Error(message); + } +} +my.InputView = instance.web.Widget.extend({ + template: 'SearchView.InputView', + start: function () { + var p = this._super.apply(this, arguments); + this.$element.on('focus', this.proxy('onFocus')); + this.$element.on('blur', this.proxy('onBlur')); + this.$element.on('keydown', this.proxy('onKeydown')); + return p; + }, + onFocus: function () { + this.trigger('focused', this); + }, + onBlur: function () { + this.$element.text(''); + this.trigger('blurred', this); + }, + getSelection: function () { + // get Text node + var root = this.$element[0].childNodes[0]; + if (!root || !root.textContent) { + // if input does not have a child node, or the child node is an + // empty string, then the selection can only be (0, 0) + return {start: 0, end: 0}; + } + if (window.getSelection) { + var domRange = window.getSelection().getRangeAt(0); + assert(domRange.startContainer === root, + "selection should be in the input view"); + assert(domRange.endContainer === root, + "selection should be in the input view"); + return { + start: domRange.startOffset, + end: domRange.endOffset + } + } else if (document.selection) { + var ieRange = document.selection.createRange(); + var rangeParent = ieRange.parentElement(); + assert(rangeParent === root, + "selection should be in the input view"); + var offsetRange = document.body.createTextRange(); + offsetRange = offsetRange.moveToElementText(rangeParent); + offsetRange.setEndPoint("EndToStart", ieRange); + var start = offsetRange.text.length; + return { + start: start, + end: start + ieRange.text.length + } + } + throw new Error("Could not get caret position"); + }, + onKeydown: function (e) { + var sel; + switch (e.which) { + // Do not insert newline, but let it bubble so searchview can use it + case $.ui.keyCode.ENTER: + e.preventDefault(); + break; + + // FIXME: may forget content if non-empty but caret at index 0, ok? + case $.ui.keyCode.BACKSPACE: + sel = this.getSelection(); + if (sel.start === 0 && sel.start === sel.end) { + e.preventDefault(); + var preceding = this.getParent().siblingSubview(this, -1); + if (preceding && (preceding instanceof my.FacetView)) { + preceding.model.destroy(); + } + } + break; + + // let left/right events propagate to view if caret is at input border + // and not a selection + case $.ui.keyCode.LEFT: + sel = this.getSelection(); + if (sel.start !== 0 || sel.start !== sel.end) { + e.stopPropagation(); + } + break; + case $.ui.keyCode.RIGHT: + sel = this.getSelection(); + var len = this.$element.text().length; + if (sel.start !== len || sel.start !== sel.end) { + e.stopPropagation(); + } + break; + } + } +}); +my.FacetView = instance.web.Widget.extend({ + template: 'SearchView.FacetView', + init: function (parent, model) { + this._super(parent); + this.model = model; + this.model.on('change', this.model_changed, this); + }, + destroy: function () { + this.model.off('change', this.model_changed, this); + this._super(); + }, + start: function () { + var self = this; + this.$element.on('focus', function () { self.trigger('focused', self); }); + this.$element.on('blur', function () { self.trigger('blurred', self); }); + this.$element.on('click', function (e) { + if ($(e.target).is('.oe_facet_remove')) { + self.model.destroy(); + return false; + } + self.$element.focus(); + e.stopPropagation(); + }); + this.$element.on('keydown', function (e) { + var keys = $.ui.keyCode; + switch (e.which) { + case keys.BACKSPACE: + case keys.DELETE: + self.model.destroy(); + return false; + } + }); + var $e = self.$element.find('> span:last-child'); + var q = $.when(this._super()); + return q.pipe(function () { + var values = self.model.values.map(function (value) { + return new my.FacetValueView(self, value).appendTo($e); + }); + + return $.when.apply(null, values); + }); + }, + model_changed: function () { + this.$element.text(this.$element.text() + '*'); + } +}); +my.FacetValueView = instance.web.Widget.extend({ + template: 'SearchView.FacetView.Value', + init: function (parent, model) { + this._super(parent); + this.model = model; + this.model.on('change', this.model_changed, this); + }, + destroy: function () { + this.model.off('change', this.model_changed, this); + this._super(); + }, + model_changed: function () { + this.$element.text(this.$element.text() + '*'); } }); @@ -74,13 +276,13 @@ instance.web.SearchView = instance.web.Widget.extend(/** @lends instance.web.Sea template: "SearchView", /** * @constructs instance.web.SearchView - * @extends instance.web.OldWidget + * @extends instance.web.Widget * * @param parent - * @param element_id * @param dataset * @param view_id * @param defaults + * @param hidden */ init: function(parent, dataset, view_id, defaults, hidden) { this._super(parent); @@ -97,7 +299,7 @@ instance.web.SearchView = instance.web.Widget.extend(/** @lends instance.web.Sea this.hidden = !!hidden; this.headless = this.hidden && !this.has_defaults; - this.filter_data = {}; + this.input_subviews = []; this.ready = $.Deferred(); }, @@ -106,33 +308,9 @@ instance.web.SearchView = instance.web.Widget.extend(/** @lends instance.web.Sea var p = this._super(); this.setup_global_completion(); - this.vs = VS.init({ - container: this.$element, - query: '', - callbacks: { - make_facet: this.proxy('make_visualsearch_facet'), - make_input: this.proxy('make_visualsearch_input'), - search: function (query, searchCollection) { - self.do_search(); - }, - facetMatches: function (callback) { - }, - valueMatches : function(facet, searchTerm, callback) { - } - } - }); - - var search = function () { self.vs.searchBox.searchEvent({}); }; - // searchQuery operations - this.vs.searchQuery - .off('add').on('add', search) - .off('change').on('change', search) - .off('reset').on('reset', search) - .off('remove').on('remove', function (record, collection, options) { - if (options['trigger_search']) { - search(); - } - }); + this.query = new my.SearchQuery() + .on('add change reset remove', this.proxy('do_search')) + .on('add change reset remove', this.proxy('renderFacets')); if (this.hidden) { this.$element.hide(); @@ -144,19 +322,52 @@ instance.web.SearchView = instance.web.Widget.extend(/** @lends instance.web.Sea model: this.model, view_id: this.view_id, context: this.dataset.get_context() }); - // FIXME: local eval of domain and context to get rid of special endpoint - var filters = this.rpc('/web/searchview/get_filters', { - model: this.model - }).then(function (filters) { self.custom_filters = filters; }); - $.when(load_view, filters) - .pipe(function (load) { return load[0]; }) - .then(this.on_loaded); + $.when(load_view) + .pipe(this.on_loaded) + .fail(function () { + self.ready.reject.apply(null, arguments); + }); } - this.$element.on('click', '.oe_vs_unfold_drawer', function () { + this.$element.on('keydown', + '.oe_searchview_input, .oe_searchview_facet', function (e) { + switch(e.which) { + case $.ui.keyCode.LEFT: + self.focusPreceding(this); + e.preventDefault(); + break; + case $.ui.keyCode.RIGHT: + self.focusFollowing(this); + e.preventDefault(); + break; + } + }); + + this.$element.on('click', '.oe_searchview_clear', function (e) { + e.stopImmediatePropagation(); + self.query.reset(); + }); + this.$element.on('click', '.oe_searchview_unfold_drawer', function (e) { + e.stopImmediatePropagation(); self.$element.toggleClass('oe_searchview_open_drawer'); }); + // Focus last input if the view itself is clicked (empty section of + // facets element) + this.$element.on('click', function (e) { + if (e.target === self.$element.find('.oe_searchview_facets')[0]) { + self.$element.find('.oe_searchview_input:last').focus(); + } + }); + // when the completion list opens/refreshes, automatically select the + // first completion item so if the user just hits [RETURN] or [TAB] it + // automatically selects it + this.$element.on('autocompleteopen', function () { + var menu = self.$element.data('autocomplete').menu; + menu.activate( + $.Event({ type: "mouseenter" }), + menu.element.children().first()); + }); return $.when(p, this.ready); }, @@ -167,81 +378,57 @@ instance.web.SearchView = instance.web.Widget.extend(/** @lends instance.web.Sea this.$element.hide(); }, + subviewForRoot: function (subview_root) { + return _(this.input_subviews).detect(function (subview) { + return subview.$element[0] === subview_root; + }); + }, + siblingSubview: function (subview, direction, wrap_around) { + var index = _(this.input_subviews).indexOf(subview) + direction; + if (wrap_around && index < 0) { + index = this.input_subviews.length - 1; + } else if (wrap_around && index >= this.input_subviews.length) { + index = 0; + } + return this.input_subviews[index]; + }, + focusPreceding: function (subview_root) { + return this.siblingSubview( + this.subviewForRoot(subview_root), -1, true) + .$element.focus(); + }, + focusFollowing: function (subview_root) { + return this.siblingSubview( + this.subviewForRoot(subview_root), +1, true) + .$element.focus(); + }, + /** * Sets up thingie where all the mess is put? */ - setup_stuff_drawer: function () { - var self = this; - $('
      ').appendTo(this.$element.find('.VS-search-box')); - var $drawer = $('
      ').appendTo(this.$element); - var $filters = $('
      ').appendTo($drawer); - - var running_count = 0; - // get total filters count - var is_group = function (i) { return i instanceof instance.web.search.FilterGroup; }; - var filters_count = _(this.controls).chain() - .flatten() - .filter(is_group) - .map(function (i) { return i.filters.length; }) - .sum() - .value(); - - var col1 = [], col2 = _(this.controls).map(function (inputs, group) { - var filters = _(inputs).filter(is_group); - return { - name: group === 'null' ? _t("Filters") : group, - filters: filters, - length: _(filters).chain().map(function (i) { - return i.filters.length; }).sum().value() - }; + select_for_drawer: function () { + return _(this.inputs).filter(function (input) { + return input.in_drawer(); }); - - while (col2.length) { - // col1 + group should be smaller than col2 + group - if ((running_count + col2[0].length) <= (filters_count - running_count)) { - running_count += col2[0].length; - col1.push(col2.shift()); - } else { - break; - } - } - - // Create a Custom Filter FilterGroup for each custom filter read from - // the db, add all of this as a group in the smallest column - [].push.call(col1.length <= col2.length ? col1 : col2, { - name: _t("Custom Filters"), - filters: _.map(this.custom_filters, function (filter) { - // FIXME: handling of ``disabled`` being set - var f = new instance.web.search.Filter({attrs: { - string: filter.name, - context: filter.context, - domain: filter.domain - }}, self); - return new instance.web.search.FilterGroup([f], self); - }), - length: 3 - }); - - return $.when( - this.render_column(col1, $('
      ').appendTo($filters)), - this.render_column(col2, $('
      ').appendTo($filters)), - (new instance.web.search.Advanced(this).appendTo($drawer))); - }, - render_column: function (column, $el) { - return $.when.apply(null, _(column).map(function (group) { - $('

      ').text(group.name).appendTo($el); - return $.when.apply(null, - _(group.filters).invoke('appendTo', $el)); - })); }, /** * Sets up search view's view-wide auto-completion widget */ setup_global_completion: function () { - // Prevent keydown from within a facet's input from reaching the - // auto-completion widget and opening the completion list - this.$element.on('keydown', '.search_facet input', function (e) { - e.stopImmediatePropagation(); + var self = this; + + // autocomplete only correctly handles being initialized on the actual + // editable element (and only an element with a @value in 1.8 e.g. + // input or textarea), cheat by setting val() on $element + this.$element.on('keydown', function () { + // keydown is triggered *before* the element's value is set, so + // delay this. Pray that setTimeout are executed in FIFO (if they + // have the same delay) as autocomplete uses the exact same trick. + // FIXME: brittle as fuck + setTimeout(function () { + self.$element.val(self.currentInputValue()); + }, 0); + }); this.$element.autocomplete({ @@ -249,7 +436,7 @@ instance.web.SearchView = instance.web.Widget.extend(/** @lends instance.web.Sea select: this.proxy('select_completion'), focus: function (e) { e.preventDefault(); }, html: true, - minLength: 0, + minLength: 1, delay: 0 }).data('autocomplete')._renderItem = function (ul, item) { // item of completion list @@ -257,14 +444,14 @@ instance.web.SearchView = instance.web.Widget.extend(/** @lends instance.web.Sea .data( "item.autocomplete", item ) .appendTo( ul ); - if (item.value !== undefined) { + if (item.facet !== undefined) { // regular completion item return $item.append( (item.label) ? $('').html(item.label) : $('').text(item.value)); } - return $item.text(item.category) + return $item.text(item.label) .css({ borderTop: '1px solid #cccccc', margin: 0, @@ -274,7 +461,14 @@ instance.web.SearchView = instance.web.Widget.extend(/** @lends instance.web.Sea clear: 'left', width: '100%' }); - } + }; + }, + /** + * Gets value out of the currently focused "input" (a + * div[contenteditable].oe_searchview_input) + */ + currentInputValue: function () { + return this.$element.find('div.oe_searchview_input:focus').text(); }, /** * Provide auto-completion result for req.term (an array to `resp`) @@ -301,50 +495,62 @@ instance.web.SearchView = instance.web.Widget.extend(/** @lends instance.web.Sea */ select_completion: function (e, ui) { e.preventDefault(); - this.vs.searchQuery.add(new VS.model.SearchFacet(_.extend( - {app: this.vs}, ui.item))); - this.vs.searchBox.searchEvent({}); + + var input_index = _(this.input_subviews).indexOf( + this.subviewForRoot( + this.$element.find('div.oe_searchview_input:focus')[0])); + this.query.add(ui.item.facet, {at: input_index / 2}); }, - - /** - * Builds the right SearchFacet view based on the facet object to render - * (e.g. readonly facets for filters) - * - * @param {Object} options - * @param {VS.model.SearchFacet} options.model facet object to render - */ - make_visualsearch_facet: function (options) { - return new instance.web.search.FilterGroupFacet(options); - -// if (options.model.get('field') instanceof instance.web.search.FilterGroup) { -// return new instance.web.search.FilterGroupFacet(options); -// } -// return new VS.ui.SearchFacet(options); + childFocused: function () { + this.$element.addClass('oe_focused'); + }, + childBlurred: function () { + this.$element.removeClass('oe_focused'); }, /** - * Proxies searches on a SearchInput to the search view's global completion * - * Also disables SearchInput.autocomplete#_move so search view's - * autocomplete can get the corresponding events, or something. - * - * @param options + * @param {openerp.web.search.SearchQuery | openerp.web.search.Facet} _1 + * @param {openerp.web.search.Facet} [_2] + * @param {Object} [options] */ - make_visualsearch_input: function (options) { - var self = this, input = new VS.ui.SearchInput(options); - input.setupAutocomplete = function () { - _.extend(this.box.autocomplete({ - minLength: 1, - delay: 0, - search: function () { - self.$element.autocomplete('search', input.box.val()); - return false; - } - }).data('autocomplete'), { - _move: function () {}, - close: function () { self.$element.autocomplete('close'); } - }); - }; - return input; + renderFacets: function (_1, _2, options) { + // _1: model if event=change, otherwise collection + // _2: undefined if event=change, otherwise model + var self = this; + var started = []; + var $e = this.$element.find('div.oe_searchview_facets'); + _.invoke(this.input_subviews, 'destroy'); + this.input_subviews = []; + + var i = new my.InputView(this); + started.push(i.appendTo($e)); + this.input_subviews.push(i); + this.query.each(function (facet) { + var f = new my.FacetView(this, facet); + started.push(f.appendTo($e)); + self.input_subviews.push(f); + + var i = new my.InputView(this); + started.push(i.appendTo($e)); + self.input_subviews.push(i); + }, this); + _.each(this.input_subviews, function (childView) { + childView.on('focused', self, self.proxy('childFocused')); + childView.on('blurred', self, self.proxy('childBlurred')); + }); + + $.when.apply(null, started).then(function () { + var input_to_focus; + // options.at: facet inserted at given index, focus next input + // otherwise just focus last input + if (!options || typeof options.at !== 'number') { + input_to_focus = _.last(self.input_subviews); + } else { + input_to_focus = self.input_subviews[(options.at + 1) * 2]; + } + + input_to_focus.$element.focus(); + }); }, /** @@ -423,14 +629,25 @@ instance.web.SearchView = instance.web.Widget.extend(/** @lends instance.web.Sea data.fields_view['arch'].children, data.fields_view.fields); + // add Filters to this.inputs, need view.controls filled + (new instance.web.search.Filters(this)); + // add custom filters to this.inputs + (new instance.web.search.CustomFilters(this)); + // add Advanced to this.inputs + (new instance.web.search.Advanced(this)); + + // build drawer + var drawer_started = $.when.apply( + null, _(this.select_for_drawer()).invoke( + 'appendTo', this.$element.find('.oe_searchview_drawer'))); + // load defaults - return $.when( - this.setup_stuff_drawer(), - $.when.apply(null, _(this.inputs).invoke('facet_for_defaults', this.defaults)) - .then(function () { - self.vs.searchQuery.reset(_(arguments).compact(), {silent: true}); - self.vs.searchBox.renderFacets(); - })) + var defaults_fetched = $.when.apply(null, _(this.inputs).invoke( + 'facet_for_defaults', this.defaults)).then(function () { + self.query.reset(_(arguments).compact(), {preventSearch: true}); + }); + + return $.when(drawer_started, defaults_fetched) .then(function () { self.ready.resolve(); }) }, /** @@ -447,53 +664,6 @@ instance.web.SearchView = instance.web.Widget.extend(/** @lends instance.web.Sea case 'add_to_dashboard': this.on_add_to_dashboard(); break; - case 'manage_filters': - this.do_action({ - res_model: 'ir.filters', - views: [[false, 'list'], [false, 'form']], - type: 'ir.actions.act_window', - context: {"search_default_user_id": this.session.uid, - "search_default_model_id": this.dataset.model}, - target: "current", - limit : 80 - }); - break; - case 'save_filter': - var data = this.build_search_data(); - var context = new instance.web.CompoundContext(); - _.each(data.contexts, function(x) { - context.add(x); - }); - var domain = new instance.web.CompoundDomain(); - _.each(data.domains, function(x) { - domain.add(x); - }); - var groupbys = _.pluck(data.groupbys, "group_by").join(); - context.add({"group_by": groupbys}); - var dial_html = QWeb.render("SearchView.managed-filters.add"); - var $dial = $(dial_html); - instance.web.dialog($dial, { - modal: true, - title: _t("Filter Entry"), - buttons: [ - {text: _t("Cancel"), click: function() { - $(this).dialog("close"); - }}, - {text: _t("OK"), click: function() { - $(this).dialog("close"); - var name = $(this).find("input").val(); - self.rpc('/web/searchview/save_filter', { - model: self.dataset.model, - context_to_save: context, - domain: domain, - name: name - }).then(function() { - self.reload_managed_filters(); - }); - }} - ] - }); - break; case '': this.do_clear(); } @@ -570,20 +740,26 @@ instance.web.SearchView = instance.web.Widget.extend(/** @lends instance.web.Sea }); }, /** - * Performs the search view collection of widget data. + * Extract search data from the view's facets. * - * If the collection went well (all fields are valid), then triggers - * :js:func:`instance.web.SearchView.on_search`. + * Result is an object with 4 (own) properties: * - * If at least one field failed its validation, triggers - * :js:func:`instance.web.SearchView.on_invalid` instead. + * errors + * An array of any error generated during data validation and + * extraction, contains the validation error objects + * domains + * Array of domains + * contexts + * Array of contexts + * groupbys + * Array of domains, in groupby order rather than view order * - * @param e jQuery event object coming from the "Search" button + * @return {Object} */ - do_search: function () { + build_search_data: function () { var domains = [], contexts = [], groupbys = [], errors = []; - this.vs.searchQuery.each(function (facet) { + this.query.each(function (facet) { var field = facet.get('field'); try { var domain = field.get_domain(facet); @@ -606,12 +782,33 @@ instance.web.SearchView = instance.web.Widget.extend(/** @lends instance.web.Sea } } }); - - if (!_.isEmpty(errors)) { - this.on_invalid(errors); + return { + domains: domains, + contexts: contexts, + groupbys: groupbys, + errors: errors + }; + }, /** + * Performs the search view collection of widget data. + * + * If the collection went well (all fields are valid), then triggers + * :js:func:`instance.web.SearchView.on_search`. + * + * If at least one field failed its validation, triggers + * :js:func:`instance.web.SearchView.on_invalid` instead. + * + * @param e jQuery event object coming from the "Search" button + */ + do_search: function (_query, options) { + if (options && options.preventSearch) { return; } - return this.on_search(domains, contexts, groupbys); + var search = this.build_search_data(); + if (!_.isEmpty(search.errors)) { + this.on_invalid(search.errors); + return; + } + return this.on_search(search.domains, search.contexts, search.groupbys); }, /** * Triggered after the SearchView has collected all relevant domains and @@ -647,40 +844,6 @@ instance.web.SearchView = instance.web.Widget.extend(/** @lends instance.web.Sea } }); -/** @namespace */ -instance.web.search = {}; - -instance.web.search.FilterGroupFacet = VS.ui.SearchFacet.extend({ - events: _.extend({ - 'click': 'selectFacet' - }, VS.ui.SearchFacet.prototype.events), - - render: function () { - this.setMode('not', 'editing'); - this.setMode('not', 'selected'); - - var value = this.model.get('value'); - this.$el.html(QWeb.render('SearchView.filters.facet', { - facet: this.model - })); - // virtual input so SearchFacet code has something to play with - this.box = $('').val(value); - - return this; - }, - enableEdit: function () { - this.selectFacet() - }, - keydown: function (e) { - var key = VS.app.hotkeys.key(e); - if (key !== 'right') { - return VS.ui.SearchFacet.prototype.keydown.call(this, e); - } - e.preventDefault(); - this.deselectFacet(); - this.options.app.searchBox.focusNextFacet(this, 1); - } -}); /** * Registry of search fields, called by :js:class:`instance.web.SearchView` to * find and instantiate its field widgets. @@ -756,6 +919,7 @@ instance.web.search.Group = instance.web.search.Widget.extend({ }); instance.web.search.Input = instance.web.search.Widget.extend( /** @lends instance.web.search.Input# */{ + _in_drawer: false, /** * @constructs instance.web.search.Input * @extends instance.web.search.Widget @@ -780,8 +944,8 @@ instance.web.search.Input = instance.web.search.Widget.extend( /** @lends instan return $.when(null) }, /** - * Returns a VS.model.SearchFacet instance for the provided defaults if - * they apply to this widget, or null if they don't. + * Returns a Facet instance for the provided defaults if they apply to + * this widget, or null if they don't. * * This default implementation will try calling * :js:func:`instance.web.search.Input#facet_for` if the widget's name @@ -797,6 +961,9 @@ instance.web.search.Input = instance.web.search.Widget.extend( /** @lends instan } return this.facet_for(defaults[this.attrs.name]); }, + in_drawer: function () { + return !!this._in_drawer; + }, get_context: function () { throw new Error( "get_context not implemented for widget " + this.attrs.type); @@ -822,6 +989,8 @@ instance.web.search.Input = instance.web.search.Widget.extend( /** @lends instan }); instance.web.search.FilterGroup = instance.web.search.Input.extend(/** @lends instance.web.search.FilterGroup# */{ template: 'SearchView.filters', + icon: 'q', + completion_label: _lt("Filter on: %s"), /** * Inclusive group of filters, creates a continuous "button" with clickable * sections (the normal display for filters is to be a self-contained button) @@ -833,36 +1002,77 @@ instance.web.search.FilterGroup = instance.web.search.Input.extend(/** @lends in * @param {instance.web.SearchView} view view in which the filters are contained */ init: function (filters, view) { + // If all filters are group_by and we're not initializing a GroupbyGroup, + // create a GroupbyGroup instead of the current FilterGroup + if (!(this instanceof instance.web.search.GroupbyGroup) && + _(filters).all(function (f) { + return f.attrs.context && f.attrs.context.group_by; })) { + return new instance.web.search.GroupbyGroup(filters, view); + } this._super(view); this.filters = filters; + this.view.query.on('add remove change reset', this.proxy('search_change')); }, start: function () { this.$element.on('click', 'li', this.proxy('toggle_filter')); return $.when(null); }, - facet_for_defaults: function (defaults) { - var fs = _(this.filters).filter(function (f) { - return f.attrs && f.attrs.name && !!defaults[f.attrs.name]; + /** + * Handles change of the search query: any of the group's filter which is + * in the search query should be visually checked in the drawer + */ + search_change: function () { + var self = this; + var $filters = this.$element.find('> li').removeClass('oe_selected'); + var facet = this.view.query.find(_.bind(this.match_facet, this)); + if (!facet) { return; } + facet.values.each(function (v) { + var i = _(self.filters).indexOf(v.get('value')); + if (i === -1) { return; } + $filters.eq(i).addClass('oe_selected'); }); - if (_.isEmpty(fs)) { return $.when(null); } - return $.when(new VS.model.SearchFacet({ + }, + /** + * Matches the group to a facet, in order to find if the group is + * represented in the current search query + */ + match_facet: function (facet) { + return facet.get('field') === this; + }, + make_facet: function (values) { + return { category: _t("Filter"), - value: _(fs).map(function (f) { - return f.attrs.string || f.attrs.name }).join(' | '), - json: fs, - field: this, - app: this.view.vs - })); + icon: this.icon, + values: values, + field: this + } + }, + make_value: function (filter) { + return { + label: filter.attrs.string || filter.attrs.help || filter.attrs.name, + value: filter + }; + }, + facet_for_defaults: function (defaults) { + var self = this; + var fs = _(this.filters).chain() + .filter(function (f) { + return f.attrs && f.attrs.name && !!defaults[f.attrs.name]; + }).map(function (f) { + return self.make_value(f); + }).value(); + if (_.isEmpty(fs)) { return $.when(null); } + return $.when(this.make_facet(fs)); }, /** * Fetches contexts for all enabled filters in the group * - * @param {VS.model.SearchFacet} facet + * @param {openerp.web.search.Facet} facet * @return {*} combined contexts of the enabled filters in this group */ get_context: function (facet) { - var contexts = _(facet.get('json')).chain() - .map(function (filter) { return filter.attrs.context; }) + var contexts = facet.values.chain() + .map(function (f) { return f.get('value').attrs.context; }) .reject(_.isEmpty) .value(); @@ -879,8 +1089,8 @@ instance.web.search.FilterGroup = instance.web.search.Input.extend(/** @lends in * @return {Array} enabled filters in this group */ get_groupby: function (facet) { - return _(facet.get('json')).chain() - .map(function (filter) { return filter.attrs.context; }) + return facet.values.chain() + .map(function (f) { return f.get('value').attrs.context; }) .reject(_.isEmpty) .value(); }, @@ -891,8 +1101,8 @@ instance.web.search.FilterGroup = instance.web.search.Input.extend(/** @lends in * @return {*} combined domains of the enabled filters in this group */ get_domain: function (facet) { - var domains = _(facet.get('json')).chain() - .map(function (filter) { return filter.attrs.domain; }) + var domains = facet.values.chain() + .map(function (f) { return f.get('value').attrs.domain; }) .reject(_.isEmpty) .value(); @@ -909,40 +1119,66 @@ instance.web.search.FilterGroup = instance.web.search.Input.extend(/** @lends in this.toggle(this.filters[$(e.target).index()]); }, toggle: function (filter) { - // FIXME: oh god, my eyes, they hurt - var self = this, fs; - var facet = this.view.vs.searchQuery.detect(function (f) { - return f.get('field') === self; }); - if (facet) { - fs = facet.get('json'); - - if (_.include(fs, filter)) { - fs = _.without(fs, filter); - } else { - fs.push(filter); + this.view.query.toggle(this.make_facet([this.make_value(filter)])); + }, + complete: function (item) { + var self = this; + item = item.toLowerCase(); + var facet_values = _(this.filters).chain() + .filter(function (filter) { + var at = { + string: filter.attrs.string || '', + help: filter.attrs.help || '', + name: filter.attrs.name || '' + }; + var include = _.str.include; + return include(at.string.toLowerCase(), item) + || include(at.help.toLowerCase(), item) + || include(at.name.toLowerCase(), item); + }) + .map(this.make_value) + .value(); + if (_(facet_values).isEmpty()) { return $.when(null); } + return $.when(_.map(facet_values, function (facet_value) { + return { + label: _.str.sprintf(self.completion_label.toString(), + facet_value.label), + facet: self.make_facet([facet_value]) } - if (_(fs).isEmpty()) { - this.view.vs.searchQuery.remove(facet, {trigger_search: true}); - } else { - facet.set({ - json: fs, - value: _(fs).map(function (f) { - return f.attrs.string || f.attrs.name }).join(' | ') - }); + })); + } +}); +instance.web.search.GroupbyGroup = instance.web.search.FilterGroup.extend({ + icon: 'w', + completion_label: _lt("Group by: %s"), + init: function (filters, view) { + this._super(filters, view); + // Not flanders: facet unicity is handled through the + // (category, field) pair of facet attributes. This is all well and + // good for regular filter groups where a group matches a facet, but for + // groupby we want a single facet. So cheat: add an attribute on the + // view which proxies to the first GroupbyGroup, so it can be used + // for every GroupbyGroup and still provides the various methods needed + // by the search view. Use weirdo name to avoid risks of conflicts + if (!this.getParent()._s_groupby) { + this.getParent()._s_groupby = { + help: "See GroupbyGroup#init", + get_context: this.proxy('get_context'), + get_domain: this.proxy('get_domain'), + get_groupby: this.proxy('get_groupby') } - return; - } else { - fs = [filter]; } - - this.view.vs.searchQuery.add({ - category: _t("Filter"), - value: _(fs).map(function (f) { - return f.attrs.string || f.attrs.name }).join(' | '), - json: fs, - field: this, - app: this.view.vs - }); + }, + match_facet: function (facet) { + return facet.get('field') === this.getParent()._s_groupby; + }, + make_facet: function (values) { + return { + category: _t("GroupBy"), + icon: this.icon, + values: values, + field: this.getParent()._s_groupby + }; } }); instance.web.search.Filter = instance.web.search.Input.extend(/** @lends instance.web.search.Filter# */{ @@ -985,28 +1221,32 @@ instance.web.search.Field = instance.web.search.Input.extend( /** @lends instanc this.load_attrs(_.extend({}, field, view_section.attrs)); }, facet_for: function (value) { - return $.when(new VS.model.SearchFacet({ - category: this.attrs.string || this.attrs.name, - value: String(value), - json: value, + return $.when({ field: this, - app: this.view.vs - })); + category: this.attrs.string || this.attrs.name, + values: [{label: String(value), value: value}] + }); }, - get_value: function (facet) { - return facet.value(); + value_from: function (facetValue) { + return facetValue.get('value'); }, get_context: function (facet) { - var val = this.get_value(facet); - // A field needs a value to be "active", and a context to send when - // active - var has_value = (val !== null && val !== ''); + var self = this; + // A field needs a context to send when active var context = this.attrs.context; - if (!(has_value && context)) { + if (!context || !facet.values.length) { return; } - return new instance.web.CompoundContext(context) - .set_eval_context({self: val}); + var contexts = facet.values.map(function (facetValue) { + return new instance.web.CompoundContext(context) + .set_eval_context({self: self.value_from(facetValue)}); + }); + + if (contexts.length === 1) { return contexts[0]; } + + return _.extend(new instance.web.CompoundContext, { + __contexts: contexts + }); }, get_groupby: function () { }, /** @@ -1021,23 +1261,37 @@ instance.web.search.Field = instance.web.search.Input.extend( /** @lends instanc * @returns {Array} domain to include in the resulting search */ make_domain: function (name, operator, facet) { - return [[name, operator, this.get_value(facet)]]; + return [[name, operator, this.value_from(facet)]]; }, get_domain: function (facet) { - var val = this.get_value(facet); - if (val === null || val === '') { - return; + if (!facet.values.length) { return; } + + var value_to_domain; + var self = this; + var domain = this.attrs['filter_domain']; + if (domain) { + value_to_domain = function (facetValue) { + return new instance.web.CompoundDomain(domain) + .set_eval_context({self: self.value_from(facetValue)}); + }; + } else { + value_to_domain = function (facetValue) { + return self.make_domain( + self.attrs.name, + self.attrs.operator || self.default_operator, + facetValue); + }; + } + var domains = facet.values.map(value_to_domain); + + if (domains.length === 1) { return domains[0]; } + for (var i = domains.length; --i;) { + domains.unshift(['|']); } - var domain = this.attrs['filter_domain']; - if (!domain) { - return this.make_domain( - this.attrs.name, - this.attrs.operator || this.default_operator, - facet); - } - return new instance.web.CompoundDomain(domain) - .set_eval_context({self: val}); + return _.extend(new instance.web.CompoundDomain, { + __domains: domains + }); } }); /** @@ -1059,15 +1313,17 @@ instance.web.search.CharField = instance.web.search.Field.extend( /** @lends ins field: '' + this.attrs.string + '', value: '' + _.str.escapeHTML(value) + ''}); return $.when([{ - category: this.attrs.string, label: label, - value: value, - field: this + facet: { + category: this.attrs.string, + field: this, + values: [{label: value, value: value}] + } }]); } }); instance.web.search.NumberField = instance.web.search.Field.extend(/** @lends instance.web.search.NumberField# */{ - get_value: function () { + value_from: function () { if (!this.$element.val()) { return null; } @@ -1110,6 +1366,22 @@ instance.web.search.FloatField = instance.web.search.NumberField.extend(/** @len } } }); + +/** + * Utility function for m2o & selection fields taking a selection/name_get pair + * (value, name) and converting it to a Facet descriptor + * + * @param {instance.web.search.Field} field holder field + * @param {Array} pair pair value to convert + */ +function facet_from(field, pair) { + return { + field: field, + category: field['attrs'].string, + values: [{label: pair[1], value: pair[0]}] + }; +} + /** * @class * @extends instance.web.search.Field @@ -1143,15 +1415,13 @@ instance.web.search.SelectionField = instance.web.search.Field.extend(/** @lends }) .map(function (sel) { return { - category: self.attrs.string, - field: self, - value: sel[1], - json: sel[0] + label: sel[1], + facet: facet_from(self, sel) }; }).value(); if (_.isEmpty(results)) { return $.when(null); } - return $.when.apply(null, [{ - category: this.attrs.string + return $.when.call(null, [{ + label: this.attrs.string }].concat(results)); }, facet_for: function (value) { @@ -1159,16 +1429,7 @@ instance.web.search.SelectionField = instance.web.search.Field.extend(/** @lends return sel[0] === value; }); if (!match) { return $.when(null); } - return $.when(new VS.model.SearchFacet({ - category: this.attrs.string, - value: match[1], - json: match[0], - field: this, - app: this.view.app - })); - }, - get_value: function (facet) { - return facet.get('json'); + return $.when(facet_from(this, match)); } }); instance.web.search.BooleanField = instance.web.search.SelectionField.extend(/** @lends instance.web.search.BooleanField# */{ @@ -1179,16 +1440,9 @@ instance.web.search.BooleanField = instance.web.search.SelectionField.extend(/** init: function () { this._super.apply(this, arguments); this.attrs.selection = [ - ['true', _t("Yes")], - ['false', _t("No")] + [true, _t("Yes")], + [false, _t("No")] ]; - }, - get_value: function (facet) { - switch (this._super(facet)) { - case 'false': return false; - case 'true': return true; - default: return null; - } } }); /** @@ -1196,23 +1450,24 @@ instance.web.search.BooleanField = instance.web.search.SelectionField.extend(/** * @extends instance.web.search.DateField */ instance.web.search.DateField = instance.web.search.Field.extend(/** @lends instance.web.search.DateField# */{ - get_value: function (facet) { - return instance.web.date_to_str(facet.get('json')); + value_from: function (facetValue) { + return instance.web.date_to_str(facetValue.get('value')); }, complete: function (needle) { var d = Date.parse(needle); if (!d) { return $.when(null); } - var value = instance.web.format_value(d, this.attrs); + var date_string = instance.web.format_value(d, this.attrs); var label = _.str.sprintf(_.str.escapeHTML( _t("Search %(field)s at: %(value)s")), { field: '' + this.attrs.string + '', - value: '' + value + ''}); + value: '' + date_string + ''}); return $.when([{ - category: this.attrs.string, label: label, - value: value, - json: d, - field: this + facet: { + category: this.attrs.string, + field: this, + values: [{label: date_string, value: d}] + } }]); } }); @@ -1228,11 +1483,12 @@ instance.web.search.DateField = instance.web.search.Field.extend(/** @lends inst * @extends instance.web.DateField */ instance.web.search.DateTimeField = instance.web.search.DateField.extend(/** @lends instance.web.search.DateTimeField# */{ - get_value: function (facet) { - return instance.web.datetime_to_str(facet.get('json')); + value_from: function (facetValue) { + return instance.web.datetime_to_str(facetValue.get('value')); } }); instance.web.search.ManyToOneField = instance.web.search.CharField.extend({ + default_operator: {}, init: function (view_section, field, view) { this._super(view_section, field, view); this.model = new instance.web.Model(this.attrs.relation); @@ -1247,13 +1503,11 @@ instance.web.search.ManyToOneField = instance.web.search.CharField.extend({ context: {} }).pipe(function (results) { if (_.isEmpty(results)) { return null; } - return [{category: self.attrs.string}].concat( + return [{label: self.attrs.string}].concat( _(results).map(function (result) { return { - category: self.attrs.string, - value: result[1], - json: result[0], - field: self + label: result[1], + facet: facet_from(self, result) }; })); }); @@ -1261,36 +1515,166 @@ instance.web.search.ManyToOneField = instance.web.search.CharField.extend({ facet_for: function (value) { var self = this; if (value instanceof Array) { - return $.when(new VS.model.SearchFacet({ - category: this.attrs.string, - value: value[1], - json: value[0], - field: this, - app: this.view.vs - })); + return $.when(facet_from(this, value)); } return this.model.call('name_get', [value], {}).pipe(function (names) { - return new VS.model.SearchFacet({ - category: self.attrs.string, - value: names[0][1], - json: names[0][0], - field: self, - app: self.view.vs - }); + if (_(names).isEmpty()) { return null; } + return facet_from(self, names[0]); }) }, - make_domain: function (name, operator, facet) { - // ``json`` -> actual auto-completed id - if (facet.get('json')) { - return [[name, '=', facet.get('json')]]; + value_from: function (facetValue) { + return facetValue.get('label'); + }, + make_domain: function (name, operator, facetValue) { + if (operator === this.default_operator) { + return [[name, '=', facetValue.get('value')]]; } - - return this._super(name, operator, facet); + return this._super(name, operator, facetValue); } }); +instance.web.search.CustomFilters = instance.web.search.Input.extend({ + template: 'SearchView.CustomFilters', + _in_drawer: true, + start: function () { + var self = this; + this.model = new instance.web.Model('ir.filters'); + this.filters = {}; + this.$element.on('submit', 'form', this.proxy('save_current')); + this.$element.on('click', 'h4', function () { + self.$element.toggleClass('oe_opened'); + }); + // FIXME: local eval of domain and context to get rid of special endpoint + return this.rpc('/web/searchview/get_filters', { + model: this.view.model + }).pipe(this.proxy('set_filters')); + }, + append_filter: function (filter) { + var self = this; + var key = _.str.sprintf('(%s)%s', filter.user_id, filter.name); + + var $filter; + if (key in this.filters) { + $filter = this.filters[key]; + } else { + var id = filter.id; + $filter = this.filters[key] = $('
    3. ') + .appendTo(this.$element.find('.oe_searchview_custom_list')) + .addClass(filter.user_id ? 'oe_searchview_custom_private' + : 'oe_searchview_custom_public') + .text(filter.name); + + $('
      - + or Import

      @@ -684,9 +676,6 @@ - - - - - - or - Discard + or Discard
      @@ -730,7 +716,7 @@
      -
      + @@ -839,7 +825,6 @@ t-att-title="help" t-attf-class="#{classnames} oe_form_label#{help ? '_help' : ''} oe_align_#{align}"> - ? @@ -991,11 +976,12 @@ +
      @@ -1034,8 +1020,8 @@
      @@ -1064,7 +1050,7 @@ -
      -
      +
      @@ -1311,7 +1297,31 @@
      +
      +
      +
      +
      + +
      + +
      ✖ + + + +
      + + + + @@ -1338,7 +1348,7 @@
      -
      +

      Select Dashboard to add this filter to:

      +
      + + + +
      -

      Advanced Search...

      +

      Advanced Search

        @@ -1487,32 +1512,29 @@ + - + - + - - - + - - +
      @@ -1526,31 +1548,22 @@
      -
      +
      - - - + + + - - - + + + - - - -
      -
      -
      -
      - - - + - + @@ -53,4 +54,5 @@ + diff --git a/addons/web_calendar/i18n/ar.po b/addons/web_calendar/i18n/ar.po index d548cc15564..18ee2d5d0dd 100644 --- a/addons/web_calendar/i18n/ar.po +++ b/addons/web_calendar/i18n/ar.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_calendar/static/src/js/calendar.js:11 diff --git a/addons/web_calendar/i18n/bg.po b/addons/web_calendar/i18n/bg.po new file mode 100644 index 00000000000..cbda046fc4e --- /dev/null +++ b/addons/web_calendar/i18n/bg.po @@ -0,0 +1,41 @@ +# Bulgarian translation for openerp-web +# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012 +# This file is distributed under the same license as the openerp-web package. +# FIRST AUTHOR , 2012. +# +msgid "" +msgstr "" +"Project-Id-Version: openerp-web\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2012-02-06 17:33+0100\n" +"PO-Revision-Date: 2012-05-16 09:33+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Bulgarian \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2012-05-17 04:49+0000\n" +"X-Generator: Launchpad (build 15259)\n" + +#. openerp-web +#: addons/web_calendar/static/src/js/calendar.js:11 +msgid "Calendar" +msgstr "Календар" + +#. openerp-web +#: addons/web_calendar/static/src/js/calendar.js:466 +#: addons/web_calendar/static/src/js/calendar.js:467 +msgid "Responsible" +msgstr "Отговорник" + +#. openerp-web +#: addons/web_calendar/static/src/js/calendar.js:504 +#: addons/web_calendar/static/src/js/calendar.js:505 +msgid "Navigator" +msgstr "Навигатор" + +#. openerp-web +#: addons/web_calendar/static/src/xml/web_calendar.xml:5 +#: addons/web_calendar/static/src/xml/web_calendar.xml:6 +msgid " " +msgstr "" diff --git a/addons/web_calendar/i18n/bn.po b/addons/web_calendar/i18n/bn.po index c12d6986880..e0314183796 100644 --- a/addons/web_calendar/i18n/bn.po +++ b/addons/web_calendar/i18n/bn.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_calendar/static/src/js/calendar.js:11 diff --git a/addons/web_calendar/i18n/bs.po b/addons/web_calendar/i18n/bs.po index e70e9fb7da7..16fb2664bda 100644 --- a/addons/web_calendar/i18n/bs.po +++ b/addons/web_calendar/i18n/bs.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_calendar/static/src/js/calendar.js:11 diff --git a/addons/web_calendar/i18n/cs.po b/addons/web_calendar/i18n/cs.po index 49ef93a10b6..3e9ad8b7184 100644 --- a/addons/web_calendar/i18n/cs.po +++ b/addons/web_calendar/i18n/cs.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" "X-Poedit-Language: Czech\n" #. openerp-web diff --git a/addons/web_calendar/i18n/da.po b/addons/web_calendar/i18n/da.po index 94be02b97a4..b009dce71c8 100644 --- a/addons/web_calendar/i18n/da.po +++ b/addons/web_calendar/i18n/da.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_calendar/static/src/js/calendar.js:11 diff --git a/addons/web_calendar/i18n/de.po b/addons/web_calendar/i18n/de.po index e72ccd1e355..ccf834b9a7d 100644 --- a/addons/web_calendar/i18n/de.po +++ b/addons/web_calendar/i18n/de.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_calendar/static/src/js/calendar.js:11 diff --git a/addons/web_calendar/i18n/en_AU.po b/addons/web_calendar/i18n/en_AU.po index 9a42c019629..25a0794d1af 100644 --- a/addons/web_calendar/i18n/en_AU.po +++ b/addons/web_calendar/i18n/en_AU.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_calendar/static/src/js/calendar.js:11 diff --git a/addons/web_calendar/i18n/en_GB.po b/addons/web_calendar/i18n/en_GB.po index a0186f24b9f..14db67c1292 100644 --- a/addons/web_calendar/i18n/en_GB.po +++ b/addons/web_calendar/i18n/en_GB.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_calendar/static/src/js/calendar.js:11 diff --git a/addons/web_calendar/i18n/es.po b/addons/web_calendar/i18n/es.po index 214a2fac0ed..9fac1e7249c 100644 --- a/addons/web_calendar/i18n/es.po +++ b/addons/web_calendar/i18n/es.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_calendar/static/src/js/calendar.js:11 diff --git a/addons/web_calendar/i18n/es_CL.po b/addons/web_calendar/i18n/es_CL.po index 7827476716c..c2c259c4694 100644 --- a/addons/web_calendar/i18n/es_CL.po +++ b/addons/web_calendar/i18n/es_CL.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_calendar/static/src/js/calendar.js:11 diff --git a/addons/web_calendar/i18n/es_CR.po b/addons/web_calendar/i18n/es_CR.po index dd7d7cf9b39..965680be1df 100644 --- a/addons/web_calendar/i18n/es_CR.po +++ b/addons/web_calendar/i18n/es_CR.po @@ -15,8 +15,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" "Language: es\n" #. openerp-web diff --git a/addons/web_calendar/i18n/es_EC.po b/addons/web_calendar/i18n/es_EC.po index d10ff0805c4..8b6c49e2a6b 100644 --- a/addons/web_calendar/i18n/es_EC.po +++ b/addons/web_calendar/i18n/es_EC.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_calendar/static/src/js/calendar.js:11 diff --git a/addons/web_calendar/i18n/et.po b/addons/web_calendar/i18n/et.po index e1cceed2854..560d6aa3e38 100644 --- a/addons/web_calendar/i18n/et.po +++ b/addons/web_calendar/i18n/et.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_calendar/static/src/js/calendar.js:11 diff --git a/addons/web_calendar/i18n/eu.po b/addons/web_calendar/i18n/eu.po index 536f1d38cad..91052543d00 100644 --- a/addons/web_calendar/i18n/eu.po +++ b/addons/web_calendar/i18n/eu.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_calendar/static/src/js/calendar.js:11 diff --git a/addons/web_calendar/i18n/fi.po b/addons/web_calendar/i18n/fi.po index e1268fc84c6..d697da1410a 100644 --- a/addons/web_calendar/i18n/fi.po +++ b/addons/web_calendar/i18n/fi.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_calendar/static/src/js/calendar.js:11 diff --git a/addons/web_calendar/i18n/fr.po b/addons/web_calendar/i18n/fr.po index 58fc6212a1c..2b0926b1f91 100644 --- a/addons/web_calendar/i18n/fr.po +++ b/addons/web_calendar/i18n/fr.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_calendar/static/src/js/calendar.js:11 diff --git a/addons/web_calendar/i18n/gl.po b/addons/web_calendar/i18n/gl.po index c87e7a72548..ca76b134c21 100644 --- a/addons/web_calendar/i18n/gl.po +++ b/addons/web_calendar/i18n/gl.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_calendar/static/src/js/calendar.js:11 diff --git a/addons/web_calendar/i18n/hr.po b/addons/web_calendar/i18n/hr.po index bde9d5d08fc..3e0a607a776 100644 --- a/addons/web_calendar/i18n/hr.po +++ b/addons/web_calendar/i18n/hr.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_calendar/static/src/js/calendar.js:11 diff --git a/addons/web_calendar/i18n/id.po b/addons/web_calendar/i18n/id.po index a87114214fc..85b077c3570 100644 --- a/addons/web_calendar/i18n/id.po +++ b/addons/web_calendar/i18n/id.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_calendar/static/src/js/calendar.js:11 diff --git a/addons/web_calendar/i18n/it.po b/addons/web_calendar/i18n/it.po index 07ccaabe51c..c42668c9505 100644 --- a/addons/web_calendar/i18n/it.po +++ b/addons/web_calendar/i18n/it.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_calendar/static/src/js/calendar.js:11 diff --git a/addons/web_calendar/i18n/ja.po b/addons/web_calendar/i18n/ja.po index 2e36f1454a8..f55bf68fa18 100644 --- a/addons/web_calendar/i18n/ja.po +++ b/addons/web_calendar/i18n/ja.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_calendar/static/src/js/calendar.js:11 diff --git a/addons/web_calendar/i18n/ka.po b/addons/web_calendar/i18n/ka.po index 4097953e771..0c818be85ff 100644 --- a/addons/web_calendar/i18n/ka.po +++ b/addons/web_calendar/i18n/ka.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_calendar/static/src/js/calendar.js:11 diff --git a/addons/web_calendar/i18n/mk.po b/addons/web_calendar/i18n/mk.po index 0f484a90355..240bc0306d9 100644 --- a/addons/web_calendar/i18n/mk.po +++ b/addons/web_calendar/i18n/mk.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_calendar/static/src/js/calendar.js:11 diff --git a/addons/web_calendar/i18n/nb.po b/addons/web_calendar/i18n/nb.po index 7cf2921f4d4..0efb03bb428 100644 --- a/addons/web_calendar/i18n/nb.po +++ b/addons/web_calendar/i18n/nb.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_calendar/static/src/js/calendar.js:11 diff --git a/addons/web_calendar/i18n/nl.po b/addons/web_calendar/i18n/nl.po index 890c6bded6b..8c0e5346e0e 100644 --- a/addons/web_calendar/i18n/nl.po +++ b/addons/web_calendar/i18n/nl.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_calendar/static/src/js/calendar.js:11 diff --git a/addons/web_calendar/i18n/nl_BE.po b/addons/web_calendar/i18n/nl_BE.po index 0f57301f2ff..2f86d745c9f 100644 --- a/addons/web_calendar/i18n/nl_BE.po +++ b/addons/web_calendar/i18n/nl_BE.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_calendar/static/src/js/calendar.js:11 diff --git a/addons/web_calendar/i18n/pl.po b/addons/web_calendar/i18n/pl.po index ca21cd5c5f3..d8a87594ca2 100644 --- a/addons/web_calendar/i18n/pl.po +++ b/addons/web_calendar/i18n/pl.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_calendar/static/src/js/calendar.js:11 diff --git a/addons/web_calendar/i18n/pt.po b/addons/web_calendar/i18n/pt.po index 96c8f2f2919..e00d4d2cebd 100644 --- a/addons/web_calendar/i18n/pt.po +++ b/addons/web_calendar/i18n/pt.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_calendar/static/src/js/calendar.js:11 diff --git a/addons/web_calendar/i18n/pt_BR.po b/addons/web_calendar/i18n/pt_BR.po index a9a11f7a030..a86e1f46bdf 100644 --- a/addons/web_calendar/i18n/pt_BR.po +++ b/addons/web_calendar/i18n/pt_BR.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_calendar/static/src/js/calendar.js:11 diff --git a/addons/web_calendar/i18n/ro.po b/addons/web_calendar/i18n/ro.po index 7d56e246fbb..eda9fb0fde7 100644 --- a/addons/web_calendar/i18n/ro.po +++ b/addons/web_calendar/i18n/ro.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_calendar/static/src/js/calendar.js:11 diff --git a/addons/web_calendar/i18n/ru.po b/addons/web_calendar/i18n/ru.po index 831a2a63781..c6aeb98e900 100644 --- a/addons/web_calendar/i18n/ru.po +++ b/addons/web_calendar/i18n/ru.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_calendar/static/src/js/calendar.js:11 diff --git a/addons/web_calendar/i18n/sk.po b/addons/web_calendar/i18n/sk.po index 6341fec641a..ee4408a188d 100644 --- a/addons/web_calendar/i18n/sk.po +++ b/addons/web_calendar/i18n/sk.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_calendar/static/src/js/calendar.js:11 diff --git a/addons/web_calendar/i18n/sl.po b/addons/web_calendar/i18n/sl.po index e7463eee561..505597efa01 100644 --- a/addons/web_calendar/i18n/sl.po +++ b/addons/web_calendar/i18n/sl.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_calendar/static/src/js/calendar.js:11 diff --git a/addons/web_calendar/i18n/sq.po b/addons/web_calendar/i18n/sq.po index d0f22815e82..e6cbb289e9a 100644 --- a/addons/web_calendar/i18n/sq.po +++ b/addons/web_calendar/i18n/sq.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_calendar/static/src/js/calendar.js:11 diff --git a/addons/web_calendar/i18n/sr@latin.po b/addons/web_calendar/i18n/sr@latin.po index 652e32167a6..507525d259a 100644 --- a/addons/web_calendar/i18n/sr@latin.po +++ b/addons/web_calendar/i18n/sr@latin.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_calendar/static/src/js/calendar.js:11 diff --git a/addons/web_calendar/i18n/sv.po b/addons/web_calendar/i18n/sv.po index 0d18e529479..f658fb3faab 100644 --- a/addons/web_calendar/i18n/sv.po +++ b/addons/web_calendar/i18n/sv.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_calendar/static/src/js/calendar.js:11 @@ -26,7 +26,7 @@ msgstr "Kalender" #: addons/web_calendar/static/src/js/calendar.js:466 #: addons/web_calendar/static/src/js/calendar.js:467 msgid "Responsible" -msgstr "" +msgstr "Ansvarig" #. openerp-web #: addons/web_calendar/static/src/js/calendar.js:504 diff --git a/addons/web_calendar/i18n/tr.po b/addons/web_calendar/i18n/tr.po index d9953e2fa78..92362caeb36 100644 --- a/addons/web_calendar/i18n/tr.po +++ b/addons/web_calendar/i18n/tr.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_calendar/static/src/js/calendar.js:11 diff --git a/addons/web_calendar/i18n/uk.po b/addons/web_calendar/i18n/uk.po index 0f70be95385..5f870abd5f0 100644 --- a/addons/web_calendar/i18n/uk.po +++ b/addons/web_calendar/i18n/uk.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_calendar/static/src/js/calendar.js:11 diff --git a/addons/web_calendar/i18n/zh_CN.po b/addons/web_calendar/i18n/zh_CN.po index 1154948183b..9a9bec08ebe 100644 --- a/addons/web_calendar/i18n/zh_CN.po +++ b/addons/web_calendar/i18n/zh_CN.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:15+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_calendar/static/src/js/calendar.js:11 diff --git a/addons/web_calendar/static/src/css/web_calendar.css b/addons/web_calendar/static/src/css/web_calendar.css index 313db123bb5..18eec963866 100644 --- a/addons/web_calendar/static/src/css/web_calendar.css +++ b/addons/web_calendar/static/src/css/web_calendar.css @@ -1,5 +1,20 @@ -#openerp_scheduler { +.oe_calendar_table { + border-top: 3px solid #eee; +} +.oe_calendar { background-color:#eee; + height: 600px; + border-right: 1px solid #eee; +} +.oe_calendar_sidebar { + width: 200px; +} +.oe_calendar_mini { + background-color: #eee; + padding: 5px; +} +.oe_calendar_filter { + padding: 0 10px; } .openerp .dhx_mini_calendar { -moz-box-shadow: none; diff --git a/addons/web_calendar/static/src/js/calendar.js b/addons/web_calendar/static/src/js/calendar.js index 959768d895e..4d738e55514 100644 --- a/addons/web_calendar/static/src/js/calendar.js +++ b/addons/web_calendar/static/src/js/calendar.js @@ -8,6 +8,7 @@ var _t = instance.web._t, var QWeb = instance.web.qweb; instance.web.views.add('calendar', 'instance.web_calendar.CalendarView'); instance.web_calendar.CalendarView = instance.web.View.extend({ + template: "CalendarView", display_name: _lt('Calendar'), // Dhtmlx scheduler ? init: function(parent, dataset, view_id, options) { @@ -98,13 +99,12 @@ instance.web_calendar.CalendarView = instance.web.View.extend({ for (var fld = 0; fld < this.fields_view.arch.children.length; fld++) { this.info_fields.push(this.fields_view.arch.children[fld].attrs.name); } - this.$element.html(QWeb.render("CalendarView", {"fields_view": this.fields_view})); this.init_scheduler(); - if (! this.sidebar && this.options.$sidebar) { + if (!this.sidebar && this.options.$sidebar) { this.sidebar = new instance.web_calendar.Sidebar(this); - this.has_been_loaded.pipe(this.sidebar.appendTo(this.options.$sidebar)); + this.has_been_loaded.pipe(this.sidebar.appendTo(this.$element.find('.oe_calendar_sidebar_container'))); } return this.has_been_loaded.resolve(); @@ -127,7 +127,7 @@ instance.web_calendar.CalendarView = instance.web.View.extend({ scheduler.config.mark_now = true; scheduler.config.day_date = '%l %j'; - scheduler.init('openerp_scheduler', null, this.mode || 'month'); + scheduler.init(this.$element.find('.oe_calendar')[0], null, this.mode || 'month'); // Remove hard coded style attributes from dhtmlx scheduler this.$element.find(".dhx_cal_navline div").removeAttr('style'); @@ -143,7 +143,7 @@ instance.web_calendar.CalendarView = instance.web.View.extend({ this.refresh_scheduler(); }, on_view_changed: function(mode, date) { - this.$element.removeClass('oe_cal_day oe_cal_week oe_cal_month').addClass('oe_cal_' + mode); + this.$element.find('.oe_calendar').removeClass('oe_cal_day oe_cal_week oe_cal_month').addClass('oe_cal_' + mode); if (!date.between(this.range_start, this.range_stop)) { this.update_range_dates(date); this.do_ranged_search(); @@ -392,18 +392,9 @@ instance.web_calendar.CalendarView = instance.web.View.extend({ var self = this; $.when(this.has_been_loaded).then(function() { self.$element.show(); - if (self.sidebar) { - self.sidebar.$element.show(); - } self.do_push_state({}); }); }, - do_hide: function() { - this._super(); - if (this.sidebar) { - this.sidebar.$element.hide(); - } - }, get_selected_ids: function() { // no way to select a record anyway return []; diff --git a/addons/web_calendar/static/src/xml/web_calendar.xml b/addons/web_calendar/static/src/xml/web_calendar.xml index 422c37dcf0a..ee9175f06ed 100644 --- a/addons/web_calendar/static/src/xml/web_calendar.xml +++ b/addons/web_calendar/static/src/xml/web_calendar.xml @@ -1,27 +1,32 @@ diff --git a/addons/web_mobile/i18n/ar.po b/addons/web_mobile/i18n/ar.po index a3423b7c99d..18bf229b3e4 100644 --- a/addons/web_mobile/i18n/ar.po +++ b/addons/web_mobile/i18n/ar.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:16+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_mobile/static/src/xml/web_mobile.xml:17 diff --git a/addons/web_mobile/i18n/bn.po b/addons/web_mobile/i18n/bn.po index 046430b17c4..55b161e5df7 100644 --- a/addons/web_mobile/i18n/bn.po +++ b/addons/web_mobile/i18n/bn.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:16+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_mobile/static/src/xml/web_mobile.xml:17 diff --git a/addons/web_mobile/i18n/cs.po b/addons/web_mobile/i18n/cs.po index 51d5486b46f..b920b29703a 100644 --- a/addons/web_mobile/i18n/cs.po +++ b/addons/web_mobile/i18n/cs.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:16+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" "X-Poedit-Language: Czech\n" #. openerp-web diff --git a/addons/web_mobile/i18n/da.po b/addons/web_mobile/i18n/da.po index f558addf136..2b4f287ff4f 100644 --- a/addons/web_mobile/i18n/da.po +++ b/addons/web_mobile/i18n/da.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:16+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_mobile/static/src/xml/web_mobile.xml:17 diff --git a/addons/web_mobile/i18n/de.po b/addons/web_mobile/i18n/de.po index 9c9a68399f5..d584d589db9 100644 --- a/addons/web_mobile/i18n/de.po +++ b/addons/web_mobile/i18n/de.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:16+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_mobile/static/src/xml/web_mobile.xml:17 diff --git a/addons/web_mobile/i18n/en_GB.po b/addons/web_mobile/i18n/en_GB.po index e715d9ec9c0..9795fe17002 100644 --- a/addons/web_mobile/i18n/en_GB.po +++ b/addons/web_mobile/i18n/en_GB.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:16+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_mobile/static/src/xml/web_mobile.xml:17 diff --git a/addons/web_mobile/i18n/es.po b/addons/web_mobile/i18n/es.po index d7f46e8424f..496bc554fe7 100644 --- a/addons/web_mobile/i18n/es.po +++ b/addons/web_mobile/i18n/es.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:16+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_mobile/static/src/xml/web_mobile.xml:17 diff --git a/addons/web_mobile/i18n/es_CL.po b/addons/web_mobile/i18n/es_CL.po index 68d55f955fb..e4e293e7ca9 100644 --- a/addons/web_mobile/i18n/es_CL.po +++ b/addons/web_mobile/i18n/es_CL.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:16+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_mobile/static/src/xml/web_mobile.xml:17 diff --git a/addons/web_mobile/i18n/es_CR.po b/addons/web_mobile/i18n/es_CR.po index 19b6c147726..585b5762f41 100644 --- a/addons/web_mobile/i18n/es_CR.po +++ b/addons/web_mobile/i18n/es_CR.po @@ -15,8 +15,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:16+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" "Language: es\n" #. openerp-web diff --git a/addons/web_mobile/i18n/es_EC.po b/addons/web_mobile/i18n/es_EC.po index 96240afc252..43a022dff80 100644 --- a/addons/web_mobile/i18n/es_EC.po +++ b/addons/web_mobile/i18n/es_EC.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:16+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_mobile/static/src/xml/web_mobile.xml:17 diff --git a/addons/web_mobile/i18n/et.po b/addons/web_mobile/i18n/et.po index 38ff1193d09..b47c24917ba 100644 --- a/addons/web_mobile/i18n/et.po +++ b/addons/web_mobile/i18n/et.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:16+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_mobile/static/src/xml/web_mobile.xml:17 diff --git a/addons/web_mobile/i18n/fi.po b/addons/web_mobile/i18n/fi.po index a4df5f3bab5..5f08f1f9734 100644 --- a/addons/web_mobile/i18n/fi.po +++ b/addons/web_mobile/i18n/fi.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:16+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_mobile/static/src/xml/web_mobile.xml:17 diff --git a/addons/web_mobile/i18n/fr.po b/addons/web_mobile/i18n/fr.po index 50bf42b858b..179b9328ac4 100644 --- a/addons/web_mobile/i18n/fr.po +++ b/addons/web_mobile/i18n/fr.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:16+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_mobile/static/src/xml/web_mobile.xml:17 diff --git a/addons/web_mobile/i18n/gl.po b/addons/web_mobile/i18n/gl.po index abd4fa0f8df..31115b8b43c 100644 --- a/addons/web_mobile/i18n/gl.po +++ b/addons/web_mobile/i18n/gl.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:16+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_mobile/static/src/xml/web_mobile.xml:17 diff --git a/addons/web_mobile/i18n/hr.po b/addons/web_mobile/i18n/hr.po index 0fcfda1664f..c879f71fdd9 100644 --- a/addons/web_mobile/i18n/hr.po +++ b/addons/web_mobile/i18n/hr.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:16+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_mobile/static/src/xml/web_mobile.xml:17 diff --git a/addons/web_mobile/i18n/it.po b/addons/web_mobile/i18n/it.po index 73302ff53da..1edfbb53a51 100644 --- a/addons/web_mobile/i18n/it.po +++ b/addons/web_mobile/i18n/it.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:16+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_mobile/static/src/xml/web_mobile.xml:17 diff --git a/addons/web_mobile/i18n/ja.po b/addons/web_mobile/i18n/ja.po index 5749006324c..3ea15aadce5 100644 --- a/addons/web_mobile/i18n/ja.po +++ b/addons/web_mobile/i18n/ja.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:16+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_mobile/static/src/xml/web_mobile.xml:17 diff --git a/addons/web_mobile/i18n/ka.po b/addons/web_mobile/i18n/ka.po index 9776ee2c4e4..b44a9f91042 100644 --- a/addons/web_mobile/i18n/ka.po +++ b/addons/web_mobile/i18n/ka.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:16+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_mobile/static/src/xml/web_mobile.xml:17 diff --git a/addons/web_mobile/i18n/mk.po b/addons/web_mobile/i18n/mk.po index b3af148ee80..28a1f981b47 100644 --- a/addons/web_mobile/i18n/mk.po +++ b/addons/web_mobile/i18n/mk.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:16+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_mobile/static/src/xml/web_mobile.xml:17 diff --git a/addons/web_mobile/i18n/nb.po b/addons/web_mobile/i18n/nb.po index 74c540ffbe5..c5476ceb30b 100644 --- a/addons/web_mobile/i18n/nb.po +++ b/addons/web_mobile/i18n/nb.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:16+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_mobile/static/src/xml/web_mobile.xml:17 diff --git a/addons/web_mobile/i18n/nl.po b/addons/web_mobile/i18n/nl.po index 2dfe8e0bd13..a252c48a085 100644 --- a/addons/web_mobile/i18n/nl.po +++ b/addons/web_mobile/i18n/nl.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:16+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_mobile/static/src/xml/web_mobile.xml:17 diff --git a/addons/web_mobile/i18n/nl_BE.po b/addons/web_mobile/i18n/nl_BE.po index e3ca1adfeb6..c15eacda6a2 100644 --- a/addons/web_mobile/i18n/nl_BE.po +++ b/addons/web_mobile/i18n/nl_BE.po @@ -8,14 +8,14 @@ msgstr "" "Project-Id-Version: openerp-web\n" "Report-Msgid-Bugs-To: FULL NAME \n" "POT-Creation-Date: 2012-02-07 10:13+0100\n" -"PO-Revision-Date: 2012-02-08 16:52+0000\n" +"PO-Revision-Date: 2012-05-15 14:19+0000\n" "Last-Translator: Els Van Vossel (Agaplan) \n" "Language-Team: Dutch (Belgium) \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:16+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-16 05:10+0000\n" +"X-Generator: Launchpad (build 15247)\n" #. openerp-web #: addons/web_mobile/static/src/xml/web_mobile.xml:17 @@ -50,12 +50,12 @@ msgstr "Verkeerde gebruikersnaam of wachtwoord" #. openerp-web #: addons/web_mobile/static/src/xml/web_mobile.xml:42 msgid "Powered by openerp.com" -msgstr "" +msgstr "Door openerp.com" #. openerp-web #: addons/web_mobile/static/src/xml/web_mobile.xml:49 msgid "Home" -msgstr "" +msgstr "Home" #. openerp-web #: addons/web_mobile/static/src/xml/web_mobile.xml:57 @@ -80,7 +80,7 @@ msgstr "Er kunnen geen records worden weergegeven" #. openerp-web #: addons/web_mobile/static/src/xml/web_mobile.xml:183 msgid "Open this resource" -msgstr "" +msgstr "Openen" #. openerp-web #: addons/web_mobile/static/src/xml/web_mobile.xml:223 diff --git a/addons/web_mobile/i18n/pl.po b/addons/web_mobile/i18n/pl.po index 3e077a4ea46..097f7510eed 100644 --- a/addons/web_mobile/i18n/pl.po +++ b/addons/web_mobile/i18n/pl.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:16+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_mobile/static/src/xml/web_mobile.xml:17 diff --git a/addons/web_mobile/i18n/pt.po b/addons/web_mobile/i18n/pt.po index 55c4dba8967..4ecefa9bfb6 100644 --- a/addons/web_mobile/i18n/pt.po +++ b/addons/web_mobile/i18n/pt.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:16+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_mobile/static/src/xml/web_mobile.xml:17 diff --git a/addons/web_mobile/i18n/pt_BR.po b/addons/web_mobile/i18n/pt_BR.po index f9796b15e68..497811a83de 100644 --- a/addons/web_mobile/i18n/pt_BR.po +++ b/addons/web_mobile/i18n/pt_BR.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:16+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_mobile/static/src/xml/web_mobile.xml:17 diff --git a/addons/web_mobile/i18n/ro.po b/addons/web_mobile/i18n/ro.po index 914c8735078..56762531bce 100644 --- a/addons/web_mobile/i18n/ro.po +++ b/addons/web_mobile/i18n/ro.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:16+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_mobile/static/src/xml/web_mobile.xml:17 diff --git a/addons/web_mobile/i18n/ru.po b/addons/web_mobile/i18n/ru.po index c8f02bf171a..4acb1f7e558 100644 --- a/addons/web_mobile/i18n/ru.po +++ b/addons/web_mobile/i18n/ru.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:16+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_mobile/static/src/xml/web_mobile.xml:17 diff --git a/addons/web_mobile/i18n/sk.po b/addons/web_mobile/i18n/sk.po index 49d3638f37d..b2c11101905 100644 --- a/addons/web_mobile/i18n/sk.po +++ b/addons/web_mobile/i18n/sk.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:16+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_mobile/static/src/xml/web_mobile.xml:17 diff --git a/addons/web_mobile/i18n/sl.po b/addons/web_mobile/i18n/sl.po index a73305929d6..ab65ecf57b5 100644 --- a/addons/web_mobile/i18n/sl.po +++ b/addons/web_mobile/i18n/sl.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:16+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_mobile/static/src/xml/web_mobile.xml:17 diff --git a/addons/web_mobile/i18n/sq.po b/addons/web_mobile/i18n/sq.po index 5c873850778..55e5257e59d 100644 --- a/addons/web_mobile/i18n/sq.po +++ b/addons/web_mobile/i18n/sq.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:16+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_mobile/static/src/xml/web_mobile.xml:17 diff --git a/addons/web_mobile/i18n/sr@latin.po b/addons/web_mobile/i18n/sr@latin.po index b02908a1732..21fb79499c9 100644 --- a/addons/web_mobile/i18n/sr@latin.po +++ b/addons/web_mobile/i18n/sr@latin.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:16+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_mobile/static/src/xml/web_mobile.xml:17 diff --git a/addons/web_mobile/i18n/sv.po b/addons/web_mobile/i18n/sv.po index 724b2621195..f4908f9a5b7 100644 --- a/addons/web_mobile/i18n/sv.po +++ b/addons/web_mobile/i18n/sv.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:16+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_mobile/static/src/xml/web_mobile.xml:17 diff --git a/addons/web_mobile/i18n/tr.po b/addons/web_mobile/i18n/tr.po index 9520a0c7019..05254f7a52f 100644 --- a/addons/web_mobile/i18n/tr.po +++ b/addons/web_mobile/i18n/tr.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:16+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_mobile/static/src/xml/web_mobile.xml:17 diff --git a/addons/web_mobile/i18n/uk.po b/addons/web_mobile/i18n/uk.po index 234c7855b65..538f4dd3d59 100644 --- a/addons/web_mobile/i18n/uk.po +++ b/addons/web_mobile/i18n/uk.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:16+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_mobile/static/src/xml/web_mobile.xml:17 diff --git a/addons/web_mobile/i18n/zh_CN.po b/addons/web_mobile/i18n/zh_CN.po index d0df2f39e70..4e862baa027 100644 --- a/addons/web_mobile/i18n/zh_CN.po +++ b/addons/web_mobile/i18n/zh_CN.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:16+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_mobile/static/src/xml/web_mobile.xml:17 diff --git a/addons/web_process/i18n/ar.po b/addons/web_process/i18n/ar.po index 179f8072114..914327edc3f 100644 --- a/addons/web_process/i18n/ar.po +++ b/addons/web_process/i18n/ar.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:16+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:07+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_process/static/src/js/process.js:261 diff --git a/addons/web_process/i18n/bn.po b/addons/web_process/i18n/bn.po index d6b3ce283ab..2e9c70a3b23 100644 --- a/addons/web_process/i18n/bn.po +++ b/addons/web_process/i18n/bn.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:16+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:07+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_process/static/src/js/process.js:261 diff --git a/addons/web_process/i18n/bs.po b/addons/web_process/i18n/bs.po index ce5d9fca516..49cd7e8b35f 100644 --- a/addons/web_process/i18n/bs.po +++ b/addons/web_process/i18n/bs.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:16+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:07+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_process/static/src/js/process.js:261 diff --git a/addons/web_process/i18n/cs.po b/addons/web_process/i18n/cs.po index a63d5ab25e6..4d628b86ed3 100644 --- a/addons/web_process/i18n/cs.po +++ b/addons/web_process/i18n/cs.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:16+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:07+0000\n" +"X-Generator: Launchpad (build 15238)\n" "X-Poedit-Language: Czech\n" #. openerp-web diff --git a/addons/web_process/i18n/de.po b/addons/web_process/i18n/de.po index e1fb05f72cb..a17da6f35d6 100644 --- a/addons/web_process/i18n/de.po +++ b/addons/web_process/i18n/de.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:16+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:07+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_process/static/src/js/process.js:261 diff --git a/addons/web_process/i18n/en_GB.po b/addons/web_process/i18n/en_GB.po index f394191da25..c6d83693680 100644 --- a/addons/web_process/i18n/en_GB.po +++ b/addons/web_process/i18n/en_GB.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:16+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:07+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_process/static/src/js/process.js:261 diff --git a/addons/web_process/i18n/es.po b/addons/web_process/i18n/es.po index c2aa964a755..6241b010f03 100644 --- a/addons/web_process/i18n/es.po +++ b/addons/web_process/i18n/es.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:16+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:07+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_process/static/src/js/process.js:261 diff --git a/addons/web_process/i18n/es_CL.po b/addons/web_process/i18n/es_CL.po index d19d5948778..11c65c05236 100644 --- a/addons/web_process/i18n/es_CL.po +++ b/addons/web_process/i18n/es_CL.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:16+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:07+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_process/static/src/js/process.js:261 diff --git a/addons/web_process/i18n/es_CR.po b/addons/web_process/i18n/es_CR.po index 9071239b34c..56ce03a7d6a 100644 --- a/addons/web_process/i18n/es_CR.po +++ b/addons/web_process/i18n/es_CR.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:16+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:07+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_process/static/src/js/process.js:261 diff --git a/addons/web_process/i18n/es_EC.po b/addons/web_process/i18n/es_EC.po index e2291829fcc..1b22db0c671 100644 --- a/addons/web_process/i18n/es_EC.po +++ b/addons/web_process/i18n/es_EC.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:16+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:07+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_process/static/src/js/process.js:261 diff --git a/addons/web_process/i18n/fi.po b/addons/web_process/i18n/fi.po index 8e142fe3995..b70dcb13a65 100644 --- a/addons/web_process/i18n/fi.po +++ b/addons/web_process/i18n/fi.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:16+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:07+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_process/static/src/js/process.js:261 diff --git a/addons/web_process/i18n/fr.po b/addons/web_process/i18n/fr.po index 02c390c7141..3c97ea59436 100644 --- a/addons/web_process/i18n/fr.po +++ b/addons/web_process/i18n/fr.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:16+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:07+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_process/static/src/js/process.js:261 diff --git a/addons/web_process/i18n/gl.po b/addons/web_process/i18n/gl.po index ef2e5749362..889f33c8f2c 100644 --- a/addons/web_process/i18n/gl.po +++ b/addons/web_process/i18n/gl.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:16+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:07+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_process/static/src/js/process.js:261 diff --git a/addons/web_process/i18n/hr.po b/addons/web_process/i18n/hr.po index f1c0c885d07..49645a644bf 100644 --- a/addons/web_process/i18n/hr.po +++ b/addons/web_process/i18n/hr.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:16+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:07+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_process/static/src/js/process.js:261 diff --git a/addons/web_process/i18n/it.po b/addons/web_process/i18n/it.po index 13e25e05474..4269c3bfa5d 100644 --- a/addons/web_process/i18n/it.po +++ b/addons/web_process/i18n/it.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:16+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:07+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_process/static/src/js/process.js:261 diff --git a/addons/web_process/i18n/ja.po b/addons/web_process/i18n/ja.po index 56293eaf9be..d2f350eea23 100644 --- a/addons/web_process/i18n/ja.po +++ b/addons/web_process/i18n/ja.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:16+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:07+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_process/static/src/js/process.js:261 diff --git a/addons/web_process/i18n/ka.po b/addons/web_process/i18n/ka.po index 8ea3dbe4e69..a029ffed7f9 100644 --- a/addons/web_process/i18n/ka.po +++ b/addons/web_process/i18n/ka.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:16+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:07+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_process/static/src/js/process.js:261 diff --git a/addons/web_process/i18n/mk.po b/addons/web_process/i18n/mk.po index 0f557c9514a..29909a57694 100644 --- a/addons/web_process/i18n/mk.po +++ b/addons/web_process/i18n/mk.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:16+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:07+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_process/static/src/js/process.js:261 diff --git a/addons/web_process/i18n/nb.po b/addons/web_process/i18n/nb.po index 9dc5cbec6e0..3a8aa36ce1c 100644 --- a/addons/web_process/i18n/nb.po +++ b/addons/web_process/i18n/nb.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:16+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:07+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_process/static/src/js/process.js:261 diff --git a/addons/web_process/i18n/nl.po b/addons/web_process/i18n/nl.po index 44ab671b6ac..5c5e956361f 100644 --- a/addons/web_process/i18n/nl.po +++ b/addons/web_process/i18n/nl.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:16+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:07+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_process/static/src/js/process.js:261 diff --git a/addons/web_process/i18n/nl_BE.po b/addons/web_process/i18n/nl_BE.po index b278d355eb3..e66e4518c47 100644 --- a/addons/web_process/i18n/nl_BE.po +++ b/addons/web_process/i18n/nl_BE.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:16+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:07+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_process/static/src/js/process.js:261 diff --git a/addons/web_process/i18n/pl.po b/addons/web_process/i18n/pl.po index cfc02b1f574..c92550eba54 100644 --- a/addons/web_process/i18n/pl.po +++ b/addons/web_process/i18n/pl.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:16+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:07+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_process/static/src/js/process.js:261 diff --git a/addons/web_process/i18n/pt.po b/addons/web_process/i18n/pt.po index 22d4c23d4a1..e465fef528d 100644 --- a/addons/web_process/i18n/pt.po +++ b/addons/web_process/i18n/pt.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:16+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:07+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_process/static/src/js/process.js:261 diff --git a/addons/web_process/i18n/pt_BR.po b/addons/web_process/i18n/pt_BR.po index e2d0e8c4d3a..ee72ef0bec9 100644 --- a/addons/web_process/i18n/pt_BR.po +++ b/addons/web_process/i18n/pt_BR.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:16+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:07+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_process/static/src/js/process.js:261 diff --git a/addons/web_process/i18n/ro.po b/addons/web_process/i18n/ro.po index 9ab645f4292..e208d558d67 100644 --- a/addons/web_process/i18n/ro.po +++ b/addons/web_process/i18n/ro.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:16+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:07+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_process/static/src/js/process.js:261 diff --git a/addons/web_process/i18n/ru.po b/addons/web_process/i18n/ru.po index 42457aca3b8..95bb891e53f 100644 --- a/addons/web_process/i18n/ru.po +++ b/addons/web_process/i18n/ru.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:16+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:07+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_process/static/src/js/process.js:261 diff --git a/addons/web_process/i18n/sl.po b/addons/web_process/i18n/sl.po new file mode 100644 index 00000000000..aa0b0ffd9dd --- /dev/null +++ b/addons/web_process/i18n/sl.po @@ -0,0 +1,118 @@ +# Slovenian translation for openerp-web +# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012 +# This file is distributed under the same license as the openerp-web package. +# FIRST AUTHOR , 2012. +# +msgid "" +msgstr "" +"Project-Id-Version: openerp-web\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2012-02-07 19:19+0100\n" +"PO-Revision-Date: 2012-05-23 20:57+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Slovenian \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2012-05-24 11:42+0000\n" +"X-Generator: Launchpad (build 15288)\n" + +#. openerp-web +#: addons/web_process/static/src/js/process.js:261 +msgid "Cancel" +msgstr "Prekliči" + +#. openerp-web +#: addons/web_process/static/src/js/process.js:262 +msgid "Save" +msgstr "Shrani" + +#. openerp-web +#: addons/web_process/static/src/xml/web_process.xml:6 +msgid "Process View" +msgstr "" + +#. openerp-web +#: addons/web_process/static/src/xml/web_process.xml:19 +msgid "Documentation" +msgstr "Dokumentacija" + +#. openerp-web +#: addons/web_process/static/src/xml/web_process.xml:19 +msgid "Read Documentation Online" +msgstr "Preberi spletno dokumentacijo" + +#. openerp-web +#: addons/web_process/static/src/xml/web_process.xml:25 +msgid "Forum" +msgstr "Forum" + +#. openerp-web +#: addons/web_process/static/src/xml/web_process.xml:25 +msgid "Community Discussion" +msgstr "Razprava skupnosti" + +#. openerp-web +#: addons/web_process/static/src/xml/web_process.xml:31 +msgid "Books" +msgstr "Knjige" + +#. openerp-web +#: addons/web_process/static/src/xml/web_process.xml:31 +msgid "Get the books" +msgstr "" + +#. openerp-web +#: addons/web_process/static/src/xml/web_process.xml:37 +msgid "OpenERP Enterprise" +msgstr "OpenERP Enterprise" + +#. openerp-web +#: addons/web_process/static/src/xml/web_process.xml:37 +msgid "Purchase OpenERP Enterprise" +msgstr "" + +#. openerp-web +#: addons/web_process/static/src/xml/web_process.xml:52 +msgid "Process" +msgstr "Proces" + +#. openerp-web +#: addons/web_process/static/src/xml/web_process.xml:56 +msgid "Notes:" +msgstr "Zapiski:" + +#. openerp-web +#: addons/web_process/static/src/xml/web_process.xml:59 +msgid "Last modified by:" +msgstr "Zadnja sprememba:" + +#. openerp-web +#: addons/web_process/static/src/xml/web_process.xml:59 +msgid "N/A" +msgstr "N/A" + +#. openerp-web +#: addons/web_process/static/src/xml/web_process.xml:62 +msgid "Subflows:" +msgstr "" + +#. openerp-web +#: addons/web_process/static/src/xml/web_process.xml:75 +msgid "Related:" +msgstr "" + +#. openerp-web +#: addons/web_process/static/src/xml/web_process.xml:88 +msgid "Select Process" +msgstr "Izberi postopek" + +#. openerp-web +#: addons/web_process/static/src/xml/web_process.xml:98 +msgid "Select" +msgstr "Izberi" + +#. openerp-web +#: addons/web_process/static/src/xml/web_process.xml:109 +msgid "Edit Process" +msgstr "" diff --git a/addons/web_process/i18n/sr@latin.po b/addons/web_process/i18n/sr@latin.po index c3254977aeb..2c2c1b32461 100644 --- a/addons/web_process/i18n/sr@latin.po +++ b/addons/web_process/i18n/sr@latin.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:16+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:07+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_process/static/src/js/process.js:261 diff --git a/addons/web_process/i18n/sv.po b/addons/web_process/i18n/sv.po index acc5819f1ac..6485aab9dea 100644 --- a/addons/web_process/i18n/sv.po +++ b/addons/web_process/i18n/sv.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:16+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:07+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_process/static/src/js/process.js:261 diff --git a/addons/web_process/i18n/tr.po b/addons/web_process/i18n/tr.po index 79bb2ff0cfb..f3bbb28beff 100644 --- a/addons/web_process/i18n/tr.po +++ b/addons/web_process/i18n/tr.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:16+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:07+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_process/static/src/js/process.js:261 diff --git a/addons/web_process/i18n/zh_CN.po b/addons/web_process/i18n/zh_CN.po index 954c8420bed..3651fb33ee6 100644 --- a/addons/web_process/i18n/zh_CN.po +++ b/addons/web_process/i18n/zh_CN.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:16+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:07+0000\n" +"X-Generator: Launchpad (build 15238)\n" #. openerp-web #: addons/web_process/static/src/js/process.js:261 diff --git a/addons/web_rpc/i18n/es_CR.po b/addons/web_rpc/i18n/es_CR.po index 045e8cc9e9c..6635d89dd40 100644 --- a/addons/web_rpc/i18n/es_CR.po +++ b/addons/web_rpc/i18n/es_CR.po @@ -14,7 +14,7 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:16+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:06+0000\n" +"X-Generator: Launchpad (build 15238)\n" diff --git a/addons/web_tests/i18n/es_CR.po b/addons/web_tests/i18n/es_CR.po index 045e8cc9e9c..671c02e948d 100644 --- a/addons/web_tests/i18n/es_CR.po +++ b/addons/web_tests/i18n/es_CR.po @@ -14,7 +14,7 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-05-08 05:16+0000\n" -"X-Generator: Launchpad (build 15204)\n" +"X-Launchpad-Export-Date: 2012-05-15 05:07+0000\n" +"X-Generator: Launchpad (build 15238)\n" diff --git a/doc/conf.py b/doc/conf.py index 69e49d0e5a7..a5ff6bed7e1 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -247,6 +247,7 @@ texinfo_documents = [ # How to display URL addresses: 'footnote', 'no', or 'inline'. #texinfo_show_urls = 'footnote' +todo_include_todos = True # Example configuration for intersphinx: refer to the Python standard library. intersphinx_mapping = { diff --git a/doc/index.rst b/doc/index.rst index 888ff7705f2..9f54b879acc 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -16,14 +16,14 @@ Contents: async rpc + search-view + Older stuff ----------- .. toctree:: :maxdepth: 2 - search-view - getting-started production widgets diff --git a/doc/search-view.rst b/doc/search-view.rst index 89051884596..f94132bf3bd 100644 --- a/doc/search-view.rst +++ b/doc/search-view.rst @@ -13,217 +13,388 @@ multiple fields). The goal for this change is twofold: * Improve the looks and behaviors of the view, and the fit within OpenERP Web's new design. -The faceted search is implemented through a monkey-patched +The internal structure of the faceted search is inspired by `VisualSearch `_ -[#]_. VisualSearch is based on `Backbone -`_ and makes significant -use of Backbone's models and views. As a result, understanding the -implementation of the OpenERP Web 6.2 search view also requires a -basic understanding of Backbone. +[#previous]_. + +As does VisualSearch, the new search view is based on `Backbone`_ and +makes significant use of Backbone's models and collections (OpenERP +Web's widgets make a good replacement for Backbone's own views). As a +result, understanding the implementation details of the OpenERP Web 7 +search view also requires a basic understanding of Backbone's models, +collections and events. .. note:: This document may mention *fetching* data. This is a shortcut for - "returning a deferred to [whatever is being fetched]". Unless - further noted, the function or method may opt to return nothing by - fetching ``null`` (which can easily be done by returning - ``$.when(null)``, which simply wraps the ``null`` in a Deferred). + "returning a :js:class:`Deferred` to [whatever is being + fetched]". Unless further noted, the function or method may opt to + return nothing by fetching ``null`` (which can easily be done by + returning ``$.when(null)``, which simply wraps the ``null`` in a + Deferred). -Interaction between the Search View and VisualSearch ----------------------------------------------------- +Working with the search view: creating new inputs +------------------------------------------------- -The core data abstraction in VisualSearch is -:js:class:`VS.model.SearchQuery`, a backbone Collection holding -instances of the :js:class:`VS.model.SearchFacet` backbone Model. +The primary component of search views, as with all other OpenERP +views, are inputs. The search view has two types of inputs — filters +and fields — but only one is easly customizable: fields. -Backbone models can hold any number of informal properties interacted -with through the :js:func:`~Backbone.Model.get` and -:js:func:`~Backbone.Model.set` methods. VisualSearch reserves three -such properties for its behavior, these properties *must* be correctly -set on all search facets created programmatically: +The mapping from OpenERP field types (and widgets) to search view +objects is stored in the ``openerp.web.search.fields`` +:js:class:`~openerp.web.Registry` where new field types and widgets +can be added. -``app`` - a reference to the VisualSearch instance using this facet. In the - search view, this instance is available as the - :js:attr:`~openerp.web.SearchView.vs` attribute to the searchview - instance. +Search view inputs have four main roles: -``category`` - the *name* of the facet, displayed in the first section of a facet - view. +Loading defaults +++++++++++++++++ -``value`` - the *displayed value* of the facet, it is directly printed to the - right of the category. +Once the search view has initialized all its inputs, it will call +:js:func:`~openerp.web.search.Input.facet_for_defaults` on each input, +passing it a mapping (a javascript object) of ``name:value`` extracted +from the action's context. -The search view uses additional keys to store state and data it needs -to associate with facet objects: +This method should fetch a :js:class:`~openerp.web.search.Facet` (or +an equivalent object) for the field's default value if applicable (if +a default value for the field is found in the ``defaults`` mapping). -``field`` - the search field instance which created the facet, used when the - search view needs to serialize the facets. +A default implementation is provided which checks if ``defaults`` +contains a non-falsy value for the field's ``@name`` and calls +:js:func:`openerp.web.search.Input.facet_for` with that value. -``json`` - the "logical" value of the facet, can be absent if the logical and - "printable" values of the facet are the same (e.g. for a basic text - field). +There is no default implementation of +:js:func:`openerp.web.search.Input.facet_for` [#no_impl]_, but +:js:class:`openerp.web.search.Field` provides one, which uses the +value as-is to fetch a :js:class:`~openerp.web.search.Facet`. - This value may be a complex javascript object such as an array (the - name stands for json-compatible value, it is not a JSON-encoded - string). +Providing completions ++++++++++++++++++++++ -.. note:: +An important component of the new search view is the auto-completion +pane, and the task of providing completion items is delegated to +inputs through the :js:func:`~openerp.web.search.Input.complete` +method. - in order to simplify getting the logical value of a search facet - model, :js:class:`VS.model.SearchFacet` has been extended with a - :js:func:`~VS.model.SearchFacet.value` method +This method should take a single argument (the string being typed by +the user) and should fetch an ``Array`` of possible completions +[#completion]_. -Extensions and patches to VisualSearch -++++++++++++++++++++++++++++++++++++++ +A default implementation is provided which fetches nothing. -.. js:function:: VS.model.SearchFacet.value() +A completion item is a javascript object with two keys (technically it +can have any number of keys, but only these two will be used by the +search view): - Bundles the logic of selecting between ``json`` and ``value`` in - order to get the logical value of a facet. +``label`` -.. js:attribute:: VS.options.callbacks.make_facet + The string which will be displayed in the completion pane. It may + be formatted using HTML (inline only), as a result if ``value`` is + interpolated into it it *must* be escaped. ``_.escape`` can be + used for this. - Called by :js:class:`VS.ui.SearchBox` when it needs to create a - new search facet *view*. By default this is not supported by - VisualSearch, and requires monkey-patching - :js:func:`VS.ui.SearchBox.renderFacet`. +``facet`` - This patch should not alter any behavior if - :js:attr:`~VS.options.callbacks.make_facet` is not used. + Either a :js:class:`~openerp.web.search.Facet` object or (more + commonly) the corresponding attributes object. This is the facet + which will be inserted into the search query if the completion + item is selected by the user. -.. js:attribute:: VS.options.callbacks.make_input +If the ``facet`` is not provided (not present, ``null``, ``undefined`` +or any other falsy value), the completion item will not be selectable +and will act as a section title of sort (the ``label`` will be +formatted differently). If an input *may* fetch multiple completion +items, it *should* prefix those with a section title using its own +name. This has no technical consequence but is clearer for users. - Similar to :js:attr:`~VS.options.callbacks.make_facet`, but called - when the :js:class:`~VS.ui.SearchBox` needs to create a search - input view. It requires monkey-patching - :js:func:`VS.ui.SearchBox.renderSearchInput`. +Providing drawer/supplementary UI ++++++++++++++++++++++++++++++++++ -Finally, :js:func:`VS.ui.SearchBox.searchEvent` is monkey-patched to -get rid of its serialize/load round-tripping of facet data: the -additional attributes needed by the search view don't round-trip (at -all) so VisualSearch must not load any data from its (fairly -simplistic) text-serialization format. +For some inputs (fields or not), interaction via autocompletion may be +awkward or even impossible. -.. note:: +These may opt to being rendered in a "drawer" as well or instead. In +that case, they will undergo the normal widget lifecycle and be +rendered inside the drawer. - a second issue is that — as of `commit 3fca87101d`_ — VisualSearch - correctly serializes facet categories containing spaces but is - unable to load them back in. It also does not handle facets with - *empty* categories correctly. +.. Found no good type-based way to handle this, since there is no MI + (so no type-tagging) and it's possible for both Field and non-Field + input to be put into the drawer, for whatever reason (e.g. some + sort of auto-detector completion item for date widgets, but a + second more usual calendar widget in the drawer for more + obvious/precise interactions) -Loading Defaults ----------------- +Any input can note its desire to be rendered in the drawer by +returning a truthy value from +:js:func:`~openerp.web.search.Input.in_drawer`. -After loading the view data, the SearchView will call -:js:func:`openerp.web.search.Input.facet_for_defaults` on each of its -inputs with the ``defaults`` mapping of key:values (where each key -corresponds to an input). This method should look into the -``defaults`` mapping and fetch the field's default value as a -:js:class:`~VS.models.SearchFacet` if applicable. +By default, :js:func:`~openerp.web.search.Input.in_drawer` returns the +value of :js:attr:`~openerp.web.search.Input._in_drawer`, which is +``false``. The behavior can be toggled either by redefining the +attribute to ``true`` (either on the class or on the input), or by +overriding :js:func:`~openerp.web.search.Input.in_drawer` itself. -The default implementation is to check if there is a default value for -the current input's name (via -:js:attr:`openerp.web.search.Input.attrs.name`) and if there is to -convert this value to a :js:class:`~VS.models.SearchFacet` by calling -:js:func:`openerp.web.search.Input.facet_for`. +The input will be rendered in the full width of the drawer, it will be +started only once (per view). -There is no built-in (default) implementation of -:js:func:`openerp.web.search.Input.facet_for`. This method should -fetch the :js:class:`~VS.models.SearchFacet` corresponding to the -"raw" value passed as argument. +.. todo:: drawer API (if a widget wants to close the drawer in some + way), part of the low-level SearchView API/interactions? -Providing auto-completion -------------------------- -An important component of the unified search view is the faceted -autocompletion pane. In order to provide good user and developer -experiences, this pane is pluggable (value-wise): each and every -control of the search view can check for (and provide) categorized -auto-completions for a given value being typed by the user. +.. todo:: handle filters and filter groups via a "driver" input which + dynamically collects, lays out and renders filters? => + exercises drawer thingies -This is done by implementing -:js:func:`openerp.web.search.Input.complete`: the method is provided -with a value to complete, and should fetch an ``Array`` of completion -values. These completion values will then be provided to the global -autocompletion list, implemented via `jquery-ui autocomplete -`_. +Programmatic interactions: internal model +----------------------------------------- -Because the search view uses a custom renderer for its completion, it -was possible to fix some incompatibilities between the attributes of -completion items and VisualSearch's facet model: +This new searchview is built around an instance of +:js:class:`~openerp.web.search.SearchQuery` available as +:js:attr:`openerp.web.SearchView.query`. -Actual completion items -+++++++++++++++++++++++ +The query is a `backbone collection`_ of +:js:class:`~openerp.web.search.Facet` objects, which can be interacted +with directly by external objects or search view controls +(e.g. widgets displayed in the drawer). -These are selectable items, and upon selection are turned into actual -search facet objects. They should have all the properties of a search -facet (as described above) and can have one more optional property: -``label``. +.. js:class:: openerp.web.search.SearchQuery -When rendering an item in the list, the renderer will first try to use -the ``label`` property if it exists (``label`` can contain HTML and -will be inserted as-is, so it can bold or emphasize some of its -elements), if it does not the ``value`` property will be used. + The current search query of the search view, provides convenience + behaviors for manipulating :js:class:`~openerp.web.search.Facet` + on top of the usual `backbone collection`_ methods. -.. note:: the ``app`` key should not be specified on completion item, - it will be set automatically when the search view creates - the facet from the item. + The query ensures all of its facets contain at least one + :js:class:`~openerp.web.search.FacetValue` instance. Otherwise, + the facet is automatically removed from the query. -Section titles -++++++++++++++ + .. js:function:: openerp.web.search.SearchQuery.add(values, options) -A second kind of completion values is the section titles. Section -titles are similar to completion items but only have a ``category`` -property. They will be rendered in a different style and can not be -selected in the auto-completion (they will be skipped). + Overridden from the base ``add`` method so that adding a facet + which is *already* in the collection will merge the value of + the new facet into the old one rather than add a second facet + with different values. -.. note:: + :param values: facet, facet attributes or array thereof + :returns: the collection itself - Technically, section title items can have any property they want - *as long as they do not have a value property*. A ``value`` - property set to ``false``, ``null`` or ``undefined`` is **not** - equivalent to not having a ``value`` property. + .. js:function:: openerp.web.search.SearchQuery.toggle(value, options) -If an input *may* fetch more than one completion item, it *should* -prepend a section title (using its own name) to the completion items. + Convenience method for toggling facet values in a query: + removes the values (through the facet itself) if they are + present, adds them if they are not. If the facet itself is not + in the collection, adds it automatically. + + A toggling is atomic: only one change event will be triggered + on the facet regardless of the number of values added to or + removed from the facet (if the facet already exists), and the + facet is only removed from the query if it has no value *at + the end* of the toggling. + + :param value: facet or facet attributes + :returns: the collection + +.. js:class:: openerp.web.search.Facet + + A `backbone model`_ representing a single facet of the current + research. May map to a search field, or to a more complex or + fuzzier input (e.g. a custom filter or an advanced search). + + .. js:attribute:: category + + The displayed name of the facet, as a ``String``. This is a + backbone model attribute. + + .. js:attribute:: field + + The :js:class:`~openerp.web.search.Input` instance which + originally created the facet [#facet-field]_, used to delegate + some operations (such as serializing the facet's values to + domains and contexts). This is a backbone model attribute. + + .. js:attribute:: values + + :js:class:`~openerp.web.search.FacetValues` as a javascript + attribute, stores all the values for the facet and helps + propagate their events to the facet. Is also available as a + backbone attribute (via ``#get`` and ``#set``) in which cases + it serializes to and deserializes from javascript arrays (via + ``Collection#toJSON`` and ``Collection#reset``). + + .. js:attribute:: [icon] + + optional, a single ASCII letter (a-z or A-Z) mapping to the + bundled mnmliconsRegular icon font. + + When a facet with an ``icon`` attribute is rendered, the icon + is displayed (in the icon font) in the first section of the + facet instead of the ``category``. + + By default, only filters make use of this facility. + +.. js:class:: openerp.web.search.FacetValues + + `Backbone collection`_ of + :js:class:`~openerp.web.search.FacetValue` instances. + +.. js:class:: openerp.web.search.FacetValue + + `Backbone model`_ representing a single value within a facet, + represents a pair of (displayed name, logical value). + + .. js:attribute:: label + + Backbone model attribute storing the "displayable" + representation of the value, visually output to the + user. Must be a string. + + .. js:attribute:: value + + Backbone model attribute storing the logical/internal value + (of itself), will be used by + :js:class:`~openerp.web.search.Input` to serialize to domains + and contexts. + + Can be of any type. Converting from facet objects ----------------------------- Ultimately, the point of the search view is to allow searching. In OpenERP this is done via :ref:`domains `. On -the other hand, the OpenERP Web 6.2 search view's state is modelled -after a collection of :js:class:`~VS.model.SearchFacet`, and each +the other hand, the OpenERP Web 7 search view's state is modelled +after a collection of :js:class:`~openerp.web.search.Facet`, and each field of a search view may have special requirements when it comes to -the domains it produces [#]_. +the domains it produces [#special]_. So there needs to be some way of mapping -:js:class:`~VS.model.SearchFacet` objects to OpenERP search data. +:js:class:`~openerp.web.search.Facet` objects to OpenERP search data. This is done via an input's :js:func:`~openerp.web.search.Input.get_domain` and :js:func:`~openerp.web.search.Input.get_context`. Each takes a -:js:class:`~VS.model.SearchFacet` and returns whatever it's supposed -to generate (a domain or a context, respectively). Either can return -``null`` if the current value does not map to a domain or context, and -can throw an :js:class:`~openerp.web.search.Invalid` exception if the -value is not valid at all for the field. +:js:class:`~openerp.web.search.Facet` and returns whatever it's +supposed to generate (a domain or a context, respectively). Either can +return ``null`` if the current value does not map to a domain or +context, and can throw an :js:class:`~openerp.web.search.Invalid` +exception if the value is not valid at all for the field. -Converting to facet objects ---------------------------- +.. note:: + + The :js:class:`~openerp.web.search.Facet` object can have any + number of values (from 1 upwards) + +.. note:: + + There is a third conversion method, + :js:func:`~openerp.web.search.Input.get_groupby`, which returns an + ``Array`` of groupby domains rather than a single context. At this + point, it is only implemented on (and used by) filters. + +Field services +++++++++++++++ + +:js:class:`~openerp.web.search.Field` provides a default +implementation of :js:func:`~openerp.web.search.Input.get_domain` and +:js:func:`~openerp.web.search.Input.get_context` taking care of most +of the peculiarities pertaining to OpenERP's handling of fields in +search views. It also provides finer hooks to let developers of new +fields and widgets customize the behavior they want without +necessarily having to reimplement all of +:js:func:`~openerp.web.search.Input.get_domain` or +:js:func:`~openerp.web.search.Input.get_context`: + +.. js:function:: openerp.web.search.Field.get_context(facet) + + If the field has no ``@context``, simply returns + ``null``. Otherwise, calls + :js:func:`~openerp.web.search.Field.value_from` once for each + :js:class:`~openerp.web.search.FacetValue` of the current + :js:class:`~openerp.web.search.Facet` (in order to extract the + basic javascript object from the + :js:class:`~openerp.web.search.FacetValue` then evaluates + ``@context`` with each of these values set as ``self``, and + returns the union of all these contexts. + + :param facet: + :type facet: openerp.web.search.Facet + :returns: a context (literal or compound) + +.. js:function:: openerp.web.search.Field.get_domain(facet) + + If the field has no ``@filter_domain``, calls + :js:func:`~openerp.web.search.Field.make_domain` once with each + :js:class:`~openerp.web.search.FacetValue` of the current + :js:class:`~openerp.web.search.Facet` as well as the field's + ``@name`` and either its ``@operator`` or + :js:attr:`~openerp.web.search.Field.default_operator`. + + If the field has an ``@filter_value``, calls + :js:func:`~openerp.web.search.Field.value_from` once per + :js:class:`~openerp.web.search.FacetValue` and evaluates + ``@filter_value`` with each of these values set as ``self``. + + In either case, "ors" all of the resulting domains (using ``|``) + if there is more than one + :js:class:`~openerp.web.search.FacetValue` and returns the union + of the result. + + :param facet: + :type facet: openerp.web.search.Facet + :returns: a domain (literal or compound) + +.. js:function:: openerp.web.search.Field.make_domain(name, operator, facetValue) + + Builds a literal domain from the provided data. Calls + :js:func:`~openerp.web.search.Field.value_from` on the + :js:class:`~openerp.web.search.FacetValue` and evaluates and sets + it as the domain's third value, uses the other two parameters as + the first two values. + + Can be overridden to build more complex default domains. + + :param String name: the field's name + :param String operator: the operator to use in the field's domain + :param facetValue: + :type facetValue: openerp.web.search.FacetValue + :returns: Array<(String, String, Object)> + +.. js:function:: openerp.web.search.Field.value_from(facetValue) + + Extracts a "bare" javascript value from the provided + :js:class:`~openerp.web.search.FacetValue`, and returns it. + + The default implementation will simply return the ``value`` + backbone property of the argument. + + :param facetValue: + :type facetValue: openerp.web.search.FacetValue + :returns: Object + +.. js:attribute:: openerp.web.search.Field.default_operator + + Operator used to build a domain when a field has no ``@operator`` + or ``@filter_domain``. ``"="`` for + :js:class:`~openerp.web.search.Field` + +Arbitrary data storage +++++++++++++++++++++++ + +:js:class:`~openerp.web.search.Facet` and +:js:class:`~openerp.web.search.FacetValue` objects (and structures) +provided by your widgets should never be altered by the search view +(or an other widget). This means you are free to add arbitrary fields +in these structures if you need to (because you have more complex +needs than the attributes described in this document). + +Ideally this should be avoided, but the possibility remains. Changes ------- -.. todo:: merge in changelog instead +.. todo:: merge in changelog instead? The displaying of the search view was significantly altered from -OpenERP Web 6.1 to OpenERP Web 6.2. +OpenERP Web 6.1 to OpenERP Web 7. As a result, while the external API used to interact with the search view does not change many internal details — including the interaction @@ -247,11 +418,11 @@ Widgets API * :js:func:`~openerp.web.search.Input.clear` has been removed since clearing the search view now simply consists of removing all search - facets from VisualSearch + facets * :js:func:`~openerp.web.search.Input.get_domain` and :js:func:`~openerp.web.search.Input.get_context` now take a - :js:class:`~VS.model.SearchFacet` as parameter, from which it's + :js:class:`~openerp.web.search.Facet` as parameter, from which it's their job to get whatever value they want * :js:func:`~openerp.web.search.Input.get_groupby` has been added. It returns @@ -271,19 +442,16 @@ Filters Fields ++++++ -* ``get_value`` now takes a :js:class:`~VS.model.SearchFacet` (instead - of taking no argument). - - A default implementation is provided as - :js:func:`openerp.web.search.Field.get_value` and simply calls - :js:func:`VS.model.SearchFacet.value`. +* ``get_value`` has been replaced by + :js:func:`~openerp.web.search.Field.value_from` as it now takes a + :js:class:`~openerp.web.search.FacetValue` argument (instead of no + argument). It provides a default implementation returning the + ``value`` property of its argument. * The third argument to - :js:func:`~openerp.web.search.Field.make_domain` is now the - :js:class:`~VS.model.SearchFacet` received by - :js:func:`~openerp.web.search.Field.get_domain`, so child classes - have all the information they need to derive the "right" resulting - domain. + :js:func:`~openerp.web.search.Field.make_domain` is now a + :js:class:`~openerp.web.search.FacetValue` so child classes have all + the information they need to derive the "right" resulting domain. Custom filters ++++++++++++++ @@ -300,12 +468,82 @@ Many To One :js:func:`openerp.web.search.ManyToOneField.setup_autocomplete` has been removed. -.. [#] the library code is untouched, all patching is performed in the - Search view's implementation module. Changes to the - VisualSearch code should only update the library to new - revisions or releases. -.. [#] search view fields may also bundle context data to add to the - search context +Advanced Search ++++++++++++++++ + +* The advanced search is now a more standard + :js:class:`~openerp.web.search.Input` configured to be rendered in + the drawer. + +* :js:class:`~openerp.web.search.ExtendedSearchProposition.Field` are + now standard widgets, with the "right" behaviors (they don't rebind + their ``$element`` in ``start()``) + +* The ad-hoc optional setting of the openerp field descriptor on a + :js:class:`~openerp.web.search.ExtendedSearchProposition.Field` has + been removed, the field descriptor is now passed as second argument + to the + :js:class:`~openerp.web.search.ExtendedSearchProposition.Field`'s + constructor, and bound to its + :js:attr:`~openerp.web.search.ExtendedSearchProposition.Field.field`. + +* Instead of its former domain triplet ``(field, operator, value)``, + :js:func:`~openerp.web.search.ExtendedSearchProposition.get_proposition` + now returns an object with two fields ``label`` and ``value``, + respectively a human-readable version of the proposition and the + corresponding domain triplet for the proposition. + +.. [#previous] + + the original view was implemented on top of a monkey-patched + VisualSearch, but as our needs diverged from VisualSearch's goal + this made less and less sense ultimately leading to a clean-room + reimplementation + +.. [#no_impl] + + In case you are extending the search view with a brand new type of + input + +.. [#completion] + + Ideally this array should not hold more than about 10 items, but + the search view does not put any constraint on this at the + moment. Note that this may change. + +.. [#facet-field] + + ``field`` does not actually need to be an instance of + :js:class:`~openerp.web.search.Input`, nor does it need to be what + created the facet, it just needs to provide the three + facet-serialization methods + :js:func:`~openerp.web.search.Input.get_domain`, + :js:func:`~openerp.web.search.Input.get_context` and + :js:func:`~openerp.web.search.Input.get_gropuby`, existing + :js:class:`~openerp.web.search.Input` subtypes merely provide + convenient base implementation for those methods. + + Complex search view inputs (especially those living in the drawer) + may prefer using object literals with the right slots returning + closed-over values or some other scheme un-bound to an actual + :js:class:`~openerp.web.search.Input`, as + :js:class:`~openerp.web.search.CustomFilters` and + :js:class:`~openerp.web.search.Advanced` do. + +.. [#special] + + search view fields may also bundle context data to add to the + search context + +.. _Backbone: + http://documentcloud.github.com/backbone/ + +.. _Backbone.Collection: +.. _Backbone collection: + http://documentcloud.github.com/backbone/#Collection + +.. _Backbone model: + http://documentcloud.github.com/backbone/#Model .. _commit 3fca87101d: - https://github.com/documentcloud/visualsearch/commit/3fca87101d + https://github.com/documentcloud/visualsearch/commit/3fca87101d