[MERGE]with latest.
bzr revid: kch@tinyerp.com-20140418084142-d8lm531l8dyk7roo
This commit is contained in:
commit
8b2bc4da90
|
@ -6,6 +6,3 @@ sys.modules['openerp.addons.web.http'] = openerp.http
|
|||
http = openerp.http
|
||||
|
||||
import controllers
|
||||
import cli
|
||||
|
||||
wsgi_postload = http.wsgi_postload
|
||||
|
|
|
@ -11,7 +11,6 @@ This module provides the core of the OpenERP Web Client.
|
|||
""",
|
||||
'depends': ['base'],
|
||||
'auto_install': True,
|
||||
'post_load': 'wsgi_postload',
|
||||
'data': [
|
||||
'views/webclient_templates.xml',
|
||||
],
|
||||
|
@ -36,7 +35,6 @@ This module provides the core of the OpenERP Web Client.
|
|||
"static/lib/jquery.ui.notify/js/jquery.notify.js",
|
||||
"static/lib/jquery.deferred-queue/jquery.deferred-queue.js",
|
||||
"static/lib/jquery.scrollTo/jquery.scrollTo-min.js",
|
||||
"static/lib/jquery.tipsy/jquery.tipsy.js",
|
||||
"static/lib/jquery.textext/jquery.textext.js",
|
||||
"static/lib/jquery.timeago/jquery.timeago.js",
|
||||
"static/lib/bootstrap/js/bootstrap.js",
|
||||
|
@ -67,7 +65,6 @@ This module provides the core of the OpenERP Web Client.
|
|||
"static/lib/jquery.ui.bootstrap/css/custom-theme/jquery-ui-1.9.0.custom.css",
|
||||
"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/jquery.textext/jquery.textext.css",
|
||||
"static/lib/fontawesome/css/font-awesome.css",
|
||||
"static/lib/bootstrap/css/bootstrap.css",
|
||||
|
@ -87,7 +84,6 @@ This module provides the core of the OpenERP Web Client.
|
|||
"static/test/data.js",
|
||||
"static/test/list-utils.js",
|
||||
"static/test/formats.js",
|
||||
"static/test/jsonrpc.js",
|
||||
"static/test/rpc-misordered.js",
|
||||
"static/test/evals.js",
|
||||
"static/test/search.js",
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
import test_js
|
|
@ -1,35 +0,0 @@
|
|||
import logging
|
||||
import optparse
|
||||
import sys
|
||||
|
||||
import unittest2
|
||||
|
||||
import openerp
|
||||
import openerp.addons.web.tests
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
class TestJs(openerp.cli.Command):
|
||||
def run(self, args):
|
||||
self.parser = parser = optparse.OptionParser()
|
||||
parser.add_option("-d", "--database", dest="db_name", default=False, help="specify the database name")
|
||||
parser.add_option("--xmlrpc-port", dest="xmlrpc_port", default=8069, help="specify the TCP port for the XML-RPC protocol", type="int")
|
||||
# proably need to add both --superadmin-password and --database-admin-password
|
||||
self.parser.parse_args(args)
|
||||
|
||||
# test ony uses db_name xmlrpc_port admin_passwd, so use the server one for the actual parsing
|
||||
|
||||
config = openerp.tools.config
|
||||
config.parse_config(args)
|
||||
# needed until runbot is fixed
|
||||
config['db_password'] = config['admin_passwd']
|
||||
|
||||
# run js tests
|
||||
openerp.netsvc.init_alternative_logger()
|
||||
suite = unittest2.TestSuite()
|
||||
suite.addTests(unittest2.TestLoader().loadTestsFromModule(openerp.addons.web.tests.test_js))
|
||||
r = unittest2.TextTestRunner(verbosity=2).run(suite)
|
||||
if r.errors or r.failures:
|
||||
sys.exit(1)
|
||||
|
||||
# vim:et:ts=4:sw=4:
|
|
@ -14,6 +14,7 @@ import hashlib
|
|||
import os
|
||||
import re
|
||||
import simplejson
|
||||
import sys
|
||||
import time
|
||||
import urllib2
|
||||
import zlib
|
||||
|
@ -33,14 +34,18 @@ import openerp.modules.registry
|
|||
from openerp.tools.translate import _
|
||||
from openerp import http
|
||||
|
||||
from openerp.http import request, serialize_exception as _serialize_exception, LazyResponse
|
||||
from openerp.http import request, serialize_exception as _serialize_exception
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
env = jinja2.Environment(
|
||||
loader=jinja2.PackageLoader('openerp.addons.web', "views"),
|
||||
autoescape=True
|
||||
)
|
||||
if hasattr(sys, 'frozen'):
|
||||
# When running on compiled windows binary, we don't have access to package loader.
|
||||
path = os.path.realpath(os.path.join(os.path.dirname(__file__), '..', 'views'))
|
||||
loader = jinja2.FileSystemLoader(path)
|
||||
else:
|
||||
loader = jinja2.PackageLoader('openerp.addons.web', "views")
|
||||
|
||||
env = jinja2.Environment(loader=loader, autoescape=True)
|
||||
env.filters["json"] = simplejson.dumps
|
||||
|
||||
#----------------------------------------------------------
|
||||
|
@ -119,6 +124,12 @@ def redirect_with_hash(*args, **kw):
|
|||
"""
|
||||
return http.redirect_with_hash(*args, **kw)
|
||||
|
||||
def abort_and_redirect(url):
|
||||
r = request.httprequest
|
||||
response = werkzeug.utils.redirect(url, 302)
|
||||
response = r.app.get_response(r, response, explicit_session=False)
|
||||
werkzeug.exceptions.abort(response)
|
||||
|
||||
def ensure_db(redirect='/web/database/selector'):
|
||||
# This helper should be used in web client auth="none" routes
|
||||
# if those routes needs a db to work with.
|
||||
|
@ -141,11 +152,14 @@ def ensure_db(redirect='/web/database/selector'):
|
|||
# Thus, we redirect the user to the same page but with the session cookie set.
|
||||
# This will force using the database route dispatcher...
|
||||
r = request.httprequest
|
||||
response = werkzeug.utils.redirect(r.url, 302)
|
||||
url_redirect = r.base_url
|
||||
if r.query_string:
|
||||
# Can't use werkzeug.wrappers.BaseRequest.url with encoded hashes:
|
||||
# https://github.com/amigrave/werkzeug/commit/b4a62433f2f7678c234cdcac6247a869f90a7eb7
|
||||
url_redirect += '?' + r.query_string
|
||||
response = werkzeug.utils.redirect(url_redirect, 302)
|
||||
request.session.db = db
|
||||
response = r.app.get_response(r, response, explicit_session=False)
|
||||
werkzeug.exceptions.abort(response)
|
||||
return
|
||||
abort_and_redirect(url_redirect)
|
||||
|
||||
# if db not provided, use the session one
|
||||
if not db:
|
||||
|
@ -163,6 +177,7 @@ def ensure_db(redirect='/web/database/selector'):
|
|||
# always switch the session to the computed db
|
||||
if db != request.session.db:
|
||||
request.session.logout()
|
||||
abort_and_redirect(request.httprequest.url)
|
||||
|
||||
request.session.db = db
|
||||
|
||||
|
@ -356,7 +371,13 @@ def manifest_glob(extension, addons=None, db=None, include_remotes=False):
|
|||
r.append((None, pattern))
|
||||
else:
|
||||
for path in glob.glob(os.path.normpath(os.path.join(addons_path, addon, pattern))):
|
||||
r.append((path, fs2web(path[len(addons_path):])))
|
||||
# Hack for IE, who limit 288Ko, 4095 rules, 31 sheets
|
||||
# http://support.microsoft.com/kb/262161/en
|
||||
if pattern == "static/lib/bootstrap/css/bootstrap.css":
|
||||
if include_remotes:
|
||||
r.insert(0, (None, fs2web(path[len(addons_path):])))
|
||||
else:
|
||||
r.append((path, fs2web(path[len(addons_path):])))
|
||||
return r
|
||||
|
||||
def manifest_list(extension, mods=None, db=None, debug=False):
|
||||
|
@ -421,6 +442,15 @@ def set_cookie_and_redirect(redirect_url):
|
|||
redirect.autocorrect_location_header = False
|
||||
return redirect
|
||||
|
||||
def login_redirect():
|
||||
url = '/web/login?'
|
||||
if request.debug:
|
||||
url += 'debug&'
|
||||
return """<html><head><script>
|
||||
window.location = '%sredirect=' + encodeURIComponent(window.location);
|
||||
</script></head></html>
|
||||
""" % (url,)
|
||||
|
||||
def load_actions_from_ir_values(key, key2, models, meta):
|
||||
Values = request.session.model('ir.values')
|
||||
actions = Values.get(key, key2, models, meta, request.context)
|
||||
|
@ -591,12 +621,13 @@ html_template = """<!DOCTYPE html>
|
|||
</html>
|
||||
"""
|
||||
|
||||
def render_bootstrap_template(db, template, values=None, debug=False, lazy=False, **kw):
|
||||
if request and request.debug:
|
||||
def render_bootstrap_template(template, values=None, debug=False, db=None, **kw):
|
||||
if not db:
|
||||
db = request.db
|
||||
if request.debug:
|
||||
debug = True
|
||||
if values is None:
|
||||
values = {}
|
||||
values.update(kw)
|
||||
values['debug'] = debug
|
||||
values['current_db'] = db
|
||||
try:
|
||||
|
@ -612,36 +643,40 @@ def render_bootstrap_template(db, template, values=None, debug=False, lazy=False
|
|||
values['modules'] = module_boot(db=db)
|
||||
values['modules'] = simplejson.dumps(values['modules'])
|
||||
|
||||
def callback(template, values):
|
||||
registry = openerp.modules.registry.RegistryManager.get(db)
|
||||
with registry.cursor() as cr:
|
||||
view_obj = registry["ir.ui.view"]
|
||||
return view_obj.render(cr, openerp.SUPERUSER_ID, template, values)
|
||||
if lazy:
|
||||
return LazyResponse(callback, template=template, values=values)
|
||||
else:
|
||||
return callback(template, values)
|
||||
return request.render(template, values, **kw)
|
||||
|
||||
class Home(http.Controller):
|
||||
|
||||
@http.route('/', type='http', auth="none")
|
||||
def index(self, s_action=None, db=None, **kw):
|
||||
return http.local_redirect('/web', query=request.params)
|
||||
return http.local_redirect('/web', query=request.params, keep_hash=True)
|
||||
|
||||
@http.route('/web', type='http', auth="none")
|
||||
def web_client(self, s_action=None, **kw):
|
||||
ensure_db()
|
||||
|
||||
if request.session.uid:
|
||||
html = render_bootstrap_template(request.session.db, "web.webclient_bootstrap")
|
||||
return request.make_response(html, {'Cache-Control': 'no-cache', 'Content-Type': 'text/html; charset=utf-8'})
|
||||
if kw.get('redirect'):
|
||||
return werkzeug.utils.redirect(kw.get('redirect'), 303)
|
||||
|
||||
headers = {
|
||||
'Cache-Control': 'no-cache',
|
||||
'Content-Type': 'text/html; charset=utf-8',
|
||||
}
|
||||
return render_bootstrap_template("web.webclient_bootstrap", headers=headers)
|
||||
else:
|
||||
return http.local_redirect('/web/login', query=request.params)
|
||||
return login_redirect()
|
||||
|
||||
@http.route('/web/login', type='http', auth="none")
|
||||
def web_login(self, redirect=None, **kw):
|
||||
ensure_db()
|
||||
|
||||
if request.httprequest.method == 'GET' and redirect and request.session.uid:
|
||||
return http.redirect_with_hash(redirect)
|
||||
|
||||
if not request.uid:
|
||||
request.uid = openerp.SUPERUSER_ID
|
||||
|
||||
values = request.params.copy()
|
||||
if not redirect:
|
||||
redirect = '/web?' + request.httprequest.query_string
|
||||
|
@ -651,7 +686,7 @@ class Home(http.Controller):
|
|||
if uid is not False:
|
||||
return http.redirect_with_hash(redirect)
|
||||
values['error'] = "Wrong login/password"
|
||||
return render_bootstrap_template(request.session.db, 'web.login', values, lazy=True)
|
||||
return render_bootstrap_template('web.login', values)
|
||||
|
||||
@http.route('/login', type='http', auth="none")
|
||||
def login(self, db, login, key, redirect="/web", **kw):
|
||||
|
@ -928,10 +963,11 @@ class Database(http.Controller):
|
|||
return simplejson.dumps([[],[{'error': openerp.tools.ustr(e), 'title': _('Backup Database')}]])
|
||||
|
||||
@http.route('/web/database/restore', type='http', auth="none")
|
||||
def restore(self, db_file, restore_pwd, new_db):
|
||||
def restore(self, db_file, restore_pwd, new_db, mode):
|
||||
try:
|
||||
copy = mode == 'copy'
|
||||
data = base64.b64encode(db_file.read())
|
||||
request.session.proxy("db").restore(restore_pwd, new_db, data)
|
||||
request.session.proxy("db").restore(restore_pwd, new_db, data, copy)
|
||||
return ''
|
||||
except openerp.exceptions.AccessDenied, e:
|
||||
raise Exception("AccessDenied")
|
||||
|
@ -1179,11 +1215,14 @@ class DataSet(http.Controller):
|
|||
|
||||
def _call_kw(self, model, method, args, kwargs):
|
||||
# Temporary implements future display_name special field for model#read()
|
||||
if method == 'read' and kwargs.get('context', {}).get('future_display_name'):
|
||||
if method in ('read', 'search_read') and kwargs.get('context', {}).get('future_display_name'):
|
||||
if 'display_name' in args[1]:
|
||||
names = dict(request.session.model(model).name_get(args[0], **kwargs))
|
||||
if method == 'read':
|
||||
names = dict(request.session.model(model).name_get(args[0], **kwargs))
|
||||
else:
|
||||
names = dict(request.session.model(model).name_search('', args[0], **kwargs))
|
||||
args[1].remove('display_name')
|
||||
records = request.session.model(model).read(*args, **kwargs)
|
||||
records = getattr(request.session.model(model), method)(*args, **kwargs)
|
||||
for record in records:
|
||||
record['display_name'] = \
|
||||
names.get(record['id']) or "%s#%d" % (model, (record['id']))
|
||||
|
@ -1596,8 +1635,8 @@ class Export(http.Controller):
|
|||
model, map(operator.itemgetter('name'), export_fields_list))
|
||||
|
||||
return [
|
||||
{'name': field_name, 'label': fields_data[field_name]}
|
||||
for field_name in fields_data.keys()
|
||||
{'name': field['name'], 'label': fields_data[field['name']]}
|
||||
for field in export_fields_list
|
||||
]
|
||||
|
||||
def fields_info(self, model, export_fields):
|
||||
|
@ -1656,6 +1695,8 @@ class Export(http.Controller):
|
|||
for k, v in self.fields_info(model, export_fields).iteritems())
|
||||
|
||||
class ExportFormat(object):
|
||||
raw_data = False
|
||||
|
||||
@property
|
||||
def content_type(self):
|
||||
""" Provides the format's content type """
|
||||
|
@ -1688,7 +1729,7 @@ class ExportFormat(object):
|
|||
ids = ids or Model.search(domain, 0, False, False, request.context)
|
||||
|
||||
field_names = map(operator.itemgetter('name'), fields)
|
||||
import_data = Model.export_data(ids, field_names, request.context).get('datas',[])
|
||||
import_data = Model.export_data(ids, field_names, self.raw_data, context=request.context).get('datas',[])
|
||||
|
||||
if import_compat:
|
||||
columns_headers = field_names
|
||||
|
@ -1741,6 +1782,8 @@ class CSVExport(ExportFormat, http.Controller):
|
|||
return data
|
||||
|
||||
class ExcelExport(ExportFormat, http.Controller):
|
||||
# Excel needs raw data to correctly handle numbers and date values
|
||||
raw_data = True
|
||||
|
||||
@http.route('/web/export/xls', type='http', auth="user")
|
||||
@serialize_exception
|
||||
|
@ -1762,14 +1805,20 @@ class ExcelExport(ExportFormat, http.Controller):
|
|||
worksheet.write(0, i, fieldname)
|
||||
worksheet.col(i).width = 8000 # around 220 pixels
|
||||
|
||||
style = xlwt.easyxf('align: wrap yes')
|
||||
base_style = xlwt.easyxf('align: wrap yes')
|
||||
date_style = xlwt.easyxf('align: wrap yes', num_format_str='YYYY-MM-DD')
|
||||
datetime_style = xlwt.easyxf('align: wrap yes', num_format_str='YYYY-MM-DD HH:mm:SS')
|
||||
|
||||
for row_index, row in enumerate(rows):
|
||||
for cell_index, cell_value in enumerate(row):
|
||||
cell_style = base_style
|
||||
if isinstance(cell_value, basestring):
|
||||
cell_value = re.sub("\r", " ", cell_value)
|
||||
if cell_value is False: cell_value = None
|
||||
worksheet.write(row_index + 1, cell_index, cell_value, style)
|
||||
elif isinstance(cell_value, datetime.datetime):
|
||||
cell_style = datetime_style
|
||||
elif isinstance(cell_value, datetime.date):
|
||||
cell_style = date_style
|
||||
worksheet.write(row_index + 1, cell_index, cell_value, cell_style)
|
||||
|
||||
fp = StringIO()
|
||||
workbook.save(fp)
|
||||
|
|
|
@ -52,7 +52,6 @@ TESTING = Template(u"""<!DOCTYPE html>
|
|||
<script src="/web/static/lib/qunit/qunit.js"></script>
|
||||
|
||||
<script type="text/javascript">
|
||||
var oe_db_info = ${db_info | n};
|
||||
// List of modules, each module is preceded by its dependencies
|
||||
var oe_all_dependencies = ${dependencies | n};
|
||||
QUnit.config.testTimeout = 5 * 60 * 1000;
|
||||
|
@ -134,16 +133,10 @@ class TestRunnerController(http.Controller):
|
|||
for mod, tests in itertools.izip(sorted_mods, tests)
|
||||
]
|
||||
|
||||
# if all three db_info parameters are present, send them to the page
|
||||
db_info = dict((k, v) for k, v in kwargs.iteritems()
|
||||
if k in ['source', 'supadmin', 'password'])
|
||||
if len(db_info) != 3:
|
||||
db_info = None
|
||||
|
||||
return TESTING.render(files=files, dependencies=json.dumps(
|
||||
[name for name in sorted_mods
|
||||
if module.get_module_resource(name, 'static')
|
||||
if manifests[name]['js']]), db_info=json.dumps(db_info))
|
||||
if manifests[name]['js']]))
|
||||
|
||||
def load_manifest(self, name):
|
||||
manifest = module.load_information_from_description_file(name)
|
||||
|
@ -164,10 +157,3 @@ class TestRunnerController(http.Controller):
|
|||
# replace OS path separators (from join & normpath) by URI ones
|
||||
yield path[len(root):].replace(os.path.sep, '/')
|
||||
|
||||
@http.route('/web/tests/set_session_value', type='json', auth="none")
|
||||
def set_session_value(self, value):
|
||||
request.session.some_test_value = value
|
||||
|
||||
@http.route('/web/tests/get_session_value', type='json', auth="none")
|
||||
def get_session_value(self):
|
||||
return request.session.some_test_value
|
||||
|
|
|
@ -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: 2014-02-13 06:08+0000\n"
|
||||
"X-Generator: Launchpad (build 16916)\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-18 06:38+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
@ -1849,7 +1849,7 @@ msgstr "الافتراضي"
|
|||
#: code:addons/web/static/src/xml/base.xml:468
|
||||
#, python-format
|
||||
msgid "OpenERP"
|
||||
msgstr "كروز"
|
||||
msgstr "OpenERP"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
@ -2213,7 +2213,7 @@ msgstr "زر"
|
|||
#: code:addons/web/static/src/xml/base.xml:440
|
||||
#, python-format
|
||||
msgid "OpenERP is a trademark of the"
|
||||
msgstr "كروز علامة تجارية ملك"
|
||||
msgstr "OpenERP علامة تجارية ملك"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
@ -2241,7 +2241,7 @@ msgstr "False"
|
|||
#: code:addons/web/static/src/xml/base.xml:426
|
||||
#, python-format
|
||||
msgid "About OpenERP"
|
||||
msgstr "حول كروز"
|
||||
msgstr "حول OpenERP"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
|
|
@ -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: 2014-02-13 06:08+0000\n"
|
||||
"X-Generator: Launchpad (build 16916)\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-18 06:38+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
|
|
@ -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: 2014-02-13 06:08+0000\n"
|
||||
"X-Generator: Launchpad (build 16916)\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-18 06:38+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
|
|
@ -9,13 +9,13 @@ msgstr ""
|
|||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2012-12-21 17:06+0000\n"
|
||||
"PO-Revision-Date: 2014-01-30 17:05+0000\n"
|
||||
"Last-Translator: Bosko Stojakovic <bluesoft83@gmail.com>\n"
|
||||
"Last-Translator: Boško Stojaković <bluesoft83@gmail.com>\n"
|
||||
"Language-Team: Bosnian <bs@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2014-02-13 06:08+0000\n"
|
||||
"X-Generator: Launchpad (build 16916)\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-18 06:38+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
|
|
@ -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: 2014-02-13 06:08+0000\n"
|
||||
"X-Generator: Launchpad (build 16916)\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-18 06:38+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
|
|
@ -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: 2014-02-13 06:08+0000\n"
|
||||
"X-Generator: Launchpad (build 16916)\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-18 06:38+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
"X-Poedit-Language: Czech\n"
|
||||
|
||||
#. module: web
|
||||
|
@ -1610,7 +1610,7 @@ msgstr "Mažu databázi"
|
|||
#: code:addons/web/static/src/xml/base.xml:467
|
||||
#, python-format
|
||||
msgid "Powered by"
|
||||
msgstr ""
|
||||
msgstr "Založeno na"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
|
|
@ -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: 2014-02-13 06:08+0000\n"
|
||||
"X-Generator: Launchpad (build 16916)\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-18 06:38+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
|
|
@ -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: 2014-02-13 06:08+0000\n"
|
||||
"X-Generator: Launchpad (build 16916)\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-18 06:39+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
|
|
@ -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: 2014-02-13 06:10+0000\n"
|
||||
"X-Generator: Launchpad (build 16916)\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-18 06:40+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
|
|
@ -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: 2014-02-13 06:09+0000\n"
|
||||
"X-Generator: Launchpad (build 16916)\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-18 06:40+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
|
|
@ -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: 2014-02-13 06:09+0000\n"
|
||||
"X-Generator: Launchpad (build 16916)\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-18 06:40+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
|
|
@ -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: 2014-02-13 06:09+0000\n"
|
||||
"X-Generator: Launchpad (build 16916)\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-18 06:40+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
|
|
@ -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: 2014-02-13 06:10+0000\n"
|
||||
"X-Generator: Launchpad (build 16916)\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-18 06:40+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
"Language: es\n"
|
||||
|
||||
#. module: web
|
||||
|
|
|
@ -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: 2014-02-13 06:09+0000\n"
|
||||
"X-Generator: Launchpad (build 16916)\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-18 06:40+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
|
|
@ -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: 2014-02-13 06:10+0000\n"
|
||||
"X-Generator: Launchpad (build 16916)\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-18 06:40+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
|
|
@ -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: 2014-02-13 06:10+0000\n"
|
||||
"X-Generator: Launchpad (build 16916)\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-18 06:40+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
|
|
@ -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: 2014-02-13 06:10+0000\n"
|
||||
"X-Generator: Launchpad (build 16916)\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-18 06:40+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
|
|
@ -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: 2014-02-17 05:44+0000\n"
|
||||
"X-Generator: Launchpad (build 16916)\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-18 06:38+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
|
|
@ -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: 2014-02-13 06:08+0000\n"
|
||||
"X-Generator: Launchpad (build 16916)\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-18 06:38+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
|
|
@ -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: 2014-02-13 06:09+0000\n"
|
||||
"X-Generator: Launchpad (build 16916)\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-18 06:39+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
|
|
@ -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: 2014-02-13 06:08+0000\n"
|
||||
"X-Generator: Launchpad (build 16916)\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-18 06:38+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
@ -853,7 +853,7 @@ msgstr "LIsää"
|
|||
#: code:addons/web/static/src/xml/base.xml:558
|
||||
#, python-format
|
||||
msgid "Toggle Form Layout Outline"
|
||||
msgstr "Näytä Sijoittelu"
|
||||
msgstr "Vaihda lomakkeen asettelua"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
@ -963,7 +963,7 @@ msgstr "Salasana vaihdettu"
|
|||
#: code:addons/web/static/src/js/view_list_editable.js:793
|
||||
#, python-format
|
||||
msgid "The form's data can not be discarded"
|
||||
msgstr "Asiakirjan dataa ei voida hylätä"
|
||||
msgstr "Lomakkeen tietoja ei voi hylätä"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
|
|
@ -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: 2014-02-13 06:08+0000\n"
|
||||
"X-Generator: Launchpad (build 16916)\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-18 06:38+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
|
|
@ -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: 2014-02-13 06:10+0000\n"
|
||||
"X-Generator: Launchpad (build 16916)\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-18 06:40+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
|
|
@ -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: 2014-02-13 06:08+0000\n"
|
||||
"X-Generator: Launchpad (build 16916)\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-18 06:39+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
|
|
@ -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: 2014-02-13 06:08+0000\n"
|
||||
"X-Generator: Launchpad (build 16916)\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-18 06:39+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
|
|
@ -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: 2014-02-13 06:08+0000\n"
|
||||
"X-Generator: Launchpad (build 16916)\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-18 06:39+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
|
|
@ -8,35 +8,35 @@ msgstr ""
|
|||
"Project-Id-Version: openerp-web\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2012-12-21 17:06+0000\n"
|
||||
"PO-Revision-Date: 2012-06-13 13:18+0000\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"PO-Revision-Date: 2014-04-09 07:11+0000\n"
|
||||
"Last-Translator: Paramjit Singh Sahota(OpenERP) <Unknown>\n"
|
||||
"Language-Team: Hindi <hi@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2014-02-13 06:08+0000\n"
|
||||
"X-Generator: Launchpad (build 16916)\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-18 06:39+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
#: code:addons/web/static/src/xml/base.xml:147
|
||||
#, python-format
|
||||
msgid "Default language:"
|
||||
msgstr ""
|
||||
msgstr "डिफ़ॉल्ट भाषाः"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
#: code:addons/web/static/src/js/coresetup.js:592
|
||||
#, python-format
|
||||
msgid "%d minutes ago"
|
||||
msgstr ""
|
||||
msgstr "%d मिनट पहले"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
#: code:addons/web/static/src/js/coresetup.js:620
|
||||
#, python-format
|
||||
msgid "Still loading...<br />Please be patient."
|
||||
msgstr ""
|
||||
msgstr "अब भी है लोड हो रहा है ... <br /> कृपया धैर्य रखें."
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
|
|
@ -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: 2014-02-13 06:09+0000\n"
|
||||
"X-Generator: Launchpad (build 16916)\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-18 06:40+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
|
|
@ -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: 2014-02-13 06:08+0000\n"
|
||||
"X-Generator: Launchpad (build 16916)\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-18 06:39+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
|
|
@ -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: 2014-02-13 06:08+0000\n"
|
||||
"X-Generator: Launchpad (build 16916)\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-18 06:39+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
|
|
@ -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: 2014-02-13 06:09+0000\n"
|
||||
"X-Generator: Launchpad (build 16916)\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-18 06:39+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
|
|
@ -14,15 +14,15 @@ msgstr ""
|
|||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2014-02-13 06:09+0000\n"
|
||||
"X-Generator: Launchpad (build 16916)\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-18 06:39+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
#: code:addons/web/static/src/xml/base.xml:147
|
||||
#, python-format
|
||||
msgid "Default language:"
|
||||
msgstr "デフォルトの言語:"
|
||||
msgstr "デフォルト言語:"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
@ -503,7 +503,7 @@ msgstr "ログ (perm_read) のビュー"
|
|||
#: code:addons/web/static/src/js/view_form.js:1071
|
||||
#, python-format
|
||||
msgid "Set Default"
|
||||
msgstr "デフォルトに設定"
|
||||
msgstr "デフォルト値設定"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
@ -524,7 +524,7 @@ msgstr "数十秒前"
|
|||
#: code:addons/web/static/src/xml/base.xml:873
|
||||
#, python-format
|
||||
msgid "Condition:"
|
||||
msgstr "状態:"
|
||||
msgstr "条件:"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
@ -1564,7 +1564,7 @@ msgstr ""
|
|||
#: code:addons/web/static/src/xml/base.xml:899
|
||||
#, python-format
|
||||
msgid "All users"
|
||||
msgstr "全てのユーザ"
|
||||
msgstr "全ユーザ"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
@ -1664,7 +1664,7 @@ msgstr ""
|
|||
#: code:addons/web/static/src/js/view_form.js:1078
|
||||
#, python-format
|
||||
msgid "Save default"
|
||||
msgstr "デフォルトに保存"
|
||||
msgstr "デフォルト値保存"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
@ -1693,7 +1693,7 @@ msgstr "項目は空です。何も保存するものはありません。"
|
|||
#: code:addons/web/static/src/xml/base.xml:567
|
||||
#, python-format
|
||||
msgid "Manage Views"
|
||||
msgstr "ビューの管理"
|
||||
msgstr "ビュー管理"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
@ -1757,7 +1757,7 @@ msgstr "次の理由でインポートに失敗しました:"
|
|||
#: code:addons/web/static/src/xml/base.xml:561
|
||||
#, python-format
|
||||
msgid "JS Tests"
|
||||
msgstr ""
|
||||
msgstr "JSテスト"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
@ -1836,7 +1836,7 @@ msgstr "ドメイン:"
|
|||
#: code:addons/web/static/src/xml/base.xml:856
|
||||
#, python-format
|
||||
msgid "Default:"
|
||||
msgstr "デフォルト:"
|
||||
msgstr "デフォルト値:"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
@ -1928,7 +1928,7 @@ msgstr ""
|
|||
#: code:addons/web/static/src/xml/base.xml:559
|
||||
#, python-format
|
||||
msgid "Set Defaults"
|
||||
msgstr ""
|
||||
msgstr "デフォルト値設定"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
@ -2417,7 +2417,7 @@ msgstr "ID:"
|
|||
#: code:addons/web/static/src/xml/base.xml:892
|
||||
#, python-format
|
||||
msgid "Only you"
|
||||
msgstr "あなただけ"
|
||||
msgstr "自分のみ"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
|
|
@ -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: 2014-02-13 06:08+0000\n"
|
||||
"X-Generator: Launchpad (build 16916)\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-18 06:39+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
|
|
@ -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: 2014-02-13 06:09+0000\n"
|
||||
"X-Generator: Launchpad (build 16916)\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-18 06:39+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
|
|
@ -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: 2014-02-13 06:09+0000\n"
|
||||
"X-Generator: Launchpad (build 16916)\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-18 06:39+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
|
|
@ -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: 2014-02-13 06:09+0000\n"
|
||||
"X-Generator: Launchpad (build 16916)\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-18 06:39+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
|
|
@ -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: 2014-02-13 06:09+0000\n"
|
||||
"X-Generator: Launchpad (build 16916)\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-18 06:39+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
|
|
@ -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: 2014-02-13 06:09+0000\n"
|
||||
"X-Generator: Launchpad (build 16916)\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-18 06:39+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
|
|
@ -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: 2014-02-13 06:09+0000\n"
|
||||
"X-Generator: Launchpad (build 16916)\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-18 06:39+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
@ -2334,7 +2334,7 @@ msgstr "'%s' нь хөрвүүлэх боломжгүй огноо, огнооц
|
|||
#: code:addons/web/static/src/xml/base.xml:325
|
||||
#, python-format
|
||||
msgid "Duplicate"
|
||||
msgstr "Хувилах"
|
||||
msgstr "Хуулбарлан үүсгэх"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
|
|
@ -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: 2014-02-13 06:09+0000\n"
|
||||
"X-Generator: Launchpad (build 16916)\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-18 06:39+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
|
|
@ -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: 2014-02-13 06:08+0000\n"
|
||||
"X-Generator: Launchpad (build 16916)\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-18 06:38+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
|
|
@ -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: 2014-02-13 06:10+0000\n"
|
||||
"X-Generator: Launchpad (build 16916)\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-18 06:40+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
|
|
@ -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: 2014-02-13 06:09+0000\n"
|
||||
"X-Generator: Launchpad (build 16916)\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-18 06:39+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
|
|
@ -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: 2014-02-13 06:09+0000\n"
|
||||
"X-Generator: Launchpad (build 16916)\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-18 06:39+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
|
|
@ -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: 2014-02-13 06:09+0000\n"
|
||||
"X-Generator: Launchpad (build 16916)\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-18 06:40+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
|
|
@ -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: 2014-02-13 06:09+0000\n"
|
||||
"X-Generator: Launchpad (build 16916)\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-18 06:39+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
|
|
@ -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: 2014-02-13 06:09+0000\n"
|
||||
"X-Generator: Launchpad (build 16916)\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-18 06:39+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
|
|
@ -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: 2014-02-13 06:09+0000\n"
|
||||
"X-Generator: Launchpad (build 16916)\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-18 06:40+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
|
|
@ -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: 2014-02-13 06:09+0000\n"
|
||||
"X-Generator: Launchpad (build 16916)\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-18 06:40+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
|
|
@ -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: 2014-02-13 06:08+0000\n"
|
||||
"X-Generator: Launchpad (build 16916)\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-18 06:38+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
|
|
@ -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: 2014-02-13 06:10+0000\n"
|
||||
"X-Generator: Launchpad (build 16916)\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-18 06:40+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
|
|
@ -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: 2014-02-13 06:09+0000\n"
|
||||
"X-Generator: Launchpad (build 16916)\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-18 06:40+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
|
|
@ -14,15 +14,15 @@ msgstr ""
|
|||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2014-02-13 06:09+0000\n"
|
||||
"X-Generator: Launchpad (build 16916)\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-18 06:40+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
#: code:addons/web/static/src/xml/base.xml:147
|
||||
#, python-format
|
||||
msgid "Default language:"
|
||||
msgstr "ภาษาหลัก:"
|
||||
msgstr "ภาษาหลัก"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
@ -475,7 +475,7 @@ msgstr "เปิดใช้งานโหมดนักพัฒนา"
|
|||
#: code:addons/web/static/src/js/chrome.js:341
|
||||
#, python-format
|
||||
msgid "Loading (%d)"
|
||||
msgstr "กำลังโหลด (% d)"
|
||||
msgstr "กำลังโหลด (%d)"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
|
|
@ -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: 2014-02-13 06:09+0000\n"
|
||||
"X-Generator: Launchpad (build 16916)\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-18 06:40+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
|
|
@ -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: 2014-02-13 06:09+0000\n"
|
||||
"X-Generator: Launchpad (build 16916)\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-18 06:40+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
|
|
@ -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: 2014-02-13 06:09+0000\n"
|
||||
"X-Generator: Launchpad (build 16916)\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-18 06:40+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
|
|
@ -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: 2014-02-13 06:10+0000\n"
|
||||
"X-Generator: Launchpad (build 16916)\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-18 06:40+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
|
|
@ -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: 2014-02-13 06:10+0000\n"
|
||||
"X-Generator: Launchpad (build 16916)\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-18 06:40+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
|
||||
#. module: web
|
||||
#. openerp-web
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
.cleditorButton {float:left; width:24px; height:24px; margin:1px 0 1px 0; background: url('images/buttons.gif')}
|
||||
.cleditorDisabled {opacity:0.3; filter:alpha(opacity=30)}
|
||||
.cleditorDivider {float:left; width:1px; height:23px; margin:1px 0 1px 0; background:#CCC}
|
||||
.cleditorPopup {border:solid 1px #999; background-color:white; position:absolute; font:10pt Arial,Verdana; cursor:default; z-index:10000}
|
||||
.cleditorPopup {border:solid 1px #999; background-color:white; color:#333333; position:absolute; font:10pt Arial,Verdana; cursor:default; z-index:10000}
|
||||
.cleditorList div {padding:2px 4px 2px 4px}
|
||||
.cleditorList p,
|
||||
.cleditorList h1,
|
||||
|
|
|
@ -1,18 +1,13 @@
|
|||
/**
|
||||
@preserve CLEditor WYSIWYG HTML Editor v1.3.0
|
||||
http://premiumsoftware.net/cleditor
|
||||
/*!
|
||||
CLEditor WYSIWYG HTML Editor v1.4.4
|
||||
http://premiumsoftware.net/CLEditor
|
||||
requires jQuery v1.4.2 or later
|
||||
|
||||
Copyright 2010, Chris Landowski, Premium Software, LLC
|
||||
Dual licensed under the MIT or GPL Version 2 licenses.
|
||||
*/
|
||||
|
||||
// ==ClosureCompiler==
|
||||
// @compilation_level SIMPLE_OPTIMIZATIONS
|
||||
// @output_file_name jquery.cleditor.min.js
|
||||
// ==/ClosureCompiler==
|
||||
|
||||
(function($) {
|
||||
(function ($) {
|
||||
|
||||
//==============
|
||||
// jQuery Plugin
|
||||
|
@ -22,7 +17,7 @@
|
|||
|
||||
// Define the defaults used for all new cleditor instances
|
||||
defaultOptions: {
|
||||
width: 500, // width not including margins, borders or padding
|
||||
width: 'auto', // width not including margins, borders or padding
|
||||
height: 250, // height not including margins, borders or padding
|
||||
controls: // controls to add to the toolbar
|
||||
"bold italic underline strikethrough subscript superscript | font size " +
|
||||
|
@ -46,7 +41,7 @@
|
|||
[["Paragraph", "<p>"], ["Header 1", "<h1>"], ["Header 2", "<h2>"],
|
||||
["Header 3", "<h3>"], ["Header 4","<h4>"], ["Header 5","<h5>"],
|
||||
["Header 6","<h6>"]],
|
||||
useCSS: false, // use CSS to style HTML when possible (not supported in ie)
|
||||
useCSS: true, // use CSS to style HTML when possible (not supported in ie)
|
||||
docType: // Document type contained within the editor
|
||||
'<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">',
|
||||
docCSSFile: // CSS file used to style the document contained within the editor
|
||||
|
@ -57,7 +52,7 @@
|
|||
|
||||
// Define all usable toolbar buttons - the init string property is
|
||||
// expanded during initialization back into the buttons object and
|
||||
// seperate object properties are created for each button.
|
||||
// separate object properties are created for each button.
|
||||
// e.g. buttons.size.title = "Font Size"
|
||||
buttons: {
|
||||
// name,title,command,popupName (""=use name)
|
||||
|
@ -109,7 +104,7 @@
|
|||
|
||||
// Loop through all matching textareas and create the editors
|
||||
this.each(function(idx, elem) {
|
||||
if (elem.tagName == "TEXTAREA") {
|
||||
if (elem.tagName.toUpperCase() === "TEXTAREA") {
|
||||
var data = $.data(elem, CLEDITOR);
|
||||
if (!data) data = new cleditor(elem, options);
|
||||
$result = $result.add(data);
|
||||
|
@ -129,6 +124,7 @@
|
|||
|
||||
// Misc constants
|
||||
BACKGROUND_COLOR = "backgroundColor",
|
||||
BLURRED = "blurred",
|
||||
BUTTON = "button",
|
||||
BUTTON_NAME = "buttonName",
|
||||
CHANGE = "change",
|
||||
|
@ -136,6 +132,7 @@
|
|||
CLICK = "click",
|
||||
DISABLED = "disabled",
|
||||
DIV_TAG = "<div>",
|
||||
FOCUSED = "focused",
|
||||
TRANSPARENT = "transparent",
|
||||
UNSELECTABLE = "unselectable",
|
||||
|
||||
|
@ -152,12 +149,15 @@
|
|||
PROMPT_CLASS = "cleditorPrompt", // prompt popup divs inside body
|
||||
MSG_CLASS = "cleditorMsg", // message popup div inside body
|
||||
|
||||
// Test for ie
|
||||
ie = $.browser.msie,
|
||||
ie6 = /msie\s6/i.test(navigator.userAgent),
|
||||
// Browser detection
|
||||
ua = navigator.userAgent.toLowerCase(),
|
||||
ie = /msie/.test(ua),
|
||||
ie6 = /msie\s6/.test(ua),
|
||||
iege11 = /(trident)(?:.*rv:([\w.]+))?/.test(ua),
|
||||
webkit = /webkit/.test(ua),
|
||||
|
||||
// Test for iPhone/iTouch/iPad
|
||||
iOS = /iphone|ipad|ipod/i.test(navigator.userAgent),
|
||||
iOS = /iphone|ipad|ipod/i.test(ua),
|
||||
|
||||
// Popups are created once as needed and shared by all editor instances
|
||||
popups = {},
|
||||
|
@ -223,19 +223,26 @@
|
|||
var $group = $(DIV_TAG)
|
||||
.addClass(GROUP_CLASS)
|
||||
.appendTo($toolbar);
|
||||
|
||||
// Initialize the group width
|
||||
var groupWidth = 0;
|
||||
|
||||
// Add the buttons to the toolbar
|
||||
$.each(options.controls.split(" "), function(idx, buttonName) {
|
||||
if (buttonName === "") return true;
|
||||
|
||||
// Divider
|
||||
if (buttonName == "|") {
|
||||
if (buttonName === "|") {
|
||||
|
||||
// Add a new divider to the group
|
||||
var $div = $(DIV_TAG)
|
||||
.addClass(DIVIDER_CLASS)
|
||||
.appendTo($group);
|
||||
|
||||
// Update the group width
|
||||
$group.width(groupWidth + 1);
|
||||
groupWidth = 0;
|
||||
|
||||
// Create a new group
|
||||
$group = $(DIV_TAG)
|
||||
.addClass(GROUP_CLASS)
|
||||
|
@ -258,6 +265,10 @@
|
|||
.appendTo($group)
|
||||
.hover(hoverEnter, hoverLeave);
|
||||
|
||||
// Update the group width
|
||||
groupWidth += 24;
|
||||
$group.width(groupWidth + 1);
|
||||
|
||||
// Prepare the button image
|
||||
var map = {};
|
||||
if (button.css) map = button.css;
|
||||
|
@ -295,7 +306,7 @@
|
|||
|
||||
// Bind the window resize event when the width or height is auto or %
|
||||
if (/auto|%/.test("" + options.width + options.height))
|
||||
$(window).resize(function() {
|
||||
$(window).bind('resize.cleditor', function () {
|
||||
//Forcefully blurred iframe contentWindow, chrome, IE, safari doesn't trigger blur on window resize and due to which text disappears
|
||||
var contentWindow = editor.$frame[0].contentWindow;
|
||||
if(!$.browser.mozilla && contentWindow){
|
||||
|
@ -306,7 +317,6 @@
|
|||
refresh(editor);
|
||||
}
|
||||
});
|
||||
|
||||
// Create the iframe and resize the controls
|
||||
refresh(editor);
|
||||
|
||||
|
@ -347,13 +357,26 @@
|
|||
return editor;
|
||||
};
|
||||
});
|
||||
|
||||
// blurred - shortcut for .bind("blurred", handler) or .trigger("blurred")
|
||||
fn.blurred = function(handler) {
|
||||
var $this = $(this);
|
||||
return handler ? $this.bind(BLURRED, handler) : $this.trigger(BLURRED);
|
||||
};
|
||||
|
||||
// change - shortcut for .bind("change", handler) or .trigger("change")
|
||||
fn.change = function(handler) {
|
||||
fn.change = function change(handler) {
|
||||
console.log('change test');
|
||||
var $this = $(this);
|
||||
return handler ? $this.bind(CHANGE, handler) : $this.trigger(CHANGE);
|
||||
};
|
||||
|
||||
// focused - shortcut for .bind("focused", handler) or .trigger("focused")
|
||||
fn.focused = function(handler) {
|
||||
var $this = $(this);
|
||||
return handler ? $this.bind(FOCUSED, handler) : $this.trigger(FOCUSED);
|
||||
};
|
||||
|
||||
//===============
|
||||
// Event Handlers
|
||||
//===============
|
||||
|
@ -369,7 +392,7 @@
|
|||
popup = popups[popupName];
|
||||
|
||||
// Check if disabled
|
||||
if (editor.disabled || $(buttonDiv).attr(DISABLED) == DISABLED)
|
||||
if (editor.disabled || $(buttonDiv).attr(DISABLED) === DISABLED)
|
||||
return;
|
||||
|
||||
// Fire the buttonClick event
|
||||
|
@ -387,7 +410,7 @@
|
|||
return false;
|
||||
|
||||
// Toggle source
|
||||
if (buttonName == "source") {
|
||||
if (buttonName === "source") {
|
||||
|
||||
// Show the iframe
|
||||
if (sourceMode(editor)) {
|
||||
|
@ -418,10 +441,10 @@
|
|||
var $popup = $(popup);
|
||||
|
||||
// URL
|
||||
if (popupName == "url") {
|
||||
if (popupName === "url") {
|
||||
|
||||
// Check for selection before showing the link url popup
|
||||
if (buttonName == "link" && selectedText(editor) === "") {
|
||||
if (buttonName === "link" && selectedText(editor) === "") {
|
||||
showMessage(editor, "A selection is required when inserting a link.", buttonDiv);
|
||||
return false;
|
||||
}
|
||||
|
@ -447,7 +470,7 @@
|
|||
}
|
||||
|
||||
// Paste as Text
|
||||
else if (popupName == "pastetext") {
|
||||
else if (popupName === "pastetext") {
|
||||
|
||||
// Wire up the submit button click event handler
|
||||
$popup.children(":button")
|
||||
|
@ -475,13 +498,13 @@
|
|||
return false; // stop propagination to document click
|
||||
}
|
||||
|
||||
// propaginate to documnt click
|
||||
// propaginate to document click
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
// Print
|
||||
else if (buttonName == "print")
|
||||
else if (buttonName === "print")
|
||||
editor.$frame[0].contentWindow.print();
|
||||
|
||||
// All other buttons
|
||||
|
@ -526,19 +549,19 @@
|
|||
useCSS = editor.options.useCSS;
|
||||
|
||||
// Get the command value
|
||||
if (buttonName == "font")
|
||||
if (buttonName === "font")
|
||||
// Opera returns the fontfamily wrapped in quotes
|
||||
value = target.style.fontFamily.replace(/"/g, "");
|
||||
else if (buttonName == "size") {
|
||||
if (target.tagName == "DIV")
|
||||
else if (buttonName === "size") {
|
||||
if (target.tagName.toUpperCase() === "DIV")
|
||||
target = target.children[0];
|
||||
value = target.innerHTML;
|
||||
}
|
||||
else if (buttonName == "style")
|
||||
else if (buttonName === "style")
|
||||
value = "<" + target.tagName + ">";
|
||||
else if (buttonName == "color")
|
||||
else if (buttonName === "color")
|
||||
value = hex(target.style.backgroundColor);
|
||||
else if (buttonName == "highlight") {
|
||||
else if (buttonName === "highlight") {
|
||||
value = hex(target.style.backgroundColor);
|
||||
if (ie) command = 'backcolor';
|
||||
else useCSS = true;
|
||||
|
@ -610,7 +633,7 @@
|
|||
$popup.html(popupContent);
|
||||
|
||||
// Color
|
||||
else if (popupName == "color") {
|
||||
else if (popupName === "color") {
|
||||
var colors = options.colors.split(" ");
|
||||
if (colors.length < 10)
|
||||
$popup.width("auto");
|
||||
|
@ -622,7 +645,7 @@
|
|||
}
|
||||
|
||||
// Font
|
||||
else if (popupName == "font")
|
||||
else if (popupName === "font")
|
||||
$.each(options.fonts.split(","), function(idx, font) {
|
||||
$(DIV_TAG).appendTo($popup)
|
||||
.css("fontFamily", font)
|
||||
|
@ -630,28 +653,28 @@
|
|||
});
|
||||
|
||||
// Size
|
||||
else if (popupName == "size")
|
||||
else if (popupName === "size")
|
||||
$.each(options.sizes.split(","), function(idx, size) {
|
||||
$(DIV_TAG).appendTo($popup)
|
||||
.html("<font size=" + size + ">" + size + "</font>");
|
||||
.html('<font size="' + size + '">' + size + '</font>');
|
||||
});
|
||||
|
||||
// Style
|
||||
else if (popupName == "style")
|
||||
else if (popupName === "style")
|
||||
$.each(options.styles, function(idx, style) {
|
||||
$(DIV_TAG).appendTo($popup)
|
||||
.html(style[1] + style[0] + style[1].replace("<", "</"));
|
||||
});
|
||||
|
||||
// URL
|
||||
else if (popupName == "url") {
|
||||
$popup.html('Enter URL:<br><input type=text value="http://" size=35><br><input type=button value="Submit">');
|
||||
else if (popupName === "url") {
|
||||
$popup.html('Enter URL:<br /><input type="text" value="http://" size="35" /><br /><input type="button" value="Submit" />');
|
||||
popupTypeClass = PROMPT_CLASS;
|
||||
}
|
||||
|
||||
// Paste as Text
|
||||
else if (popupName == "pastetext") {
|
||||
$popup.html('Paste your content here and click submit.<br /><textarea cols=40 rows=3></textarea><br /><input type=button value=Submit>');
|
||||
else if (popupName === "pastetext") {
|
||||
$popup.html('Paste your content here and click submit.<br /><textarea cols="40" rows="3"></textarea><br /><input type="button" value="Submit" />');
|
||||
popupTypeClass = PROMPT_CLASS;
|
||||
}
|
||||
|
||||
|
@ -720,12 +743,12 @@
|
|||
}
|
||||
|
||||
// Execute the command and check for error
|
||||
var success = true, description;
|
||||
if (ie && command.toLowerCase() == "inserthtml")
|
||||
var success = true, message;
|
||||
if (ie && command.toLowerCase() === "inserthtml")
|
||||
getRange(editor).pasteHTML(value);
|
||||
else {
|
||||
try { success = editor.doc.execCommand(command, 0, value || null); }
|
||||
catch (err) { description = err.description; success = false; }
|
||||
catch (err) { message = err.message; success = false; }
|
||||
if (!success) {
|
||||
if ("cutcopypaste".indexOf(command) > -1)
|
||||
showMessage(editor, "For security reasons, your browser does not support the " +
|
||||
|
@ -733,13 +756,14 @@
|
|||
button);
|
||||
else
|
||||
showMessage(editor,
|
||||
(description ? description : "Error executing the " + command + " command."),
|
||||
(message ? message : "Error executing the " + command + " command."),
|
||||
button);
|
||||
}
|
||||
}
|
||||
|
||||
// Enable the buttons
|
||||
// Enable the buttons and update the textarea
|
||||
refreshButtons(editor);
|
||||
updateTextArea(editor, true);
|
||||
return success;
|
||||
|
||||
}
|
||||
|
@ -765,19 +789,26 @@
|
|||
return editor.$frame[0].contentWindow.getSelection();
|
||||
}
|
||||
|
||||
// Returns the hex value for the passed in string.
|
||||
// hex("rgb(255, 0, 0)"); // #FF0000
|
||||
// hex("#FF0000"); // #FF0000
|
||||
// hex("#F00"); // #FF0000
|
||||
// hex - returns the hex value for the passed in color string
|
||||
function hex(s) {
|
||||
var m = /rgba?\((\d+), (\d+), (\d+)/.exec(s),
|
||||
c = s.split("");
|
||||
|
||||
// hex("rgb(255, 0, 0)") returns #FF0000
|
||||
var m = /rgba?\((\d+), (\d+), (\d+)/.exec(s);
|
||||
if (m) {
|
||||
s = ( m[1] << 16 | m[2] << 8 | m[3] ).toString(16);
|
||||
s = (m[1] << 16 | m[2] << 8 | m[3]).toString(16);
|
||||
while (s.length < 6)
|
||||
s = "0" + s;
|
||||
return "#" + s;
|
||||
}
|
||||
return "#" + (s.length == 6 ? s : c[1] + c[1] + c[2] + c[2] + c[3] + c[3]);
|
||||
|
||||
// hex("#F00") returns #FF0000
|
||||
var c = s.split("");
|
||||
if (s.length === 4)
|
||||
return "#" + c[1] + c[1] + c[2] + c[2] + c[3] + c[3];
|
||||
|
||||
// hex("#FF0000") returns #FF0000
|
||||
return s;
|
||||
|
||||
}
|
||||
|
||||
// hidePopups - hides all popups
|
||||
|
@ -792,9 +823,8 @@
|
|||
|
||||
// imagesPath - returns the path to the images folder
|
||||
function imagesPath() {
|
||||
var cssFile = "jquery.cleditor.css",
|
||||
href = $("link[href$='" + cssFile +"']").attr("href");
|
||||
return href.substr(0, href.length - cssFile.length) + "images/";
|
||||
var href = $("link[href*=cleditor]").attr("href");
|
||||
return href.replace(/^(.*\/)[^\/]+$/, '$1') + "images/";
|
||||
}
|
||||
|
||||
// imageUrl - Returns the css url string for a filemane
|
||||
|
@ -813,7 +843,7 @@
|
|||
editor.$frame.remove();
|
||||
|
||||
// Create a new iframe
|
||||
var $frame = editor.$frame = $('<iframe frameborder="0" src="javascript:true;">')
|
||||
var $frame = editor.$frame = $('<iframe frameborder="0" src="javascript:true;" />')
|
||||
.hide()
|
||||
.appendTo($main);
|
||||
|
||||
|
@ -833,14 +863,14 @@
|
|||
|
||||
// Work around for bug in IE which causes the editor to lose
|
||||
// focus when clicking below the end of the document.
|
||||
if (ie)
|
||||
if (ie || iege11)
|
||||
$doc.click(function() {focus(editor);});
|
||||
|
||||
// Load the content
|
||||
updateFrame(editor);
|
||||
|
||||
// Bind the ie specific iframe event handlers
|
||||
if (ie) {
|
||||
if (ie || iege11) {
|
||||
|
||||
// Save the current user selection. This code is needed since IE will
|
||||
// reset the selection just after the beforedeactivate event and just
|
||||
|
@ -848,19 +878,19 @@
|
|||
$doc.bind("beforedeactivate beforeactivate selectionchange keypress", function(e) {
|
||||
|
||||
// Flag the editor as inactive
|
||||
if (e.type == "beforedeactivate")
|
||||
if (e.type === "beforedeactivate")
|
||||
editor.inactive = true;
|
||||
|
||||
// Get rid of the bogus selection and flag the editor as active
|
||||
else if (e.type == "beforeactivate") {
|
||||
|
||||
// Get rid of the bogus selection and flag the editor as active
|
||||
else if (e.type === "beforeactivate") {
|
||||
if (!editor.inactive && editor.range && editor.range.length > 1)
|
||||
editor.range.shift();
|
||||
delete editor.inactive;
|
||||
}
|
||||
|
||||
// Save the selection when the editor is active
|
||||
// Save the selection when the editor is active
|
||||
else if (!editor.inactive) {
|
||||
if (!editor.range)
|
||||
if (!editor.range)
|
||||
editor.range = [];
|
||||
editor.range.unshift(getRange(editor));
|
||||
|
||||
|
@ -871,22 +901,31 @@
|
|||
|
||||
});
|
||||
|
||||
// Restore the text range when the iframe gains focus
|
||||
// Restore the text range and trigger focused event when the iframe gains focus
|
||||
$frame.focus(function() {
|
||||
restoreRange(editor);
|
||||
$(editor).triggerHandler(FOCUSED);
|
||||
});
|
||||
|
||||
// Trigger blurred event when the iframe looses focus
|
||||
$frame.blur(function() {
|
||||
$(editor).triggerHandler(BLURRED);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
// Update the textarea when the iframe loses focus
|
||||
($.browser.mozilla ? $doc : $(contentWindow)).blur(function() {
|
||||
updateTextArea(editor, true);
|
||||
});
|
||||
// Trigger focused and blurred events for all other browsers
|
||||
else {
|
||||
$(editor.$frame[0].contentWindow)
|
||||
.focus(function () { $(editor).triggerHandler(FOCUSED); })
|
||||
.blur(function () { $(editor).triggerHandler(BLURRED); });
|
||||
}
|
||||
|
||||
// Enable the toolbar buttons as the user types or clicks
|
||||
// Enable the toolbar buttons and update the textarea as the user types or clicks
|
||||
$doc.click(hidePopups)
|
||||
.bind("keyup mouseup", function() {
|
||||
refreshButtons(editor);
|
||||
updateTextArea(editor, true);
|
||||
});
|
||||
|
||||
// Show the textarea for iPhone/iTouch/iPad or
|
||||
|
@ -906,7 +945,7 @@
|
|||
$toolbar.height(hgt);
|
||||
|
||||
// Resize the iframe
|
||||
hgt = (/%/.test("" + options.height) ? $main.height() : parseInt(options.height)) - hgt;
|
||||
hgt = (/%/.test("" + options.height) ? $main.height() : parseInt(options.height, 10)) - hgt;
|
||||
$frame.width(wid).height(hgt);
|
||||
|
||||
// Resize the textarea. IE6 textareas have a 1px top
|
||||
|
@ -927,7 +966,7 @@
|
|||
function refreshButtons(editor) {
|
||||
|
||||
// Webkit requires focus before queryCommandEnabled will return anything but false
|
||||
if (!iOS && $.browser.webkit && !editor.focused) {
|
||||
if (!iOS && webkit && !editor.focused) {
|
||||
editor.$frame[0].contentWindow.focus();
|
||||
window.focus();
|
||||
editor.focused = true;
|
||||
|
@ -963,14 +1002,14 @@
|
|||
if (enabled === undefined)
|
||||
enabled = true;
|
||||
}
|
||||
else if (((inSourceMode || iOS) && button.name != "source") ||
|
||||
(ie && (command == "undo" || command == "redo")))
|
||||
else if (((inSourceMode || iOS) && button.name !== "source") ||
|
||||
(ie && (command === "undo" || command === "redo")))
|
||||
enabled = false;
|
||||
else if (command && command != "print") {
|
||||
if (ie && command == "hilitecolor")
|
||||
else if (command && command !== "print") {
|
||||
if (ie && command === "hilitecolor")
|
||||
command = "backcolor";
|
||||
// IE does not support inserthtml, so it's always enabled
|
||||
if (!ie || command != "inserthtml") {
|
||||
if (!ie || command !== "inserthtml") {
|
||||
try {enabled = queryObj.queryCommandEnabled(command);}
|
||||
catch (err) {enabled = false;}
|
||||
}
|
||||
|
@ -991,8 +1030,12 @@
|
|||
|
||||
// restoreRange - restores the current ie selection
|
||||
function restoreRange(editor) {
|
||||
if (ie && editor.range)
|
||||
editor.range[0].select();
|
||||
if (editor.range) {
|
||||
if (ie)
|
||||
editor.range[0].select();
|
||||
else if (iege11)
|
||||
getSelection(editor).addRange(editor.range[0]);
|
||||
}
|
||||
}
|
||||
|
||||
// select - selects all the text in either the textarea or iframe
|
||||
|
@ -1084,7 +1127,7 @@
|
|||
// of potentially heavy updateFrame callbacks.
|
||||
if (updateFrameCallback) {
|
||||
var sum = checksum(code);
|
||||
if (checkForChange && editor.areaChecksum == sum)
|
||||
if (checkForChange && editor.areaChecksum === sum)
|
||||
return;
|
||||
editor.areaChecksum = sum;
|
||||
}
|
||||
|
@ -1100,7 +1143,7 @@
|
|||
editor.frameChecksum = checksum(html);
|
||||
|
||||
// Update the iframe and trigger the change event
|
||||
if (html != $body.html()) {
|
||||
if (html !== $body.html()) {
|
||||
$body.html(html);
|
||||
$(editor).triggerHandler(CHANGE);
|
||||
}
|
||||
|
@ -1119,7 +1162,7 @@
|
|||
// of potentially heavy updateTextArea callbacks.
|
||||
if (updateTextAreaCallback) {
|
||||
var sum = checksum(html);
|
||||
if (checkForChange && editor.frameChecksum == sum)
|
||||
if (checkForChange && editor.frameChecksum === sum)
|
||||
return;
|
||||
editor.frameChecksum = sum;
|
||||
}
|
||||
|
@ -1132,7 +1175,7 @@
|
|||
editor.areaChecksum = checksum(code);
|
||||
|
||||
// Update the textarea and trigger the change event
|
||||
if (code != $area.val()) {
|
||||
if (code !== $area.val()) {
|
||||
$area.val(code);
|
||||
$(editor).triggerHandler(CHANGE);
|
||||
}
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
/*
|
||||
CLEditor WYSIWYG HTML Editor v1.3.0
|
||||
http://premiumsoftware.net/cleditor
|
||||
requires jQuery v1.4.2 or later
|
||||
|
||||
Copyright 2010, Chris Landowski, Premium Software, LLC
|
||||
Dual licensed under the MIT or GPL Version 2 licenses.
|
||||
*/
|
||||
(function(e){function aa(a){var b=this,c=a.target,d=e.data(c,x),h=s[d],f=h.popupName,i=p[f];if(!(b.disabled||e(c).attr(n)==n)){var g={editor:b,button:c,buttonName:d,popup:i,popupName:f,command:h.command,useCSS:b.options.useCSS};if(h.buttonClick&&h.buttonClick(a,g)===false)return false;if(d=="source"){if(t(b)){delete b.range;b.$area.hide();b.$frame.show();c.title=h.title}else{b.$frame.hide();b.$area.show();c.title="Show Rich Text"}setTimeout(function(){u(b)},100)}else if(!t(b))if(f){var j=e(i);if(f==
|
||||
"url"){if(d=="link"&&M(b)===""){z(b,"A selection is required when inserting a link.",c);return false}j.children(":button").unbind(q).bind(q,function(){var k=j.find(":text"),o=e.trim(k.val());o!==""&&v(b,g.command,o,null,g.button);k.val("http://");r();w(b)})}else f=="pastetext"&&j.children(":button").unbind(q).bind(q,function(){var k=j.find("textarea"),o=k.val().replace(/\n/g,"<br />");o!==""&&v(b,g.command,o,null,g.button);k.val("");r();w(b)});if(c!==e.data(i,A)){N(b,i,c);return false}return}else if(d==
|
||||
"print")b.$frame[0].contentWindow.print();else if(!v(b,g.command,g.value,g.useCSS,c))return false;w(b)}}function O(a){a=e(a.target).closest("div");a.css(H,a.data(x)?"#FFF":"#FFC")}function P(a){e(a.target).closest("div").css(H,"transparent")}function ba(a){var b=a.data.popup,c=a.target;if(!(b===p.msg||e(b).hasClass(B))){var d=e.data(b,A),h=e.data(d,x),f=s[h],i=f.command,g,j=this.options.useCSS;if(h=="font")g=c.style.fontFamily.replace(/"/g,"");else if(h=="size"){if(c.tagName=="DIV")c=c.children[0];
|
||||
g=c.innerHTML}else if(h=="style")g="<"+c.tagName+">";else if(h=="color")g=Q(c.style.backgroundColor);else if(h=="highlight"){g=Q(c.style.backgroundColor);if(l)i="backcolor";else j=true}b={editor:this,button:d,buttonName:h,popup:b,popupName:f.popupName,command:i,value:g,useCSS:j};if(!(f.popupClick&&f.popupClick(a,b)===false)){if(b.command&&!v(this,b.command,b.value,b.useCSS,d))return false;r();w(this)}}}function C(a){for(var b=1,c=0,d=0;d<a.length;++d){b=(b+a.charCodeAt(d))%65521;c=(c+b)%65521}return c<<
|
||||
16|b}function R(a,b,c,d,h){if(p[a])return p[a];var f=e(m).hide().addClass(ca).appendTo("body");if(d)f.html(d);else if(a=="color"){b=b.colors.split(" ");b.length<10&&f.width("auto");e.each(b,function(i,g){e(m).appendTo(f).css(H,"#"+g)});c=da}else if(a=="font")e.each(b.fonts.split(","),function(i,g){e(m).appendTo(f).css("fontFamily",g).html(g)});else if(a=="size")e.each(b.sizes.split(","),function(i,g){e(m).appendTo(f).html("<font size="+g+">"+g+"</font>")});else if(a=="style")e.each(b.styles,function(i,
|
||||
g){e(m).appendTo(f).html(g[1]+g[0]+g[1].replace("<","</"))});else if(a=="url"){f.html('Enter URL:<br><input type=text value="http://" size=35><br><input type=button value="Submit">');c=B}else if(a=="pastetext"){f.html("Paste your content here and click submit.<br /><textarea cols=40 rows=3></textarea><br /><input type=button value=Submit>");c=B}if(!c&&!d)c=S;f.addClass(c);l&&f.attr(I,"on").find("div,font,p,h1,h2,h3,h4,h5,h6").attr(I,"on");if(f.hasClass(S)||h===true)f.children().hover(O,P);p[a]=f[0];
|
||||
return f[0]}function T(a,b){if(b){a.$area.attr(n,n);a.disabled=true}else{a.$area.removeAttr(n);delete a.disabled}try{if(l)a.doc.body.contentEditable=!b;else a.doc.designMode=!b?"on":"off"}catch(c){}u(a)}function v(a,b,c,d,h){D(a);if(!l){if(d===undefined||d===null)d=a.options.useCSS;a.doc.execCommand("styleWithCSS",0,d.toString())}d=true;var f;if(l&&b.toLowerCase()=="inserthtml")y(a).pasteHTML(c);else{try{d=a.doc.execCommand(b,0,c||null)}catch(i){f=i.description;d=false}d||("cutcopypaste".indexOf(b)>
|
||||
-1?z(a,"For security reasons, your browser does not support the "+b+" command. Try using the keyboard shortcut or context menu instead.",h):z(a,f?f:"Error executing the "+b+" command.",h))}u(a);return d}function w(a){setTimeout(function(){t(a)?a.$area.focus():a.$frame[0].contentWindow.focus();u(a)},0)}function y(a){if(l)return J(a).createRange();return J(a).getRangeAt(0)}function J(a){if(l)return a.doc.selection;return a.$frame[0].contentWindow.getSelection()}function Q(a){var b=/rgba?\((\d+), (\d+), (\d+)/.exec(a),
|
||||
c=a.split("");if(b)for(a=(b[1]<<16|b[2]<<8|b[3]).toString(16);a.length<6;)a="0"+a;return"#"+(a.length==6?a:c[1]+c[1]+c[2]+c[2]+c[3]+c[3])}function r(){e.each(p,function(a,b){e(b).hide().unbind(q).removeData(A)})}function U(){var a=e("link[href$='jquery.cleditor.css']").attr("href");return a.substr(0,a.length-19)+"images/"}function K(a){var b=a.$main,c=a.options;a.$frame&&a.$frame.remove();var d=a.$frame=e('<iframe frameborder="0" src="javascript:true;">').hide().appendTo(b),h=d[0].contentWindow,f=
|
||||
a.doc=h.document,i=e(f);f.open();f.write(c.docType+"<html>"+(c.docCSSFile===""?"":'<head><link rel="stylesheet" type="text/css" href="'+c.docCSSFile+'" /></head>')+'<body style="'+c.bodyStyle+'"></body></html>');f.close();l&&i.click(function(){w(a)});E(a);if(l){i.bind("beforedeactivate beforeactivate selectionchange keypress",function(g){if(g.type=="beforedeactivate")a.inactive=true;else if(g.type=="beforeactivate"){!a.inactive&&a.range&&a.range.length>1&&a.range.shift();delete a.inactive}else if(!a.inactive){if(!a.range)a.range=
|
||||
[];for(a.range.unshift(y(a));a.range.length>2;)a.range.pop()}});d.focus(function(){D(a)})}(e.browser.mozilla?i:e(h)).blur(function(){V(a,true)});i.click(r).bind("keyup mouseup",function(){u(a)});L?a.$area.show():d.show();e(function(){var g=a.$toolbar,j=g.children("div:last"),k=b.width();j=j.offset().top+j.outerHeight()-g.offset().top+1;g.height(j);j=(/%/.test(""+c.height)?b.height():parseInt(c.height))-j;d.width(k).height(j);a.$area.width(k).height(ea?j-2:j);T(a,a.disabled);u(a)})}function u(a){if(!L&&
|
||||
e.browser.webkit&&!a.focused){a.$frame[0].contentWindow.focus();window.focus();a.focused=true}var b=a.doc;if(l)b=y(a);var c=t(a);e.each(a.$toolbar.find("."+W),function(d,h){var f=e(h),i=e.cleditor.buttons[e.data(h,x)],g=i.command,j=true;if(a.disabled)j=false;else if(i.getEnabled){j=i.getEnabled({editor:a,button:h,buttonName:i.name,popup:p[i.popupName],popupName:i.popupName,command:i.command,useCSS:a.options.useCSS});if(j===undefined)j=true}else if((c||L)&&i.name!="source"||l&&(g=="undo"||g=="redo"))j=
|
||||
false;else if(g&&g!="print"){if(l&&g=="hilitecolor")g="backcolor";if(!l||g!="inserthtml")try{j=b.queryCommandEnabled(g)}catch(k){j=false}}if(j){f.removeClass(X);f.removeAttr(n)}else{f.addClass(X);f.attr(n,n)}})}function D(a){l&&a.range&&a.range[0].select()}function M(a){D(a);if(l)return y(a).text;return J(a).toString()}function z(a,b,c){var d=R("msg",a.options,fa);d.innerHTML=b;N(a,d,c)}function N(a,b,c){var d,h,f=e(b);if(c){var i=e(c);d=i.offset();h=--d.left;d=d.top+i.height()}else{i=a.$toolbar;
|
||||
d=i.offset();h=Math.floor((i.width()-f.width())/2)+d.left;d=d.top+i.height()-2}r();f.css({left:h,top:d}).show();if(c){e.data(b,A,c);f.bind(q,{popup:b},e.proxy(ba,a))}setTimeout(function(){f.find(":text,textarea").eq(0).focus().select()},100)}function t(a){return a.$area.is(":visible")}function E(a,b){var c=a.$area.val(),d=a.options,h=d.updateFrame,f=e(a.doc.body);if(h){var i=C(c);if(b&&a.areaChecksum==i)return;a.areaChecksum=i}c=h?h(c):c;c=c.replace(/<(?=\/?script)/ig,"<");if(d.updateTextArea)a.frameChecksum=
|
||||
C(c);if(c!=f.html()){f.html(c);e(a).triggerHandler(F)}}function V(a,b){var c=e(a.doc.body).html(),d=a.options,h=d.updateTextArea,f=a.$area;if(h){var i=C(c);if(b&&a.frameChecksum==i)return;a.frameChecksum=i}c=h?h(c):c;if(d.updateFrame)a.areaChecksum=C(c);if(c!=f.val()){f.val(c);e(a).triggerHandler(F)}}e.cleditor={defaultOptions:{width:500,height:250,controls:"bold italic underline strikethrough subscript superscript | font size style | color highlight removeformat | bullets numbering | outdent indent | alignleft center alignright justify | undo redo | rule image link unlink | cut copy paste pastetext | print source",
|
||||
colors:"FFF FCC FC9 FF9 FFC 9F9 9FF CFF CCF FCF CCC F66 F96 FF6 FF3 6F9 3FF 6FF 99F F9F BBB F00 F90 FC6 FF0 3F3 6CC 3CF 66C C6C 999 C00 F60 FC3 FC0 3C0 0CC 36F 63F C3C 666 900 C60 C93 990 090 399 33F 60C 939 333 600 930 963 660 060 366 009 339 636 000 300 630 633 330 030 033 006 309 303",fonts:"Arial,Arial Black,Comic Sans MS,Courier New,Narrow,Garamond,Georgia,Impact,Sans Serif,Serif,Tahoma,Trebuchet MS,Verdana",sizes:"1,2,3,4,5,6,7",styles:[["Paragraph","<p>"],["Header 1","<h1>"],["Header 2","<h2>"],
|
||||
["Header 3","<h3>"],["Header 4","<h4>"],["Header 5","<h5>"],["Header 6","<h6>"]],useCSS:false,docType:'<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">',docCSSFile:"",bodyStyle:"margin:4px; font:10pt Arial,Verdana; cursor:text"},buttons:{init:"bold,,|italic,,|underline,,|strikethrough,,|subscript,,|superscript,,|font,,fontname,|size,Font Size,fontsize,|style,,formatblock,|color,Font Color,forecolor,|highlight,Text Highlight Color,hilitecolor,color|removeformat,Remove Formatting,|bullets,,insertunorderedlist|numbering,,insertorderedlist|outdent,,|indent,,|alignleft,Align Text Left,justifyleft|center,,justifycenter|alignright,Align Text Right,justifyright|justify,,justifyfull|undo,,|redo,,|rule,Insert Horizontal Rule,inserthorizontalrule|image,Insert Image,insertimage,url|link,Insert Hyperlink,createlink,url|unlink,Remove Hyperlink,|cut,,|copy,,|paste,,|pastetext,Paste as Text,inserthtml,|print,,|source,Show Source"},
|
||||
imagesPath:function(){return U()}};e.fn.cleditor=function(a){var b=e([]);this.each(function(c,d){if(d.tagName=="TEXTAREA"){var h=e.data(d,Y);h||(h=new cleditor(d,a));b=b.add(h)}});return b};var H="backgroundColor",A="button",x="buttonName",F="change",Y="cleditor",q="click",n="disabled",m="<div>",I="unselectable",W="cleditorButton",X="cleditorDisabled",ca="cleditorPopup",S="cleditorList",da="cleditorColor",B="cleditorPrompt",fa="cleditorMsg",l=e.browser.msie,ea=/msie\s6/i.test(navigator.userAgent),
|
||||
L=/iphone|ipad|ipod/i.test(navigator.userAgent),p={},Z,s=e.cleditor.buttons;e.each(s.init.split("|"),function(a,b){var c=b.split(","),d=c[0];s[d]={stripIndex:a,name:d,title:c[1]===""?d.charAt(0).toUpperCase()+d.substr(1):c[1],command:c[2]===""?d:c[2],popupName:c[3]===""?d:c[3]}});delete s.init;cleditor=function(a,b){var c=this;c.options=b=e.extend({},e.cleditor.defaultOptions,b);var d=c.$area=e(a).hide().data(Y,c).blur(function(){E(c,true)}),h=c.$main=e(m).addClass("cleditorMain").width(b.width).height(b.height),
|
||||
f=c.$toolbar=e(m).addClass("cleditorToolbar").appendTo(h),i=e(m).addClass("cleditorGroup").appendTo(f);e.each(b.controls.split(" "),function(g,j){if(j==="")return true;if(j=="|"){e(m).addClass("cleditorDivider").appendTo(i);i=e(m).addClass("cleditorGroup").appendTo(f)}else{var k=s[j],o=e(m).data(x,k.name).addClass(W).attr("title",k.title).bind(q,e.proxy(aa,c)).appendTo(i).hover(O,P),G={};if(k.css)G=k.css;else if(k.image)G.backgroundImage="url("+U()+k.image+")";if(k.stripIndex)G.backgroundPosition=
|
||||
k.stripIndex*-24;o.css(G);l&&o.attr(I,"on");k.popupName&&R(k.popupName,b,k.popupClass,k.popupContent,k.popupHover)}});h.insertBefore(d).append(d);if(!Z){e(document).click(function(g){g=e(g.target);g.add(g.parents()).is("."+B)||r()});Z=true}/auto|%/.test(""+b.width+b.height)&&e(window).resize(function(){K(c)});K(c)};var $=cleditor.prototype;e.each([["clear",function(a){a.$area.val("");E(a)}],["disable",T],["execCommand",v],["focus",w],["hidePopups",r],["sourceMode",t,true],["refresh",K],["select",
|
||||
function(a){setTimeout(function(){t(a)?a.$area.select():v(a,"selectall")},0)}],["selectedHTML",function(a){D(a);a=y(a);if(l)return a.htmlText;var b=e("<layer>")[0];b.appendChild(a.cloneContents());return b.innerHTML},true],["selectedText",M,true],["showMessage",z],["updateFrame",E],["updateTextArea",V]],function(a,b){$[b[0]]=function(){for(var c=[this],d=0;d<arguments.length;d++)c.push(arguments[d]);c=b[1].apply(this,c);if(b[2])return c;return this}});$.change=function(a){var b=e(this);return a?b.bind(F,
|
||||
a):b.trigger(F)}})(jQuery);
|
|
@ -13,7 +13,7 @@
|
|||
}
|
||||
.fa {
|
||||
display: inline-block;
|
||||
font-family: FontAwesome;
|
||||
font-family: FontAwesome !important;
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
line-height: 1;
|
||||
|
|
|
@ -1,250 +0,0 @@
|
|||
// tipsy, facebook style tooltips for jquery
|
||||
// version 1.0.0a
|
||||
// (c) 2008-2010 jason frame [jason@onehackoranother.com]
|
||||
// released under the MIT license
|
||||
|
||||
(function($) {
|
||||
|
||||
function maybeCall(thing, ctx) {
|
||||
return (typeof thing == 'function') ? (thing.call(ctx)) : thing;
|
||||
};
|
||||
|
||||
function Tipsy(element, options) {
|
||||
this.$element = $(element);
|
||||
this.options = options;
|
||||
this.enabled = true;
|
||||
this.fixTitle();
|
||||
};
|
||||
|
||||
Tipsy.prototype = {
|
||||
show: function() {
|
||||
$.fn.tipsy.clear();
|
||||
if (!this.$element.parent().length) {
|
||||
return;
|
||||
}
|
||||
var title = this.getTitle();
|
||||
if (title && this.enabled) {
|
||||
var $tip = this.tip();
|
||||
|
||||
$tip.find('.tipsy-inner')[this.options.html ? 'html' : 'text'](title);
|
||||
$tip[0].className = 'tipsy '; // reset classname in case of dynamic gravity
|
||||
$tip.openerpClass('oe_tooltip');
|
||||
$tip.remove().css({top: 0, left: 0, visibility: 'hidden', display: 'block'}).prependTo(document.body);
|
||||
|
||||
var pos = $.extend({}, this.$element.offset(), {
|
||||
width: this.$element[0].offsetWidth,
|
||||
height: this.$element[0].offsetHeight
|
||||
});
|
||||
|
||||
var actualWidth = $tip[0].offsetWidth,
|
||||
actualHeight = $tip[0].offsetHeight,
|
||||
gravity = maybeCall(this.options.gravity, this.$element[0]);
|
||||
|
||||
var tp;
|
||||
switch (gravity.charAt(0)) {
|
||||
case 'n':
|
||||
tp = {top: pos.top + pos.height + this.options.offset, left: pos.left + pos.width / 2 - actualWidth / 2};
|
||||
break;
|
||||
case 's':
|
||||
tp = {top: pos.top - actualHeight - this.options.offset, left: pos.left + pos.width / 2 - actualWidth / 2};
|
||||
break;
|
||||
case 'e':
|
||||
tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth - this.options.offset};
|
||||
break;
|
||||
case 'w':
|
||||
tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width + this.options.offset};
|
||||
break;
|
||||
}
|
||||
|
||||
if (gravity.length == 2) {
|
||||
if (gravity.charAt(1) == 'w') {
|
||||
tp.left = pos.left + pos.width / 2 - 15;
|
||||
} else {
|
||||
tp.left = pos.left + pos.width / 2 - actualWidth + 15;
|
||||
}
|
||||
}
|
||||
|
||||
$tip.css(tp).addClass('tipsy-' + gravity);
|
||||
$tip.find('.tipsy-arrow')[0].className = 'tipsy-arrow tipsy-arrow-' + gravity.charAt(0);
|
||||
if (this.options.className) {
|
||||
$tip.addClass(maybeCall(this.options.className, this.$element[0]));
|
||||
}
|
||||
|
||||
if (this.options.fade) {
|
||||
$tip.stop().css({opacity: 0, display: 'block', visibility: 'visible'}).animate({opacity: this.options.opacity});
|
||||
} else {
|
||||
$tip.css({visibility: 'visible', opacity: this.options.opacity});
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
hide: function() {
|
||||
if (this.options.fade) {
|
||||
this.tip().stop().fadeOut(function() { $(this).remove(); });
|
||||
} else {
|
||||
this.tip().remove();
|
||||
}
|
||||
},
|
||||
|
||||
fixTitle: function() {
|
||||
var $e = this.$element;
|
||||
if ($e.attr('title') || typeof($e.attr('original-title')) != 'string') {
|
||||
$e.attr('original-title', $e.attr('title') || '').removeAttr('title');
|
||||
}
|
||||
},
|
||||
|
||||
getTitle: function() {
|
||||
var title, $e = this.$element, o = this.options;
|
||||
this.fixTitle();
|
||||
var title, o = this.options;
|
||||
if (typeof o.title == 'string') {
|
||||
title = $e.attr(o.title == 'title' ? 'original-title' : o.title);
|
||||
} else if (typeof o.title == 'function') {
|
||||
title = o.title.call($e[0]);
|
||||
}
|
||||
title = ('' + title).replace(/(^\s*|\s*$)/, "");
|
||||
return title || o.fallback;
|
||||
},
|
||||
|
||||
tip: function() {
|
||||
if (!this.$tip) {
|
||||
this.$tip = $('<div class="tipsy"></div>').html('<div class="tipsy-arrow"></div><div class="tipsy-inner"></div>');
|
||||
}
|
||||
return this.$tip;
|
||||
},
|
||||
|
||||
validate: function() {
|
||||
if (!this.$element[0].parentNode) {
|
||||
this.hide();
|
||||
this.$element = null;
|
||||
this.options = null;
|
||||
}
|
||||
},
|
||||
|
||||
enable: function() { this.enabled = true; },
|
||||
disable: function() { this.enabled = false; },
|
||||
toggleEnabled: function() { this.enabled = !this.enabled; }
|
||||
};
|
||||
|
||||
$.fn.tipsy = function(options) {
|
||||
|
||||
if (options === true) {
|
||||
return this.data('tipsy');
|
||||
} else if (typeof options == 'string') {
|
||||
var tipsy = this.data('tipsy');
|
||||
if (tipsy) tipsy[options]();
|
||||
return this;
|
||||
}
|
||||
|
||||
options = $.extend({}, $.fn.tipsy.defaults, options);
|
||||
|
||||
function get(ele) {
|
||||
var tipsy = $.data(ele, 'tipsy');
|
||||
if (!tipsy) {
|
||||
tipsy = new Tipsy(ele, $.fn.tipsy.elementOptions(ele, options));
|
||||
$.data(ele, 'tipsy', tipsy);
|
||||
}
|
||||
return tipsy;
|
||||
}
|
||||
|
||||
function enter() {
|
||||
var tipsy = get(this);
|
||||
tipsy.hoverState = 'in';
|
||||
if (options.delayIn == 0) {
|
||||
tipsy.show();
|
||||
} else {
|
||||
tipsy.fixTitle();
|
||||
setTimeout(function() { if (tipsy.hoverState == 'in') tipsy.show(); }, options.delayIn);
|
||||
}
|
||||
};
|
||||
|
||||
function leave() {
|
||||
var tipsy = get(this);
|
||||
tipsy.hoverState = 'out';
|
||||
if (options.delayOut == 0) {
|
||||
tipsy.hide();
|
||||
} else {
|
||||
setTimeout(function() { if (tipsy.hoverState == 'out') tipsy.hide(); }, options.delayOut);
|
||||
}
|
||||
};
|
||||
|
||||
if (!options.live) this.each(function() { get(this); });
|
||||
|
||||
if (options.trigger != 'manual') {
|
||||
var binder = options.live ? 'live' : 'bind',
|
||||
eventIn = options.trigger == 'hover' ? 'mouseenter' : 'focus',
|
||||
eventOut = options.trigger == 'hover' ? 'mouseleave' : 'blur';
|
||||
this[binder](eventIn, enter)[binder](eventOut, leave);
|
||||
}
|
||||
|
||||
return this;
|
||||
|
||||
};
|
||||
|
||||
$.fn.tipsy.clear = function() {
|
||||
$('div.tipsy').stop().remove();
|
||||
}
|
||||
|
||||
$.fn.tipsy.defaults = {
|
||||
className: null,
|
||||
delayIn: 0,
|
||||
delayOut: 0,
|
||||
fade: false,
|
||||
fallback: '',
|
||||
gravity: 'n',
|
||||
html: false,
|
||||
live: false,
|
||||
offset: 0,
|
||||
opacity: 0.8,
|
||||
title: 'title',
|
||||
trigger: 'hover'
|
||||
};
|
||||
|
||||
// Overwrite this method to provide options on a per-element basis.
|
||||
// For example, you could store the gravity in a 'tipsy-gravity' attribute:
|
||||
// return $.extend({}, options, {gravity: $(ele).attr('tipsy-gravity') || 'n' });
|
||||
// (remember - do not modify 'options' in place!)
|
||||
$.fn.tipsy.elementOptions = function(ele, options) {
|
||||
return $.metadata ? $.extend({}, options, $(ele).metadata()) : options;
|
||||
};
|
||||
|
||||
$.fn.tipsy.autoNS = function() {
|
||||
return $(this).offset().top > ($(document).scrollTop() + $(window).height() / 2) ? 's' : 'n';
|
||||
};
|
||||
|
||||
$.fn.tipsy.autoWE = function() {
|
||||
return $(this).offset().left > ($(document).scrollLeft() + $(window).width() / 2) ? 'e' : 'w';
|
||||
};
|
||||
|
||||
/**
|
||||
* yields a closure of the supplied parameters, producing a function that takes
|
||||
* no arguments and is suitable for use as an autogravity function like so:
|
||||
*
|
||||
* @param margin (int) - distance from the viewable region edge that an
|
||||
* element should be before setting its tooltip's gravity to be away
|
||||
* from that edge.
|
||||
* @param prefer (string, e.g. 'n', 'sw', 'w') - the direction to prefer
|
||||
* if there are no viewable region edges effecting the tooltip's
|
||||
* gravity. It will try to vary from this minimally, for example,
|
||||
* if 'sw' is preferred and an element is near the right viewable
|
||||
* region edge, but not the top edge, it will set the gravity for
|
||||
* that element's tooltip to be 'se', preserving the southern
|
||||
* component.
|
||||
*/
|
||||
$.fn.tipsy.autoBounds = function(margin, prefer) {
|
||||
return function() {
|
||||
var dir = {ns: prefer[0], ew: (prefer.length > 1 ? prefer[1] : false)},
|
||||
boundTop = $(document).scrollTop() + margin,
|
||||
boundLeft = $(document).scrollLeft() + margin,
|
||||
$this = $(this);
|
||||
|
||||
if ($this.offset().top < boundTop) dir.ns = 'n';
|
||||
if ($this.offset().left < boundLeft) dir.ew = 'w';
|
||||
if ($(window).width() + $(document).scrollLeft() - $this.offset().left < margin) dir.ew = 'e';
|
||||
if ($(window).height() + $(document).scrollTop() - $this.offset().top < margin) dir.ns = 's';
|
||||
|
||||
return dir.ns + (dir.ew ? dir.ew : '');
|
||||
}
|
||||
};
|
||||
|
||||
})(jQuery);
|
|
@ -1,25 +0,0 @@
|
|||
.tipsy { font-size: 90%; position: absolute; padding: 5px; z-index: 100000; overflow: hidden;}
|
||||
.tipsy-inner { background-color: #000; color: #FFF; max-width: 500px; padding: 5px 8px 4px 8px; }
|
||||
|
||||
/* Rounded corners */
|
||||
.tipsy-inner { border-radius: 3px; -moz-border-radius: 3px; -webkit-border-radius: 3px; }
|
||||
|
||||
/* Uncomment for shadow */
|
||||
.tipsy-inner { box-shadow: 0 0 5px #000000; -webkit-box-shadow: 0 0 5px #000000; -moz-box-shadow: 0 0 5px #000000; }
|
||||
|
||||
.tipsy-arrow { position: absolute; width: 0; height: 0; line-height: 0; border: 5px dashed #000; }
|
||||
|
||||
/* Rules to colour arrows */
|
||||
.tipsy-arrow-n { border-bottom-color: #000; }
|
||||
.tipsy-arrow-s { border-top-color: #000; }
|
||||
.tipsy-arrow-e { border-left-color: #000; }
|
||||
.tipsy-arrow-w { border-right-color: #000; }
|
||||
|
||||
.tipsy-n .tipsy-arrow { top: 0px; left: 50%; margin-left: -5px; border-bottom-style: solid; border-top: none; border-left-color: transparent; border-right-color: transparent; }
|
||||
.tipsy-nw .tipsy-arrow { top: 0; left: 10px; border-bottom-style: solid; border-top: none; border-left-color: transparent; border-right-color: transparent;}
|
||||
.tipsy-ne .tipsy-arrow { top: 0; right: 10px; border-bottom-style: solid; border-top: none; border-left-color: transparent; border-right-color: transparent;}
|
||||
.tipsy-s .tipsy-arrow { bottom: 0; left: 50%; margin-left: -5px; border-top-style: solid; border-bottom: none; border-left-color: transparent; border-right-color: transparent; }
|
||||
.tipsy-sw .tipsy-arrow { bottom: 0; left: 10px; border-top-style: solid; border-bottom: none; border-left-color: transparent; border-right-color: transparent; }
|
||||
.tipsy-se .tipsy-arrow { bottom: 0; right: 10px; border-top-style: solid; border-bottom: none; border-left-color: transparent; border-right-color: transparent; }
|
||||
.tipsy-e .tipsy-arrow { right: 0; top: 50%; margin-top: -5px; border-left-style: solid; border-right: none; border-top-color: transparent; border-bottom-color: transparent; }
|
||||
.tipsy-w .tipsy-arrow { left: 0; top: 50%; margin-top: -5px; border-right-style: solid; border-left: none; border-top-color: transparent; border-bottom-color: transparent; }
|
|
@ -1,6 +1,6 @@
|
|||
// Underscore.js 1.5.2
|
||||
// Underscore.js 1.6.0
|
||||
// http://underscorejs.org
|
||||
// (c) 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
|
||||
// (c) 2009-2014 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
|
||||
// Underscore may be freely distributed under the MIT license.
|
||||
|
||||
(function() {
|
||||
|
@ -65,7 +65,7 @@
|
|||
}
|
||||
|
||||
// Current version.
|
||||
_.VERSION = '1.5.2';
|
||||
_.VERSION = '1.6.0';
|
||||
|
||||
// Collection Functions
|
||||
// --------------------
|
||||
|
@ -74,7 +74,7 @@
|
|||
// Handles objects with the built-in `forEach`, arrays, and raw objects.
|
||||
// Delegates to **ECMAScript 5**'s native `forEach` if available.
|
||||
var each = _.each = _.forEach = function(obj, iterator, context) {
|
||||
if (obj == null) return;
|
||||
if (obj == null) return obj;
|
||||
if (nativeForEach && obj.forEach === nativeForEach) {
|
||||
obj.forEach(iterator, context);
|
||||
} else if (obj.length === +obj.length) {
|
||||
|
@ -87,6 +87,7 @@
|
|||
if (iterator.call(context, obj[keys[i]], keys[i], obj) === breaker) return;
|
||||
}
|
||||
}
|
||||
return obj;
|
||||
};
|
||||
|
||||
// Return the results of applying the iterator to each element.
|
||||
|
@ -152,10 +153,10 @@
|
|||
};
|
||||
|
||||
// Return the first value which passes a truth test. Aliased as `detect`.
|
||||
_.find = _.detect = function(obj, iterator, context) {
|
||||
_.find = _.detect = function(obj, predicate, context) {
|
||||
var result;
|
||||
any(obj, function(value, index, list) {
|
||||
if (iterator.call(context, value, index, list)) {
|
||||
if (predicate.call(context, value, index, list)) {
|
||||
result = value;
|
||||
return true;
|
||||
}
|
||||
|
@ -166,33 +167,33 @@
|
|||
// Return all the elements that pass a truth test.
|
||||
// Delegates to **ECMAScript 5**'s native `filter` if available.
|
||||
// Aliased as `select`.
|
||||
_.filter = _.select = function(obj, iterator, context) {
|
||||
_.filter = _.select = function(obj, predicate, context) {
|
||||
var results = [];
|
||||
if (obj == null) return results;
|
||||
if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context);
|
||||
if (nativeFilter && obj.filter === nativeFilter) return obj.filter(predicate, context);
|
||||
each(obj, function(value, index, list) {
|
||||
if (iterator.call(context, value, index, list)) results.push(value);
|
||||
if (predicate.call(context, value, index, list)) results.push(value);
|
||||
});
|
||||
return results;
|
||||
};
|
||||
|
||||
// Return all the elements for which a truth test fails.
|
||||
_.reject = function(obj, iterator, context) {
|
||||
_.reject = function(obj, predicate, context) {
|
||||
return _.filter(obj, function(value, index, list) {
|
||||
return !iterator.call(context, value, index, list);
|
||||
return !predicate.call(context, value, index, list);
|
||||
}, context);
|
||||
};
|
||||
|
||||
// Determine whether all of the elements match a truth test.
|
||||
// Delegates to **ECMAScript 5**'s native `every` if available.
|
||||
// Aliased as `all`.
|
||||
_.every = _.all = function(obj, iterator, context) {
|
||||
iterator || (iterator = _.identity);
|
||||
_.every = _.all = function(obj, predicate, context) {
|
||||
predicate || (predicate = _.identity);
|
||||
var result = true;
|
||||
if (obj == null) return result;
|
||||
if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context);
|
||||
if (nativeEvery && obj.every === nativeEvery) return obj.every(predicate, context);
|
||||
each(obj, function(value, index, list) {
|
||||
if (!(result = result && iterator.call(context, value, index, list))) return breaker;
|
||||
if (!(result = result && predicate.call(context, value, index, list))) return breaker;
|
||||
});
|
||||
return !!result;
|
||||
};
|
||||
|
@ -200,13 +201,13 @@
|
|||
// Determine if at least one element in the object matches a truth test.
|
||||
// Delegates to **ECMAScript 5**'s native `some` if available.
|
||||
// Aliased as `any`.
|
||||
var any = _.some = _.any = function(obj, iterator, context) {
|
||||
iterator || (iterator = _.identity);
|
||||
var any = _.some = _.any = function(obj, predicate, context) {
|
||||
predicate || (predicate = _.identity);
|
||||
var result = false;
|
||||
if (obj == null) return result;
|
||||
if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context);
|
||||
if (nativeSome && obj.some === nativeSome) return obj.some(predicate, context);
|
||||
each(obj, function(value, index, list) {
|
||||
if (result || (result = iterator.call(context, value, index, list))) return breaker;
|
||||
if (result || (result = predicate.call(context, value, index, list))) return breaker;
|
||||
});
|
||||
return !!result;
|
||||
};
|
||||
|
@ -232,25 +233,19 @@
|
|||
|
||||
// Convenience version of a common use case of `map`: fetching a property.
|
||||
_.pluck = function(obj, key) {
|
||||
return _.map(obj, function(value){ return value[key]; });
|
||||
return _.map(obj, _.property(key));
|
||||
};
|
||||
|
||||
// Convenience version of a common use case of `filter`: selecting only objects
|
||||
// containing specific `key:value` pairs.
|
||||
_.where = function(obj, attrs, first) {
|
||||
if (_.isEmpty(attrs)) return first ? void 0 : [];
|
||||
return _[first ? 'find' : 'filter'](obj, function(value) {
|
||||
for (var key in attrs) {
|
||||
if (attrs[key] !== value[key]) return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
_.where = function(obj, attrs) {
|
||||
return _.filter(obj, _.matches(attrs));
|
||||
};
|
||||
|
||||
// Convenience version of a common use case of `find`: getting the first object
|
||||
// containing specific `key:value` pairs.
|
||||
_.findWhere = function(obj, attrs) {
|
||||
return _.where(obj, attrs, true);
|
||||
return _.find(obj, _.matches(attrs));
|
||||
};
|
||||
|
||||
// Return the maximum element or (element-based computation).
|
||||
|
@ -260,13 +255,15 @@
|
|||
if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {
|
||||
return Math.max.apply(Math, obj);
|
||||
}
|
||||
if (!iterator && _.isEmpty(obj)) return -Infinity;
|
||||
var result = {computed : -Infinity, value: -Infinity};
|
||||
var result = -Infinity, lastComputed = -Infinity;
|
||||
each(obj, function(value, index, list) {
|
||||
var computed = iterator ? iterator.call(context, value, index, list) : value;
|
||||
computed > result.computed && (result = {value : value, computed : computed});
|
||||
if (computed > lastComputed) {
|
||||
result = value;
|
||||
lastComputed = computed;
|
||||
}
|
||||
});
|
||||
return result.value;
|
||||
return result;
|
||||
};
|
||||
|
||||
// Return the minimum element (or element-based computation).
|
||||
|
@ -274,16 +271,18 @@
|
|||
if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {
|
||||
return Math.min.apply(Math, obj);
|
||||
}
|
||||
if (!iterator && _.isEmpty(obj)) return Infinity;
|
||||
var result = {computed : Infinity, value: Infinity};
|
||||
var result = Infinity, lastComputed = Infinity;
|
||||
each(obj, function(value, index, list) {
|
||||
var computed = iterator ? iterator.call(context, value, index, list) : value;
|
||||
computed < result.computed && (result = {value : value, computed : computed});
|
||||
if (computed < lastComputed) {
|
||||
result = value;
|
||||
lastComputed = computed;
|
||||
}
|
||||
});
|
||||
return result.value;
|
||||
return result;
|
||||
};
|
||||
|
||||
// Shuffle an array, using the modern version of the
|
||||
// Shuffle an array, using the modern version of the
|
||||
// [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle).
|
||||
_.shuffle = function(obj) {
|
||||
var rand;
|
||||
|
@ -297,11 +296,12 @@
|
|||
return shuffled;
|
||||
};
|
||||
|
||||
// Sample **n** random values from an array.
|
||||
// If **n** is not specified, returns a single random element from the array.
|
||||
// Sample **n** random values from a collection.
|
||||
// If **n** is not specified, returns a single random element.
|
||||
// The internal `guard` argument allows it to work with `map`.
|
||||
_.sample = function(obj, n, guard) {
|
||||
if (arguments.length < 2 || guard) {
|
||||
if (n == null || guard) {
|
||||
if (obj.length !== +obj.length) obj = _.values(obj);
|
||||
return obj[_.random(obj.length - 1)];
|
||||
}
|
||||
return _.shuffle(obj).slice(0, Math.max(0, n));
|
||||
|
@ -309,12 +309,14 @@
|
|||
|
||||
// An internal function to generate lookup iterators.
|
||||
var lookupIterator = function(value) {
|
||||
return _.isFunction(value) ? value : function(obj){ return obj[value]; };
|
||||
if (value == null) return _.identity;
|
||||
if (_.isFunction(value)) return value;
|
||||
return _.property(value);
|
||||
};
|
||||
|
||||
// Sort the object's values by a criterion produced by an iterator.
|
||||
_.sortBy = function(obj, value, context) {
|
||||
var iterator = lookupIterator(value);
|
||||
_.sortBy = function(obj, iterator, context) {
|
||||
iterator = lookupIterator(iterator);
|
||||
return _.pluck(_.map(obj, function(value, index, list) {
|
||||
return {
|
||||
value: value,
|
||||
|
@ -334,9 +336,9 @@
|
|||
|
||||
// An internal function used for aggregate "group by" operations.
|
||||
var group = function(behavior) {
|
||||
return function(obj, value, context) {
|
||||
return function(obj, iterator, context) {
|
||||
var result = {};
|
||||
var iterator = value == null ? _.identity : lookupIterator(value);
|
||||
iterator = lookupIterator(iterator);
|
||||
each(obj, function(value, index) {
|
||||
var key = iterator.call(context, value, index, obj);
|
||||
behavior(result, key, value);
|
||||
|
@ -348,7 +350,7 @@
|
|||
// Groups the object's values by a criterion. Pass either a string attribute
|
||||
// to group by, or a function that returns the criterion.
|
||||
_.groupBy = group(function(result, key, value) {
|
||||
(_.has(result, key) ? result[key] : (result[key] = [])).push(value);
|
||||
_.has(result, key) ? result[key].push(value) : result[key] = [value];
|
||||
});
|
||||
|
||||
// Indexes the object's values by a criterion, similar to `groupBy`, but for
|
||||
|
@ -367,7 +369,7 @@
|
|||
// Use a comparator function to figure out the smallest index at which
|
||||
// an object should be inserted so as to maintain order. Uses binary search.
|
||||
_.sortedIndex = function(array, obj, iterator, context) {
|
||||
iterator = iterator == null ? _.identity : lookupIterator(iterator);
|
||||
iterator = lookupIterator(iterator);
|
||||
var value = iterator.call(context, obj);
|
||||
var low = 0, high = array.length;
|
||||
while (low < high) {
|
||||
|
@ -399,7 +401,9 @@
|
|||
// allows it to work with `_.map`.
|
||||
_.first = _.head = _.take = function(array, n, guard) {
|
||||
if (array == null) return void 0;
|
||||
return (n == null) || guard ? array[0] : slice.call(array, 0, n);
|
||||
if ((n == null) || guard) return array[0];
|
||||
if (n < 0) return [];
|
||||
return slice.call(array, 0, n);
|
||||
};
|
||||
|
||||
// Returns everything but the last entry of the array. Especially useful on
|
||||
|
@ -414,11 +418,8 @@
|
|||
// values in the array. The **guard** check allows it to work with `_.map`.
|
||||
_.last = function(array, n, guard) {
|
||||
if (array == null) return void 0;
|
||||
if ((n == null) || guard) {
|
||||
return array[array.length - 1];
|
||||
} else {
|
||||
return slice.call(array, Math.max(array.length - n, 0));
|
||||
}
|
||||
if ((n == null) || guard) return array[array.length - 1];
|
||||
return slice.call(array, Math.max(array.length - n, 0));
|
||||
};
|
||||
|
||||
// Returns everything but the first entry of the array. Aliased as `tail` and `drop`.
|
||||
|
@ -459,6 +460,17 @@
|
|||
return _.difference(array, slice.call(arguments, 1));
|
||||
};
|
||||
|
||||
// Split an array into two arrays: one whose elements all satisfy the given
|
||||
// predicate, and one whose elements all do not satisfy the predicate.
|
||||
_.partition = function(array, predicate, context) {
|
||||
predicate = lookupIterator(predicate);
|
||||
var pass = [], fail = [];
|
||||
each(array, function(elem) {
|
||||
(predicate.call(context, elem) ? pass : fail).push(elem);
|
||||
});
|
||||
return [pass, fail];
|
||||
};
|
||||
|
||||
// Produce a duplicate-free version of the array. If the array has already
|
||||
// been sorted, you have the option of using a faster algorithm.
|
||||
// Aliased as `unique`.
|
||||
|
@ -492,7 +504,7 @@
|
|||
var rest = slice.call(arguments, 1);
|
||||
return _.filter(_.uniq(array), function(item) {
|
||||
return _.every(rest, function(other) {
|
||||
return _.indexOf(other, item) >= 0;
|
||||
return _.contains(other, item);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
@ -507,7 +519,7 @@
|
|||
// Zip together multiple lists into a single array -- elements that share
|
||||
// an index go together.
|
||||
_.zip = function() {
|
||||
var length = _.max(_.pluck(arguments, "length").concat(0));
|
||||
var length = _.max(_.pluck(arguments, 'length').concat(0));
|
||||
var results = new Array(length);
|
||||
for (var i = 0; i < length; i++) {
|
||||
results[i] = _.pluck(arguments, '' + i);
|
||||
|
@ -613,19 +625,27 @@
|
|||
};
|
||||
|
||||
// Partially apply a function by creating a version that has had some of its
|
||||
// arguments pre-filled, without changing its dynamic `this` context.
|
||||
// arguments pre-filled, without changing its dynamic `this` context. _ acts
|
||||
// as a placeholder, allowing any combination of arguments to be pre-filled.
|
||||
_.partial = function(func) {
|
||||
var args = slice.call(arguments, 1);
|
||||
var boundArgs = slice.call(arguments, 1);
|
||||
return function() {
|
||||
return func.apply(this, args.concat(slice.call(arguments)));
|
||||
var position = 0;
|
||||
var args = boundArgs.slice();
|
||||
for (var i = 0, length = args.length; i < length; i++) {
|
||||
if (args[i] === _) args[i] = arguments[position++];
|
||||
}
|
||||
while (position < arguments.length) args.push(arguments[position++]);
|
||||
return func.apply(this, args);
|
||||
};
|
||||
};
|
||||
|
||||
// Bind all of an object's methods to that object. Useful for ensuring that
|
||||
// all callbacks defined on an object belong to it.
|
||||
// Bind a number of an object's methods to that object. Remaining arguments
|
||||
// are the method names to be bound. Useful for ensuring that all callbacks
|
||||
// defined on an object belong to it.
|
||||
_.bindAll = function(obj) {
|
||||
var funcs = slice.call(arguments, 1);
|
||||
if (funcs.length === 0) throw new Error("bindAll must be passed function names");
|
||||
if (funcs.length === 0) throw new Error('bindAll must be passed function names');
|
||||
each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });
|
||||
return obj;
|
||||
};
|
||||
|
@ -664,12 +684,13 @@
|
|||
var previous = 0;
|
||||
options || (options = {});
|
||||
var later = function() {
|
||||
previous = options.leading === false ? 0 : new Date;
|
||||
previous = options.leading === false ? 0 : _.now();
|
||||
timeout = null;
|
||||
result = func.apply(context, args);
|
||||
context = args = null;
|
||||
};
|
||||
return function() {
|
||||
var now = new Date;
|
||||
var now = _.now();
|
||||
if (!previous && options.leading === false) previous = now;
|
||||
var remaining = wait - (now - previous);
|
||||
context = this;
|
||||
|
@ -679,6 +700,7 @@
|
|||
timeout = null;
|
||||
previous = now;
|
||||
result = func.apply(context, args);
|
||||
context = args = null;
|
||||
} else if (!timeout && options.trailing !== false) {
|
||||
timeout = setTimeout(later, remaining);
|
||||
}
|
||||
|
@ -692,24 +714,33 @@
|
|||
// leading edge, instead of the trailing.
|
||||
_.debounce = function(func, wait, immediate) {
|
||||
var timeout, args, context, timestamp, result;
|
||||
|
||||
var later = function() {
|
||||
var last = _.now() - timestamp;
|
||||
if (last < wait) {
|
||||
timeout = setTimeout(later, wait - last);
|
||||
} else {
|
||||
timeout = null;
|
||||
if (!immediate) {
|
||||
result = func.apply(context, args);
|
||||
context = args = null;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return function() {
|
||||
context = this;
|
||||
args = arguments;
|
||||
timestamp = new Date();
|
||||
var later = function() {
|
||||
var last = (new Date()) - timestamp;
|
||||
if (last < wait) {
|
||||
timeout = setTimeout(later, wait - last);
|
||||
} else {
|
||||
timeout = null;
|
||||
if (!immediate) result = func.apply(context, args);
|
||||
}
|
||||
};
|
||||
timestamp = _.now();
|
||||
var callNow = immediate && !timeout;
|
||||
if (!timeout) {
|
||||
timeout = setTimeout(later, wait);
|
||||
}
|
||||
if (callNow) result = func.apply(context, args);
|
||||
if (callNow) {
|
||||
result = func.apply(context, args);
|
||||
context = args = null;
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
};
|
||||
|
@ -731,11 +762,7 @@
|
|||
// allowing you to adjust arguments, run code before and after, and
|
||||
// conditionally execute the original function.
|
||||
_.wrap = function(func, wrapper) {
|
||||
return function() {
|
||||
var args = [func];
|
||||
push.apply(args, arguments);
|
||||
return wrapper.apply(this, args);
|
||||
};
|
||||
return _.partial(wrapper, func);
|
||||
};
|
||||
|
||||
// Returns a function that is the composition of a list of functions, each
|
||||
|
@ -765,8 +792,9 @@
|
|||
|
||||
// Retrieve the names of an object's properties.
|
||||
// Delegates to **ECMAScript 5**'s native `Object.keys`
|
||||
_.keys = nativeKeys || function(obj) {
|
||||
if (obj !== Object(obj)) throw new TypeError('Invalid object');
|
||||
_.keys = function(obj) {
|
||||
if (!_.isObject(obj)) return [];
|
||||
if (nativeKeys) return nativeKeys(obj);
|
||||
var keys = [];
|
||||
for (var key in obj) if (_.has(obj, key)) keys.push(key);
|
||||
return keys;
|
||||
|
@ -921,7 +949,8 @@
|
|||
// from different frames are.
|
||||
var aCtor = a.constructor, bCtor = b.constructor;
|
||||
if (aCtor !== bCtor && !(_.isFunction(aCtor) && (aCtor instanceof aCtor) &&
|
||||
_.isFunction(bCtor) && (bCtor instanceof bCtor))) {
|
||||
_.isFunction(bCtor) && (bCtor instanceof bCtor))
|
||||
&& ('constructor' in a && 'constructor' in b)) {
|
||||
return false;
|
||||
}
|
||||
// Add the first object to the stack of traversed objects.
|
||||
|
@ -1061,6 +1090,30 @@
|
|||
return value;
|
||||
};
|
||||
|
||||
_.constant = function(value) {
|
||||
return function () {
|
||||
return value;
|
||||
};
|
||||
};
|
||||
|
||||
_.property = function(key) {
|
||||
return function(obj) {
|
||||
return obj[key];
|
||||
};
|
||||
};
|
||||
|
||||
// Returns a predicate for checking whether an object has a given set of `key:value` pairs.
|
||||
_.matches = function(attrs) {
|
||||
return function(obj) {
|
||||
if (obj === attrs) return true; //avoid comparing an object to itself.
|
||||
for (var key in attrs) {
|
||||
if (attrs[key] !== obj[key])
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// Run a function **n** times.
|
||||
_.times = function(n, iterator, context) {
|
||||
var accum = Array(Math.max(0, n));
|
||||
|
@ -1077,6 +1130,9 @@
|
|||
return min + Math.floor(Math.random() * (max - min + 1));
|
||||
};
|
||||
|
||||
// A (possibly faster) way to get the current timestamp as an integer.
|
||||
_.now = Date.now || function() { return new Date().getTime(); };
|
||||
|
||||
// List of HTML entities for escaping.
|
||||
var entityMap = {
|
||||
escape: {
|
||||
|
@ -1273,4 +1329,16 @@
|
|||
|
||||
});
|
||||
|
||||
// AMD registration happens at the end for compatibility with AMD loaders
|
||||
// that may not enforce next-turn semantics on modules. Even though general
|
||||
// practice for AMD registration is to be anonymous, underscore registers
|
||||
// as a named module because, like jQuery, it is a base library that is
|
||||
// popular enough to be bundled in a third party lib, but not be part of
|
||||
// an AMD load request. Those cases could generate an error when an
|
||||
// anonymous define() is called outside of a loader request.
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
define('underscore', [], function() {
|
||||
return _;
|
||||
});
|
||||
}
|
||||
}).call(this);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
@charset "UTF-8";
|
||||
@charset "utf-8";
|
||||
@font-face {
|
||||
font-family: "mnmliconsRegular";
|
||||
src: url("/web/static/src/font/mnmliconsv21-webfont.eot") format("eot");
|
||||
|
@ -127,7 +127,7 @@
|
|||
font-weight: bold;
|
||||
font-size: inherit;
|
||||
}
|
||||
.openerp a.button:link, .openerp a.button:visited, .openerp button, .openerp .oe_button, .openerp input[type='submit'], .openerp .ui-dialog-buttonpane .ui-dialog-buttonset .ui-button {
|
||||
.openerp a.button:link, .openerp a.button:visited, .openerp button, .openerp .oe_button, .openerp input[type='submit'] {
|
||||
display: inline-block;
|
||||
border: 1px solid rgba(0, 0, 0, 0.4);
|
||||
color: #4c4c4c;
|
||||
|
@ -152,7 +152,7 @@
|
|||
-webkit-font-smoothing: antialiased;
|
||||
outline: none;
|
||||
}
|
||||
.openerp a.button:hover, .openerp button:hover, .openerp .oe_button:hover, .openerp input[type='submit']:hover, .openerp .ui-dialog-buttonpane .ui-dialog-buttonset .ui-button.ui-state-hover {
|
||||
.openerp a.button:hover, .openerp button:hover, .openerp .oe_button:hover, .openerp input[type='submit']:hover {
|
||||
background-color: #ececec;
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#f6f6f6), to(#e3e3e3));
|
||||
background-image: -webkit-linear-gradient(top, #f6f6f6, #e3e3e3);
|
||||
|
@ -163,7 +163,7 @@
|
|||
cursor: pointer;
|
||||
background-position: 0;
|
||||
}
|
||||
.openerp a.button:focus, .openerp button:focus, .openerp .oe_button:focus, .openerp input[type='submit']:focus, .openerp .ui-dialog-buttonpane .ui-dialog-buttonset .ui-button.ui-state-focus {
|
||||
.openerp a.button:focus, .openerp button:focus, .openerp .oe_button:focus, .openerp input[type='submit']:focus {
|
||||
border: 1px solid #80bfff;
|
||||
background-position: 0;
|
||||
background-color: #ececec;
|
||||
|
@ -177,7 +177,7 @@
|
|||
-webkit-box-shadow: 0 0 3px #80bfff, 0 1px 1px rgba(255, 255, 255, 0.8) inset;
|
||||
box-shadow: 0 0 3px #80bfff, 0 1px 1px rgba(255, 255, 255, 0.8) inset;
|
||||
}
|
||||
.openerp a.button:active, .openerp a.button.active, .openerp button:active, .openerp .oe_button:active, .openerp .oe_button.active, .openerp input[type='submit']:active, .openerp input[type='submit'].active, .openerp .ui-dialog-buttonpane .ui-dialog-buttonset .ui-button.ui-state-active {
|
||||
.openerp a.button:active, .openerp a.button.active, .openerp button:active, .openerp .oe_button:active, .openerp .oe_button.active, .openerp input[type='submit']:active, .openerp input[type='submit'].active {
|
||||
background-color: #ececec;
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#e3e3e3), to(#f6f6f6));
|
||||
background-image: -webkit-linear-gradient(top, #e3e3e3, #f6f6f6);
|
||||
|
@ -212,148 +212,6 @@
|
|||
.openerp .ui-tabs {
|
||||
position: static;
|
||||
}
|
||||
.openerp.ui-dialog {
|
||||
display: none;
|
||||
height: auto !important;
|
||||
padding: 6px;
|
||||
background-color: rgba(60, 60, 60, 0.7);
|
||||
border: 1px solid;
|
||||
border-color: #888888 #555555 #444444;
|
||||
-moz-border-radius: 8px;
|
||||
-webkit-border-radius: 8px;
|
||||
border-radius: 8px;
|
||||
-moz-box-shadow: 0 1px 12px rgba(0, 0, 0, 0.6);
|
||||
-webkit-box-shadow: 0 1px 12px rgba(0, 0, 0, 0.6);
|
||||
box-shadow: 0 1px 12px rgba(0, 0, 0, 0.6);
|
||||
-webkit-background-clip: padding-box;
|
||||
-moz-background-clip: padding-box;
|
||||
background-clip: padding-box;
|
||||
}
|
||||
.openerp.ui-dialog .ui-dialog-content {
|
||||
padding: 0;
|
||||
}
|
||||
.openerp.ui-dialog .ui-dialog-titlebar, .openerp.ui-dialog .ui-dialog-content, .openerp.ui-dialog .ui-dialog-buttonpane {
|
||||
padding: 16px;
|
||||
}
|
||||
.openerp.ui-dialog .ui-dialog-titlebar {
|
||||
border-top: none;
|
||||
border-left: none;
|
||||
border-right: none;
|
||||
border-bottom: 1px solid #cacaca;
|
||||
-moz-border-radius: 2px 2px 0 0;
|
||||
-webkit-border-radius: 2px 2px 0 0;
|
||||
border-radius: 2px 2px 0 0;
|
||||
background-color: #ededed;
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#fcfcfc), to(#dedede));
|
||||
background-image: -webkit-linear-gradient(top, #fcfcfc, #dedede);
|
||||
background-image: -moz-linear-gradient(top, #fcfcfc, #dedede);
|
||||
background-image: -ms-linear-gradient(top, #fcfcfc, #dedede);
|
||||
background-image: -o-linear-gradient(top, #fcfcfc, #dedede);
|
||||
background-image: linear-gradient(to bottom, #fcfcfc, #dedede);
|
||||
}
|
||||
.openerp.ui-dialog .ui-dialog-titlebar .ui-dialog-title {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.openerp.ui-dialog .ui-dialog-content {
|
||||
background: white;
|
||||
width: auto !important;
|
||||
}
|
||||
.openerp.ui-dialog .ui-dialog-buttonpane {
|
||||
border-top: 1px solid #e0e0e0;
|
||||
background: #f5f7f9;
|
||||
margin: 0;
|
||||
-moz-border-radius: 0 0 2px 2px;
|
||||
-webkit-border-radius: 0 0 2px 2px;
|
||||
border-radius: 0 0 2px 2px;
|
||||
}
|
||||
.openerp.ui-dialog .ui-dialog-buttonpane button {
|
||||
margin: 0 4px 0 0;
|
||||
}
|
||||
.openerp.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset {
|
||||
float: left;
|
||||
}
|
||||
.openerp.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset .ui-button {
|
||||
margin-right: 4px;
|
||||
}
|
||||
.openerp.ui-dialog .ui-dialog-titlebar-close {
|
||||
padding: 0;
|
||||
}
|
||||
.openerp.ui-dialog .ui-dialog-titlebar-close .ui-icon-closethick {
|
||||
display: none;
|
||||
}
|
||||
.openerp.ui-dialog .ui-dialog-titlebar-close:before {
|
||||
content: "×";
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
line-height: 16px;
|
||||
color: black;
|
||||
text-shadow: 0 1px 0 white;
|
||||
padding: 0;
|
||||
cursor: pointer;
|
||||
background: transparent;
|
||||
border: 0;
|
||||
}
|
||||
.openerp.ui-dialog .ui-dialog-titlebar-close:before:hover {
|
||||
color: black;
|
||||
text-decoration: none;
|
||||
}
|
||||
.openerp.ui-dialog .oe_about {
|
||||
background-color: white;
|
||||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAGCAYAAADgzO9IAAAAKUlEQVQIHWO8e/fufwYsgAUkJigoiCIF5DMyoYggcUiXgNnBiGQKmAkARpcEQeriln4AAAAASUVORK5CYII=);
|
||||
-moz-border-radius: 0 0 2px 2px;
|
||||
-webkit-border-radius: 0 0 2px 2px;
|
||||
border-radius: 0 0 2px 2px;
|
||||
}
|
||||
.openerp.ui-dialog .oe_about a {
|
||||
color: #7c7bad;
|
||||
}
|
||||
.openerp.ui-dialog .oe_about a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
.openerp.ui-dialog .oe_about a:focus {
|
||||
outline: none;
|
||||
}
|
||||
.openerp.ui-dialog .oe_about .oe_logo {
|
||||
margin-left: -6px;
|
||||
}
|
||||
.openerp.ui-dialog .oe_about .oe_bottom {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
text-shadow: 0 1px 1px #999999;
|
||||
background-color: #8a0e0e;
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#b41616), to(#600606));
|
||||
background-image: -webkit-linear-gradient(top, #b41616, #600606);
|
||||
background-image: -moz-linear-gradient(top, #b41616, #600606);
|
||||
background-image: -ms-linear-gradient(top, #b41616, #600606);
|
||||
background-image: -o-linear-gradient(top, #b41616, #600606);
|
||||
background-image: linear-gradient(to bottom, #b41616, #600606);
|
||||
color: #eeeeee;
|
||||
padding: 0 16px;
|
||||
-moz-border-radius: 0 0 2px 2px;
|
||||
-webkit-border-radius: 0 0 2px 2px;
|
||||
border-radius: 0 0 2px 2px;
|
||||
}
|
||||
.openerp.ui-dialog .oe_about .oe_bottom a {
|
||||
color: #eeeeee;
|
||||
}
|
||||
.openerp.ui-dialog.oe_act_window .ui-dialog-content {
|
||||
padding: 0px;
|
||||
}
|
||||
.openerp .modal-backdrop {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: 1040;
|
||||
background-color: black;
|
||||
filter: alpha(opacity=30);
|
||||
opacity: 0.3;
|
||||
}
|
||||
.openerp .oe_i {
|
||||
font-family: "mnmliconsRegular" !important;
|
||||
font-size: 21px;
|
||||
|
@ -368,6 +226,7 @@
|
|||
.openerp .oe_left {
|
||||
float: left;
|
||||
margin-right: 8px;
|
||||
width: 305px;
|
||||
}
|
||||
.openerp .oe_right {
|
||||
float: right;
|
||||
|
@ -456,11 +315,54 @@
|
|||
background: #ed6f6a;
|
||||
}
|
||||
.openerp .oe_button_box {
|
||||
width: 270px;
|
||||
text-align: right;
|
||||
width: 400px;
|
||||
text-align: left;
|
||||
}
|
||||
.openerp .oe_button_box button {
|
||||
margin: 4px;
|
||||
.openerp .oe_button_box .oe_stat_button:hover {
|
||||
background: #7c7bad;
|
||||
color: white;
|
||||
}
|
||||
.openerp .oe_button_box .oe_stat_button:hover .fa {
|
||||
color: white;
|
||||
}
|
||||
.openerp .oe_button_box .oe_stat_button {
|
||||
font-weight: normal;
|
||||
display: inline-table;
|
||||
width: 33% !important;
|
||||
height: 42px;
|
||||
margin: 0px -1px -1px 0px;
|
||||
padding: 0;
|
||||
color: #666666;
|
||||
border: 1px solid #dddddd;
|
||||
border-radius: 0;
|
||||
box-shadow: none;
|
||||
background: white;
|
||||
}
|
||||
.openerp .oe_button_box .oe_stat_button > div {
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
text-align: left;
|
||||
padding: 0;
|
||||
line-height: 120%;
|
||||
}
|
||||
.openerp .oe_button_box .oe_stat_button .stat_button_icon {
|
||||
color: #7c7bad;
|
||||
font-size: 24px;
|
||||
padding: 0px 3px;
|
||||
width: 37px;
|
||||
text-align: center;
|
||||
}
|
||||
.openerp .oe_button_box .oe_stat_button .oe_form_field_percent_pie {
|
||||
width: 42px;
|
||||
}
|
||||
.openerp .oe_button_box .oe_stat_button .oe_form_field_bar_chart {
|
||||
width: 42px;
|
||||
}
|
||||
.openerp .oe_button_box .oe_stat_button svg {
|
||||
width: 38px;
|
||||
height: 38px;
|
||||
display: inline;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.openerp .oe_avatar > img {
|
||||
max-height: 90px;
|
||||
|
@ -576,7 +478,7 @@
|
|||
display: inline-block;
|
||||
height: 12px;
|
||||
width: 12px;
|
||||
vertical-align: bottom;
|
||||
vertical-align: top;
|
||||
border-radius: 10px;
|
||||
margin: 1px 0;
|
||||
}
|
||||
|
@ -602,40 +504,6 @@
|
|||
font-style: italic;
|
||||
text-decoration: none;
|
||||
}
|
||||
.openerp.oe_tooltip {
|
||||
font-size: 12px;
|
||||
}
|
||||
.openerp.oe_tooltip .oe_tooltip_string {
|
||||
color: #ffdd55;
|
||||
font-weight: bold;
|
||||
font-size: 13px;
|
||||
}
|
||||
.openerp.oe_tooltip .oe_tooltip_help {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
.openerp.oe_tooltip .oe_tooltip_technical {
|
||||
padding: 0 0 4px 0;
|
||||
margin: 5px 0 0 15px;
|
||||
}
|
||||
.openerp.oe_tooltip .oe_tooltip_technical li {
|
||||
list-style: circle;
|
||||
}
|
||||
.openerp.oe_tooltip .oe_tooltip_technical_title {
|
||||
font-weight: bold;
|
||||
}
|
||||
.openerp.oe_tooltip .oe_tooltip_close {
|
||||
margin: -5px 0 0 2px;
|
||||
cursor: default;
|
||||
float: right;
|
||||
color: white;
|
||||
}
|
||||
.openerp.oe_tooltip .oe_tooltip_close:hover {
|
||||
color: #999999;
|
||||
cursor: pointer;
|
||||
}
|
||||
.openerp.oe_tooltip .oe_tooltip_message {
|
||||
max-width: 310px;
|
||||
}
|
||||
.openerp .oe_notebook {
|
||||
margin: 8px 0;
|
||||
padding: 0 16px;
|
||||
|
@ -1197,11 +1065,6 @@
|
|||
margin-left: -6px;
|
||||
}
|
||||
.openerp .oe_about .oe_bottom {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
text-shadow: 0 1px 1px #999999;
|
||||
background-color: #8a0e0e;
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#b41616), to(#600606));
|
||||
|
@ -1248,12 +1111,14 @@
|
|||
width: 100%;
|
||||
}
|
||||
.openerp .oe_view_manager .oe_view_manager_body {
|
||||
display: table-row;
|
||||
height: inherit;
|
||||
}
|
||||
.openerp .oe_view_manager .oe_view_manager_view_kanban:not(:empty) {
|
||||
height: inherit;
|
||||
}
|
||||
.openerp .oe_view_manager[data-view-type=kanban] .oe_view_manager_body {
|
||||
display: table-row;
|
||||
}
|
||||
.openerp .oe_view_manager table.oe_view_manager_header {
|
||||
border-collapse: separate;
|
||||
width: 100%;
|
||||
|
@ -2025,7 +1890,7 @@
|
|||
.openerp .oe_form > :not(.oe_form_nosheet) header {
|
||||
padding-left: 2px;
|
||||
}
|
||||
.openerp .oe_form > :not(.oe_form_nosheet) header ul {
|
||||
.openerp .oe_form > :not(.oe_form_nosheet) header ul:not(.oe_tooltip_technical) {
|
||||
display: inline-block;
|
||||
float: right;
|
||||
}
|
||||
|
@ -2339,10 +2204,9 @@
|
|||
}
|
||||
.openerp .oe_form .oe_form_embedded_html {
|
||||
position: relative;
|
||||
width: 600px;
|
||||
margin-left: 130px;
|
||||
margin-top: 32px;
|
||||
margin-bottom: 32px;
|
||||
width: 100%;
|
||||
margin: auto;
|
||||
overflow: auto;
|
||||
text-align: justify;
|
||||
}
|
||||
.openerp .oe_form .oe_form_field_html .oe_input_icon {
|
||||
|
@ -2878,7 +2742,7 @@
|
|||
padding: 3px 6px;
|
||||
white-space: pre-line;
|
||||
}
|
||||
.openerp .oe_list_content > tbody > tr > td > button, .openerp .oe_list_content > tbody > tr > th > button {
|
||||
.openerp .oe_list_content > tbody > tr > td > button.btn_img, .openerp .oe_list_content > tbody > tr > th > button.btn_img {
|
||||
border: none;
|
||||
background: transparent;
|
||||
padding: 0;
|
||||
|
@ -3388,9 +3252,6 @@ body.oe_single_form .oe_single_form_container {
|
|||
.openerp_ie ul.oe_form_status li.oe_active > .arrow span, .openerp_ie ul.oe_form_status_clickable li.oe_active > .arrow span {
|
||||
background-color: #729fcf !important;
|
||||
}
|
||||
.openerp_ie .ui-dialog-buttonpane .ui-dialog-buttonset .ui-button {
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#EFEFEF', endColorstr='#D8D8D8');
|
||||
}
|
||||
|
||||
@media print {
|
||||
.openerp {
|
||||
|
@ -3437,6 +3298,67 @@ body.oe_single_form .oe_single_form_container {
|
|||
height: 18px;
|
||||
}
|
||||
|
||||
.tooltip {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
font-family: "Lucida Grande", Helvetica, Verdana, Arial, sans-serif;
|
||||
color: #4c4c4c;
|
||||
font-size: 12px;
|
||||
background: white;
|
||||
text-shadow: 0 1px 1px rgba(255, 255, 255, 0.5);
|
||||
background-color: transparent;
|
||||
}
|
||||
.tooltip .tooltip-inner {
|
||||
text-align: left !important;
|
||||
max-width: 350px;
|
||||
}
|
||||
.tooltip .tooltip-inner .oe_tooltip_string {
|
||||
color: #ffdd55;
|
||||
font-weight: bold;
|
||||
font-size: 13px;
|
||||
}
|
||||
.tooltip .tooltip-inner .oe_tooltip_help {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
.tooltip .tooltip-inner .oe_tooltip_technical {
|
||||
padding: 0 0 4px 0;
|
||||
margin: 5px 0 0 15px;
|
||||
}
|
||||
.tooltip .tooltip-inner .oe_tooltip_technical li {
|
||||
list-style: circle;
|
||||
}
|
||||
.tooltip .tooltip-inner .oe_tooltip_technical_title {
|
||||
font-weight: bold;
|
||||
}
|
||||
.tooltip .tooltip-inner .oe_tooltip_close {
|
||||
margin: -5px 0 0 2px;
|
||||
cursor: default;
|
||||
float: right;
|
||||
color: white;
|
||||
}
|
||||
.tooltip .tooltip-inner .oe_tooltip_close:hover {
|
||||
color: #999999;
|
||||
cursor: pointer;
|
||||
}
|
||||
.tooltip .tooltip-inner .oe_tooltip_message {
|
||||
max-width: 310px;
|
||||
}
|
||||
.modal .modal-header button.close {
|
||||
border: none;
|
||||
background: none;
|
||||
padding: 1px;
|
||||
height: 18px;
|
||||
font-size: 20px;
|
||||
}
|
||||
.modal .modal-footer {
|
||||
text-align: left;
|
||||
}
|
||||
.modal .oe_act_window.modal-body{
|
||||
padding: 0;
|
||||
}
|
||||
.modal .oe_button{
|
||||
margin: 0 4px 0 0;
|
||||
}
|
||||
input[type="radio"], input[type="checkbox"] {
|
||||
margin-right: 4px;
|
||||
margin-left: 4px;
|
||||
|
|
|
@ -218,7 +218,7 @@ $sheet-padding: 16px
|
|||
font-size: inherit
|
||||
// }}}
|
||||
// Button style {{{
|
||||
a.button:link, a.button:visited, button, .oe_button, input[type='submit'], .ui-dialog-buttonpane .ui-dialog-buttonset .ui-button
|
||||
a.button:link, a.button:visited, button, .oe_button, input[type='submit']
|
||||
display: inline-block
|
||||
border: 1px solid rgba(0,0,0,0.4)
|
||||
color: #4c4c4c
|
||||
|
@ -233,18 +233,18 @@ $sheet-padding: 16px
|
|||
-webkit-font-smoothing: antialiased
|
||||
outline: none
|
||||
|
||||
a.button:hover, button:hover,.oe_button:hover, input[type='submit']:hover, .ui-dialog-buttonpane .ui-dialog-buttonset .ui-button.ui-state-hover
|
||||
a.button:hover, button:hover,.oe_button:hover, input[type='submit']:hover
|
||||
@include vertical-gradient(#f6f6f6, #e3e3e3)
|
||||
cursor: pointer
|
||||
background-position: 0
|
||||
|
||||
a.button:focus, button:focus, .oe_button:focus, input[type='submit']:focus, .ui-dialog-buttonpane .ui-dialog-buttonset .ui-button.ui-state-focus
|
||||
a.button:focus, button:focus, .oe_button:focus, input[type='submit']:focus
|
||||
border: 1px solid #80bfff
|
||||
background-position: 0
|
||||
@include vertical-gradient(#f6f6f6, #e3e3e3)
|
||||
@include box-shadow((0 0 3px #80bfff, 0 1px 1px rgba(255, 255, 255, .8) inset))
|
||||
|
||||
a.button:active, a.button.active, button:active, .oe_button:active, .oe_button.active, input[type='submit']:active, input[type='submit'].active, .ui-dialog-buttonpane .ui-dialog-buttonset .ui-button.ui-state-active
|
||||
a.button:active, a.button.active, button:active, .oe_button:active, .oe_button.active, input[type='submit']:active, input[type='submit'].active
|
||||
@include vertical-gradient(#e3e3e3, #f6f6f6)
|
||||
@include box-shadow(none)
|
||||
|
||||
|
@ -272,105 +272,6 @@ $sheet-padding: 16px
|
|||
.ui-tabs
|
||||
position: static
|
||||
|
||||
// Modal box
|
||||
&.ui-dialog
|
||||
display: none
|
||||
height: auto !important
|
||||
padding: 6px
|
||||
//overflow: hidden
|
||||
background-color: rgba(60,60,60,0.7)
|
||||
border: 1px solid
|
||||
border-color: #888 #555 #444
|
||||
//overflow: hidden
|
||||
@include radius(8px)
|
||||
@include box-shadow(0 1px 12px rgba(0, 0, 0, 0.6))
|
||||
@include background-clip()
|
||||
.ui-dialog-content
|
||||
padding: 0
|
||||
.ui-dialog-titlebar, .ui-dialog-content, .ui-dialog-buttonpane
|
||||
padding: 16px
|
||||
.ui-dialog-titlebar
|
||||
border-top: none
|
||||
border-left: none
|
||||
border-right: none
|
||||
border-bottom: 1px solid #cacaca
|
||||
@include radius(2px 2px 0 0)
|
||||
@include vertical-gradient(#FCFCFC, #DEDEDE)
|
||||
.ui-dialog-title
|
||||
margin: 0
|
||||
padding: 0
|
||||
.ui-dialog-content
|
||||
background: white
|
||||
width: auto !important
|
||||
.ui-dialog-buttonpane
|
||||
border-top: 1px solid #e0e0e0
|
||||
background: #f5f7f9
|
||||
margin: 0
|
||||
@include radius(0 0 2px 2px)
|
||||
button
|
||||
margin: 0 4px 0 0
|
||||
.ui-dialog-buttonset
|
||||
float: left
|
||||
.ui-button
|
||||
margin-right: 4px
|
||||
.ui-dialog-titlebar-close
|
||||
padding: 0
|
||||
.ui-icon-closethick
|
||||
display: none
|
||||
&:before
|
||||
content: "×"
|
||||
font-size: 18px
|
||||
font-weight: bold
|
||||
line-height: 16px
|
||||
color: black
|
||||
text-shadow: 0 1px 0 white
|
||||
padding: 0
|
||||
cursor: pointer
|
||||
background: transparent
|
||||
border: 0
|
||||
&:hover
|
||||
color: black
|
||||
text-decoration: none
|
||||
.oe_about
|
||||
background-color: white
|
||||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAGCAYAAADgzO9IAAAAKUlEQVQIHWO8e/fufwYsgAUkJigoiCIF5DMyoYggcUiXgNnBiGQKmAkARpcEQeriln4AAAAASUVORK5CYII=)
|
||||
@include radius(0 0 2px 2px)
|
||||
a
|
||||
color: $link-color
|
||||
&:hover
|
||||
text-decoration: underline
|
||||
&:focus
|
||||
outline: none
|
||||
.oe_logo
|
||||
margin-left: -6px
|
||||
.oe_bottom
|
||||
position: absolute
|
||||
top: 50%
|
||||
left: 0
|
||||
right: 0
|
||||
bottom: 0
|
||||
text-shadow: 0 1px 1px #999999
|
||||
@include vertical-gradient(#b41616, #600606)
|
||||
color: #eee
|
||||
padding: 0 16px
|
||||
@include radius(0 0 2px 2px)
|
||||
a
|
||||
color: #eee
|
||||
|
||||
&.ui-dialog.oe_act_window
|
||||
.ui-dialog-content
|
||||
padding: 0px
|
||||
|
||||
.modal-backdrop
|
||||
position: fixed
|
||||
top: 0
|
||||
right: 0
|
||||
bottom: 0
|
||||
left: 0
|
||||
z-index: 1040
|
||||
background-color: black
|
||||
@include opacity(.3)
|
||||
|
||||
// }}}
|
||||
// Generic classes {{{
|
||||
.oe_i
|
||||
|
@ -385,6 +286,7 @@ $sheet-padding: 16px
|
|||
.oe_left
|
||||
float: left
|
||||
margin-right: 8px
|
||||
width: 305px
|
||||
.oe_right
|
||||
float: right
|
||||
margin-left: 8px
|
||||
|
@ -429,10 +331,46 @@ $sheet-padding: 16px
|
|||
&:hover
|
||||
background: #ED6F6A
|
||||
.oe_button_box
|
||||
width: 270px
|
||||
text-align: right
|
||||
button
|
||||
margin: 4px
|
||||
width: 400px
|
||||
text-align: left
|
||||
.oe_stat_button:hover
|
||||
background: #7c7bad
|
||||
color: white
|
||||
.fa
|
||||
color: white
|
||||
.oe_stat_button
|
||||
font-weight: normal
|
||||
display: inline-table
|
||||
width: 33% !important
|
||||
height: 42px
|
||||
margin: 0px -1px -1px 0px
|
||||
padding: 0
|
||||
color: #666
|
||||
border: 1px solid #dddddd
|
||||
border-radius: 0
|
||||
box-shadow: none
|
||||
background: white
|
||||
> div
|
||||
display: table-cell
|
||||
vertical-align: middle
|
||||
text-align: left
|
||||
padding: 0
|
||||
line-height: 120%
|
||||
.stat_button_icon
|
||||
color: #7C7BAD
|
||||
font-size: 24px
|
||||
padding: 0px 3px
|
||||
width: 37px
|
||||
text-align: center
|
||||
.oe_form_field_percent_pie
|
||||
width: 42px
|
||||
.oe_form_field_bar_chart
|
||||
width: 42px
|
||||
svg
|
||||
width: 38px
|
||||
height: 38px
|
||||
display: inline
|
||||
vertical-align: middle
|
||||
.oe_avatar
|
||||
> img
|
||||
max-height: 90px
|
||||
|
@ -514,7 +452,7 @@ $sheet-padding: 16px
|
|||
display: inline-block
|
||||
height: 12px
|
||||
width: 12px
|
||||
vertical-align: bottom
|
||||
vertical-align: top
|
||||
border-radius: 10px
|
||||
margin: 1px 0
|
||||
&.oe_form_invalid
|
||||
|
@ -534,33 +472,6 @@ $sheet-padding: 16px
|
|||
text-decoration: none
|
||||
margin-bottom: 1px
|
||||
// }}}
|
||||
// Tooltips {{{
|
||||
&.oe_tooltip
|
||||
font-size: 12px
|
||||
.oe_tooltip_string
|
||||
color: #FD5
|
||||
font-weight: bold
|
||||
font-size: 13px
|
||||
.oe_tooltip_help
|
||||
white-space: pre-wrap
|
||||
.oe_tooltip_technical
|
||||
padding: 0 0 4px 0
|
||||
margin: 5px 0 0 15px
|
||||
li
|
||||
list-style: circle
|
||||
.oe_tooltip_technical_title
|
||||
font-weight: bold
|
||||
.oe_tooltip_close
|
||||
margin: -5px 0 0 2px
|
||||
cursor: default
|
||||
float: right
|
||||
color: white
|
||||
&:hover
|
||||
color: #999
|
||||
cursor: pointer
|
||||
.oe_tooltip_message
|
||||
max-width: 310px
|
||||
// }}}
|
||||
// Notebook {{{
|
||||
.oe_notebook
|
||||
margin: 8px 0
|
||||
|
@ -999,11 +910,6 @@ $sheet-padding: 16px
|
|||
.oe_logo
|
||||
margin-left: -6px
|
||||
.oe_bottom
|
||||
position: absolute
|
||||
top: 50%
|
||||
left: 0
|
||||
right: 0
|
||||
bottom: 0
|
||||
text-shadow: 0 1px 1px #999999
|
||||
@include vertical-gradient(#b41616, #600606)
|
||||
color: #eee
|
||||
|
@ -1037,10 +943,12 @@ $sheet-padding: 16px
|
|||
height: inherit
|
||||
width: 100%
|
||||
.oe_view_manager_body
|
||||
display: table-row
|
||||
height: inherit
|
||||
.oe_view_manager_view_kanban:not(:empty)
|
||||
height: inherit
|
||||
&[data-view-type=kanban]
|
||||
.oe_view_manager_body
|
||||
display: table-row
|
||||
|
||||
table.oe_view_manager_header
|
||||
border-collapse: separate
|
||||
|
@ -1642,7 +1550,7 @@ $sheet-padding: 16px
|
|||
// FormView.header {{{
|
||||
.oe_form > :not(.oe_form_nosheet) header
|
||||
padding-left: 2px
|
||||
ul
|
||||
ul:not(.oe_tooltip_technical)
|
||||
display: inline-block
|
||||
float: right
|
||||
.oe_button
|
||||
|
@ -1893,10 +1801,9 @@ $sheet-padding: 16px
|
|||
overflow: hidden
|
||||
.oe_form_embedded_html
|
||||
position: relative
|
||||
width: 600px
|
||||
margin-left: 130px
|
||||
margin-top: 32px
|
||||
margin-bottom: 32px
|
||||
width: 100%
|
||||
margin: auto
|
||||
overflow: auto
|
||||
text-align: justify
|
||||
.oe_form_field_html .oe_input_icon
|
||||
float: right
|
||||
|
@ -2313,7 +2220,7 @@ $sheet-padding: 16px
|
|||
padding: 3px 6px
|
||||
white-space: pre-line
|
||||
> td, > th
|
||||
> button
|
||||
> button.btn_img
|
||||
border: none
|
||||
background: transparent
|
||||
padding: 0
|
||||
|
@ -2732,9 +2639,6 @@ body.oe_single_form
|
|||
> .arrow span
|
||||
background-color: #729fcf !important
|
||||
|
||||
// jquery ui for ie
|
||||
.ui-dialog-buttonpane .ui-dialog-buttonset .ui-button
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#EFEFEF', endColorstr='#D8D8D8')
|
||||
// }}}
|
||||
|
||||
// @media print {{{
|
||||
|
@ -2772,6 +2676,44 @@ body.oe_single_form
|
|||
overflow: hidden !important
|
||||
// }}}
|
||||
|
||||
// End of customize
|
||||
|
||||
// Customize bootstrap3 for tooltip
|
||||
.tooltip
|
||||
padding: 0
|
||||
margin: 0
|
||||
font-family: "Lucida Grande", Helvetica, Verdana, Arial, sans-serif
|
||||
color: #4c4c4c
|
||||
font-size: 12px
|
||||
background: white
|
||||
text-shadow: 0 1px 1px rgba(255, 255, 255, 0.5)
|
||||
background-color: transparent
|
||||
.tooltip-inner
|
||||
text-align: left !important
|
||||
max-width: 350px
|
||||
.oe_tooltip_string
|
||||
color: #FD5
|
||||
font-weight: bold
|
||||
font-size: 13px
|
||||
.oe_tooltip_help
|
||||
white-space: pre-wrap
|
||||
.oe_tooltip_technical
|
||||
padding: 0 0 4px 0
|
||||
margin: 5px 0 0 15px
|
||||
li
|
||||
list-style: circle
|
||||
.oe_tooltip_technical_title
|
||||
font-weight: bold
|
||||
.oe_tooltip_close
|
||||
margin: -5px 0 0 2px
|
||||
cursor: default
|
||||
float: right
|
||||
color: white
|
||||
&:hover
|
||||
color: #999
|
||||
cursor: pointer
|
||||
.oe_tooltip_message
|
||||
max-width: 310px
|
||||
|
||||
// Hack for ui icon {{{
|
||||
.ui-icon
|
||||
|
@ -2779,6 +2721,21 @@ body.oe_single_form
|
|||
height: 18px
|
||||
// End hack}}}
|
||||
|
||||
// Customized modal according bootstrap3
|
||||
.modal
|
||||
.modal-header button.close
|
||||
border: none
|
||||
background: none
|
||||
padding: 1px
|
||||
height: 18px
|
||||
font-size: 20px
|
||||
.modal-footer
|
||||
text-align: left
|
||||
.oe_button
|
||||
margin: 0 4px 0 0
|
||||
.oe_act_window.modal-body
|
||||
padding: 0
|
||||
|
||||
input[type="radio"], input[type="checkbox"]
|
||||
margin-right: 4px
|
||||
margin-left: 4px
|
||||
|
|
|
@ -56,16 +56,6 @@ instance.web.action_warn = function(element, action) {
|
|||
};
|
||||
instance.web.client_actions.add("action_warn", "instance.web.action_warn");
|
||||
|
||||
/**
|
||||
* 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").openerpClass();
|
||||
return result;
|
||||
};
|
||||
|
||||
/**
|
||||
A useful class to handle dialogs.
|
||||
|
||||
|
@ -81,6 +71,8 @@ instance.web.Dialog = instance.web.Widget.extend({
|
|||
@param {Widget} parent
|
||||
@param {dictionary} options A dictionary that will be forwarded to jQueryUI Dialog. Additionaly, that
|
||||
dictionary can contain the following keys:
|
||||
- size: one of the following: 'large', 'medium', 'small'
|
||||
- dialogClass: class to add to the body of dialog
|
||||
- buttons: Deprecated. The buttons key is not propagated to jQueryUI Dialog. It must be a dictionary (key = button
|
||||
label, value = click handler) or a list of dictionaries (each element in the dictionary is send to the
|
||||
corresponding method of a jQuery element targeting the <button> tag). It is deprecated because all dialogs
|
||||
|
@ -94,60 +86,15 @@ instance.web.Dialog = instance.web.Widget.extend({
|
|||
this._super(parent);
|
||||
this.content_to_set = content;
|
||||
this.dialog_options = {
|
||||
modal: true,
|
||||
destroy_on_close: true,
|
||||
width: 900,
|
||||
min_width: 0,
|
||||
max_width: '95%',
|
||||
height: 'auto',
|
||||
min_height: 0,
|
||||
max_height: $(window.top).height() - 200,
|
||||
autoOpen: false,
|
||||
position: [false, 40],
|
||||
size: 'large', //'medium', 'small'
|
||||
buttons: null,
|
||||
beforeClose: function () {
|
||||
self.trigger("closing");
|
||||
},
|
||||
resizeStop: function() {
|
||||
self.trigger("resized");
|
||||
},
|
||||
};
|
||||
if (options) {
|
||||
_.extend(this.dialog_options, options);
|
||||
}
|
||||
this.on("closing", this, this._closing);
|
||||
this.$buttons = $('<div class="ui-dialog-buttonpane ui-widget-content ui-helper-clearfix"><span class="oe_dialog_custom_buttons"/></div>');
|
||||
},
|
||||
_get_options: function() {
|
||||
var self = this;
|
||||
var o = _.extend({}, this.dialog_options);
|
||||
var sizes = {
|
||||
width: $(window.top).width(),
|
||||
height: $(window.top).height(),
|
||||
};
|
||||
_.each(sizes, function(available_size, unit) {
|
||||
o[unit] = self._get_size(o[unit], available_size);
|
||||
o['min_' + unit] = self._get_size(o['min_' + unit] || 0, available_size);
|
||||
o['max_' + unit] = self._get_size(o['max_' + unit] || 0, available_size);
|
||||
if (o[unit] !== 'auto' && o['min_' + unit] && o[unit] < o['min_' + unit]) {
|
||||
o[unit] = o['min_' + unit];
|
||||
}
|
||||
if (o[unit] !== 'auto' && o['max_' + unit] && o[unit] > o['max_' + unit]) {
|
||||
o[unit] = o['max_' + unit];
|
||||
}
|
||||
});
|
||||
o.title = o.title || this.dialog_title;
|
||||
return o;
|
||||
},
|
||||
_get_size: function(val, available_size) {
|
||||
val = val.toString();
|
||||
if (val === 'auto') {
|
||||
return val;
|
||||
} else if (val.slice(-1) === "%") {
|
||||
return Math.round(available_size / 100 * parseInt(val.slice(0, -1), 10));
|
||||
} else {
|
||||
return parseInt(val, 10);
|
||||
}
|
||||
this.$buttons = $('<div class="modal-footer"><span class="oe_dialog_custom_buttons"/></div>');
|
||||
},
|
||||
renderElement: function() {
|
||||
if (this.content_to_set) {
|
||||
|
@ -165,8 +112,7 @@ instance.web.Dialog = instance.web.Widget.extend({
|
|||
if (!this.dialog_inited) {
|
||||
this.init_dialog();
|
||||
}
|
||||
this.$el.dialog('open');
|
||||
this.$el.dialog("widget").append(this.$buttons);
|
||||
this.$buttons.insertAfter(this.$dialog_box.find(".modal-body"));
|
||||
return this;
|
||||
},
|
||||
_add_buttons: function(buttons) {
|
||||
|
@ -191,16 +137,39 @@ instance.web.Dialog = instance.web.Widget.extend({
|
|||
@return The result returned by start().
|
||||
*/
|
||||
init_dialog: function() {
|
||||
var options = this._get_options();
|
||||
var self = this;
|
||||
var options = _.extend({}, this.dialog_options);
|
||||
options.title = options.title || this.dialog_title;
|
||||
if (options.buttons) {
|
||||
this._add_buttons(options.buttons);
|
||||
delete(options.buttons);
|
||||
}
|
||||
this.renderElement();
|
||||
instance.web.dialog(this.$el, options);
|
||||
if (options.height === 'auto' && options.max_height) {
|
||||
this.$el.css({ 'max-height': options.max_height, 'overflow-y': 'auto' });
|
||||
|
||||
this.$dialog_box = $(QWeb.render('Dialog', options)).appendTo("body");
|
||||
this.$el.modal({
|
||||
'backdrop': false,
|
||||
'keyboard': true,
|
||||
});
|
||||
if (options.size !== 'large'){
|
||||
var dialog_class_size = this.$dialog_box.find('.modal-lg').removeClass('modal-lg')
|
||||
if (options.size === 'small'){
|
||||
dialog_class_size.addClass('modal-sm');
|
||||
}
|
||||
}
|
||||
|
||||
this.$el.appendTo(this.$dialog_box.find(".modal-body"));
|
||||
var $dialog_content = this.$dialog_box.find('.modal-content');
|
||||
if (options.dialogClass){
|
||||
$dialog_content.find(".modal-body").addClass(options.dialogClass);
|
||||
}
|
||||
$dialog_content.openerpClass();
|
||||
|
||||
this.$dialog_box.on('hidden.bs.modal', this, function(){
|
||||
self.close();
|
||||
});
|
||||
this.$dialog_box.modal('show');
|
||||
|
||||
this.dialog_inited = true;
|
||||
var res = this.start();
|
||||
return res;
|
||||
|
@ -208,9 +177,12 @@ instance.web.Dialog = instance.web.Widget.extend({
|
|||
/**
|
||||
Closes the popup, if destroy_on_close was passed to the constructor, it is also destroyed.
|
||||
*/
|
||||
close: function() {
|
||||
if (this.dialog_inited && this.$el.is(":data(dialog)")) {
|
||||
this.$el.dialog('close');
|
||||
close: function(reason) {
|
||||
if (this.dialog_inited) {
|
||||
this.trigger("closing", reason);
|
||||
if (this.$el.is(":data(bs.modal)")) { // may have been destroyed by closing signal
|
||||
this.$el.parents('.modal').modal('hide');
|
||||
}
|
||||
}
|
||||
},
|
||||
_closing: function() {
|
||||
|
@ -225,18 +197,25 @@ instance.web.Dialog = instance.web.Widget.extend({
|
|||
/**
|
||||
Destroys the popup, also closes it.
|
||||
*/
|
||||
destroy: function () {
|
||||
destroy: function (reason) {
|
||||
this.$buttons.remove();
|
||||
var self = this;
|
||||
_.each(this.getChildren(), function(el) {
|
||||
el.destroy();
|
||||
});
|
||||
if (! this.__tmp_dialog_closing) {
|
||||
this.__tmp_dialog_destroying = true;
|
||||
this.close();
|
||||
this.close(reason);
|
||||
this.__tmp_dialog_destroying = undefined;
|
||||
}
|
||||
if (this.dialog_inited && !this.isDestroyed() && this.$el.is(":data(dialog)")) {
|
||||
this.$el.dialog('destroy');
|
||||
if (this.dialog_inited && !this.isDestroyed() && this.$el.is(":data(bs.modal)")) {
|
||||
//we need this to put the instruction to remove modal from DOM at the end
|
||||
//of the queue, otherwise it might already have been removed before the modal-backdrop
|
||||
//is removed when pressing escape key
|
||||
var $parent = this.$el.parents('.modal');
|
||||
setTimeout(function () {
|
||||
$parent.remove();
|
||||
},0);
|
||||
}
|
||||
this._super();
|
||||
}
|
||||
|
@ -256,7 +235,7 @@ instance.web.CrashManager = instance.web.Class.extend({
|
|||
new (handler)(this, error).display();
|
||||
return;
|
||||
}
|
||||
if (error.data.name === "openerp.http.SessionExpiredException") {
|
||||
if (error.data.name === "openerp.http.SessionExpiredException" || error.data.name === "werkzeug.exceptions.Forbidden") {
|
||||
this.show_warning({type: "Session Expired", data: { message: _t("Your OpenERP session expired. Please refresh the current web page.") }});
|
||||
return;
|
||||
}
|
||||
|
@ -274,12 +253,13 @@ instance.web.CrashManager = instance.web.Class.extend({
|
|||
if (error.data.exception_type === "except_osv") {
|
||||
error = _.extend({}, error, {data: _.extend({}, error.data, {message: error.data.arguments[0] + "\n\n" + error.data.arguments[1]})});
|
||||
}
|
||||
instance.web.dialog($('<div>' + QWeb.render('CrashManager.warning', {error: error}) + '</div>'), {
|
||||
new instance.web.Dialog(this, {
|
||||
size: 'medium',
|
||||
title: "OpenERP " + (_.str.capitalize(error.type) || "Warning"),
|
||||
buttons: [
|
||||
{text: _t("Ok"), click: function() { $(this).dialog("close"); }}
|
||||
]
|
||||
});
|
||||
{text: _t("Ok"), click: function() { this.parents('.modal').modal('hide'); }}
|
||||
],
|
||||
}, $('<div>' + QWeb.render('CrashManager.warning', {error: error}) + '</div>')).open();
|
||||
},
|
||||
show_error: function(error) {
|
||||
if (!this.active) {
|
||||
|
@ -287,17 +267,12 @@ instance.web.CrashManager = instance.web.Class.extend({
|
|||
}
|
||||
var buttons = {};
|
||||
buttons[_t("Ok")] = function() {
|
||||
$(this).dialog("close");
|
||||
this.parents('.modal').modal('hide');
|
||||
};
|
||||
var dialog = new instance.web.Dialog(this, {
|
||||
new instance.web.Dialog(this, {
|
||||
title: "OpenERP " + _.str.capitalize(error.type),
|
||||
width: '80%',
|
||||
height: '50%',
|
||||
min_width: '800px',
|
||||
min_height: '600px',
|
||||
buttons: buttons
|
||||
}).open();
|
||||
dialog.$el.html(QWeb.render('CrashManager.error', {session: instance.session, error: error}));
|
||||
}, QWeb.render('CrashManager.error', {session: instance.session, error: error})).open();
|
||||
},
|
||||
show_message: function(exception) {
|
||||
this.show_error({
|
||||
|
@ -344,16 +319,17 @@ instance.web.RedirectWarningHandler = instance.web.Dialog.extend(instance.web.Ex
|
|||
error = this.error;
|
||||
error.data.message = error.data.arguments[0];
|
||||
|
||||
instance.web.dialog($('<div>' + QWeb.render('CrashManager.warning', {error: error}) + '</div>'), {
|
||||
new instance.web.Dialog(this, {
|
||||
size: 'medium',
|
||||
title: "OpenERP " + (_.str.capitalize(error.type) || "Warning"),
|
||||
buttons: [
|
||||
{text: _t("Ok"), click: function() { $(this).dialog("close"); }},
|
||||
{text: _t("Ok"), click: function() { this.$el.parents('.modal').modal('hide'); }},
|
||||
{text: error.data.arguments[2], click: function() {
|
||||
window.location.href='#action='+error.data.arguments[1];
|
||||
$(this).dialog("close");
|
||||
this.$el.parents('.modal').modal('hide');
|
||||
}}
|
||||
]
|
||||
});
|
||||
],
|
||||
}, QWeb.render('CrashManager.warning', {error: error})).open();
|
||||
this.destroy();
|
||||
}
|
||||
});
|
||||
|
@ -500,20 +476,20 @@ instance.web.DatabaseManager = instance.web.Widget.extend({
|
|||
* @param {String} error.error message of the error dialog
|
||||
*/
|
||||
display_error: function (error) {
|
||||
return instance.web.dialog($('<div>'), {
|
||||
modal: true,
|
||||
return new instance.web.Dialog(this, {
|
||||
size: 'medium',
|
||||
title: error.title,
|
||||
buttons: [
|
||||
{text: _t("Ok"), click: function() { $(this).dialog("close"); }}
|
||||
{text: _t("Ok"), click: function() { this.$el.parents('.modal').modal('hide'); }}
|
||||
]
|
||||
}).html(error.error);
|
||||
}, $('<div>').html(error.error)).open();
|
||||
},
|
||||
do_create: function(form) {
|
||||
var self = this;
|
||||
var fields = $(form).serializeArray();
|
||||
self.rpc("/web/database/create", {'fields': fields}).done(function(result) {
|
||||
if (result) {
|
||||
instance.web.redirect('/web')
|
||||
instance.web.redirect('/web');
|
||||
} else {
|
||||
alert("Failed to create database");
|
||||
}
|
||||
|
@ -733,13 +709,13 @@ instance.web.ChangePassword = instance.web.Widget.extend({
|
|||
});
|
||||
},
|
||||
display_error: function (error) {
|
||||
return instance.web.dialog($('<div>'), {
|
||||
modal: true,
|
||||
return new instance.web.Dialog(this, {
|
||||
size: 'medium',
|
||||
title: error.title,
|
||||
buttons: [
|
||||
{text: _t("Ok"), click: function() { $(this).dialog("close"); }}
|
||||
{text: _t("Ok"), click: function() { this.$el.parents('.modal').modal('hide'); }}
|
||||
]
|
||||
}).html(error.error);
|
||||
}, $('<div>').html(error.error)).open();
|
||||
},
|
||||
});
|
||||
instance.web.client_actions.add("change_password", "instance.web.ChangePassword");
|
||||
|
@ -1054,8 +1030,11 @@ instance.web.UserMenu = instance.web.Widget.extend({
|
|||
e.preventDefault();
|
||||
window.location = $.param.querystring( window.location.href, 'debug');
|
||||
});
|
||||
instance.web.dialog($help, {autoOpen: true,
|
||||
modal: true, width: 507, height: 290, resizable: false, title: _t("About")});
|
||||
new instance.web.Dialog(this, {
|
||||
size: 'medium',
|
||||
dialogClass: 'oe_act_window',
|
||||
title: _t("About"),
|
||||
}, $help).open();
|
||||
});
|
||||
},
|
||||
});
|
||||
|
@ -1099,8 +1078,8 @@ instance.web.Client = instance.web.Widget.extend({
|
|||
},
|
||||
bind_events: function() {
|
||||
var self = this;
|
||||
this.$el.on('mouseenter', '.oe_systray > div:not([data-tipsy=true])', function() {
|
||||
$(this).attr('data-tipsy', 'true').tipsy().trigger('mouseenter');
|
||||
this.$el.on('mouseenter', '.oe_systray > div:not([data-toggle=tooltip])', function() {
|
||||
$(this).attr('data-toggle', 'tooltip').tooltip().trigger('mouseenter');
|
||||
});
|
||||
this.$el.on('click', '.oe_dropdown_toggle', function(ev) {
|
||||
ev.preventDefault();
|
||||
|
@ -1124,7 +1103,7 @@ instance.web.Client = instance.web.Widget.extend({
|
|||
}, 0);
|
||||
});
|
||||
instance.web.bus.on('click', this, function(ev) {
|
||||
$.fn.tipsy.clear();
|
||||
$.fn.tooltip('destroy');
|
||||
if (!$(ev.target).is('input[type=file]')) {
|
||||
self.$el.find('.oe_dropdown_menu.oe_opened, .oe_dropdown_toggle.oe_opened').removeClass('oe_opened');
|
||||
}
|
||||
|
@ -1264,9 +1243,9 @@ instance.web.WebClient = instance.web.Client.extend({
|
|||
};
|
||||
self.action_manager.do_action(result);
|
||||
var form = self.action_manager.dialog_widget.views.form.controller;
|
||||
form.on("on_button_cancel", self.action_manager.dialog, self.action_manager.dialog.close);
|
||||
form.on("on_button_cancel", self.action_manager, self.action_manager.dialog_stop);
|
||||
form.on('record_saved', self, function() {
|
||||
self.action_manager.dialog.close();
|
||||
self.action_manager.dialog_stop();
|
||||
self.update_logo();
|
||||
});
|
||||
});
|
||||
|
@ -1337,12 +1316,13 @@ instance.web.WebClient = instance.web.Client.extend({
|
|||
if (_.isEmpty(state) || state.action == "login") {
|
||||
self.menu.has_been_loaded.done(function() {
|
||||
new instance.web.Model("res.users").call("read", [self.session.uid, ["action_id"]]).done(function(data) {
|
||||
var first_menu_id = self.menu.$el.find("a:first").data("menu");
|
||||
if(first_menu_id)
|
||||
self.menu.menu_click(first_menu_id);
|
||||
|
||||
if(data.action_id) {
|
||||
self.action_manager.do_action(data.action_id[0]);
|
||||
self.menu.open_action(data.action_id[0]);
|
||||
} else {
|
||||
var first_menu_id = self.menu.$el.find("a:first").data("menu");
|
||||
if(first_menu_id)
|
||||
self.menu.menu_click(first_menu_id);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@ -1488,24 +1468,6 @@ instance.web.embed = function (origin, dbname, login, key, action, options) {
|
|||
client.insertAfter(currentScript);
|
||||
};
|
||||
|
||||
openerp.web.LoginForm = openerp.web.Widget.extend({
|
||||
init: function ($form) {
|
||||
this._super(/* no parent */);
|
||||
this.setElement($form);
|
||||
this.$el.on('submit', this.on_submit);
|
||||
this.start();
|
||||
},
|
||||
start: function () {
|
||||
if (location.hash) {
|
||||
this.$el.attr('action', this.$el.attr('action') + location.hash);
|
||||
}
|
||||
return this._super();
|
||||
},
|
||||
on_submit: function () {
|
||||
return true;
|
||||
},
|
||||
});
|
||||
|
||||
})();
|
||||
|
||||
// vim:et fdc=0 fdl=0 foldnestmax=3 fdm=syntax:
|
||||
|
|
|
@ -271,7 +271,12 @@ instance.web.Session.include( /** @lends instance.web.Session# */{
|
|||
for(var i=0; i<cookies.length; ++i) {
|
||||
var cookie = cookies[i].replace(/^\s*/, '');
|
||||
if(cookie.indexOf(nameEQ) === 0) {
|
||||
return JSON.parse(decodeURIComponent(cookie.substring(nameEQ.length)));
|
||||
try {
|
||||
return JSON.parse(decodeURIComponent(cookie.substring(nameEQ.length)));
|
||||
} catch(err) {
|
||||
// wrong cookie, delete it
|
||||
this.set_cookie(name, '', -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
@ -783,6 +788,11 @@ instance.web.unblockUI = function() {
|
|||
return $.unblockUI.apply($, arguments);
|
||||
};
|
||||
|
||||
|
||||
/* Bootstrap defaults overwrite */
|
||||
$.fn.tooltip.Constructor.DEFAULTS.placement = 'bottom';
|
||||
$.fn.tooltip.Constructor.DEFAULTS.html = true;
|
||||
|
||||
/**
|
||||
* Registry for all the client actions key: tag value: widget
|
||||
*/
|
||||
|
|
|
@ -27,6 +27,7 @@ instance.web.Query = instance.web.Class.extend({
|
|||
this._fields = fields;
|
||||
this._filter = [];
|
||||
this._context = {};
|
||||
this._lazy = true;
|
||||
this._limit = false;
|
||||
this._offset = 0;
|
||||
this._order_by = [];
|
||||
|
@ -36,6 +37,7 @@ instance.web.Query = instance.web.Class.extend({
|
|||
var q = new instance.web.Query(this._model, this._fields);
|
||||
q._context = this._context;
|
||||
q._filter = this._filter;
|
||||
q._lazy = this._lazy;
|
||||
q._limit = this._limit;
|
||||
q._offset = this._offset;
|
||||
q._order_by = this._order_by;
|
||||
|
@ -51,6 +53,7 @@ instance.web.Query = instance.web.Class.extend({
|
|||
q._context = new instance.web.CompoundContext(
|
||||
q._context, to_set.context);
|
||||
break;
|
||||
case 'lazy':
|
||||
case 'limit':
|
||||
case 'offset':
|
||||
case 'order_by':
|
||||
|
@ -140,6 +143,7 @@ instance.web.Query = instance.web.Class.extend({
|
|||
domain: this._model.domain(this._filter),
|
||||
context: ctx,
|
||||
offset: this._offset,
|
||||
lazy: this._lazy,
|
||||
limit: this._limit,
|
||||
orderby: instance.web.serialize_sort(this._order_by) || false
|
||||
}).then(function (results) {
|
||||
|
@ -148,8 +152,9 @@ instance.web.Query = instance.web.Class.extend({
|
|||
result.__context = result.__context || {};
|
||||
result.__context.group_by = result.__context.group_by || [];
|
||||
_.defaults(result.__context, ctx);
|
||||
var grouping_fields = self._lazy ? [grouping[0]] : grouping;
|
||||
return new instance.web.QueryGroup(
|
||||
self._model.name, grouping[0], result);
|
||||
self._model.name, grouping_fields, result);
|
||||
});
|
||||
});
|
||||
},
|
||||
|
@ -175,6 +180,18 @@ instance.web.Query = instance.web.Class.extend({
|
|||
if (!domain) { return this; }
|
||||
return this.clone({filter: domain});
|
||||
},
|
||||
/**
|
||||
* Creates a new query with the provided parameter lazy replacing the current
|
||||
* query's own.
|
||||
*
|
||||
* @param {Boolean} lazy indicates if the read_group should return only the
|
||||
* first level of groupby records, or should return the records grouped by
|
||||
* all levels at once (so, it makes only 1 db request).
|
||||
* @returns {openerp.web.Query}
|
||||
*/
|
||||
lazy: function (lazy) {
|
||||
return this.clone({lazy: lazy});
|
||||
},
|
||||
/**
|
||||
* Creates a new query with the provided limit replacing the current
|
||||
* query's own limit
|
||||
|
@ -213,7 +230,7 @@ instance.web.Query = instance.web.Class.extend({
|
|||
});
|
||||
|
||||
instance.web.QueryGroup = instance.web.Class.extend({
|
||||
init: function (model, grouping_field, read_group_group) {
|
||||
init: function (model, grouping_fields, read_group_group) {
|
||||
// In cases where group_by_no_leaf and no group_by, the result of
|
||||
// read_group has aggregate fields but no __context or __domain.
|
||||
// Create default (empty) values for those so that things don't break
|
||||
|
@ -221,11 +238,12 @@ instance.web.QueryGroup = instance.web.Class.extend({
|
|||
{__context: {group_by: []}, __domain: []},
|
||||
read_group_group);
|
||||
|
||||
var count_key = (grouping_fields[0] && grouping_fields[0].split(':')[0]) + '_count';
|
||||
var aggregates = {};
|
||||
_(fixed_group).each(function (value, key) {
|
||||
if (key.indexOf('__') === 0
|
||||
|| key === grouping_field
|
||||
|| key === grouping_field + '_count') {
|
||||
|| _.contains(grouping_fields, key)
|
||||
|| (key === count_key)) {
|
||||
return;
|
||||
}
|
||||
aggregates[key] = value || 0;
|
||||
|
@ -234,16 +252,21 @@ instance.web.QueryGroup = instance.web.Class.extend({
|
|||
this.model = new instance.web.Model(
|
||||
model, fixed_group.__context, fixed_group.__domain);
|
||||
|
||||
var raw_field = grouping_field && grouping_field.split(':')[0];
|
||||
var group_size = fixed_group[raw_field + '_count'] || fixed_group.__count || 0;
|
||||
var group_size = fixed_group[count_key] || fixed_group.__count || 0;
|
||||
var leaf_group = fixed_group.__context.group_by.length === 0;
|
||||
|
||||
var value = (grouping_fields.length === 1)
|
||||
? fixed_group[grouping_fields[0]]
|
||||
: _.map(grouping_fields, function (field) { return fixed_group[field]; });
|
||||
var grouped_on = (grouping_fields.length === 1)
|
||||
? grouping_fields[0]
|
||||
: grouping_fields;
|
||||
this.attributes = {
|
||||
folded: !!(fixed_group.__fold),
|
||||
grouped_on: grouping_field,
|
||||
grouped_on: grouped_on,
|
||||
// if terminal group (or no group) and group_by_no_leaf => use group.__count
|
||||
length: group_size,
|
||||
value: fixed_group[raw_field],
|
||||
value: value,
|
||||
// A group is open-able if it's not a leaf in group_by_no_leaf mode
|
||||
has_children: !(leaf_group && fixed_group.__context['group_by_no_leaf']),
|
||||
|
||||
|
@ -448,7 +471,8 @@ instance.web.DataSet = instance.web.Class.extend(instance.web.PropertiesMixin,
|
|||
* Read records.
|
||||
*
|
||||
* @param {Array} ids identifiers of the records to read
|
||||
* @param {Array} fields fields to read and return, by default all fields are returned
|
||||
* @param {Array} [fields] fields to read and return, by default all fields are returned
|
||||
* @param {Object} [options]
|
||||
* @returns {$.Deferred}
|
||||
*/
|
||||
read_ids: function (ids, fields, options) {
|
||||
|
@ -456,10 +480,28 @@ instance.web.DataSet = instance.web.Class.extend(instance.web.PropertiesMixin,
|
|||
return $.Deferred().resolve([]);
|
||||
|
||||
options = options || {};
|
||||
// TODO: reorder results to match ids list
|
||||
return this._model.call('read',
|
||||
[ids, fields || false],
|
||||
{context: this.get_context(options.context)});
|
||||
var method = 'read';
|
||||
var ids_arg = ids;
|
||||
var context = this.get_context(options.context);
|
||||
if (options.check_access_rule === true){
|
||||
method = 'search_read';
|
||||
ids_arg = [['id', 'in', ids]];
|
||||
context = new instance.web.CompoundContext(context, {active_test: false});
|
||||
}
|
||||
return this._model.call(method,
|
||||
[ids_arg, fields || false],
|
||||
{context: context})
|
||||
.then(function (records) {
|
||||
if (records.length <= 1) { return records; }
|
||||
var indexes = {};
|
||||
for (var i = 0; i < ids.length; i++) {
|
||||
indexes[ids[i]] = i;
|
||||
}
|
||||
records.sort(function (a, b) {
|
||||
return indexes[a.id] - indexes[b.id];
|
||||
});
|
||||
return records;
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Read a slice of the records represented by this DataSet, based on its
|
||||
|
@ -904,6 +946,10 @@ instance.web.BufferedDataSet = instance.web.DataSetStatic.extend({
|
|||
sign = -1;
|
||||
field = field.slice(1);
|
||||
}
|
||||
//m2o should be searched based on value[1] not based whole value(i.e. [id, value])
|
||||
if(_.isArray(a[field]) && a[field].length == 2 && _.isString(a[field][1])){
|
||||
return sign * compare(a[field][1], b[field][1]);
|
||||
}
|
||||
return sign * compare(a[field], b[field]);
|
||||
}, 0);
|
||||
});
|
||||
|
|
|
@ -46,7 +46,6 @@ instance.web.DataExport = instance.web.Dialog.extend({
|
|||
start: function() {
|
||||
var self = this;
|
||||
this._super.apply(this, arguments);
|
||||
self.$el.removeClass('ui-dialog-content ui-widget-content');
|
||||
|
||||
var got_fields = new $.Deferred();
|
||||
this.$el.find('#import_compat').change(function() {
|
||||
|
@ -119,6 +118,7 @@ instance.web.DataExport = instance.web.Dialog.extend({
|
|||
if (select_exp.val()) {
|
||||
self.exports.unlink([parseInt(select_exp.val(), 10)]);
|
||||
select_exp.remove();
|
||||
self.$el.find("#fields_list option").remove();
|
||||
if (self.$el.find('#saved_export_list option').length <= 1) {
|
||||
self.$el.find('#ExistsExportList').hide();
|
||||
}
|
||||
|
@ -166,18 +166,16 @@ instance.web.DataExport = instance.web.Dialog.extend({
|
|||
export_fields: _(fields).map(function (field) {
|
||||
return [0, 0, {name: field}];
|
||||
})
|
||||
}, function (export_list_id) {
|
||||
if (!export_list_id.result) {
|
||||
}).then(function (export_list_id) {
|
||||
if (!export_list_id) {
|
||||
return;
|
||||
}
|
||||
self.$el.find("#saved_export_list").append(
|
||||
new Option(value, export_list_id.result));
|
||||
if (self.$el.find("#saved_export_list").is(":hidden")) {
|
||||
if (!self.$el.find("#saved_export_list").length || self.$el.find("#saved_export_list").is(":hidden")) {
|
||||
self.show_exports_list();
|
||||
}
|
||||
self.$el.find("#saved_export_list").append( new Option(value, export_list_id) );
|
||||
});
|
||||
this.on_show_save_list();
|
||||
this.$el.find("#fields_list option").remove();
|
||||
},
|
||||
on_click: function(id, record) {
|
||||
var self = this;
|
||||
|
@ -414,7 +412,6 @@ instance.web.DataExport = instance.web.Dialog.extend({
|
|||
});
|
||||
},
|
||||
close: function() {
|
||||
this.$el.remove();
|
||||
this._super();
|
||||
}
|
||||
});
|
||||
|
|
|
@ -355,7 +355,7 @@ instance.web.SearchView = instance.web.Widget.extend(/** @lends instance.web.Sea
|
|||
}
|
||||
},
|
||||
'autocompleteopen': function () {
|
||||
this.$el.autocomplete('widget').css('z-index', 1004);
|
||||
this.$el.autocomplete('widget').css('z-index', 9999);
|
||||
},
|
||||
},
|
||||
/**
|
||||
|
@ -677,6 +677,11 @@ instance.web.SearchView = instance.web.Widget.extend(/** @lends instance.web.Sea
|
|||
* @returns instance.web.search.Field
|
||||
*/
|
||||
make_field: function (item, field, parent) {
|
||||
// M2O combined with selection widget is pointless and broken in search views,
|
||||
// but has been used in the past for unsupported hacks -> ignore it
|
||||
if (field.type === "many2one" && item.attrs.widget === "selection"){
|
||||
item.attrs.widget = undefined;
|
||||
}
|
||||
var obj = instance.web.search.fields.get_any( [item.attrs.widget, field.type]);
|
||||
if(obj) {
|
||||
return new (obj) (item, field, parent || this);
|
||||
|
@ -1555,9 +1560,6 @@ instance.web.search.ManyToOneField = instance.web.search.CharField.extend({
|
|||
this.model = new instance.web.Model(this.attrs.relation);
|
||||
},
|
||||
complete: function (needle) {
|
||||
if (this.attrs.operator || this.attrs.filter_domain) {
|
||||
return this._super(needle);
|
||||
}
|
||||
var self = this;
|
||||
// FIXME: "concurrent" searches (multiple requests, mis-ordered responses)
|
||||
var context = instance.web.pyeval.eval(
|
||||
|
|
|
@ -196,7 +196,6 @@ openerp.testing = {};
|
|||
});
|
||||
};
|
||||
|
||||
var db = window['oe_db_info'];
|
||||
testing.section = function (name, options, body) {
|
||||
if (_.isFunction(options)) {
|
||||
body = options;
|
||||
|
@ -235,40 +234,6 @@ openerp.testing = {};
|
|||
.push(env._oe.setup, env._oe.teardown)
|
||||
.push(options.setup, options.teardown);
|
||||
var opts = _.defaults({}, options, env._oe);
|
||||
// FIXME: if this test is ignored, will still query
|
||||
if (opts.rpc === 'rpc' && !db) {
|
||||
QUnit.config.autostart = false;
|
||||
db = {
|
||||
source: null,
|
||||
supadmin: null,
|
||||
password: null
|
||||
};
|
||||
var $msg = $('<form style="margin: 0 1em 1em;">')
|
||||
.append('<h3>A test needs to clone a database</h3>')
|
||||
.append('<h4>Please provide the source clone information</h4>')
|
||||
.append(' Source DB: ').append('<input name="source">').append('<br>')
|
||||
.append(' DB Password: ').append('<input name="supadmin">').append('<br>')
|
||||
.append('Admin Password: ').append('<input name="password">').append('<br>')
|
||||
.append('<input type="submit" value="OK"/>')
|
||||
.submit(function (e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
db.source = $msg.find('input[name=source]').val();
|
||||
db.supadmin = $msg.find('input[name=supadmin]').val();
|
||||
db.password = $msg.find('input[name=password]').val();
|
||||
QUnit.start();
|
||||
$.unblockUI();
|
||||
});
|
||||
$.blockUI({
|
||||
message: $msg,
|
||||
css: {
|
||||
fontFamily: 'monospace',
|
||||
textAlign: 'left',
|
||||
whiteSpace: 'pre-wrap',
|
||||
cursor: 'default'
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
QUnit.test(name, function () {
|
||||
var instance = openerp;
|
||||
|
@ -302,44 +267,6 @@ openerp.testing = {};
|
|||
instance.session.responses[spec] = handler;
|
||||
};
|
||||
break;
|
||||
case 'rpc':
|
||||
async = true;
|
||||
(function () {
|
||||
// Bunch of random base36 characters
|
||||
var dbname = 'test_' + Math.random().toString(36).slice(2);
|
||||
// Add db setup/teardown at the start of the stack
|
||||
case_stack = case_stack.unshift(function (instance) {
|
||||
// FIXME hack: don't want the session to go through shitty loading process of everything
|
||||
instance.session.session_init = testing.noop;
|
||||
instance.session.load_modules = testing.noop;
|
||||
instance.session.session_bind();
|
||||
return instance.session.rpc('/web/database/duplicate', {
|
||||
fields: [
|
||||
{name: 'super_admin_pwd', value: db.supadmin},
|
||||
{name: 'db_original_name', value: db.source},
|
||||
{name: 'db_name', value: dbname}
|
||||
]
|
||||
}).then(function (result) {
|
||||
if (result.error) {
|
||||
return $.Deferred().reject(result.error).promise();
|
||||
}
|
||||
return instance.session.session_authenticate(
|
||||
dbname, 'admin', db.password, true);
|
||||
});
|
||||
}, function (instance) {
|
||||
return instance.session.rpc('/web/database/drop', {
|
||||
fields: [
|
||||
{name: 'drop_pwd', value: db.supadmin},
|
||||
{name: 'drop_db', value: dbname}
|
||||
]
|
||||
}).then(function (result) {
|
||||
if (result.error) {
|
||||
return $.Deferred().reject(result.error).promise();
|
||||
}
|
||||
return result;
|
||||
});
|
||||
});
|
||||
})();
|
||||
}
|
||||
|
||||
// Always execute tests asynchronously
|
||||
|
|
|
@ -586,13 +586,13 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
|
|||
this._internal_set_values(result.value, processed);
|
||||
}
|
||||
if (!_.isEmpty(result.warning)) {
|
||||
instance.web.dialog($(QWeb.render("CrashManager.warning", result.warning)), {
|
||||
new instance.web.Dialog(this, {
|
||||
size: 'medium',
|
||||
title:result.warning.title,
|
||||
modal: true,
|
||||
buttons: [
|
||||
{text: _t("Ok"), click: function() { $(this).dialog("close"); }}
|
||||
{text: _t("Ok"), click: function() { this.parents('.modal').modal('hide'); }}
|
||||
]
|
||||
});
|
||||
}, QWeb.render("CrashManager.warning", result.warning)).open();
|
||||
}
|
||||
|
||||
return $.Deferred().resolve();
|
||||
|
@ -631,6 +631,9 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
|
|||
});
|
||||
}
|
||||
return $.when();
|
||||
}).fail(function() {
|
||||
self.save_list.pop();
|
||||
return $.when();
|
||||
});
|
||||
}
|
||||
return iterate();
|
||||
|
@ -967,9 +970,12 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
|
|||
context: {
|
||||
'bin_size': true,
|
||||
'future_display_name': true
|
||||
}
|
||||
},
|
||||
check_access_rule: true
|
||||
}).then(function(r) {
|
||||
self.trigger('load_record', r);
|
||||
}).fail(function (){
|
||||
self.do_action('history_back');
|
||||
});
|
||||
}
|
||||
});
|
||||
|
@ -1077,7 +1083,6 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
|
|||
};
|
||||
})
|
||||
.value();
|
||||
|
||||
var d = new instance.web.Dialog(this, {
|
||||
title: _t("Set Default"),
|
||||
args: {
|
||||
|
@ -1277,6 +1282,9 @@ instance.web.form.FormRenderingEngine = instance.web.form.FormRenderingEngineInt
|
|||
var defs = [];
|
||||
_.each(this.to_replace, function(el) {
|
||||
defs.push(el[0].replace(el[1]));
|
||||
if (el[1].children().length) {
|
||||
el[0].$el.append(el[1].children());
|
||||
}
|
||||
});
|
||||
this.to_replace = [];
|
||||
return $.when.apply($, defs);
|
||||
|
@ -1304,7 +1312,7 @@ instance.web.form.FormRenderingEngine = instance.web.form.FormRenderingEngineInt
|
|||
var tagname = $tag[0].nodeName.toLowerCase();
|
||||
if (this.tags_registry.contains(tagname)) {
|
||||
this.tags_to_init.push($tag);
|
||||
return $tag;
|
||||
return (tagname === 'button') ? this.process_button($tag) : $tag;
|
||||
}
|
||||
var fn = self['process_' + tagname];
|
||||
if (fn) {
|
||||
|
@ -1321,6 +1329,13 @@ instance.web.form.FormRenderingEngine = instance.web.form.FormRenderingEngineInt
|
|||
return $tag;
|
||||
}
|
||||
},
|
||||
process_button: function ($button) {
|
||||
var self = this;
|
||||
$button.children().each(function() {
|
||||
self.process($(this));
|
||||
});
|
||||
return $button;
|
||||
},
|
||||
process_widget: function($widget) {
|
||||
this.widgets_to_init.push($widget);
|
||||
return $widget;
|
||||
|
@ -1820,7 +1835,7 @@ instance.web.form.FormWidget = instance.web.Widget.extend(instance.web.form.Invi
|
|||
this.$el.addClass(this.node.attrs["class"] || "");
|
||||
},
|
||||
destroy: function() {
|
||||
$.fn.tipsy.clear();
|
||||
$.fn.tooltip('destroy');
|
||||
this._super.apply(this, arguments);
|
||||
},
|
||||
/**
|
||||
|
@ -1852,9 +1867,8 @@ instance.web.form.FormWidget = instance.web.Widget.extend(instance.web.form.Invi
|
|||
widget = widget || this;
|
||||
trigger = trigger || this.$el;
|
||||
options = _.extend({
|
||||
delayIn: 500,
|
||||
delayOut: 0,
|
||||
fade: true,
|
||||
delay: { show: 500, hide: 0 },
|
||||
trigger: 'hover',
|
||||
title: function() {
|
||||
var template = widget.template + '.tooltip';
|
||||
if (!QWeb.has_template(template)) {
|
||||
|
@ -1865,12 +1879,12 @@ instance.web.form.FormWidget = instance.web.Widget.extend(instance.web.form.Invi
|
|||
widget: widget
|
||||
});
|
||||
},
|
||||
gravity: $.fn.tipsy.autoBounds(50, 'nw'),
|
||||
html: true,
|
||||
opacity: 0.85,
|
||||
trigger: 'hover'
|
||||
}, options || {});
|
||||
$(trigger).tipsy(options);
|
||||
//only show tooltip if we are in debug or if we have a help to show, otherwise it will display
|
||||
//as empty
|
||||
if (instance.session.debug || widget.node.attrs.help || (widget.field && widget.field.help)){
|
||||
$(trigger).tooltip(options);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Builds a new context usable for operations related to fields by merging
|
||||
|
@ -1906,6 +1920,8 @@ instance.web.form.WidgetButton = instance.web.form.FormWidget.extend({
|
|||
template: 'WidgetButton',
|
||||
init: function(field_manager, node) {
|
||||
node.attrs.type = node.attrs['data-button-type'];
|
||||
this.is_stat_button = /\boe_stat_button\b/.test(node.attrs['class']);
|
||||
this.icon = node.attrs.icon && "<span class=\"fa " + node.attrs.icon + " fa-fw\"></span>";
|
||||
this._super(field_manager, node);
|
||||
this.force_disabled = false;
|
||||
this.string = (this.node.attrs.string || '').replace(/_/g, '');
|
||||
|
@ -1941,26 +1957,23 @@ instance.web.form.WidgetButton = instance.web.form.FormWidget.extend({
|
|||
var exec_action = function() {
|
||||
if (self.node.attrs.confirm) {
|
||||
var def = $.Deferred();
|
||||
var dialog = instance.web.dialog($('<div/>').text(self.node.attrs.confirm), {
|
||||
var dialog = new instance.web.Dialog(this, {
|
||||
title: _t('Confirm'),
|
||||
modal: true,
|
||||
buttons: [
|
||||
{text: _t("Cancel"), click: function() {
|
||||
$(this).dialog("close");
|
||||
this.parents('.modal').modal('hide');
|
||||
}
|
||||
},
|
||||
{text: _t("Ok"), click: function() {
|
||||
var self2 = this;
|
||||
self.on_confirmed().always(function() {
|
||||
$(self2).dialog("close");
|
||||
self2.parents('.modal').modal('hide');
|
||||
});
|
||||
}
|
||||
}
|
||||
],
|
||||
beforeClose: function() {
|
||||
def.resolve();
|
||||
},
|
||||
});
|
||||
}, $('<div/>').text(self.node.attrs.confirm)).open();
|
||||
dialog.on("closing", null, function() {def.resolve();});
|
||||
return def.promise();
|
||||
} else {
|
||||
return self.on_confirmed();
|
||||
|
@ -1976,11 +1989,12 @@ instance.web.form.WidgetButton = instance.web.form.FormWidget.extend({
|
|||
var self = this;
|
||||
|
||||
var context = this.build_context();
|
||||
|
||||
return this.view.do_execute_action(
|
||||
_.extend({}, this.node.attrs, {context: context}),
|
||||
this.view.dataset, this.view.datarecord.id, function () {
|
||||
self.view.recursive_reload();
|
||||
this.view.dataset, this.view.datarecord.id, function (reason) {
|
||||
if (!_.isObject(reason)) {
|
||||
self.view.recursive_reload();
|
||||
}
|
||||
});
|
||||
},
|
||||
check_disable: function() {
|
||||
|
@ -2107,8 +2121,8 @@ instance.web.form.AbstractField = instance.web.form.FormWidget.extend(instance.w
|
|||
this.$el.find('.oe_field_translate').click(this.on_translate);
|
||||
}
|
||||
this.$label = this.view ? this.view.$el.find('label[for=' + this.id_for_label + ']') : $();
|
||||
this.do_attach_tooltip(this, this.$label[0] || this.$el);
|
||||
if (instance.session.debug) {
|
||||
this.do_attach_tooltip(this, this.$label[0] || this.$el);
|
||||
this.$label.off('dblclick').on('dblclick', function() {
|
||||
console.log("Field '%s' of type '%s' in View: %o", self.name, (self.node.attrs.widget || self.field.type), self.view);
|
||||
window.w = self;
|
||||
|
@ -2253,7 +2267,7 @@ instance.web.form.ReinitializeFieldMixin = _.extend({}, instance.web.form.Reini
|
|||
/**
|
||||
Some hack to make placeholders work in ie9.
|
||||
*/
|
||||
if ($.browser.msie && $.browser.version === "9.0") {
|
||||
if (!('placeholder' in document.createElement('input'))) {
|
||||
document.addEventListener("DOMNodeInserted",function(event){
|
||||
var nodename = event.target.nodeName.toLowerCase();
|
||||
if ( nodename === "input" || nodename == "textarea" ) {
|
||||
|
@ -2423,6 +2437,76 @@ instance.web.form.FieldFloat = instance.web.form.FieldChar.extend({
|
|||
}
|
||||
});
|
||||
|
||||
instance.web.form.FieldCharDomain = instance.web.form.AbstractField.extend(instance.web.form.ReinitializeFieldMixin, {
|
||||
init: function(field_manager, node) {
|
||||
this._super.apply(this, arguments);
|
||||
},
|
||||
start: function() {
|
||||
var self = this;
|
||||
this._super.apply(this, arguments);
|
||||
this.on("change:effective_readonly", this, function () {
|
||||
this.display_field();
|
||||
this.render_value();
|
||||
});
|
||||
this.display_field();
|
||||
return this._super();
|
||||
},
|
||||
render_value: function() {
|
||||
this.$('button.select_records').css('visibility', this.get('effective_readonly') ? 'hidden': '');
|
||||
},
|
||||
set_value: function(value_) {
|
||||
var self = this;
|
||||
this.set('value', value_ || false);
|
||||
this.display_field();
|
||||
},
|
||||
display_field: function() {
|
||||
var self = this;
|
||||
this.$el.html(instance.web.qweb.render("FieldCharDomain", {widget: this}));
|
||||
if (this.get('value')) {
|
||||
var model = this.options.model || this.field_manager.get_field_value(this.options.model_field);
|
||||
var domain = instance.web.pyeval.eval('domain', this.get('value'));
|
||||
var ds = new instance.web.DataSetStatic(self, model, self.build_context());
|
||||
ds.call('search_count', [domain]).then(function (results) {
|
||||
$('.oe_domain_count', self.$el).text(results + ' records selected');
|
||||
$('button span', self.$el).text(' Change selection');
|
||||
});
|
||||
} else {
|
||||
$('.oe_domain_count', this.$el).text('0 record selected');
|
||||
$('button span', this.$el).text(' Select records');
|
||||
};
|
||||
this.$('.select_records').on('click', self.on_click);
|
||||
},
|
||||
on_click: function(ev) {
|
||||
var self = this;
|
||||
var model = this.options.model || this.field_manager.get_field_value(this.options.model_field);
|
||||
this.pop = new instance.web.form.SelectCreatePopup(this);
|
||||
this.pop.select_element(
|
||||
model, {title: 'Select records...'},
|
||||
[], this.build_context());
|
||||
this.pop.on("elements_selected", self, function(element_ids) {
|
||||
if (this.pop.$('input.oe_list_record_selector').prop('checked')) {
|
||||
var search_data = this.pop.searchview.build_search_data();
|
||||
var domain_done = instance.web.pyeval.eval_domains_and_contexts({
|
||||
domains: search_data.domains,
|
||||
contexts: search_data.contexts,
|
||||
group_by_seq: search_data.groupbys || []
|
||||
}).then(function (results) {
|
||||
return results.domain;
|
||||
});
|
||||
}
|
||||
else {
|
||||
var domain = ["id", "in", element_ids];
|
||||
var domain_done = $.Deferred().resolve(domain);
|
||||
}
|
||||
$.when(domain_done).then(function (domain) {
|
||||
var domain = self.pop.dataset.domain.concat(domain || []);
|
||||
self.set_value(JSON.stringify(domain))
|
||||
});
|
||||
});
|
||||
event.preventDefault();
|
||||
},
|
||||
});
|
||||
|
||||
instance.web.DateTimeWidget = instance.web.Widget.extend({
|
||||
template: "web.datepicker",
|
||||
jqueryui_object: 'datetimepicker',
|
||||
|
@ -2805,6 +2889,87 @@ instance.web.form.FieldProgressBar = instance.web.form.AbstractField.extend({
|
|||
}
|
||||
});
|
||||
|
||||
/**
|
||||
The PercentPie field expect a float from 0 to 100.
|
||||
*/
|
||||
instance.web.form.FieldPercentPie = instance.web.form.AbstractField.extend({
|
||||
template: 'FieldPercentPie',
|
||||
|
||||
render_value: function() {
|
||||
var value = this.get('value'),
|
||||
formatted_value = Math.round(value || 0) + '%',
|
||||
svg = this.$('svg')[0];
|
||||
|
||||
svg.innerHTML = "";
|
||||
nv.addGraph(function() {
|
||||
var width = 42, height = 42;
|
||||
var chart = nv.models.pieChart()
|
||||
.width(width)
|
||||
.height(height)
|
||||
.margin({top: 0, right: 0, bottom: 0, left: 0})
|
||||
.donut(true)
|
||||
.showLegend(false)
|
||||
.showLabels(false)
|
||||
.tooltips(false)
|
||||
.color(['#7C7BAD','#DDD'])
|
||||
.donutRatio(0.62);
|
||||
|
||||
d3.select(svg)
|
||||
.datum([{'x': 'value', 'y': value}, {'x': 'complement', 'y': 100 - value}])
|
||||
.transition()
|
||||
.call(chart)
|
||||
.attr('style', 'width: ' + width + 'px; height:' + height + 'px;');
|
||||
|
||||
d3.select(svg)
|
||||
.append("text")
|
||||
.attr({x: width/2, y: height/2 + 3, 'text-anchor': 'middle'})
|
||||
.style({"font-size": "10px", "font-weight": "bold"})
|
||||
.text(formatted_value);
|
||||
|
||||
return chart;
|
||||
});
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
The FieldBarChart expectsa list of values (indeed)
|
||||
*/
|
||||
instance.web.form.FieldBarChart = instance.web.form.AbstractField.extend({
|
||||
template: 'FieldBarChart',
|
||||
|
||||
render_value: function() {
|
||||
var value = JSON.parse(this.get('value'));
|
||||
var svg = this.$('svg')[0];
|
||||
svg.innerHTML = "";
|
||||
nv.addGraph(function() {
|
||||
var width = 34, height = 34;
|
||||
var chart = nv.models.discreteBarChart()
|
||||
.x(function (d) { return d.tooltip })
|
||||
.y(function (d) { return d.value })
|
||||
.width(width)
|
||||
.height(height)
|
||||
.margin({top: 0, right: 0, bottom: 0, left: 0})
|
||||
.tooltips(false)
|
||||
.showValues(false)
|
||||
.transitionDuration(350)
|
||||
.showXAxis(false)
|
||||
.showYAxis(false);
|
||||
|
||||
d3.select(svg)
|
||||
.datum([{key: 'values', values: value}])
|
||||
.transition()
|
||||
.call(chart)
|
||||
.attr('style', 'width: ' + (width + 4) + 'px; height: ' + (height + 8) + 'px;');
|
||||
|
||||
nv.utils.windowResize(chart.update);
|
||||
|
||||
return chart;
|
||||
});
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
instance.web.form.FieldSelection = instance.web.form.AbstractField.extend(instance.web.form.ReinitializeFieldMixin, {
|
||||
template: 'FieldSelection',
|
||||
|
@ -2835,9 +3000,7 @@ instance.web.form.FieldSelection = instance.web.form.AbstractField.extend(instan
|
|||
var def;
|
||||
if (this.field.type === "many2one") {
|
||||
var model = new openerp.Model(openerp.session, this.field.relation);
|
||||
def = model.call("search", [this.get("domain")], {"context": this.build_context()}).then(function(record_ids) {
|
||||
return model.call("name_get", [record_ids] , {"context": self.build_context()});
|
||||
});
|
||||
def = model.call("name_search", ['', this.get("domain")], {"context": this.build_context()});
|
||||
} else {
|
||||
var values = _.reject(this.field.selection, function (v) { return v[0] === false && v[1] === ''; });
|
||||
def = $.when(values);
|
||||
|
@ -3127,7 +3290,8 @@ instance.web.form.CompletionFieldMixin = {
|
|||
if (self.options.quick_create === undefined || self.options.quick_create) {
|
||||
new instance.web.DataSet(this, this.field.relation, self.build_context())
|
||||
.name_create(name).done(function(data) {
|
||||
self.add_id(data[0]);
|
||||
if (!self.get('effective_readonly'))
|
||||
self.add_id(data[0]);
|
||||
}).fail(function(error, event) {
|
||||
event.preventDefault();
|
||||
slow_create();
|
||||
|
@ -3175,7 +3339,7 @@ instance.web.form.M2ODialog = instance.web.Dialog.extend({
|
|||
init: function(parent) {
|
||||
this._super(parent, {
|
||||
title: _.str.sprintf(_t("Add %s"), parent.string),
|
||||
width: 312,
|
||||
size: 'medium',
|
||||
});
|
||||
},
|
||||
start: function() {
|
||||
|
@ -3243,7 +3407,7 @@ instance.web.form.FieldMany2One = instance.web.form.AbstractField.extend(instanc
|
|||
delete this.$drop_down;
|
||||
}
|
||||
if (this.$input) {
|
||||
this.$input.closest(".ui-dialog .ui-dialog-content").off('scroll');
|
||||
this.$input.closest(".modal .modal-content").off('scroll');
|
||||
this.$input.off('keyup blur autocompleteclose autocompleteopen ' +
|
||||
'focus focusout change keydown');
|
||||
delete this.$input;
|
||||
|
@ -3286,20 +3450,25 @@ instance.web.form.FieldMany2One = instance.web.form.AbstractField.extend(instanc
|
|||
return;
|
||||
}
|
||||
var pop = new instance.web.form.FormOpenPopup(self);
|
||||
pop.show_element(
|
||||
self.field.relation,
|
||||
self.get("value"),
|
||||
self.build_context(),
|
||||
{
|
||||
title: _t("Open: ") + self.string
|
||||
}
|
||||
);
|
||||
pop.on('write_completed', self, function(){
|
||||
self.display_value = {};
|
||||
self.display_value_backup = {};
|
||||
self.render_value();
|
||||
self.focus();
|
||||
self.view.do_onchange(self);
|
||||
var context = self.build_context().eval();
|
||||
var model_obj = new instance.web.Model(self.field.relation);
|
||||
model_obj.call('get_formview_id', [self.get("value"), context]).then(function(view_id){
|
||||
pop.show_element(
|
||||
self.field.relation,
|
||||
self.get("value"),
|
||||
self.build_context(),
|
||||
{
|
||||
title: _t("Open: ") + self.string,
|
||||
view_id: view_id
|
||||
}
|
||||
);
|
||||
pop.on('write_completed', self, function(){
|
||||
self.display_value = {};
|
||||
self.display_value_backup = {};
|
||||
self.render_value();
|
||||
self.focus();
|
||||
self.view.do_onchange(self);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -3336,7 +3505,7 @@ instance.web.form.FieldMany2One = instance.web.form.AbstractField.extend(instanc
|
|||
self.$input.autocomplete("close");
|
||||
}
|
||||
}, 50);
|
||||
this.$input.closest(".ui-dialog .ui-dialog-content").on('scroll', this, close_autocomplete);
|
||||
this.$input.closest(".modal .modal-content").on('scroll', this, close_autocomplete);
|
||||
|
||||
self.ed_def = $.Deferred();
|
||||
self.uned_def = $.Deferred();
|
||||
|
@ -3361,7 +3530,7 @@ instance.web.form.FieldMany2One = instance.web.form.AbstractField.extend(instanc
|
|||
}
|
||||
self.floating = false;
|
||||
}
|
||||
if (used && self.get("value") === false && ! self.no_ed) {
|
||||
if (used && self.get("value") === false && ! self.no_ed && (self.options.no_create === false || self.options.no_create === undefined)) {
|
||||
self.ed_def.reject();
|
||||
self.uned_def.reject();
|
||||
self.ed_def = $.Deferred();
|
||||
|
@ -3497,13 +3666,10 @@ instance.web.form.FieldMany2One = instance.web.form.AbstractField.extend(instanc
|
|||
.html(link);
|
||||
if (! this.options.no_open)
|
||||
$link.click(function () {
|
||||
self.do_action({
|
||||
type: 'ir.actions.act_window',
|
||||
res_model: self.field.relation,
|
||||
res_id: self.get("value"),
|
||||
views: [[false, 'form']],
|
||||
target: 'current',
|
||||
context: self.build_context().eval(),
|
||||
var context = self.build_context().eval();
|
||||
var model_obj = new instance.web.Model(self.field.relation);
|
||||
model_obj.call('get_formview_action', [self.get("value"), context]).then(function(action){
|
||||
self.do_action(action);
|
||||
});
|
||||
return false;
|
||||
});
|
||||
|
@ -4306,7 +4472,7 @@ instance.web.form.FieldMany2ManyTags = instance.web.form.AbstractField.extend(in
|
|||
if (data.id) {
|
||||
self.add_id(data.id);
|
||||
} else {
|
||||
ignore_blur = true;
|
||||
self.ignore_blur = true;
|
||||
data.action();
|
||||
}
|
||||
this.trigger('setSuggestions', {result : []});
|
||||
|
@ -4346,7 +4512,7 @@ instance.web.form.FieldMany2ManyTags = instance.web.form.AbstractField.extend(in
|
|||
if (this.get("effective_readonly"))
|
||||
return;
|
||||
var self = this;
|
||||
var ignore_blur = false;
|
||||
self.ignore_blur = false;
|
||||
self.$text = this.$("textarea");
|
||||
self.$text.textext(self.initialize_texttext()).bind('getSuggestions', function(e, data) {
|
||||
var _this = this;
|
||||
|
@ -4366,11 +4532,11 @@ instance.web.form.FieldMany2ManyTags = instance.web.form.AbstractField.extend(in
|
|||
self.$text
|
||||
.focusin(function () {
|
||||
self.trigger('focused');
|
||||
ignore_blur = false;
|
||||
self.ignore_blur = false;
|
||||
})
|
||||
.focusout(function() {
|
||||
self.$text.trigger("setInputData", "");
|
||||
if (!ignore_blur) {
|
||||
if (!self.ignore_blur) {
|
||||
self.trigger('blurred');
|
||||
}
|
||||
}).keydown(function(e) {
|
||||
|
@ -4448,6 +4614,10 @@ instance.web.form.FieldMany2ManyTags = instance.web.form.AbstractField.extend(in
|
|||
width: width,
|
||||
minHeight: height
|
||||
});
|
||||
},
|
||||
_search_create_popup: function() {
|
||||
self.ignore_blur = true;
|
||||
return instance.web.form.CompletionFieldMixin._search_create_popup.apply(this, arguments);
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -4860,13 +5030,12 @@ instance.web.form.AbstractFormPopup = instance.web.Widget.extend({
|
|||
var self = this;
|
||||
this.renderElement();
|
||||
var dialog = new instance.web.Dialog(this, {
|
||||
min_width: '800px',
|
||||
dialogClass: 'oe_act_window',
|
||||
close: function() {
|
||||
self.check_exit(true);
|
||||
},
|
||||
title: this.options.title || "",
|
||||
}, this.$el).open();
|
||||
dialog.on('closing', this, function (e){
|
||||
self.check_exit(true);
|
||||
});
|
||||
this.$buttonpane = dialog.$buttons;
|
||||
this.start();
|
||||
},
|
||||
|
@ -4933,8 +5102,8 @@ instance.web.form.AbstractFormPopup = instance.web.Widget.extend({
|
|||
},
|
||||
destroy: function () {
|
||||
this.trigger('closed');
|
||||
if (this.$el.is(":data(dialog)")) {
|
||||
this.$el.dialog('close');
|
||||
if (this.$el.is(":data(bs.modal)")) {
|
||||
this.$el.parents('.modal').modal('hide');
|
||||
}
|
||||
this._super();
|
||||
},
|
||||
|
@ -5009,7 +5178,7 @@ instance.web.form.SelectCreatePopup = instance.web.form.AbstractFormPopup.extend
|
|||
this.searchview.on('search_data', self, function(domains, contexts, groupbys) {
|
||||
if (self.initial_ids) {
|
||||
self.do_search(domains.concat([[["id", "in", self.initial_ids]], self.domain]),
|
||||
contexts, groupbys);
|
||||
contexts.concat(self.context), groupbys);
|
||||
self.initial_ids = undefined;
|
||||
} else {
|
||||
self.do_search(domains.concat([self.domain]), contexts.concat(self.context), groupbys);
|
||||
|
@ -5854,6 +6023,36 @@ instance.web.form.X2ManyCounter = instance.web.form.AbstractField.extend(instanc
|
|||
}
|
||||
});
|
||||
|
||||
/**
|
||||
This widget is intended to be used on stat button numeric fields. It will display
|
||||
the value many2many and one2many. It is a read-only field that will
|
||||
display a simple string "<value of field> <label of the field>"
|
||||
*/
|
||||
instance.web.form.StatInfo = instance.web.form.AbstractField.extend({
|
||||
is_field_number: true,
|
||||
init: function() {
|
||||
this._super.apply(this, arguments);
|
||||
this.internal_set_value(0);
|
||||
},
|
||||
set_value: function(value_) {
|
||||
if (value_ === false || value_ === undefined) {
|
||||
value_ = 0;
|
||||
}
|
||||
this._super.apply(this, [value_]);
|
||||
},
|
||||
render_value: function() {
|
||||
var options = {
|
||||
value: this.get("value") || 0,
|
||||
};
|
||||
if (! this.node.attrs.nolabel) {
|
||||
options.text = this.string
|
||||
}
|
||||
this.$el.html(QWeb.render("StatInfo", options));
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Registry of form fields, called by :js:`instance.web.FormView`.
|
||||
*
|
||||
|
@ -5867,6 +6066,7 @@ instance.web.form.widgets = new instance.web.Registry({
|
|||
'url' : 'instance.web.form.FieldUrl',
|
||||
'text' : 'instance.web.form.FieldText',
|
||||
'html' : 'instance.web.form.FieldTextHtml',
|
||||
'char_domain': 'instance.web.form.FieldCharDomain',
|
||||
'date' : 'instance.web.form.FieldDate',
|
||||
'datetime' : 'instance.web.form.FieldDatetime',
|
||||
'selection' : 'instance.web.form.FieldSelection',
|
||||
|
@ -5881,6 +6081,8 @@ instance.web.form.widgets = new instance.web.Registry({
|
|||
'reference' : 'instance.web.form.FieldReference',
|
||||
'boolean' : 'instance.web.form.FieldBoolean',
|
||||
'float' : 'instance.web.form.FieldFloat',
|
||||
'percentpie': 'instance.web.form.FieldPercentPie',
|
||||
'barchart': 'instance.web.form.FieldBarChart',
|
||||
'integer': 'instance.web.form.FieldFloat',
|
||||
'float_time': 'instance.web.form.FieldFloat',
|
||||
'progressbar': 'instance.web.form.FieldProgressBar',
|
||||
|
@ -5891,6 +6093,7 @@ instance.web.form.widgets = new instance.web.Registry({
|
|||
'monetary': 'instance.web.form.FieldMonetary',
|
||||
'many2many_checkboxes': 'instance.web.form.FieldMany2ManyCheckBoxes',
|
||||
'x2many_counter': 'instance.web.form.X2ManyCounter',
|
||||
'statinfo': 'instance.web.form.StatInfo',
|
||||
});
|
||||
|
||||
/**
|
||||
|
|
|
@ -408,6 +408,9 @@ instance.web.ListView = instance.web.View.extend( /** @lends instance.web.ListVi
|
|||
if (total) {
|
||||
var range_start = this.page * limit + 1;
|
||||
var range_stop = range_start - 1 + limit;
|
||||
if (this.records.length) {
|
||||
range_stop = range_start - 1 + this.records.length;
|
||||
}
|
||||
if (range_stop > total) {
|
||||
range_stop = total;
|
||||
}
|
||||
|
@ -534,7 +537,8 @@ instance.web.ListView = instance.web.View.extend( /** @lends instance.web.ListVi
|
|||
[record.get('id')],
|
||||
_.pluck(_(this.columns).filter(function (r) {
|
||||
return r.tag === 'field';
|
||||
}), 'name')
|
||||
}), 'name'),
|
||||
{check_access_rule: true}
|
||||
).done(function (records) {
|
||||
var values = records[0];
|
||||
if (!values) {
|
||||
|
@ -602,7 +606,17 @@ instance.web.ListView = instance.web.View.extend( /** @lends instance.web.ListVi
|
|||
_(ids).each(function (id) {
|
||||
self.records.remove(self.records.get(id));
|
||||
});
|
||||
self.configure_pager(self.dataset);
|
||||
if (self.records.length === 0 && self.dataset.size() > 0) {
|
||||
//Trigger previous manually to navigate to previous page,
|
||||
//If all records are deleted on current page.
|
||||
self.$pager.find('ul li:first a').trigger('click');
|
||||
} else if (self.dataset.size() == self.limit()) {
|
||||
//Reload listview to update current page with next page records
|
||||
//because pager going to be hidden if dataset.size == limit
|
||||
self.reload();
|
||||
} else {
|
||||
self.configure_pager(self.dataset);
|
||||
}
|
||||
self.compute_aggregates();
|
||||
});
|
||||
},
|
||||
|
@ -2247,8 +2261,8 @@ instance.web.list.Button = instance.web.list.Column.extend({
|
|||
attrs = this.modifiers_for(row_data);
|
||||
}
|
||||
if (attrs.invisible) { return ''; }
|
||||
|
||||
return QWeb.render('ListView.row.button', {
|
||||
var template = this.icon && 'ListView.row.button' || 'ListView.row.text_button';
|
||||
return QWeb.render(template, {
|
||||
widget: this,
|
||||
prefix: instance.session.prefix,
|
||||
disabled: attrs.readonly
|
||||
|
|
|
@ -126,10 +126,19 @@
|
|||
* as an editable row at the top or bottom of the list)
|
||||
*/
|
||||
do_add_record: function () {
|
||||
var self = this;
|
||||
if (this.editable()) {
|
||||
this.$el.find('table:first').show();
|
||||
this.$el.find('.oe_view_nocontent').remove();
|
||||
this.start_edition();
|
||||
this.start_edition().then(function(){
|
||||
var fields = self.editor.form.fields;
|
||||
self.editor.form.fields_order.some(function(field){
|
||||
if (fields[field].$el.is(':visible')){
|
||||
fields[field].$el.find("input").select();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
});
|
||||
} else {
|
||||
this._super();
|
||||
}
|
||||
|
|
|
@ -25,9 +25,9 @@ instance.web.ActionManager = instance.web.Widget.extend({
|
|||
this._super.apply(this, arguments);
|
||||
this.$el.on('click', 'a.oe_breadcrumb_item', this.on_breadcrumb_clicked);
|
||||
},
|
||||
dialog_stop: function () {
|
||||
dialog_stop: function (reason) {
|
||||
if (this.dialog) {
|
||||
this.dialog.destroy();
|
||||
this.dialog.destroy(reason);
|
||||
}
|
||||
this.dialog = null;
|
||||
},
|
||||
|
@ -408,12 +408,12 @@ instance.web.ActionManager = instance.web.Widget.extend({
|
|||
if (this.dialog_widget && !this.dialog_widget.isDestroyed()) {
|
||||
this.dialog_widget.destroy();
|
||||
}
|
||||
this.dialog_stop();
|
||||
this.dialog_stop(executor.action);
|
||||
this.dialog = new instance.web.Dialog(this, {
|
||||
title: executor.action.name,
|
||||
dialogClass: executor.klass,
|
||||
});
|
||||
this.dialog.on("closing", null, options.on_close);
|
||||
this.dialog.dialog_title = executor.action.name;
|
||||
if (widget instanceof instance.web.ViewManager) {
|
||||
_.extend(widget.flags, {
|
||||
$buttons: this.dialog.$buttons,
|
||||
|
@ -426,7 +426,7 @@ instance.web.ActionManager = instance.web.Widget.extend({
|
|||
this.dialog.open();
|
||||
return initialized;
|
||||
} else {
|
||||
this.dialog_stop();
|
||||
this.dialog_stop(executor.action);
|
||||
this.inner_action = executor.action;
|
||||
this.inner_widget = widget;
|
||||
executor.post_process(widget);
|
||||
|
@ -581,7 +581,7 @@ instance.web.ViewManager = instance.web.Widget.extend({
|
|||
var self = this;
|
||||
this.$el.find('.oe_view_manager_switch a').click(function() {
|
||||
self.switch_mode($(this).data('view-type'));
|
||||
}).tipsy();
|
||||
}).tooltip();
|
||||
var views_ids = {};
|
||||
_.each(this.views_src, function(view) {
|
||||
self.views[view.view_type] = $.extend({}, view, {
|
||||
|
@ -639,7 +639,7 @@ instance.web.ViewManager = instance.web.Widget.extend({
|
|||
this.$el
|
||||
.find('.oe_view_manager_switch a').filter('[data-view-type="' + view_type + '"]')
|
||||
.parent().addClass('active');
|
||||
|
||||
this.$el.attr("data-view-type", view_type);
|
||||
return $.when(view_promise).done(function () {
|
||||
_.each(_.keys(self.views), function(view_name) {
|
||||
var controller = self.views[view_name].controller;
|
||||
|
@ -926,7 +926,7 @@ instance.web.ViewManagerAction = instance.web.ViewManager.extend({
|
|||
current_view = this.views[this.active_view].controller;
|
||||
switch (val) {
|
||||
case 'fvg':
|
||||
var dialog = new instance.web.Dialog(this, { title: _t("Fields View Get"), width: '95%' }).open();
|
||||
var dialog = new instance.web.Dialog(this, { title: _t("Fields View Get") }).open();
|
||||
$('<pre>').text(instance.web.json_node_to_xml(current_view.fields_view.arch, true)).appendTo(dialog.$el);
|
||||
break;
|
||||
case 'tests':
|
||||
|
@ -943,7 +943,7 @@ instance.web.ViewManagerAction = instance.web.ViewManager.extend({
|
|||
this.dataset.call('perm_read', [ids]).done(function(result) {
|
||||
var dialog = new instance.web.Dialog(this, {
|
||||
title: _.str.sprintf(_t("View Log (%s)"), self.dataset.model),
|
||||
width: 400
|
||||
size: 'medium',
|
||||
}, QWeb.render('ViewManagerDebugViewLog', {
|
||||
perm : result[0],
|
||||
format : instance.web.format_value
|
||||
|
@ -986,7 +986,7 @@ instance.web.ViewManagerAction = instance.web.ViewManager.extend({
|
|||
new instance.web.Dialog(self, {
|
||||
title: _.str.sprintf(_t("Model %s fields"),
|
||||
self.dataset.model),
|
||||
width: '95%'}, $root).open();
|
||||
}, $root).open();
|
||||
});
|
||||
break;
|
||||
case 'edit_workflow':
|
||||
|
@ -1157,10 +1157,8 @@ instance.web.Sidebar = instance.web.Widget.extend({
|
|||
this.$('.oe_form_dropdown_section').each(function() {
|
||||
$(this).toggle(!!$(this).find('li').length);
|
||||
});
|
||||
|
||||
self.$("[title]").tipsy({
|
||||
'html': true,
|
||||
'delayIn': 500,
|
||||
self.$("[title]").tooltip({
|
||||
delay: { show: 500, hide: 0}
|
||||
});
|
||||
},
|
||||
/**
|
||||
|
@ -1223,7 +1221,7 @@ instance.web.Sidebar = instance.web.Widget.extend({
|
|||
domain = $.Deferred().resolve(undefined);
|
||||
}
|
||||
if (ids.length === 0) {
|
||||
instance.web.dialog($("<div />").text(_t("You must choose at least one record.")), { title: _t("Warning"), modal: true });
|
||||
new instance.web.Dialog(this, { title: _t("Warning"), size: 'medium',}, $("<div />").text(_t("You must choose at least one record."))).open();
|
||||
return false;
|
||||
}
|
||||
var active_ids_context = {
|
||||
|
@ -1402,7 +1400,7 @@ instance.web.View = instance.web.Widget.extend({
|
|||
// Wrong group_by values will simply fail and forbid rendering of the destination view
|
||||
var ncontext = new instance.web.CompoundContext(
|
||||
_.object(_.reject(_.pairs(dataset.get_context().eval()), function(pair) {
|
||||
return pair[0].match('^(?:(?:default_|search_default_).+|group_by|group_by_no_leaf|active_id|active_ids)$') !== null;
|
||||
return pair[0].match('^(?:(?:default_|search_default_).+|.+_view_ref|group_by|group_by_no_leaf|active_id|active_ids)$') !== null;
|
||||
}))
|
||||
);
|
||||
ncontext.add(action_data.context || {});
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
(function() {
|
||||
/*
|
||||
* object.watch polyfill
|
||||
*
|
||||
* 2012-04-03
|
||||
*
|
||||
* By Eli Grey, http://eligrey.com
|
||||
* Public Domain.
|
||||
* NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
|
||||
*/
|
||||
|
||||
// object.watch
|
||||
if (!Object.prototype.watch) {
|
||||
Object.defineProperty(Object.prototype, "watch", {
|
||||
enumerable: false
|
||||
, configurable: true
|
||||
, writable: false
|
||||
, value: function (prop, handler) {
|
||||
var
|
||||
oldval = this[prop]
|
||||
, newval = oldval
|
||||
, getter = function () {
|
||||
return newval;
|
||||
}
|
||||
, setter = function (val) {
|
||||
oldval = newval;
|
||||
return newval = handler.call(this, prop, oldval, val);
|
||||
}
|
||||
;
|
||||
|
||||
if (delete this[prop]) { // can't watch constants
|
||||
Object.defineProperty(this, prop, {
|
||||
get: getter
|
||||
, set: setter
|
||||
, enumerable: true
|
||||
, configurable: true
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// object.unwatch
|
||||
if (!Object.prototype.unwatch) {
|
||||
Object.defineProperty(Object.prototype, "unwatch", {
|
||||
enumerable: false
|
||||
, configurable: true
|
||||
, writable: false
|
||||
, value: function (prop) {
|
||||
var val = this[prop];
|
||||
delete this[prop]; // remove accessors
|
||||
this[prop] = val;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
})();
|
||||
|
|
@ -32,7 +32,20 @@
|
|||
<t t-esc="message"/>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<t t-name="Dialog">
|
||||
<div class="modal" tabindex="-1" data-backdrop="static" role="dialog" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h3 class="modal-title"><t t-raw="title"/></h3>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
<t t-name="CrashManager.warning">
|
||||
<table cellspacing="0" cellpadding="0" border="0" class="oe_dialog_warning">
|
||||
<tr>
|
||||
|
@ -231,17 +244,24 @@
|
|||
</div>
|
||||
<table align="center" class="db_option_table">
|
||||
<tr>
|
||||
<td><label for="restore_db">File:</label></td>
|
||||
<td><input type="file" name="db_file" class="required" autofocus="autofocus"/></td>
|
||||
<td><label for="restore_pwd">Master Password:</label></td>
|
||||
<td><input type="password" name="restore_pwd" class="required" autofocus="autofocus"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label for="restore_pwd">Master Password:</label></td>
|
||||
<td><input type="password" name="restore_pwd" class="required"/></td>
|
||||
<td><label for="restore_db">File:</label></td>
|
||||
<td><input type="file" name="db_file" class="required"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label for="new_db">New database name:</label></td>
|
||||
<td><input type="text" name="new_db" class="required"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label for="mode">Mode:</label></td>
|
||||
<td><select name="mode" class="required">
|
||||
<option value="restore">Backup Restore</option>
|
||||
<option value="copy">Copy of an existing database</option>
|
||||
</select></td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
<form id="db_change_password" name="change_pwd_form" style="display: none;">
|
||||
|
@ -592,10 +612,16 @@
|
|||
<div class="oe_sidebar">
|
||||
<t t-foreach="widget.sections" t-as="section">
|
||||
<div class="oe_form_dropdown_section">
|
||||
<button class="oe_dropdown_toggle oe_dropdown_arrow">
|
||||
<button class="oe_dropdown_toggle oe_dropdown_arrow" t-if="section.name != 'buttons'">
|
||||
<t t-if="section.name == 'files'" t-raw="widget.items[section.name].length || ''"/>
|
||||
<t t-esc="section.label"/>
|
||||
</button>
|
||||
<t t-if="section.name == 'buttons'" t-foreach="widget.items[section.name]" t-as="item" t-att-class="item.classname">
|
||||
<button t-att-title="item.title or ''" t-att-data-section="section.name" t-att-data-index="item_index" t-att-href="item.url"
|
||||
target="_blank" class="oe_sidebar_button oe_highlight">
|
||||
<t t-raw="item.label"/>
|
||||
</button>
|
||||
</t>
|
||||
<ul class="oe_dropdown_menu">
|
||||
<li t-foreach="widget.items[section.name]" t-as="item" t-att-class="item.classname">
|
||||
<t t-if="section.name == 'files'">
|
||||
|
@ -772,11 +798,16 @@
|
|||
</span>
|
||||
</t>
|
||||
</t>
|
||||
<button t-name="ListView.row.text_button" type="button"
|
||||
t-att-title="widget.string" t-att-disabled="disabled || undefined"
|
||||
t-att-class="disabled ? 'oe_list_button_disabled btn' : 'btn'">
|
||||
<t t-esc="widget.string"/>
|
||||
</button>
|
||||
<button t-name="ListView.row.button" type="button"
|
||||
t-att-title="widget.string" t-att-disabled="disabled || undefined"
|
||||
t-att-class="disabled ? 'oe_list_button_disabled' : undefined"
|
||||
><img t-attf-src="#{prefix}/web/static/src/img/icons/#{widget.icon}.png"
|
||||
t-att-alt="widget.string"/></button>
|
||||
t-att-class="disabled ? 'oe_list_button_disabled btn_img' : 'btn_img'"
|
||||
><img t-attf-src="#{prefix}/web/static/src/img/icons/#{widget.icon}.png"
|
||||
t-att-alt="widget.string"/></button>
|
||||
<t t-extend="ListView.row">
|
||||
<!-- adds back padding to row being rendered after edition, if necessary
|
||||
(if not deletable add back padding), otherwise the row being added is
|
||||
|
@ -912,7 +943,6 @@
|
|||
</t>
|
||||
<t t-name="FormRenderingLabel">
|
||||
<label t-att-for="_for"
|
||||
t-att-title="help"
|
||||
t-attf-class="#{classnames} oe_form_label#{help ? '_help' : ''} oe_align_#{align}">
|
||||
<t t-esc="string"/>
|
||||
</label>
|
||||
|
@ -974,7 +1004,7 @@
|
|||
</li>
|
||||
<li t-if="widget.field and widget.field.selection" data-item="selection">
|
||||
<span class="oe_tooltip_technical_title">Selection:</span>
|
||||
<ul>
|
||||
<ul class="oe_tooltip_technical">
|
||||
<li t-foreach="widget.field.selection" t-as="option">
|
||||
[<t t-esc="option[0]"/>]
|
||||
<t t-if="option[1]"> - </t>
|
||||
|
@ -1049,6 +1079,16 @@
|
|||
</t>
|
||||
</div>
|
||||
</t>
|
||||
<t t-name="FieldCharDomain">
|
||||
<div class="oe_form_field">
|
||||
<span class="oe_domain_count"/>
|
||||
<button class="oe_button oe_link select_records" type="button"
|
||||
t-att-style="widget.node.attrs.style"
|
||||
t-att-accesskey="widget.node.attrs.accesskey">
|
||||
<span class="fa fa-arrow-right"/>
|
||||
</button>
|
||||
</div>
|
||||
</t>
|
||||
<t t-name="web.datepicker">
|
||||
<span>
|
||||
<t t-set="placeholder" t-value="widget.getParent().node and widget.getParent().node.attrs.placeholder"/>
|
||||
|
@ -1188,6 +1228,18 @@
|
|||
<span></span>
|
||||
</span>
|
||||
</t>
|
||||
<t t-name="FieldPercentPie">
|
||||
<div class="oe_form_field oe_form_field_percent_pie" t-att-style="widget.node.attrs.style">
|
||||
<svg></svg>
|
||||
<span t-if="widget.string"><t t-esc="widget.string"/></span>
|
||||
</div>
|
||||
</t>
|
||||
<t t-name="FieldBarChart">
|
||||
<div class="oe_form_field oe_form_field_bar_chart" t-att-style="widget.node.attrs.style">
|
||||
<svg></svg>
|
||||
<span t-if="widget.string"><t t-esc="widget.string"/></span>
|
||||
</div>
|
||||
</t>
|
||||
<t t-name="FieldStatus">
|
||||
<ul t-att-class="'oe_form_field_status ' + (widget.options.clickable ? 'oe_form_status_clickable' : 'oe_form_status')" t-att-style="widget.node.attrs.style"/>
|
||||
</t>
|
||||
|
@ -1252,7 +1304,7 @@
|
|||
<td>
|
||||
<t t-call="HiddenInputFile">
|
||||
<t t-set="fileupload_id" t-value="widget.fileupload_id"/>
|
||||
<t t-set="fileupload_style" t-translation="off">width: 83px;</t>
|
||||
<t t-set="fileupload_style" t-translation="off">overflow-x: hidden</t>
|
||||
<button class="oe_button oe_field_button" type="button">
|
||||
<img t-att-src='_s + "/web/static/src/img/icons/STOCK_DIRECTORY.png"'/>
|
||||
<span>Select</span>
|
||||
|
@ -1351,13 +1403,15 @@
|
|||
</div>
|
||||
</t>
|
||||
<t t-name="WidgetButton">
|
||||
<button type="button" class="oe_button oe_form_button"
|
||||
<button type="button" t-att-class="widget.is_stat_button ? 'oe_stat_button btn btn-default' : 'oe_button oe_form_button'"
|
||||
t-att-style="widget.node.attrs.style"
|
||||
t-att-tabindex="widget.node.attrs.tabindex"
|
||||
t-att-autofocus="widget.node.attrs.autofocus"
|
||||
t-att-accesskey="widget.node.attrs.accesskey">
|
||||
<img t-if="widget.node.attrs.icon" t-att-src="_s + widget.node.attrs.icon" width="16" height="16"/>
|
||||
<span t-if="widget.string"><t t-esc="widget.string"/></span>
|
||||
<img t-if="!widget.is_stat_button and widget.node.attrs.icon " t-att-src="_s + widget.node.attrs.icon" width="16" height="16"/>
|
||||
<div t-if="widget.is_stat_button and widget.icon" class="stat_button_icon"><t t-raw="widget.icon"/></div>
|
||||
<span t-if="widget.string and !widget.is_stat_button"><t t-esc="widget.string"/></span>
|
||||
<div t-if="widget.string and widget.is_stat_button"><t t-esc="widget.string"/></div>
|
||||
</button>
|
||||
</t>
|
||||
<t t-name="WidgetButton.tooltip" t-extend="WidgetLabel.tooltip">
|
||||
|
@ -1930,4 +1984,7 @@
|
|||
<t t-name="X2ManyCounter">
|
||||
<a href="javascript:void(0)"><t t-esc="text"/></a>
|
||||
</t>
|
||||
<t t-name="StatInfo">
|
||||
<strong><t t-esc="value"/></strong>
|
||||
<t t-esc="text"/></t>
|
||||
</templates>
|
||||
|
|
|
@ -1,3 +1,32 @@
|
|||
openerp.testing.section('data.dataset', {
|
||||
rpc: 'mock',
|
||||
dependencies: ['web.data'],
|
||||
}, function (test) {
|
||||
test('read_ids', {asserts: 2}, function (instance, _, mock) {
|
||||
var d = new instance.web.DataSet(null, 'foo');
|
||||
mock('foo:read', function (args) {
|
||||
var ids = args[0];
|
||||
deepEqual(ids, [3, 1, 2]);
|
||||
return [
|
||||
{id: 1, a: 'bar'},
|
||||
{id: 2, a: 'baz'},
|
||||
{id: 3, a: 'foo'}
|
||||
];
|
||||
});
|
||||
|
||||
return d.read_ids([3, 1, 2]).then(function (records) {
|
||||
deepEqual(
|
||||
records,
|
||||
[
|
||||
{id: 3, a: 'foo'},
|
||||
{id: 1, a: 'bar'},
|
||||
{id: 2, a: 'baz'}
|
||||
]
|
||||
)
|
||||
});
|
||||
})
|
||||
});
|
||||
|
||||
openerp.testing.section('data.model.group_by', {
|
||||
rpc: 'mock',
|
||||
dependencies: ['web.data'],
|
||||
|
|
|
@ -1,210 +0,0 @@
|
|||
(function() {
|
||||
|
||||
var ropenerp = window.openerp;
|
||||
|
||||
var openerp = ropenerp.declare($, _, QWeb2);
|
||||
|
||||
ropenerp.testing.section('jsonrpc', {},
|
||||
function (test) {
|
||||
test('basic-jsonrpc', {asserts: 1}, function () {
|
||||
var session = new openerp.Session();
|
||||
return session.rpc("/gen_session_id", {}).then(function(result) {
|
||||
ok(result.length > 0, "Result returned by /gen_session_id");
|
||||
});
|
||||
});
|
||||
test('basic-jsonprpc', {asserts: 1}, function () {
|
||||
var session = new openerp.Session();
|
||||
session.origin_server = false;
|
||||
return session.rpc("/gen_session_id", {}).then(function(result) {
|
||||
ok(result.length > 0, "Result returned by /gen_session_id");
|
||||
});
|
||||
});
|
||||
// desactivated because the phantomjs runner crash
|
||||
/*test('basic-jsonprpc2', {asserts: 1}, function () {
|
||||
var session = new openerp.Session();
|
||||
session.origin_server = false;
|
||||
return session.rpc("/gen_session_id", {}, {force2step: true}).then(function(result) {
|
||||
ok(result.length > 0, "Result returned by /gen_session_id");
|
||||
});
|
||||
});*/
|
||||
test('session-jsonrpc', {asserts: 2}, function () {
|
||||
var session = new openerp.Session();
|
||||
var tmp = _.uniqueId("something");
|
||||
return session.rpc("/web/tests/set_session_value", {value: tmp}).then(function() {
|
||||
ok(true, "set_session returned");
|
||||
return session.rpc("/web/tests/get_session_value", {});
|
||||
}).then(function(result) {
|
||||
equal(result, tmp, "Got the same value from the session");
|
||||
});
|
||||
});
|
||||
test('session-jsonprpc', {asserts: 2}, function () {
|
||||
var session = new openerp.Session();
|
||||
session.origin_server = false;
|
||||
var tmp = _.uniqueId("something");
|
||||
return session.rpc("/web/tests/set_session_value", {value: tmp}).then(function() {
|
||||
ok(true, "set_session returned");
|
||||
return session.rpc("/web/tests/get_session_value", {});
|
||||
}).then(function(result) {
|
||||
equal(result, tmp, "Got the same value from the session");
|
||||
});
|
||||
});
|
||||
// desactivated because the phantomjs runner crash
|
||||
/*test('session-jsonprpc2', {asserts: 2}, function () {
|
||||
var session = new openerp.Session();
|
||||
session.origin_server = false;
|
||||
var tmp = _.uniqueId("something");
|
||||
return session.rpc("/web/tests/set_session_value", {value: tmp}, {force2step: true}).then(function() {
|
||||
ok(true, "set_session returned");
|
||||
return session.rpc("/web/tests/get_session_value", {}, {force2step: true});
|
||||
}).then(function(result) {
|
||||
equal(result, tmp, "Got the same value from the session");
|
||||
});
|
||||
});*/
|
||||
test('overridesession-jsonrpc', {asserts: 4}, function () {
|
||||
var origin_session = new openerp.Session();
|
||||
var origin_tmp = _.uniqueId("something");
|
||||
var session = new openerp.Session(null, null, {override_session: true});
|
||||
var tmp = _.uniqueId("something_else");
|
||||
return session.rpc("/web/tests/set_session_value", {value: tmp}).then(function() {
|
||||
ok(true, "set_session returned");
|
||||
return origin_session.rpc("/web/tests/set_session_value", {value: origin_tmp});
|
||||
}).then(function(result) {
|
||||
ok(true, "set_session on origin returned");
|
||||
return session.rpc("/web/tests/get_session_value", {});
|
||||
}).then(function(result) {
|
||||
equal(result, tmp, "Got the same value from the session");
|
||||
notEqual(result, origin_tmp, "Values in the different sessions should be different");
|
||||
});
|
||||
});
|
||||
test('overridesession-jsonprpc', {asserts: 4}, function () {
|
||||
var origin_session = new openerp.Session();
|
||||
var origin_tmp = _.uniqueId("something");
|
||||
var session = new openerp.Session(null, null, {override_session: true});
|
||||
var tmp = _.uniqueId("something_else");
|
||||
session.origin_server = false;
|
||||
return session.rpc("/web/tests/set_session_value", {value: tmp}).then(function() {
|
||||
ok(true, "set_session returned");
|
||||
return origin_session.rpc("/web/tests/set_session_value", {value: origin_tmp});
|
||||
}).then(function(result) {
|
||||
ok(true, "set_session on origin returned");
|
||||
return session.rpc("/web/tests/get_session_value", {});
|
||||
}).then(function(result) {
|
||||
equal(result, tmp, "Got the same value from the session");
|
||||
notEqual(result, origin_tmp, "Values in the different sessions should be different");
|
||||
});
|
||||
});
|
||||
// desactivated because the phantomjs runner crash
|
||||
/*test('overridesession-jsonprpc2', {asserts: 4}, function () {
|
||||
var origin_session = new openerp.Session();
|
||||
var origin_tmp = _.uniqueId("something");
|
||||
var session = new openerp.Session(null, null, {override_session: true});
|
||||
var tmp = _.uniqueId("something_else");
|
||||
session.origin_server = false;
|
||||
return session.rpc("/web/tests/set_session_value", {value: tmp}, {force2step: true}).then(function() {
|
||||
ok(true, "set_session returned");
|
||||
return origin_session.rpc("/web/tests/set_session_value", {value: origin_tmp});
|
||||
}).then(function(result) {
|
||||
ok(true, "set_session on origin returned");
|
||||
return session.rpc("/web/tests/get_session_value", {}, {force2step: true});
|
||||
}).then(function(result) {
|
||||
equal(result, tmp, "Got the same value from the session");
|
||||
notEqual(result, origin_tmp, "Values in the different sessions should be different");
|
||||
});
|
||||
});*/
|
||||
test('timeout-jsonrpc', {asserts: 1}, function () {
|
||||
var session = new openerp.Session();
|
||||
return session.rpc("/gen_session_id", {}, {timeout: 1}).then(function() {
|
||||
ok(false, "the request incorrectly succeeded");
|
||||
return $.when();
|
||||
}, function(a, e) {
|
||||
e.preventDefault();
|
||||
ok(true, "the request correctly failed");
|
||||
return $.when();
|
||||
});
|
||||
});
|
||||
test('timeout-jsonprpc', {asserts: 1}, function () {
|
||||
var session = new openerp.Session();
|
||||
session.origin_server = false;
|
||||
return session.rpc("/gen_session_id", {}, {timeout: 1}).then(function() {
|
||||
ok(false, "the request incorrectly succeeded");
|
||||
return $.when();
|
||||
}, function(a, e) {
|
||||
e.preventDefault();
|
||||
ok(true, "the request correctly failed");
|
||||
return $.when();
|
||||
});
|
||||
});
|
||||
// desactivated because the phantomjs runner crash
|
||||
/*test('timeout-jsonprpc2', {asserts: 1}, function () {
|
||||
var session = new openerp.Session();
|
||||
session.origin_server = false;
|
||||
return session.rpc("/gen_session_id", {}, {force2step: true, timeout: 1}).then(function() {
|
||||
ok(false, "the request incorrectly succeeded");
|
||||
return $.when();
|
||||
}, function(a, e) {
|
||||
e.preventDefault();
|
||||
ok(true, "the request correctly failed");
|
||||
return $.when();
|
||||
});
|
||||
});*/
|
||||
});
|
||||
|
||||
var login = "admin";
|
||||
var password = "admin";
|
||||
|
||||
ropenerp.testing.section('jsonrpc-auth', {
|
||||
rpc: "rpc",
|
||||
},
|
||||
function (test) {
|
||||
test('basic-auth', {asserts: 3}, function () {
|
||||
var db = ropenerp.session.db;
|
||||
var session = new openerp.Session(null, null, {override_session: true});
|
||||
equal(session.uid, undefined, "uid is expected to be undefined");
|
||||
return session.session_authenticate(db, login, password).then(function() {
|
||||
equal(session.uid, 1, "Admin's uid must be 1");
|
||||
return session.rpc("/web/dataset/call_kw", {
|
||||
model: "res.users",
|
||||
method: "read",
|
||||
args: [1, ["login"]],
|
||||
kwargs: {},
|
||||
}).then(function(result) {
|
||||
equal(result.login, "admin", "Admin's name must be 'admin'");
|
||||
});
|
||||
});
|
||||
});
|
||||
test('share-sessions', {asserts: 6}, function () {
|
||||
var db = ropenerp.session.db;
|
||||
var session = new openerp.Session(null, null, {override_session: true});
|
||||
var session2;
|
||||
return session.session_authenticate(db, login, password).then(function() {
|
||||
equal(session.uid, 1, "Admin's uid must be 1");
|
||||
session2 = new openerp.Session(null, null, {session_id: session.session_id});
|
||||
equal(session2.uid, undefined, "uid should be undefined");
|
||||
equal(session2.override_session, true, "overwrite_session should be true");
|
||||
return session2.session_reload();
|
||||
}).then(function() {
|
||||
equal(session2.uid, session.uid);
|
||||
equal(session2.uid, 1);
|
||||
return session2.rpc("/web/dataset/call_kw", {
|
||||
model: "res.users",
|
||||
method: "read",
|
||||
args: [1, ["login"]],
|
||||
kwargs: {},
|
||||
}).then(function(result) {
|
||||
equal(result.login, "admin", "Admin's name must be 'admin'");
|
||||
});
|
||||
});
|
||||
});
|
||||
test('models', {asserts: 2}, function () {
|
||||
var db = ropenerp.session.db;
|
||||
var session = new openerp.Session(null, null, {override_session: true});
|
||||
return session.session_authenticate(db, login, password).then(function() {
|
||||
return session.model("res.users").call("search_read", {fields: ["login"], domain: [["id", "=", 1]]});
|
||||
}).then(function(result) {
|
||||
equal(result.length, 1, "Must have one result");
|
||||
equal(result[0].login, "admin", "Must have admin's login");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
})();
|
|
@ -81,7 +81,7 @@ openerp.testing.section('editor', {
|
|||
test('toggle-edition-save', {
|
||||
asserts: 4,
|
||||
setup: function (instance, $s, mock) {
|
||||
mock('test.model:read', function () {
|
||||
mock('test.model:search_read', function () {
|
||||
return [{id: 42, a: false, b: false, c: false}];
|
||||
});
|
||||
}
|
||||
|
@ -183,6 +183,15 @@ openerp.testing.section('list.edition', {
|
|||
}
|
||||
return [];
|
||||
});
|
||||
mock('demo:search_read', function (args) {
|
||||
// args[0][0] = ["id", "=", 42]
|
||||
// args[0][0] = 42
|
||||
var id = args[0][0][2];
|
||||
if (id in records) {
|
||||
return [records[id]];
|
||||
}
|
||||
return [];
|
||||
});
|
||||
mock('demo:fields_view_get', function () {
|
||||
return {
|
||||
type: 'tree',
|
||||
|
@ -316,11 +325,13 @@ openerp.testing.section('list.edition.onwrite', {
|
|||
mock('demo:read', function (args, kwargs) {
|
||||
if (_.isEmpty(args[0])) {
|
||||
return [];
|
||||
} else if (_.isEqual(args[0], [1])) {
|
||||
return [
|
||||
{id: 1, a: 'some value'}
|
||||
];
|
||||
} else if (_.isEqual(args[0], [42])) {
|
||||
}
|
||||
throw new Error(JSON.stringify(_.toArray(arguments)));
|
||||
});
|
||||
mock('demo:search_read', function (args, kwargs) {
|
||||
if (_.isEqual(args[0], [['id', 'in', [1]]])) {
|
||||
return [{id: 1, a: 'some value'}];
|
||||
} else if (_.isEqual(args[0], [['id', 'in', [42]]])) {
|
||||
return [ {id: 42, a: 'foo'} ];
|
||||
}
|
||||
throw new Error(JSON.stringify(_.toArray(arguments)));
|
||||
|
|
|
@ -18,8 +18,12 @@ openerp.testing.section('list.buttons', {
|
|||
return [
|
||||
{id: 1, a: 'foo'}, {id: 2, a: 'bar'}, {id: 3, a: 'baz'}
|
||||
];
|
||||
} else if (_.isEqual(args[0], [2])) {
|
||||
// button action virtually removed record
|
||||
}
|
||||
throw new Error(JSON.stringify(_.toArray(arguments)));
|
||||
});
|
||||
mock('demo:search_read', function (args, kwargs) {
|
||||
console.log(args);
|
||||
if (_.isEqual(args[0], [['id', 'in', [2]]])) {
|
||||
return [];
|
||||
}
|
||||
throw new Error(JSON.stringify(_.toArray(arguments)));
|
||||
|
|
|
@ -620,29 +620,33 @@ openerp.testing.section('search.completions', {
|
|||
{relation: 'dummy.model'}, view);
|
||||
return f.complete("bob");
|
||||
});
|
||||
test("M2O custom operator", {asserts: 6}, function (instance) {
|
||||
var view = { inputs: [], };
|
||||
test("M2O custom operator", {asserts: 10}, function (instance, $s, mock) {
|
||||
mock('dummy.model:name_search', function (args, kwargs) {
|
||||
deepEqual(args, [], "should have no positional arguments");
|
||||
// the operator is meant for the final search term generation, not the autocompletion
|
||||
equal(kwargs.operator, undefined, "operator should not be used for autocompletion")
|
||||
strictEqual(kwargs.name, 'bob');
|
||||
return [[42, "Match"]];
|
||||
});
|
||||
var view = {inputs: [], dataset: {get_context: function () {}}};
|
||||
var f = new instance.web.search.ManyToOneField(
|
||||
{attrs: {string: 'Dummy', operator:'ilike'}},
|
||||
{attrs: {string: 'Dummy', operator: 'ilike'}},
|
||||
{relation: 'dummy.model'}, view);
|
||||
|
||||
return f.complete('bob')
|
||||
.done(function (completions) {
|
||||
equal(completions.length, 1, "should provide a single completion");
|
||||
var c = completions[0];
|
||||
equal(c.label, "Search <em>Dummy</em> for: <strong>bob</strong>",
|
||||
"should propose fuzzy searching of the value");
|
||||
ok(c.facet, "should have a facet");
|
||||
.done(function (c) {
|
||||
equal(c.length, 2, "should return result + title");
|
||||
var title = c[0];
|
||||
equal(title.label, f.attrs.string, "title should match field name");
|
||||
ok(!title.facet, "title should not have a facet");
|
||||
|
||||
var facet = new instance.web.search.Facet(c.facet);
|
||||
equal(facet.get('category'), f.attrs.string,
|
||||
"completion facet should bear the field's name");
|
||||
strictEqual(facet.get('field'), f,
|
||||
"completion facet should yield the field");
|
||||
deepEqual(facet.values.toJSON(), [{label: 'bob', value: 'bob'}],
|
||||
"facet should have a single value using the completion item");
|
||||
var f1 = new instance.web.search.Facet(c[1].facet);
|
||||
equal(c[1].label, "Match");
|
||||
equal(f1.get('category'), f.attrs.string);
|
||||
equal(f1.get('field'), f);
|
||||
deepEqual(f1.values.toJSON(), [{label: 'Match', value: 42}]);
|
||||
});
|
||||
});
|
||||
});
|
||||
test('Integer: invalid', {asserts: 1}, function (instance) {
|
||||
var view = {inputs: []};
|
||||
var f = new instance.web.search.IntegerField(
|
||||
|
|
|
@ -59,7 +59,7 @@ class QUnitSuite(unittest.TestSuite):
|
|||
'timeout': self.timeout,
|
||||
'inject': os.path.join(ROOT, 'qunit-phantomjs-bridge.js')
|
||||
})
|
||||
], stdout=subprocess.PIPE)
|
||||
], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||
|
||||
try:
|
||||
while True:
|
||||
|
@ -75,7 +75,12 @@ class QUnitSuite(unittest.TestSuite):
|
|||
phantom.terminate()
|
||||
|
||||
def process(self, line, result):
|
||||
args = json.loads(line)
|
||||
try:
|
||||
args = json.loads(line)
|
||||
except ValueError: # phantomjs stderr
|
||||
if 'CoreText' not in line:
|
||||
print line
|
||||
return False
|
||||
event_name = args[0]
|
||||
|
||||
if event_name == 'qunit.done':
|
||||
|
|
|
@ -1,21 +1,24 @@
|
|||
import urllib
|
||||
import urlparse
|
||||
from openerp import sql_db, tools
|
||||
from qunitsuite.suite import QUnitSuite
|
||||
|
||||
class WebSuite(QUnitSuite):
|
||||
def __init__(self):
|
||||
def __init__(self, module):
|
||||
url = urlparse.urlunsplit([
|
||||
'http',
|
||||
'localhost:{port}'.format(port=tools.config['xmlrpc_port']),
|
||||
'/web/tests',
|
||||
'mod=*&source={db}&supadmin={supadmin}&password={password}'.format(
|
||||
db=tools.config['db_name'],
|
||||
supadmin=tools.config['admin_passwd'],
|
||||
password='admin'),
|
||||
urllib.urlencode({
|
||||
'mod': module,
|
||||
'source': tools.config['db_name'],
|
||||
'supadmin': tools.config['admin_passwd'],
|
||||
'password': 'admin',
|
||||
}),
|
||||
''
|
||||
])
|
||||
super(WebSuite, self).__init__(url, 50000)
|
||||
|
||||
def load_tests(loader, standard_tests, _):
|
||||
standard_tests.addTest(WebSuite())
|
||||
standard_tests.addTest(WebSuite('web'))
|
||||
return standard_tests
|
||||
|
|
|
@ -38,11 +38,14 @@
|
|||
{% endif %}
|
||||
</div>
|
||||
|
||||
<hr/>
|
||||
{% if debug %}
|
||||
<input type="hidden" name="debug" value=""/>
|
||||
{% endif %}
|
||||
<input type="submit" value="Continue" class="btn btn-primary pull-right"/>
|
||||
|
||||
<noscript>
|
||||
<hr/>
|
||||
<input type="submit" value="Continue" class="btn btn-primary pull-right"/>
|
||||
</noscript>
|
||||
|
||||
<div class="oe_single_form_footer">
|
||||
<a class="oe_login_manage_db" href="/web/database/manager{% if debug %}?debug{% endif %}">Manage Databases</a> |
|
||||
|
|
|
@ -47,6 +47,10 @@
|
|||
|
||||
<template id="web.login_layout" name="Login Layout">
|
||||
<t t-call="web.layout">
|
||||
<t t-set="head">
|
||||
<link href="/web/static/src/css/base.css" rel="stylesheet"/>
|
||||
<link href="/web/static/lib/bootstrap/css/bootstrap.css" rel="stylesheet"/>
|
||||
</t>
|
||||
<t t-set="body_classname" t-value="'oe_single_form'"/>
|
||||
<div class="oe_single_form_container modal-content">
|
||||
<div class="oe_single_form_logo">
|
||||
|
@ -54,6 +58,14 @@
|
|||
</div>
|
||||
<hr/>
|
||||
<t t-raw="0"/>
|
||||
|
||||
<div class="oe_single_form_footer" t-if="not disable_footer">
|
||||
<t t-if="not disable_database_manager">
|
||||
<a class="oe_login_manage_db" t-attf-href="/web/database/manager{{ '?debug' if debug else '' }}">Manage Databases</a>
|
||||
<span class="oe_footer_seperator"> | </span>
|
||||
</t>
|
||||
<a href="http://www.openerp.com" target="_blank">Powered by <span>OpenERP</span></a>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</template>
|
||||
|
@ -79,22 +91,7 @@
|
|||
|
||||
<template id="web.login" name="Login">
|
||||
<t t-call="web.login_layout">
|
||||
<t t-set="head">
|
||||
<t t-foreach="css" t-as="css_file">
|
||||
<link rel="stylesheet" t-att-href="css_file"/>
|
||||
</t>
|
||||
<t t-foreach="js" t-as="js_file">
|
||||
<script type="text/javascript" t-att-src="js_file"></script>
|
||||
</t>
|
||||
<script type="text/javascript">
|
||||
$(function() {
|
||||
var s = new openerp.init(<t t-raw="modules"/>);
|
||||
var login_form = new openerp.web.LoginForm($('.oe_login_form'));
|
||||
});
|
||||
</script>
|
||||
</t>
|
||||
|
||||
<form class="oe_login_form" role="form" t-attf-action="/web/login{{ '?debug' if debug else '' }}" method="post">
|
||||
<form class="oe_login_form" role="form" t-attf-action="/web/login{{ '?debug' if debug else '' }}" method="post" onsubmit="this.action = this.action + location.hash">
|
||||
|
||||
<t t-call="web.database_select"/>
|
||||
|
||||
|
@ -105,7 +102,7 @@
|
|||
|
||||
<div class="form-group field-password">
|
||||
<label for="password" class="control-label">Password</label>
|
||||
<input type="password" name="password" id="password" class="form-control" required="required"/>
|
||||
<input type="password" name="password" id="password" class="form-control" required="required" t-att-autofocus="'autofocus' if login else None"/>
|
||||
</div>
|
||||
|
||||
<p class="alert alert-danger" t-if="error">
|
||||
|
@ -121,14 +118,6 @@
|
|||
</div>
|
||||
|
||||
</form>
|
||||
<div class="oe_single_form_footer" t-if="not disable_footer">
|
||||
<t t-if="not disable_database_manager">
|
||||
<a class="oe_login_manage_db" t-attf-href="/web/database/manager{{ '?debug' if debug else '' }}">Manage Databases</a>
|
||||
<span class="oe_footer_seperator"> | </span>
|
||||
</t>
|
||||
<a href="http://www.openerp.com" target="_blank">Powered by <span>OpenERP</span></a>
|
||||
</div>
|
||||
|
||||
</t>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ OpenERP Web Calendar view.
|
|||
==========================
|
||||
|
||||
""",
|
||||
'author': 'OpenERP SA, Valentino Lab (Kalysto)',
|
||||
'version': '2.0',
|
||||
'depends': ['web'],
|
||||
'data' : [],
|
||||
|
|
|
@ -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: 2014-02-13 06:10+0000\n"
|
||||
"X-Generator: Launchpad (build 16916)\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-18 06:40+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
|
||||
#. module: web_calendar
|
||||
#. openerp-web
|
||||
|
|
|
@ -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: 2014-02-13 06:10+0000\n"
|
||||
"X-Generator: Launchpad (build 16916)\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-18 06:40+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
|
||||
#. module: web_calendar
|
||||
#. openerp-web
|
||||
|
|
|
@ -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: 2014-02-13 06:10+0000\n"
|
||||
"X-Generator: Launchpad (build 16916)\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-18 06:40+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
|
||||
#. module: web_calendar
|
||||
#. openerp-web
|
||||
|
|
|
@ -9,13 +9,13 @@ msgstr ""
|
|||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2012-12-21 17:06+0000\n"
|
||||
"PO-Revision-Date: 2014-01-30 17:05+0000\n"
|
||||
"Last-Translator: Bosko Stojakovic <bluesoft83@gmail.com>\n"
|
||||
"Last-Translator: Boško Stojaković <bluesoft83@gmail.com>\n"
|
||||
"Language-Team: Bosnian <bs@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
|
||||
"X-Generator: Launchpad (build 16916)\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-18 06:40+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
|
||||
#. module: web_calendar
|
||||
#. openerp-web
|
||||
|
|
|
@ -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: 2014-02-13 06:10+0000\n"
|
||||
"X-Generator: Launchpad (build 16916)\n"
|
||||
"X-Launchpad-Export-Date: 2014-04-18 06:40+0000\n"
|
||||
"X-Generator: Launchpad (build 16985)\n"
|
||||
|
||||
#. module: web_calendar
|
||||
#. openerp-web
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue