diff options
| author | Christophe Simonis <chs@openerp.com> | 2011-11-08 17:36:44 +0100 |
|---|---|---|
| committer | Christophe Simonis <chs@openerp.com> | 2011-11-08 17:36:44 +0100 |
| commit | 2ea47dc3b2aac73256f361c8ca65de7d8cb40e2c (patch) | |
| tree | 48ba730f8783b0dcfae4d1230c9f4aeea7a9ff1a | |
| parent | 1b7125432843d0db93628b04e56065e77d7d14ee (diff) | |
| parent | 61823d98e9177aefa0e6aecd8750ce2bcb192e9a (diff) | |
merge upstream
bzr revid: chs@openerp.com-20111108163644-8mlg48lua376lzgg
121 files changed, 4814 insertions, 1182 deletions
diff --git a/addons/web/__openerp__.py b/addons/web/__openerp__.py index 1cff3c7956b..50febe0de90 100644 --- a/addons/web/__openerp__.py +++ b/addons/web/__openerp__.py @@ -11,6 +11,7 @@ "static/lib/datejs/sugarpak.js", "static/lib/datejs/extras.js", "static/lib/jquery/jquery-1.6.2.js", + "static/lib/jquery.MD5/jquery.md5.js", "static/lib/jquery.form/jquery.form.js", "static/lib/jquery.validate/jquery.validate.js", "static/lib/jquery.ba-bbq/jquery.ba-bbq.js", @@ -43,6 +44,7 @@ "static/src/js/view_list.js", "static/src/js/view_list_editable.js", "static/src/js/view_tree.js", + "static/src/js/view_editor.js" ], 'css' : [ "static/lib/jquery.superfish/css/superfish.css", @@ -52,4 +54,7 @@ "static/src/css/data_export.css", "static/src/css/data_import.css", ], + 'qweb' : [ + "static/src/xml/*.xml", + ], } diff --git a/addons/web/common/openerplib/main.py b/addons/web/common/openerplib/main.py index 5cae9ce4636..773ea020d52 100644 --- a/addons/web/common/openerplib/main.py +++ b/addons/web/common/openerplib/main.py @@ -129,6 +129,18 @@ class XmlRPCConnector(Connector): # TODO should try except and wrap exception into LibException return getattr(service, method)(*args) +class XmlRPCSConnector(XmlRPCConnector): + """ + A type of connector that uses the secured XMLRPC protocol. + """ + PROTOCOL = 'xmlrpcs' + + __logger = _getChildLogger(_logger, 'connector.xmlrpcs') + + def __init__(self, hostname, port=8071): + super(XmlRPCSConnector, self).__init__(hostname, port) + self.url = 'https://%s:%d/xmlrpc' % (self.hostname, self.port) + class NetRPC_Exception(Exception): """ Exception for NetRPC errors. @@ -438,6 +450,7 @@ class Model(object): :return: A list of dictionaries containing all the specified fields. """ record_ids = self.search(domain or [], offset, limit or False, order or False, context or {}) + if not record_ids: return [] records = self.read(record_ids, fields or [], context or {}) return records @@ -450,15 +463,17 @@ def get_connector(hostname=None, protocol="xmlrpc", port="auto"): :param port: The number of the port. Defaults to auto. """ if port == 'auto': - port = 8069 if protocol=="xmlrpc" else 8070 + port = 8069 if protocol=="xmlrpc" else (8070 if protocol == "netrpc" else 8071) if protocol == "xmlrpc": return XmlRPCConnector(hostname, port) + elif protocol == "xmlrpcs": + return XmlRPCSConnector(hostname, port) elif protocol == "netrpc": return NetRPCConnector(hostname, port) elif protocol == "local": return LocalConnector() else: - raise ValueError("You must choose xmlrpc or netrpc or local") + raise ValueError("You must choose xmlrpc(s), netrpc or local") def get_connection(hostname=None, protocol="xmlrpc", port='auto', database=None, login=None, password=None, user_id=None): diff --git a/addons/web/controllers/main.py b/addons/web/controllers/main.py index 8120141b4f6..74285b1f444 100644 --- a/addons/web/controllers/main.py +++ b/addons/web/controllers/main.py @@ -24,19 +24,51 @@ openerpweb = web.common.http # OpenERP Web web Controllers #---------------------------------------------------------- -def concat_files(file_list): - """ Concatenate file content + +def concat_xml(file_list): + """Concatenate xml files return (concat,timestamp) concat: concatenation of file content timestamp: max(os.path.getmtime of file_list) """ + root = None + files_timestamp = 0 + for fname in file_list: + ftime = os.path.getmtime(fname) + if ftime > files_timestamp: + files_timestamp = ftime + + xml = ElementTree.parse(fname).getroot() + + if root is None: + root = ElementTree.Element(xml.tag) + #elif root.tag != xml.tag: + # raise ValueError("Root tags missmatch: %r != %r" % (root.tag, xml.tag)) + + for child in xml.getchildren(): + root.append(child) + return ElementTree.tostring(root, 'utf-8'), files_timestamp + + +def concat_files(file_list, reader=None): + """ Concatenate file content + return (concat,timestamp) + concat: concatenation of file content, read by `reader` + timestamp: max(os.path.getmtime of file_list) + """ + if reader is None: + def reader(f): + with open(f) as fp: + return fp.read() + files_content = [] files_timestamp = 0 for fname in file_list: ftime = os.path.getmtime(fname) if ftime > files_timestamp: files_timestamp = ftime - files_content.append(open(fname).read()) + + files_content.append(reader(fname)) files_concat = "".join(files_content) return files_concat,files_timestamp @@ -98,10 +130,42 @@ class WebClient(openerpweb.Controller): def jslist(self, req, mods=None): return self.manifest_list(req, mods, 'js') + @openerpweb.jsonrequest + def qweblist(self, req, mods=None): + return self.manifest_list(req, mods, 'qweb') + @openerpweb.httprequest def css(self, req, mods=None): - files = [f[0] for f in self.manifest_glob(req, mods, 'css')] - content,timestamp = concat_files(files) + + files = list(self.manifest_glob(req, mods, 'css')) + file_map = dict(files) + + rx_import = re.compile(r"""@import\s+('|")(?!'|"|/|https?://)""", re.U) + rx_url = re.compile(r"""url\s*\(\s*('|"|)(?!'|"|/|https?://)""", re.U) + + + def reader(f): + """read the a css file and absolutify all relative uris""" + with open(f) as fp: + data = fp.read() + + web_path = file_map[f] + web_dir = os.path.dirname(web_path) + + data = re.sub( + rx_import, + r"""@import \1%s/""" % (web_dir,), + data, + ) + + data = re.sub( + rx_url, + r"""url(\1%s/""" % (web_dir,), + data, + ) + return data + + content,timestamp = concat_files((f[0] for f in files), reader) # TODO use timestamp to set Last mofified date and E-tag return req.make_response(content, [('Content-Type', 'text/css')]) @@ -113,6 +177,14 @@ class WebClient(openerpweb.Controller): return req.make_response(content, [('Content-Type', 'application/javascript')]) @openerpweb.httprequest + def qweb(self, req, mods=None): + files = [f[0] for f in self.manifest_glob(req, mods, 'qweb')] + content,timestamp = concat_xml(files) + # TODO use timestamp to set Last mofified date and E-tag + return req.make_response(content, [('Content-Type', 'text/xml')]) + + + @openerpweb.httprequest def home(self, req, s_action=None, **kw): js = "\n ".join('<script type="text/javascript" src="%s"></script>'%i for i in self.manifest_list(req, None, 'js')) css = "\n ".join('<link rel="stylesheet" href="%s">'%i for i in self.manifest_list(req, None, 'css')) @@ -451,7 +523,7 @@ def clean_action(req, action, do_not_eval=False): # values come from the server, we can just eval them if isinstance(action.get('context'), basestring): action['context'] = eval( action['context'], eval_ctx ) or {} - + if isinstance(action.get('domain'), basestring): action['domain'] = eval( action['domain'], eval_ctx ) or [] else: @@ -1412,7 +1484,7 @@ class Import(View): return fields @openerpweb.httprequest - def detect_data(self, req, csvfile, csvsep, csvdel, csvcode, jsonp): + def detect_data(self, req, csvfile, csvsep=',', csvdel='"', csvcode='utf-8', jsonp='callback'): try: data = list(csv.reader( csvfile, quotechar=str(csvdel), delimiter=str(csvsep))) diff --git a/addons/web/po/ar.po b/addons/web/po/ar.po new file mode 100644 index 00000000000..0aac2c8aed2 --- /dev/null +++ b/addons/web/po/ar.po @@ -0,0 +1,699 @@ +# Arabic translation for openerp-web +# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011 +# This file is distributed under the same license as the openerp-web package. +# FIRST AUTHOR <EMAIL@ADDRESS>, 2011. +# +msgid "" +msgstr "" +"Project-Id-Version: openerp-web\n" +"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n" +"POT-Creation-Date: 2011-10-07 10:38+0200\n" +"PO-Revision-Date: 2011-11-08 05:44+0000\n" +"Last-Translator: Ahmad Khayyat <Unknown>\n" +"Language-Team: Arabic <ar@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: 2011-11-08 06:12+0000\n" +"X-Generator: Launchpad (build 14231)\n" + +#: addons/web/static/src/js/view_form.js:355 +msgid "" +"Warning, the record has been modified, your changes will be discarded." +msgstr "تحذير، تم تحرير السجل، تعديلاتك سيتم تجاهلها" + +#: addons/web/static/src/js/view_form.js:1659 +msgid "<em> Search More...</em>" +msgstr "<em> مزيداً من البحث...</em>" + +#: addons/web/static/src/js/view_form.js:1672 +#, python-format +msgid "<em> Create \"<strong>%s</strong>\"</em>" +msgstr "<em> إنشاء \"<strong>%s</strong>\"</em>" + +#: addons/web/static/src/js/view_form.js:1678 +msgid "<em> Create and Edit...</em>" +msgstr "<em> إنشاء و تحرير...</em>" + +#: addons/web/static/src/js/views.js:568 +msgid "You must choose at least one record." +msgstr "عليك إختيار سجل واحد علي الأقل." + +#: addons/web/static/src/js/views.js:569 +msgid "Warning" +msgstr "تحذير" + +#: addons/web/static/src/js/views.js:609 +msgid "Translations" +msgstr "ترجمات" + +#: addons/web/static/src/js/views.js:614 addons/web/static/src/xml/base.xml:0 +msgid "Save" +msgstr "حفظ" + +#: addons/web/static/src/js/views.js:615 +msgid "Close" +msgstr "إغلاق" + +#: addons/web/static/src/xml/base.xml:0 +msgid "x" +msgstr "x" + +#: addons/web/static/src/xml/base.xml:0 +msgid "#{title}" +msgstr "#{لقب}" + +#: addons/web/static/src/xml/base.xml:0 +msgid "#{text}" +msgstr "#{text}" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Powered by" +msgstr "مدعوم من kifcaliph و" + +#: addons/web/static/src/xml/base.xml:0 +msgid "openerp.com" +msgstr "openerp.com" + +#: addons/web/static/src/xml/base.xml:0 +msgid "." +msgstr "." + +#: addons/web/static/src/xml/base.xml:0 +msgid "Loading..." +msgstr "جاري التحميل..." + +#: addons/web/static/src/xml/base.xml:0 +msgid "Create" +msgstr "إنشاء" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Drop" +msgstr "إزالة" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Backup" +msgstr "نسخة إحتياطية" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Restore" +msgstr "استرجاع" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Password" +msgstr "كلمة المرور" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Back to Login" +msgstr "العودة للدخول" + +#: addons/web/static/src/xml/base.xml:0 +msgid "CREATE DATABASE" +msgstr "إنشاء قاعدة بيانات" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Master password:" +msgstr "كلمة المرور الرئيسية:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "New database name:" +msgstr "اسم قاعدة البيانات الجديدة:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Load Demonstration data:" +msgstr "تحميل البيانات الوهمية:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Default language:" +msgstr "اللغة الافتراضية:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Admin password:" +msgstr "كلمة مرور المشرف العام:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Confirm password:" +msgstr "تأكيد كلمة المرور:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "DROP DATABASE" +msgstr "إسقاط قاعدة البيانات" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Database:" +msgstr "قاعدة البيانات:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Master Password:" +msgstr "كلمة المرور الرئيسية:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "BACKUP DATABASE" +msgstr "نسخ إحتياطي لقاعدة البيانات" + +#: addons/web/static/src/xml/base.xml:0 +msgid "RESTORE DATABASE" +msgstr "إسترجاع قاعدة بيانات" + +#: addons/web/static/src/xml/base.xml:0 +msgid "File:" +msgstr "ملف:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "CHANGE MASTER PASSWORD" +msgstr "تغيير كلمة المرور الرئيسية" + +#: addons/web/static/src/xml/base.xml:0 +msgid "New master password:" +msgstr "كلمة مرور رئيسية جديدة:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Confirm new master password:" +msgstr "تأكيد كلمة المرور الرئيسية الجديدة:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "User:" +msgstr "مستخدم:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Password:" +msgstr "كلمة المرور:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Database" +msgstr "قاعدة بيانات" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Login" +msgstr "تسجيل الدخول" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Bad username or password" +msgstr "اسم مستخدم او كلمة مرور خاطئة" + +#: addons/web/static/src/xml/base.xml:0 +msgid "" +"We think that daily job activities can be more intuitive, efficient, " +"automated, .. and even fun." +msgstr "نؤمن بأن نشاط العمل اليومي يمكن أن يكون بديهي، فعال، سريع و ممتع" + +#: addons/web/static/src/xml/base.xml:0 +msgid "OpenERP's vision to be:" +msgstr "رؤي برنامج OpenERP هي:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Full featured" +msgstr "كامل الأوصاف" + +#: addons/web/static/src/xml/base.xml:0 +msgid "" +"Today's enterprise challenges are multiple. We provide one module for each " +"need." +msgstr "" +"تتعدد تحديات المنشآت اليوم، و لذلك نوفر العديد من الوحدات البرمجية لكل " +"احتياج." + +#: addons/web/static/src/xml/base.xml:0 +msgid "Open Source" +msgstr "مفتوح المصدر" + +#: addons/web/static/src/xml/base.xml:0 +msgid "" +"To Build a great product, we rely on the knowledge of thousands of " +"contributors." +msgstr "لبناء منتج قوي، نحن نعتمد علي معرفة ألاف المساهمين." + +#: addons/web/static/src/xml/base.xml:0 +msgid "User Friendly" +msgstr "سهل الإستخدام" + +#: addons/web/static/src/xml/base.xml:0 +msgid "" +"In order to be productive, people need clean and easy to use interface." +msgstr "تتمثل الإنتاجية في حاجة الأفراد إلي إستخدام واجهة سهلة و لائقة." + +#: addons/web/static/src/xml/base.xml:0 +msgid "(" +msgstr "(" + +#: addons/web/static/src/xml/base.xml:0 +msgid ")" +msgstr ")" + +#: addons/web/static/src/xml/base.xml:0 +msgid "LOGOUT" +msgstr "تسجيل الخروج" + +#: addons/web/static/src/xml/base.xml:0 +msgid "«" +msgstr "«" + +#: addons/web/static/src/xml/base.xml:0 +msgid "»" +msgstr "»" + +#: addons/web/static/src/xml/base.xml:0 +msgid "oe_secondary_menu_item" +msgstr "oe_secondary_menu_item" + +#: addons/web/static/src/xml/base.xml:0 +msgid "oe_secondary_submenu_item" +msgstr "oe_secondary_submenu_item" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Hide this tip" +msgstr "إخفاء هذه الملحوظة" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Disable all tips" +msgstr "تعطيل جميع الإرشادات" + +#: addons/web/static/src/xml/base.xml:0 +msgid "View#" +msgstr "View#" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Fields" +msgstr "حقول" + +#: addons/web/static/src/xml/base.xml:0 +msgid "View labels" +msgstr "عرض التسميات" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Sidebar Relates" +msgstr "روابط الشريط الجانبي" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Field" +msgstr "حقل" + +#: addons/web/static/src/xml/base.xml:0 +msgid ":" +msgstr ":" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Translate view" +msgstr "ترجمة العرض" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Translate sidebar" +msgstr "ترجمة الشريط الجانبي" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Delete" +msgstr "حذف" + +#: addons/web/static/src/xml/base.xml:0 +msgid "First" +msgstr "الأول" + +#: addons/web/static/src/xml/base.xml:0 +msgid "<" +msgstr "<" + +#: addons/web/static/src/xml/base.xml:0 +msgid ">" +msgstr ">" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Last" +msgstr "الأخير" + +#: addons/web/static/src/xml/base.xml:0 +msgid "♻" +msgstr "♻" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Save & Edit" +msgstr "حفظ و تحرير" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Create & Edit" +msgstr "إنشاء و تحرير" + +#: addons/web/static/src/xml/base.xml:0 +msgid "New" +msgstr "جديد" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Duplicate" +msgstr "تكرار" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Readonly/Editable" +msgstr "للقراءة فقط/قابل للتحرير" + +#: addons/web/static/src/xml/base.xml:0 +msgid "<<" +msgstr ">>" + +#: addons/web/static/src/xml/base.xml:0 +msgid "0" +msgstr "0" + +#: addons/web/static/src/xml/base.xml:0 +msgid "/" +msgstr "/" + +#: addons/web/static/src/xml/base.xml:0 +msgid ">>" +msgstr ">>" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Add" +msgstr "اضافة" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Unhandled widget" +msgstr "أداة غير معالجة" + +#: addons/web/static/src/xml/base.xml:0 +msgid "?" +msgstr "؟" + +#: addons/web/static/src/xml/base.xml:0 +msgid "#" +msgstr "#" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Done" +msgstr "تم" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Open..." +msgstr "فتح..." + +#: addons/web/static/src/xml/base.xml:0 +msgid "Create..." +msgstr "إنشاء..." + +#: addons/web/static/src/xml/base.xml:0 +msgid "Search..." +msgstr "بحث..." + +#: addons/web/static/src/xml/base.xml:0 +msgid "..." +msgstr "..." + +#: addons/web/static/src/xml/base.xml:0 +msgid "Uploading ..." +msgstr "جاري التحميل..." + +#: addons/web/static/src/xml/base.xml:0 +msgid "Select" +msgstr "حدّد" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Save As" +msgstr "حفظ كـ" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Clear" +msgstr "إفراغ" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Advanced Filter" +msgstr "مرشحات متقدمة" + +#: addons/web/static/src/xml/base.xml:0 +msgid "-- Filters --" +msgstr "-- مرشحات --" + +#: addons/web/static/src/xml/base.xml:0 +msgid "-- Actions --" +msgstr "-- إجراءات --" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Save Filter" +msgstr "حفظ المرشح" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Manage Filters" +msgstr "إدارة المرشحات" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Filter Name:" +msgstr "اسم المرشح:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "(Any existing filter with the same name will be replaced)" +msgstr "(لاحظ أن أي مرشح بنفس الاسم سيتم إستبداله)" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Any of the following conditions must match" +msgstr "يجب تطابق أي من الشروط التالية" + +#: addons/web/static/src/xml/base.xml:0 +msgid "All the following conditions must match" +msgstr "يجب تطابق كل الشروط التالية" + +#: addons/web/static/src/xml/base.xml:0 +msgid "None of the following conditions must match" +msgstr "لا يجب تطابق أي من الشروط التالية" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Add condition" +msgstr "إضافة شرط" + +#: addons/web/static/src/xml/base.xml:0 +msgid "and" +msgstr "و" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Cancel" +msgstr "إلغاء" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Save & New" +msgstr "حفظ و جديد" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Save & Close" +msgstr "حفظ و إغلاق" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Export" +msgstr "تصدير" + +#: addons/web/static/src/xml/base.xml:0 +msgid "" +"This wizard will export all data that matches the current search criteria to " +"a CSV file.\n" +" You can export all data or only the fields that can be " +"reimported after modification." +msgstr "" +"هذا المعالج سيقوم بتصدير كافة البيانات التي تطابق شروط البحث الحالية لملف " +"CSV.\n" +" يمكنك تصدير كل البيانات أو الحقول التي يمكن إستيرادها بعد " +"التعديل." + +#: addons/web/static/src/xml/base.xml:0 +msgid "Export Type:" +msgstr "نوع التصدير:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Import Compatible Export" +msgstr "إستيراد بيانات ملائمة للتصدير" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Export all Data" +msgstr "تصدير جميع البيانات" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Export Formats" +msgstr "تنسيقات التصدير" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Available fields" +msgstr "الحقول المتوفرة" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Fields to export" +msgstr "حقول للتصدير" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Save fields list" +msgstr "حفظ قائمة الحقول" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Remove" +msgstr "إزالة" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Remove All" +msgstr "إزالة الكل" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Name" +msgstr "اسم" + +#: addons/web/static/src/xml/base.xml:0 +msgid " " +msgstr " " + +#: addons/web/static/src/xml/base.xml:0 +msgid "Save as:" +msgstr "حفظ باسم:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Ok" +msgstr "تم" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Saved exports:" +msgstr "مُصدرة محفوظة:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Old Password:" +msgstr "كلمة المرور القديمة:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "New Password:" +msgstr "كلمة المرور الجديدة:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Confirm Password:" +msgstr "تأكيد كلمة المرور:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Import" +msgstr "استيراد" + +#: addons/web/static/src/xml/base.xml:0 +msgid "1. Import a .CSV file" +msgstr "إستيراد ملف .CSV" + +#: addons/web/static/src/xml/base.xml:0 +msgid "" +"Select a .CSV file to import. If you need a sample of file to import,\n" +" you should use the export tool with the \"Import Compatible\" option." +msgstr "" +"اختر ملف .CSV للإستيراد. إذا كنت بحاجة إلى عينة ملف للاستيراد،\n" +" يجب عليك إستخدام أداة تصدير مع الخيار \" Compatible\" option." + +#: addons/web/static/src/xml/base.xml:0 +msgid "CSV File:" +msgstr "ملف CSV :" + +#: addons/web/static/src/xml/base.xml:0 +msgid "2. Check your file format" +msgstr "تأكد من إمتداد الملف" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Import Options" +msgstr "خيارات الاستيراد" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Does your file have titles?" +msgstr "هل لملفك عناوين؟" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Separator:" +msgstr "فاصل :" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Delimiter:" +msgstr "محدد:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Encoding:" +msgstr "ترميز:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "UTF-8" +msgstr "UTF-8" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Latin 1" +msgstr "Latin 1" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Lines to skip" +msgstr "خطوط للتجاهل" + +#: addons/web/static/src/xml/base.xml:0 +msgid "The import failed due to:" +msgstr "فشلت عملية الإستيراد للأسباب التالية:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Here is a preview of the file we could not import:" +msgstr "هذه معاينة لملف لم يتمكن من إستيراده:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "OpenERP Web" +msgstr "OpenERP عبر الإنترنت" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Version" +msgstr "الإصدار" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Copyright © 2011-TODAY OpenERP SA. All Rights Reserved." +msgstr "جميع حقوق النشر محفوظة لـ © 2011-TODAY OpenERP SA." + +#: addons/web/static/src/xml/base.xml:0 +msgid "OpenERP is a trademark of the" +msgstr "OpenERP هي علامة تجارية لـ" + +#: addons/web/static/src/xml/base.xml:0 +msgid "OpenERP SA Company" +msgstr "شركة OpenERP SA" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Licenced under the terms of" +msgstr "النظام مرخص بشروط" + +#: addons/web/static/src/xml/base.xml:0 +msgid "GNU Affero General Public License" +msgstr "GNU Affero General Public License" + +#: addons/web/static/src/xml/base.xml:0 +msgid "About OpenERP" +msgstr "عن OpenERP" + +#: addons/web/static/src/xml/base.xml:0 +msgid "OpenERP" +msgstr "OpenERP" + +#: addons/web/static/src/xml/base.xml:0 +msgid "" +"is a free enterprise-scale software system that is designed to boost\n" +" productivity and profit through data integration. It connects, " +"improves and\n" +" manages business processes in areas such as sales, finance, " +"supply chain,\n" +" project management, production, services, CRM, etc..." +msgstr "" +"هو نظام حر يناسب المؤسسات و الشركات و تم تصميمه لتعزيز\n" +" الإنتاجية و الربح من خلال تكامل البيانات. فيمكنك من ربط، و " +"تحسين، و\n" +" إدارة العمليات التجارية في إدارات مثل المبيعات، المحاسبة " +"المالية، المخازن،\n" +" إدارة المشروعات، الإنتاج و العمليات الصناعية، و القطاع الخدمي، , " +"إدارة علاقات العملاء..." + +#: addons/web/static/src/xml/base.xml:0 +msgid "" +"The system is platform-independent, and can be installed on Windows, Mac OS " +"X,\n" +" and various Linux and other Unix-based distributions. Its " +"architecture enables\n" +" new functionality to be rapidly created, modifications to be " +"made to a\n" +" production system and migration to a new version to be " +"straightforward." +msgstr "" +"يعمل البرنامج مع العديد من الأنظمة مثل Windows، و Mac OS X، و\n" +" معظم أنظمة لينكس بالإضافة إلي اليونكس. فلقد تم تصميمه ليتيح " +"إمكانية\n" +" إضافة وظائف أخري له بسهولة، و برمجته و تعديله بسرعه ليلائم " +"الواقع العملي\n" +" كما أنه يتيح سهولة نقل البيانات من إصدار إلي إصدار." + +#: addons/web/static/src/xml/base.xml:0 +msgid "" +"Depending on your needs, OpenERP is available through a web or application " +"client." +msgstr "" +"حسب إحتياجاتك، نظام OpenERP متاح من خلال تطبيق الويب أو البرنامج المحلي." diff --git a/addons/web/po/da.po b/addons/web/po/da.po index cefd844d49a..c0931065d1e 100644 --- a/addons/web/po/da.po +++ b/addons/web/po/da.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-10-12 04:44+0000\n" -"X-Generator: Launchpad (build 14124)\n" +"X-Launchpad-Export-Date: 2011-11-01 05:09+0000\n" +"X-Generator: Launchpad (build 14197)\n" #: addons/web/static/src/js/view_form.js:355 msgid "" diff --git a/addons/web/po/de.po b/addons/web/po/de.po index 027f34f9866..0a26630321f 100644 --- a/addons/web/po/de.po +++ b/addons/web/po/de.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-10-11 05:42+0000\n" -"X-Generator: Launchpad (build 14123)\n" +"X-Launchpad-Export-Date: 2011-11-01 05:09+0000\n" +"X-Generator: Launchpad (build 14197)\n" #: addons/web/static/src/js/view_form.js:355 msgid "" diff --git a/addons/web/po/es.po b/addons/web/po/es.po index 508b4e62245..9bd7071871b 100644 --- a/addons/web/po/es.po +++ b/addons/web/po/es.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-10-20 04:48+0000\n" -"X-Generator: Launchpad (build 14165)\n" +"X-Launchpad-Export-Date: 2011-11-01 05:09+0000\n" +"X-Generator: Launchpad (build 14197)\n" #: addons/web/static/src/js/view_form.js:355 msgid "" diff --git a/addons/web/po/es_EC.po b/addons/web/po/es_EC.po index eb2283f6fe5..588408ba979 100644 --- a/addons/web/po/es_EC.po +++ b/addons/web/po/es_EC.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-10-08 05:29+0000\n" -"X-Generator: Launchpad (build 14110)\n" +"X-Launchpad-Export-Date: 2011-11-01 05:09+0000\n" +"X-Generator: Launchpad (build 14197)\n" #: addons/web/static/src/js/view_form.js:355 msgid "" diff --git a/addons/web/po/et.po b/addons/web/po/et.po index 75269bf5cda..6b6da84f3a5 100644 --- a/addons/web/po/et.po +++ b/addons/web/po/et.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-10-11 05:42+0000\n" -"X-Generator: Launchpad (build 14123)\n" +"X-Launchpad-Export-Date: 2011-11-01 05:09+0000\n" +"X-Generator: Launchpad (build 14197)\n" #: addons/web/static/src/js/view_form.js:355 msgid "" diff --git a/addons/web/po/fr.po b/addons/web/po/fr.po index a4287a31030..df35344c558 100644 --- a/addons/web/po/fr.po +++ b/addons/web/po/fr.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-10-24 05:18+0000\n" -"X-Generator: Launchpad (build 14185)\n" +"X-Launchpad-Export-Date: 2011-11-01 05:09+0000\n" +"X-Generator: Launchpad (build 14197)\n" #: addons/web/static/src/js/view_form.js:355 msgid "" diff --git a/addons/web/po/gl.po b/addons/web/po/gl.po index b43664b9bee..34b2d50085f 100644 --- a/addons/web/po/gl.po +++ b/addons/web/po/gl.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-10-20 04:48+0000\n" -"X-Generator: Launchpad (build 14165)\n" +"X-Launchpad-Export-Date: 2011-11-01 05:09+0000\n" +"X-Generator: Launchpad (build 14197)\n" #: addons/web/static/src/js/view_form.js:355 msgid "" diff --git a/addons/web/po/it.po b/addons/web/po/it.po index fc53244533b..647030fd4ea 100644 --- a/addons/web/po/it.po +++ b/addons/web/po/it.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-10-09 05:22+0000\n" -"X-Generator: Launchpad (build 14110)\n" +"X-Launchpad-Export-Date: 2011-11-01 05:09+0000\n" +"X-Generator: Launchpad (build 14197)\n" #: addons/web/static/src/js/view_form.js:355 msgid "" diff --git a/addons/web/po/nl_BE.po b/addons/web/po/nl_BE.po index 2a2dccb1712..3d649b59b9d 100644 --- a/addons/web/po/nl_BE.po +++ b/addons/web/po/nl_BE.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-10-08 05:29+0000\n" -"X-Generator: Launchpad (build 14110)\n" +"X-Launchpad-Export-Date: 2011-11-01 05:09+0000\n" +"X-Generator: Launchpad (build 14197)\n" #: addons/web/static/src/js/view_form.js:355 msgid "" diff --git a/addons/web/po/pl.po b/addons/web/po/pl.po new file mode 100644 index 00000000000..fde2196a73e --- /dev/null +++ b/addons/web/po/pl.po @@ -0,0 +1,687 @@ +# Polish translation for openerp-web +# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011 +# This file is distributed under the same license as the openerp-web package. +# FIRST AUTHOR <EMAIL@ADDRESS>, 2011. +# +msgid "" +msgstr "" +"Project-Id-Version: openerp-web\n" +"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n" +"POT-Creation-Date: 2011-10-07 10:38+0200\n" +"PO-Revision-Date: 2011-11-04 16:44+0000\n" +"Last-Translator: Grzegorz Grzelak (OpenGLOBE.pl) <grzegorz@openglobe.pl>\n" +"Language-Team: Polish <pl@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: 2011-11-05 06:04+0000\n" +"X-Generator: Launchpad (build 14231)\n" + +#: addons/web/static/src/js/view_form.js:355 +msgid "" +"Warning, the record has been modified, your changes will be discarded." +msgstr "Uwaga, rekord został zmodyfikowany, twoje zmiany zostaną odrzucone." + +#: addons/web/static/src/js/view_form.js:1659 +msgid "<em> Search More...</em>" +msgstr "<em> Szukaj dalej...</em>" + +#: addons/web/static/src/js/view_form.js:1672 +#, python-format +msgid "<em> Create \"<strong>%s</strong>\"</em>" +msgstr "<em> Utwórz \"<strong>%s</strong>\"</em>" + +#: addons/web/static/src/js/view_form.js:1678 +msgid "<em> Create and Edit...</em>" +msgstr "<em> Utwórz i edytuj...</em>" + +#: addons/web/static/src/js/views.js:568 +msgid "You must choose at least one record." +msgstr "Musisz wybrac co najmniej jeden rekord." + +#: addons/web/static/src/js/views.js:569 +msgid "Warning" +msgstr "Ostrzeżenie" + +#: addons/web/static/src/js/views.js:609 +msgid "Translations" +msgstr "Tłumaczenia" + +#: addons/web/static/src/js/views.js:614 addons/web/static/src/xml/base.xml:0 +msgid "Save" +msgstr "Zapisz" + +#: addons/web/static/src/js/views.js:615 +msgid "Close" +msgstr "Zamknij" + +#: addons/web/static/src/xml/base.xml:0 +msgid "x" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "#{title}" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "#{text}" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Powered by" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "openerp.com" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "." +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Loading..." +msgstr "Wczytywanie..." + +#: addons/web/static/src/xml/base.xml:0 +msgid "Create" +msgstr "Utwórz" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Drop" +msgstr "Usuń bazę danych" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Backup" +msgstr "Kopia zapasowa bazy danych" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Restore" +msgstr "Odtwórz bazę danych" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Password" +msgstr "Hasło" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Back to Login" +msgstr "Wróć do logowania" + +#: addons/web/static/src/xml/base.xml:0 +msgid "CREATE DATABASE" +msgstr "UTWÓRZ BAZĘ DANYCH" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Master password:" +msgstr "Hasło madrzędne:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "New database name:" +msgstr "Nazwa nowej bazy danych:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Load Demonstration data:" +msgstr "Wczytaj dane demonstracyjne:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Default language:" +msgstr "Domyślny język:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Admin password:" +msgstr "Hasło admina:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Confirm password:" +msgstr "Potwierdź hasło:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "DROP DATABASE" +msgstr "USUŃ BAZĘ DANYCH" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Database:" +msgstr "Baza danych:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Master Password:" +msgstr "Hasło nadrzędne:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "BACKUP DATABASE" +msgstr "ZAPISZ BAZĘ" + +#: addons/web/static/src/xml/base.xml:0 +msgid "RESTORE DATABASE" +msgstr "ODTWÓRZ BAZĘ" + +#: addons/web/static/src/xml/base.xml:0 +msgid "File:" +msgstr "Plik:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "CHANGE MASTER PASSWORD" +msgstr "ZMIEŃ HASŁO NADRZĘDNE" + +#: addons/web/static/src/xml/base.xml:0 +msgid "New master password:" +msgstr "Nowe hasło nadrzędne:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Confirm new master password:" +msgstr "Potwierdź nowe hasło nadrzędne:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "User:" +msgstr "Użytkownik:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Password:" +msgstr "Hasło:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Database" +msgstr "Baza danych" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Login" +msgstr "Login" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Bad username or password" +msgstr "Niepoprawna nazwa użytkownika lub hasło" + +#: addons/web/static/src/xml/base.xml:0 +msgid "" +"We think that daily job activities can be more intuitive, efficient, " +"automated, .. and even fun." +msgstr "" +"Sądzimy, że codzienne zadania mogą być bardziej intuicyjne, efektywne, " +"zautomatyzowan, ... a nawet przyjemne." + +#: addons/web/static/src/xml/base.xml:0 +msgid "OpenERP's vision to be:" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Full featured" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "" +"Today's enterprise challenges are multiple. We provide one module for each " +"need." +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Open Source" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "" +"To Build a great product, we rely on the knowledge of thousands of " +"contributors." +msgstr "" +"Przy budowie wielkiego produktu polegamy na wiedzy tysięcy społeczników." + +#: addons/web/static/src/xml/base.xml:0 +msgid "User Friendly" +msgstr "Przyjazne dla użytkownika" + +#: addons/web/static/src/xml/base.xml:0 +msgid "" +"In order to be productive, people need clean and easy to use interface." +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "(" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid ")" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "LOGOUT" +msgstr "WYLOGUJ" + +#: addons/web/static/src/xml/base.xml:0 +msgid "«" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "»" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "oe_secondary_menu_item" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "oe_secondary_submenu_item" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Hide this tip" +msgstr "Ukryj tę wskazówkę" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Disable all tips" +msgstr "Wyłącz wszystkie wskazówki" + +#: addons/web/static/src/xml/base.xml:0 +msgid "View#" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Fields" +msgstr "Pola" + +#: addons/web/static/src/xml/base.xml:0 +msgid "View labels" +msgstr "Pokaż etykiety" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Sidebar Relates" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Field" +msgstr "Pole" + +#: addons/web/static/src/xml/base.xml:0 +msgid ":" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Translate view" +msgstr "Przetłumacz widok" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Translate sidebar" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Delete" +msgstr "Usuń" + +#: addons/web/static/src/xml/base.xml:0 +msgid "First" +msgstr "Pierwsze" + +#: addons/web/static/src/xml/base.xml:0 +msgid "<" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid ">" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Last" +msgstr "Ostatnie" + +#: addons/web/static/src/xml/base.xml:0 +msgid "♻" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Save & Edit" +msgstr "Zapisz i edytuj" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Create & Edit" +msgstr "Utwórz i edytuj" + +#: addons/web/static/src/xml/base.xml:0 +msgid "New" +msgstr "Nowy" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Duplicate" +msgstr "Duplikuj" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Readonly/Editable" +msgstr "Tylko odczyt/Edytowalne" + +#: addons/web/static/src/xml/base.xml:0 +msgid "<<" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "0" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "/" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid ">>" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Add" +msgstr "Dodaj" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Unhandled widget" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "?" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "#" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Done" +msgstr "Wykonano" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Open..." +msgstr "Otwórz..." + +#: addons/web/static/src/xml/base.xml:0 +msgid "Create..." +msgstr "Utwórz..." + +#: addons/web/static/src/xml/base.xml:0 +msgid "Search..." +msgstr "Wyszukaj..." + +#: addons/web/static/src/xml/base.xml:0 +msgid "..." +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Uploading ..." +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Select" +msgstr "Wybierz" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Save As" +msgstr "Zapisz jako" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Clear" +msgstr "Wyczyść" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Advanced Filter" +msgstr "Zaawansowany filtr" + +#: addons/web/static/src/xml/base.xml:0 +msgid "-- Filters --" +msgstr "-- Filtry --" + +#: addons/web/static/src/xml/base.xml:0 +msgid "-- Actions --" +msgstr "-- Akcje --" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Save Filter" +msgstr "Zapisz filtr" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Manage Filters" +msgstr "Zarządzaj filtrami" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Filter Name:" +msgstr "Nazwa filtra:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "(Any existing filter with the same name will be replaced)" +msgstr "(Każdy filtr o tej samej nazwie zostanie zamazany)" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Any of the following conditions must match" +msgstr "Jeden z tych warunków musi być spełniony" + +#: addons/web/static/src/xml/base.xml:0 +msgid "All the following conditions must match" +msgstr "Wszystkie warunki muszą być spełnione" + +#: addons/web/static/src/xml/base.xml:0 +msgid "None of the following conditions must match" +msgstr "Żadeń z tych warunków nie może być spełniony" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Add condition" +msgstr "Dodaj warunek" + +#: addons/web/static/src/xml/base.xml:0 +msgid "and" +msgstr "i" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Cancel" +msgstr "Anuluj" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Save & New" +msgstr "Zapisz i nowy" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Save & Close" +msgstr "Zapisz i zamknij" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Export" +msgstr "Eksportuj" + +#: addons/web/static/src/xml/base.xml:0 +msgid "" +"This wizard will export all data that matches the current search criteria to " +"a CSV file.\n" +" You can export all data or only the fields that can be " +"reimported after modification." +msgstr "" +"Ten kreator wyeksportuje wszystkie dane, które spełniają bieżące kryteria " +"wyszukiwania, do pliku CSV.\n" +" Możesz eksportować wszystkie dane lub tylko pola, które mają być " +"importowane po zmianie." + +#: addons/web/static/src/xml/base.xml:0 +msgid "Export Type:" +msgstr "Typ eksportu:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Import Compatible Export" +msgstr "Eksport kompatybilny z importem" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Export all Data" +msgstr "Eksportuj wszystkie dane" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Export Formats" +msgstr "Format eksportu" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Available fields" +msgstr "Dostępne pola" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Fields to export" +msgstr "Pola do eksportu" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Save fields list" +msgstr "Zapisz listę pól" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Remove" +msgstr "Usuń" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Remove All" +msgstr "Usuń wszystko" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Name" +msgstr "Nazwa" + +#: addons/web/static/src/xml/base.xml:0 +msgid " " +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Save as:" +msgstr "Zapisz jako:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Ok" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Saved exports:" +msgstr "Zapisane eksporty" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Old Password:" +msgstr "Poprzednie hasło:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "New Password:" +msgstr "Nowe hasło:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Confirm Password:" +msgstr "Potwierdź hasło:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Import" +msgstr "Importuj" + +#: addons/web/static/src/xml/base.xml:0 +msgid "1. Import a .CSV file" +msgstr "1. Importuj plik .CSV" + +#: addons/web/static/src/xml/base.xml:0 +msgid "" +"Select a .CSV file to import. If you need a sample of file to import,\n" +" you should use the export tool with the \"Import Compatible\" option." +msgstr "" +"Wybierz plik .CSV do importu. Jeśli chcesz zobaczyć przykład pliku do " +"importu,\n" +" powinieneś wyeksportować dane z opcją \"Kompatybilne z importem\"." + +#: addons/web/static/src/xml/base.xml:0 +msgid "CSV File:" +msgstr "Plik CSV:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "2. Check your file format" +msgstr "2. Sprawdź format pliku" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Import Options" +msgstr "Opcje importu" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Does your file have titles?" +msgstr "Czy plik zawiera nazwy pól?" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Separator:" +msgstr "Separator:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Delimiter:" +msgstr "Znak dziesiętny:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Encoding:" +msgstr "Kodowanie:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "UTF-8" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Latin 1" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Lines to skip" +msgstr "Linie do pominięcia" + +#: addons/web/static/src/xml/base.xml:0 +msgid "The import failed due to:" +msgstr "Import się nie udał z powodu:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Here is a preview of the file we could not import:" +msgstr "Oto podgląd pliku, którego nie można zaimportować:" + +#: addons/web/static/src/xml/base.xml:0 +msgid "OpenERP Web" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Version" +msgstr "Wersja" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Copyright © 2011-TODAY OpenERP SA. All Rights Reserved." +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "OpenERP is a trademark of the" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "OpenERP SA Company" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "Licenced under the terms of" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "GNU Affero General Public License" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "About OpenERP" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "OpenERP" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "" +"is a free enterprise-scale software system that is designed to boost\n" +" productivity and profit through data integration. It connects, " +"improves and\n" +" manages business processes in areas such as sales, finance, " +"supply chain,\n" +" project management, production, services, CRM, etc..." +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "" +"The system is platform-independent, and can be installed on Windows, Mac OS " +"X,\n" +" and various Linux and other Unix-based distributions. Its " +"architecture enables\n" +" new functionality to be rapidly created, modifications to be " +"made to a\n" +" production system and migration to a new version to be " +"straightforward." +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "" +"Depending on your needs, OpenERP is available through a web or application " +"client." +msgstr "" diff --git a/addons/web/po/sl.po b/addons/web/po/sl.po index bc63e7ff313..54349249817 100644 --- a/addons/web/po/sl.po +++ b/addons/web/po/sl.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-10-20 04:48+0000\n" -"X-Generator: Launchpad (build 14165)\n" +"X-Launchpad-Export-Date: 2011-11-01 05:09+0000\n" +"X-Generator: Launchpad (build 14197)\n" #: addons/web/static/src/js/view_form.js:355 msgid "" diff --git a/addons/web/static/lib/jquery.MD5/README.md b/addons/web/static/lib/jquery.MD5/README.md new file mode 100644 index 00000000000..88778a7a3bf --- /dev/null +++ b/addons/web/static/lib/jquery.MD5/README.md @@ -0,0 +1,32 @@ +# jQuery MD5 Plugin + +## Usage +Create ([hex](http://en.wikipedia.org/wiki/Hexadecimal)-encoded) [MD5](http://en.wikipedia.org/wiki/MD5) hash of a given string value: + + var md5 = $.md5('value'); + +Create ([hex](http://en.wikipedia.org/wiki/Hexadecimal)-encoded) [HMAC](http://en.wikipedia.org/wiki/HMAC)-MD5 hash of a given string value and key: + + var md5 = $.md5('value', 'key'); + +Create raw [MD5](http://en.wikipedia.org/wiki/MD5) hash of a given string value: + + var md5 = $.md5('value', null, true); + +Create raw [HMAC](http://en.wikipedia.org/wiki/HMAC)-MD5 hash of a given string value and key: + + var md5 = $.md5('value', 'key', true); + +## Requirements +None. + +If [jQuery](http://jquery.com/) is not available, the md5 function will be added to the global object: + + var md5 = md5('value'); + +## License +Released under the [MIT license](http://creativecommons.org/licenses/MIT/). + +## Source Code & Download +* Browse and checkout the [source code](https://github.com/blueimp/jQuery-MD5). +* [Download](https://github.com/blueimp/jQuery-MD5/archives/master) the project to add the plugin to your website. diff --git a/addons/web/static/lib/jquery.MD5/README.txt b/addons/web/static/lib/jquery.MD5/README.txt new file mode 100644 index 00000000000..8a8cbf4db2a --- /dev/null +++ b/addons/web/static/lib/jquery.MD5/README.txt @@ -0,0 +1,32 @@ +jQuery MD5 Plugin +================= + +Usage +----- +Create (hex-encoded) MD5 hash of a given string value: + var md5 = $.md5('value'); + +Create (hex-encoded) HMAC-MD5 hash of a given string value and key: + var md5 = $.md5('value', 'key'); + +Create raw MD5 hash of a given string value: + var md5 = $.md5('value', null, true); + +Create raw HMAC-MD5 hash of a given string value and key: + var md5 = $.md5('value', 'key', true); + +Requirements +------------ +None. + +If jQuery is not available, the md5 function will be added to the global object: + var md5 = md5('value'); + +License +------- +Released under the MIT license: +http://creativecommons.org/licenses/MIT/ + +Source Code & Download +---------------------- +https://github.com/blueimp/jQuery-MD5 diff --git a/addons/web/static/lib/jquery.MD5/jquery.md5.js b/addons/web/static/lib/jquery.MD5/jquery.md5.js new file mode 100644 index 00000000000..bf9bbe97b55 --- /dev/null +++ b/addons/web/static/lib/jquery.MD5/jquery.md5.js @@ -0,0 +1,269 @@ +/* + * jQuery MD5 Plugin 1.2.1 + * https://github.com/blueimp/jQuery-MD5 + * + * Copyright 2010, Sebastian Tschan + * https://blueimp.net + * + * Licensed under the MIT license: + * http://creativecommons.org/licenses/MIT/ + * + * Based on + * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message + * Digest Algorithm, as defined in RFC 1321. + * Version 2.2 Copyright (C) Paul Johnston 1999 - 2009 + * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet + * Distributed under the BSD License + * See http://pajhome.org.uk/crypt/md5 for more info. + */ + +/*jslint bitwise: true */ +/*global unescape, jQuery */ + +(function ($) { + 'use strict'; + + /* + * Add integers, wrapping at 2^32. This uses 16-bit operations internally + * to work around bugs in some JS interpreters. + */ + function safe_add(x, y) { + var lsw = (x & 0xFFFF) + (y & 0xFFFF), + msw = (x >> 16) + (y >> 16) + (lsw >> 16); + return (msw << 16) | (lsw & 0xFFFF); + } + + /* + * Bitwise rotate a 32-bit number to the left. + */ + function bit_rol(num, cnt) { + return (num << cnt) | (num >>> (32 - cnt)); + } + + /* + * These functions implement the four basic operations the algorithm uses. + */ + function md5_cmn(q, a, b, x, s, t) { + return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s), b); + } + function md5_ff(a, b, c, d, x, s, t) { + return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t); + } + function md5_gg(a, b, c, d, x, s, t) { + return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t); + } + function md5_hh(a, b, c, d, x, s, t) { + return md5_cmn(b ^ c ^ d, a, b, x, s, t); + } + function md5_ii(a, b, c, d, x, s, t) { + return md5_cmn(c ^ (b | (~d)), a, b, x, s, t); + } + + /* + * Calculate the MD5 of an array of little-endian words, and a bit length. + */ + function binl_md5(x, len) { + /* append padding */ + x[len >> 5] |= 0x80 << ((len) % 32); + x[(((len + 64) >>> 9) << 4) + 14] = len; + + var i, olda, oldb, oldc, oldd, + a = 1732584193, + b = -271733879, + c = -1732584194, + d = 271733878; + + for (i = 0; i < x.length; i += 16) { + olda = a; + oldb = b; + oldc = c; + oldd = d; + + a = md5_ff(a, b, c, d, x[i], 7, -680876936); + d = md5_ff(d, a, b, c, x[i + 1], 12, -389564586); + c = md5_ff(c, d, a, b, x[i + 2], 17, 606105819); + b = md5_ff(b, c, d, a, x[i + 3], 22, -1044525330); + a = md5_ff(a, b, c, d, x[i + 4], 7, -176418897); + d = md5_ff(d, a, b, c, x[i + 5], 12, 1200080426); + c = md5_ff(c, d, a, b, x[i + 6], 17, -1473231341); + b = md5_ff(b, c, d, a, x[i + 7], 22, -45705983); + a = md5_ff(a, b, c, d, x[i + 8], 7, 1770035416); + d = md5_ff(d, a, b, c, x[i + 9], 12, -1958414417); + c = md5_ff(c, d, a, b, x[i + 10], 17, -42063); + b = md5_ff(b, c, d, a, x[i + 11], 22, -1990404162); + a = md5_ff(a, b, c, d, x[i + 12], 7, 1804603682); + d = md5_ff(d, a, b, c, x[i + 13], 12, -40341101); + c = md5_ff(c, d, a, b, x[i + 14], 17, -1502002290); + b = md5_ff(b, c, d, a, x[i + 15], 22, 1236535329); + + a = md5_gg(a, b, c, d, x[i + 1], 5, -165796510); + d = md5_gg(d, a, b, c, x[i + 6], 9, -1069501632); + c = md5_gg(c, d, a, b, x[i + 11], 14, 643717713); + b = md5_gg(b, c, d, a, x[i], 20, -373897302); + a = md5_gg(a, b, c, d, x[i + 5], 5, -701558691); + d = md5_gg(d, a, b, c, x[i + 10], 9, 38016083); + c = md5_gg(c, d, a, b, x[i + 15], 14, -660478335); + b = md5_gg(b, c, d, a, x[i + 4], 20, -405537848); + a = md5_gg(a, b, c, d, x[i + 9], 5, 568446438); + d = md5_gg(d, a, b, c, x[i + 14], 9, -1019803690); + c = md5_gg(c, d, a, b, x[i + 3], 14, -187363961); + b = md5_gg(b, c, d, a, x[i + 8], 20, 1163531501); + a = md5_gg(a, b, c, d, x[i + 13], 5, -1444681467); + d = md5_gg(d, a, b, c, x[i + 2], 9, -51403784); + c = md5_gg(c, d, a, b, x[i + 7], 14, 1735328473); + b = md5_gg(b, c, d, a, x[i + 12], 20, -1926607734); + + a = md5_hh(a, b, c, d, x[i + 5], 4, -378558); + d = md5_hh(d, a, b, c, x[i + 8], 11, -2022574463); + c = md5_hh(c, d, a, b, x[i + 11], 16, 1839030562); + b = md5_hh(b, c, d, a, x[i + 14], 23, -35309556); + a = md5_hh(a, b, c, d, x[i + 1], 4, -1530992060); + d = md5_hh(d, a, b, c, x[i + 4], 11, 1272893353); + c = md5_hh(c, d, a, b, x[i + 7], 16, -155497632); + b = md5_hh(b, c, d, a, x[i + 10], 23, -1094730640); + a = md5_hh(a, b, c, d, x[i + 13], 4, 681279174); + d = md5_hh(d, a, b, c, x[i], 11, -358537222); + c = md5_hh(c, d, a, b, x[i + 3], 16, -722521979); + b = md5_hh(b, c, d, a, x[i + 6], 23, 76029189); + a = md5_hh(a, b, c, d, x[i + 9], 4, -640364487); + d = md5_hh(d, a, b, c, x[i + 12], 11, -421815835); + c = md5_hh(c, d, a, b, x[i + 15], 16, 530742520); + b = md5_hh(b, c, d, a, x[i + 2], 23, -995338651); + + a = md5_ii(a, b, c, d, x[i], 6, -198630844); + d = md5_ii(d, a, b, c, x[i + 7], 10, 1126891415); + c = md5_ii(c, d, a, b, x[i + 14], 15, -1416354905); + b = md5_ii(b, c, d, a, x[i + 5], 21, -57434055); + a = md5_ii(a, b, c, d, x[i + 12], 6, 1700485571); + d = md5_ii(d, a, b, c, x[i + 3], 10, -1894986606); + c = md5_ii(c, d, a, b, x[i + 10], 15, -1051523); + b = md5_ii(b, c, d, a, x[i + 1], 21, -2054922799); + a = md5_ii(a, b, c, d, x[i + 8], 6, 1873313359); + d = md5_ii(d, a, b, c, x[i + 15], 10, -30611744); + c = md5_ii(c, d, a, b, x[i + 6], 15, -1560198380); + b = md5_ii(b, c, d, a, x[i + 13], 21, 1309151649); + a = md5_ii(a, b, c, d, x[i + 4], 6, -145523070); + d = md5_ii(d, a, b, c, x[i + 11], 10, -1120210379); + c = md5_ii(c, d, a, b, x[i + 2], 15, 718787259); + b = md5_ii(b, c, d, a, x[i + 9], 21, -343485551); + + a = safe_add(a, olda); + b = safe_add(b, oldb); + c = safe_add(c, oldc); + d = safe_add(d, oldd); + } + return [a, b, c, d]; + } + + /* + * Convert an array of little-endian words to a string + */ + function binl2rstr(input) { + var i, + output = ''; + for (i = 0; i < input.length * 32; i += 8) { + output += String.fromCharCode((input[i >> 5] >>> (i % 32)) & 0xFF); + } + return output; + } + + /* + * Convert a raw string to an array of little-endian words + * Characters >255 have their high-byte silently ignored. + */ + function rstr2binl(input) { + var i, + output = []; + output[(input.length >> 2) - 1] = undefined; + for (i = 0; i < output.length; i += 1) { + output[i] = 0; + } + for (i = 0; i < input.length * 8; i += 8) { + output[i >> 5] |= (input.charCodeAt(i / 8) & 0xFF) << (i % 32); + } + return output; + } + + /* + * Calculate the MD5 of a raw string + */ + function rstr_md5(s) { + return binl2rstr(binl_md5(rstr2binl(s), s.length * 8)); + } + + /* + * Calculate the HMAC-MD5, of a key and some data (raw strings) + */ + function rstr_hmac_md5(key, data) { + var i, + bkey = rstr2binl(key), + ipad = [], + opad = [], + hash; + ipad[15] = opad[15] = undefined; + if (bkey.length > 16) { + bkey = binl_md5(bkey, key.length * 8); + } + for (i = 0; i < 16; i += 1) { + ipad[i] = bkey[i] ^ 0x36363636; + opad[i] = bkey[i] ^ 0x5C5C5C5C; + } + hash = binl_md5(ipad.concat(rstr2binl(data)), 512 + data.length * 8); + return binl2rstr(binl_md5(opad.concat(hash), 512 + 128)); + } + + /* + * Convert a raw string to a hex string + */ + function rstr2hex(input) { + var hex_tab = '0123456789abcdef', + output = '', + x, + i; + for (i = 0; i < input.length; i += 1) { + x = input.charCodeAt(i); + output += hex_tab.charAt((x >>> 4) & 0x0F) + + hex_tab.charAt(x & 0x0F); + } + return output; + } + + /* + * Encode a string as utf-8 + */ + function str2rstr_utf8(input) { + return unescape(encodeURIComponent(input)); + } + + /* + * Take string arguments and return either raw or hex encoded strings + */ + function raw_md5(s) { + return rstr_md5(str2rstr_utf8(s)); + } + function hex_md5(s) { + return rstr2hex(raw_md5(s)); + } + function raw_hmac_md5(k, d) { + return rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d)); + } + function hex_hmac_md5(k, d) { + return rstr2hex(raw_hmac_md5(k, d)); + } + + $.md5 = function (string, key, raw) { + if (!key) { + if (!raw) { + return hex_md5(string); + } else { + return raw_md5(string); + } + } + if (!raw) { + return hex_hmac_md5(key, string); + } else { + return raw_hmac_md5(key, string); + } + }; + +}(typeof jQuery === 'function' ? jQuery : this));
\ No newline at end of file diff --git a/addons/web/static/lib/jquery.MD5/tests/index.html b/addons/web/static/lib/jquery.MD5/tests/index.html new file mode 100644 index 00000000000..27ba8d3607d --- /dev/null +++ b/addons/web/static/lib/jquery.MD5/tests/index.html @@ -0,0 +1,43 @@ +<!DOCTYPE HTML> +<!-- +/* + * jQuery MD5 Plugin Tests 1.1 + * https://github.com/blueimp/jQuery-MD5 + * + * Copyright 2010, Sebastian Tschan + * https://blueimp.net + * + * Licensed under the MIT license: + * http://creativecommons.org/licenses/MIT/ + */ +--> +<html lang="en"> +<head> +<meta charset="utf-8"> +<title>jQuery MD5 Plugin Tests</title> +<link rel="stylesheet" href="http://code.jquery.com/qunit/git/qunit.css"> +</head> +<body> +<h1 id="qunit-header">jQuery MD5 Plugin Tests</h1> +<h2 id="qunit-banner"></h2> +<div id="qunit-testrunner-toolbar"></div> +<h2 id="qunit-userAgent"></h2> +<ol id="qunit-tests"></ol> +<script src="//ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js"></script> +<script> +(function ($) { + 'use strict'; + var nojquery = /nojquery=true/.test(location.search); + $('<label><input type="checkbox">nojquery<\/label>').click(function () { + location.search = nojquery ? '' : '?nojquery=true'; + }).appendTo('body').children(':first').attr('checked', nojquery); + if (nojquery) { + window.jQuery = null; + } +}(window.jQuery)); +</script> +<script src="../jquery.md5.js"></script> +<script src="http://code.jquery.com/qunit/git/qunit.js"></script> +<script src="tests.js"></script> +</body> +</html>
\ No newline at end of file diff --git a/addons/web/static/lib/jquery.MD5/tests/tests.js b/addons/web/static/lib/jquery.MD5/tests/tests.js new file mode 100644 index 00000000000..ab70f2f991b --- /dev/null +++ b/addons/web/static/lib/jquery.MD5/tests/tests.js @@ -0,0 +1,57 @@ +/* + * jQuery MD5 Plugin Tests 1.1 + * https://github.com/blueimp/jQuery-MD5 + * + * Copyright 2010, Sebastian Tschan + * https://blueimp.net + * + * Licensed under the MIT license: + * http://creativecommons.org/licenses/MIT/ + */ + +/*global jQuery, module, test, strictEqual */ + +(function ($) { + 'use strict'; + + module('Hex-encoded MD5'); + + test('Creating hex-encoded MD5 hash of an ASCII value', function () { + strictEqual($.md5('value'), '2063c1608d6e0baf80249c42e2be5804'); + }); + + test('Creating hex-encoded MD5 hash of an UTF-8 value', function () { + strictEqual($.md5('日本'), '4dbed2e657457884e67137d3514119b3'); + }); + + module('Hex-encoded HMAC-MD5'); + + test('Creating hex-encoded HMAC-MD5 hash of an ASCII value and key', function () { + strictEqual($.md5('value', 'key'), '01433efd5f16327ea4b31144572c67f6'); + }); + + test('Creating hex-encoded HMAC-MD5 hash of an UTF-8 value and key', function () { + strictEqual($.md5('日本', '日本'), 'c78b8c7357926981cc04740bd3e9d015'); + }); + + module('Raw MD5'); + + test('Creating raw MD5 hash of an ASCII value', function () { + strictEqual($.md5('value', null, true), ' c\xc1`\x8dn\x0b\xaf\x80$\x9cB\xe2\xbeX\x04'); + }); + + test('Creating raw MD5 hash of an UTF-8 value', function () { + strictEqual($.md5('日本', null, true), 'M\xbe\xd2\xe6WEx\x84\xe6q7\xd3QA\x19\xb3'); + }); + + module('Raw HMAC-MD5'); + + test('Creating raw HMAC-MD5 hash of an ASCII value and key', function () { + strictEqual($.md5('value', 'key', true), '\x01C>\xfd_\x162~\xa4\xb3\x11DW,g\xf6'); + }); + + test('Creating raw HMAC-MD5 hash of an UTF-8 value and key', function () { + strictEqual($.md5('日本', '日本', true), '\xc7\x8b\x8csW\x92i\x81\xcc\x04t\x0b\xd3\xe9\xd0\x15'); + }); + +}(typeof jQuery === 'function' ? jQuery : this));
\ No newline at end of file diff --git a/addons/web/static/src/css/base.css b/addons/web/static/src/css/base.css index 6872b921435..94e36d60419 100644 --- a/addons/web/static/src/css/base.css +++ b/addons/web/static/src/css/base.css @@ -159,7 +159,7 @@ body.openerp, .openerp textarea, .openerp input, .openerp select, .openerp optio } .db_container { - width: 15%; + width: 196px; background: #666666; } @@ -801,13 +801,15 @@ label.error { -moz-border-radius-topright: 7px; border-top-right-radius: 7px; } -.openerp .oe-listview table.oe-listview-content tfoot td:first-child, +.openerp .oe-listview table.oe-listview-content tfoot tr:last-child th:first-child, +.openerp .oe-listview table.oe-listview-content tfoot tr:last-child td:first-child, .openerp .oe-listview table.oe-listview-content tbody:last-child tr:last-child th:first-child { -webkit-border-bottom-left-radius: 7px; -moz-border-radius-bottomleft: 7px; border-bottom-left-radius: 7px; } -.openerp .oe-listview table.oe-listview-content tfoot td:last-child, +.openerp .oe-listview table.oe-listview-content tfoot tr:last-child th:last-child, +.openerp .oe-listview table.oe-listview-content tfoot tr:last-child td:last-child, .openerp .oe-listview table.oe-listview-content tbody:last-child tr:last-child td:last-child { -webkit-border-bottom-right-radius: 7px; -moz-border-radius-bottomright: 7px; @@ -844,7 +846,7 @@ label.error { .openerp .oe_frame.oe_forms { clear: both; } -.openerp table.oe_frame td { +.openerp table.oe_frame { color: #4c4c4c; } .openerp td.oe_form_frame_cell { @@ -872,7 +874,6 @@ label.error { } .openerp .oe_forms label.oe_label, .openerp .oe_forms label.oe_label_help { - text-align: right; margin: 3px 0 0 10px; } .openerp label.oe_label_help span { @@ -883,6 +884,18 @@ label.error { top: -4px; padding: 0 2px; } +.openerp .oe_align_left { + text-align: left; +} +.openerp .oe_align_right { + text-align: right; +} +.openerp .oe_align_center { + text-align: center; +} +.openerp .oe_forms .oe_form_paragraph { + margin: 3px 0 0 0; +} /* Inputs */ .openerp .oe_forms input[type="text"], .openerp .oe_forms input[type="password"], .openerp .oe_forms select, .openerp .oe_forms textarea { @@ -1075,7 +1088,7 @@ label.error { list-style: none; } .openerp .oe-view-manager-logs li:before { - content: '→ '; + content: '\2192 '; } .openerp .oe-view-manager-logs a { text-decoration: none; @@ -1408,3 +1421,31 @@ ul.oe-arrow-list li.oe-arrow-list-selected .oe-arrow-list-after { border-color: rgba(0,0,0,0); border-left-color: #B5B9FF; } +.openerp .oe_view_editor { + border-collapse: collapse; + padding: 0; + align: left; + width: 100%; +} +.openerp .oe_view_editor_colum{ + font-size: 90%; + font-weight: normal; + padding: 0; + border-bottom: 1px solid #CFCCCC; +} +.openerp .oe_view_editor_row:hover{ + background-color: #F3F3F3; +} +.openerp .oe_view_editor_tree_grid{ + text-align: left; + white-space: nowrap; + border-collapse: collapse; + width: 100%; +} +.openerp .oe_view_editor_tree_grid a:hover { + color: blue; +} +.openerp .oe_view_editor_tree_grid a { + display: block; +} + diff --git a/addons/web/static/src/css/data_import.css b/addons/web/static/src/css/data_import.css index 1fb3b22aa45..e5d1c9a910c 100644 --- a/addons/web/static/src/css/data_import.css +++ b/addons/web/static/src/css/data_import.css @@ -11,6 +11,22 @@ .openerp .oe_import_grid-row .oe_import_grid-cell { border-bottom: 1px solid #E3E3E3; } + +.openerp .oe-import-no-result .oe-import-result { + display: none; +} +.openerp .oe-import fieldset { + cursor: pointer; +} +.openerp .oe-import fieldset legend:before { + content: '\25BC '; +} +.openerp .oe-import fieldset.oe-closed legend:before { + content: '\25B6 '; +} +.openerp .oe-import fieldset.oe-closed table { + display: none; +} .openerp .separator.horizontal { font-weight: bold; border-bottom-width: 1px; diff --git a/addons/web/static/src/js/boot.js b/addons/web/static/src/js/boot.js index f41185be0c6..5fba5f4d8d4 100644 --- a/addons/web/static/src/js/boot.js +++ b/addons/web/static/src/js/boot.js @@ -59,7 +59,7 @@ openerp.web = function(instance) { openerp.web.formats(instance); openerp.web.chrome(instance); openerp.web.data(instance); - var files = ["views","search","list","form","list_editable","web_mobile","view_tree","data_export","data_import"]; + var files = ["views","search","list","form","list_editable","web_mobile","view_tree","data_export","data_import","view_editor"]; for(var i=0; i<files.length; i++) { if(openerp.web[files[i]]) { openerp.web[files[i]](instance); diff --git a/addons/web/static/src/js/chrome.js b/addons/web/static/src/js/chrome.js index bdb8e23c20b..d85942feead 100644 --- a/addons/web/static/src/js/chrome.js +++ b/addons/web/static/src/js/chrome.js @@ -29,11 +29,11 @@ openerp.web.Notification = openerp.web.Widget.extend(/** @lends openerp.web.Not warn: function(title, text) { this.$element.notify('create', 'oe_notification_alert', { title: title, - text: text, + text: text }, { - expires: false, + expires: false }); - }, + } }); @@ -136,10 +136,10 @@ openerp.web.Dialog = openerp.web.OldWidget.extend(/** @lends openerp.web.Dialog# } }); -openerp.web.CrashManager = openerp.web.SessionAware.extend({ - init: function(parent) { - this._super((parent || {}).session); - this.session.on_rpc_error.add(this.on_rpc_error); +openerp.web.CrashManager = openerp.web.CallbackEnabled.extend({ + init: function() { + this._super(); + openerp.connection.on_rpc_error.add(this.on_rpc_error); }, on_rpc_error: function(error) { this.error = error; @@ -195,10 +195,20 @@ openerp.web.Loading = openerp.web.Widget.extend(/** @lends openerp.web.Loading# init: function(parent, element_id) { this._super(parent, element_id); this.count = 0; + this.blocked_ui = false; this.session.on_rpc_request.add_first(this.on_rpc_event, 1); this.session.on_rpc_response.add_last(this.on_rpc_event, -1); }, on_rpc_event : function(increment) { + var self = this; + if (!this.count && increment === 1) { + // Block UI after 3s + this.long_running_timer = setTimeout(function () { + self.blocked_ui = true; + $.blockUI(); + }, 3000); + } + this.count += increment; if (this.count) { //this.$element.html(QWeb.render("Loading", {})); @@ -206,6 +216,12 @@ openerp.web.Loading = openerp.web.Widget.extend(/** @lends openerp.web.Loading# this.$element.show(); this.widget_parent.$element.addClass('loading'); } else { + clearTimeout(this.long_running_timer); + // Don't unblock if blocked by somebody else + if (self.blocked_ui) { + this.blocked_ui = false; + $.unblockUI(); + } this.$element.fadeOut(); this.widget_parent.$element.removeClass('loading'); } @@ -343,7 +359,7 @@ openerp.web.Database = openerp.web.Widget.extend(/** @lends openerp.web.Database self.$option_id.find("form[name=create_db_form]").validate({ submitHandler: function (form) { var fields = $(form).serializeArray(); - $.blockUI({message:'<img src="/web/static/src/img/throbber2.gif">'}); + $.blockUI(); self.rpc("/web/database/create", {'fields': fields}, function(result) { if (result.error) { $.unblockUI(); @@ -392,7 +408,7 @@ openerp.web.Database = openerp.web.Widget.extend(/** @lends openerp.web.Database .html(QWeb.render("BackupDB", self)) .find("form[name=backup_db_form]").validate({ submitHandler: function (form) { - $.blockUI({message:'<img src="/web/static/src/img/throbber2.gif">'}); + $.blockUI(); self.session.get_file({ form: form, error: function (body) { @@ -413,7 +429,7 @@ openerp.web.Database = openerp.web.Widget.extend(/** @lends openerp.web.Database self.$option_id.find("form[name=restore_db_form]").validate({ submitHandler: function (form) { - $.blockUI({message:'<img src="/web/static/src/img/throbber2.gif">'}); + $.blockUI(); $(form).ajaxSubmit({ url: '/web/database/restore', type: 'POST', @@ -943,17 +959,15 @@ openerp.web.WebClient = openerp.web.Widget.extend(/** @lends openerp.web.WebClie this._super(null, element_id); openerp.webclient = this; - QWeb.add_template("/web/static/src/xml/base.xml"); var params = {}; if(jQuery.param != undefined && jQuery.deparam(jQuery.param.querystring()).kitten != undefined) { this.$element.addClass("kitten-mode-activated"); } this.$element.html(QWeb.render("Interface", params)); - this.notification = new openerp.web.Notification(); - this.session = new openerp.web.Session(); + this.notification = new openerp.web.Notification(this); this.loading = new openerp.web.Loading(this,"oe_loading"); - this.crashmanager = new openerp.web.CrashManager(this); + this.crashmanager = new openerp.web.CrashManager(); this.header = new openerp.web.Header(this); this.login = new openerp.web.Login(this); diff --git a/addons/web/static/src/js/core.js b/addons/web/static/src/js/core.js index 1b6a6302f72..951e6e2b01f 100644 --- a/addons/web/static/src/js/core.js +++ b/addons/web/static/src/js/core.js @@ -237,8 +237,8 @@ openerp.web.Registry = openerp.web.Class.extend( /** @lends openerp.web.Registry * registry was created. * * An object path is simply a dotted name from the openerp root to the - * object pointed to (e.g. ``"openerp.web.Session"`` for an OpenERP - * session object). + * object pointed to (e.g. ``"openerp.web.Connection"`` for an OpenERP + * connection object). * * @constructs openerp.web.Registry * @param {Object} mapping a mapping of keys to object-paths @@ -338,9 +338,9 @@ openerp.web.CallbackEnabled = openerp.web.Class.extend(/** @lends openerp.web.Ca } }); -openerp.web.Session = openerp.web.CallbackEnabled.extend( /** @lends openerp.web.Session# */{ +openerp.web.Connection = openerp.web.CallbackEnabled.extend( /** @lends openerp.web.Connection# */{ /** - * @constructs openerp.web.Session + * @constructs openerp.web.Connection * @extends openerp.web.CallbackEnabled * * @param {String} [server] JSON-RPC endpoint hostname @@ -364,7 +364,9 @@ openerp.web.Session = openerp.web.CallbackEnabled.extend( /** @lends openerp.web // TODO: session should have an optional name indicating that they'll // be saved to (and revived from) cookies this.name = 'session'; + this.do_load_qweb(['/web/webclient/qweb']); }, + start: function() { this.session_restore(); }, @@ -484,9 +486,11 @@ openerp.web.Session = openerp.web.CallbackEnabled.extend( /** @lends openerp.web self.user_context = result.context; self.db = result.db; self.session_save(); + self.on_session_valid(); return true; }).then(success_callback); }, + login: function() { this.session_login.apply(this, arguments); }, /** * Reloads uid and session_id from local storage, if they exist */ @@ -574,6 +578,7 @@ openerp.web.Session = openerp.web.CallbackEnabled.extend( /** @lends openerp.web self.rpc('/web/webclient/jslist', {"mods": modules}, function(files) { self.do_load_js(file_list.concat(files)); }); + self.rpc('/web/webclient/qweblist', {"mods": modules}, self.do_load_qweb); openerp._modules_loaded = true; }); }); @@ -607,6 +612,12 @@ openerp.web.Session = openerp.web.CallbackEnabled.extend( /** @lends openerp.web this.on_modules_loaded(); } }, + do_load_qweb: function(files) { + var self = this; + _.each(files, function(file) { + openerp.web.qweb.add_template(file); + }); + }, on_modules_loaded: function() { for(var j=0; j<this.module_list.length; j++) { var mod = this.module_list[j]; @@ -713,36 +724,6 @@ openerp.web.Session = openerp.web.CallbackEnabled.extend( /** @lends openerp.web } }); -openerp.web.SessionAware = openerp.web.CallbackEnabled.extend(/** @lends openerp.web.SessionAware# */{ - /** - * Utility class that any class is allowed to extend to easy common manipulations. - * - * It provides rpc calls, callback on all methods preceded by "on_" or "do_" and a - * logging facility. - * - * @constructs openerp.web.SessionAware - * @extends openerp.web.CallbackEnabled - * - * @param {openerp.web.Session} session - */ - init: function(session) { - this._super(); - this.session = session; - }, - /** - * Performs a JSON-RPC call - * - * @param {String} url endpoint url - * @param {Object} data RPC parameters - * @param {Function} success RPC call success callback - * @param {Function} error RPC call error callback - * @returns {jQuery.Deferred} deferred object for the RPC call - */ - rpc: function(url, data, success, error) { - return this.session.rpc(url, data, success, error); - } -}); - /** * Base class for all visual components. Provides a lot of functionalities helpful * for the management of a part of the DOM. @@ -753,8 +734,6 @@ openerp.web.SessionAware = openerp.web.CallbackEnabled.extend(/** @lends openerp * destroyed too). * - Insertion in DOM. * - * Widget also extends SessionAware for ease of use. - * * Guide to create implementations of the Widget class: * ============================================== * @@ -795,7 +774,7 @@ openerp.web.SessionAware = openerp.web.CallbackEnabled.extend(/** @lends openerp * * That will kill the widget in a clean way and erase its content from the dom. */ -openerp.web.Widget = openerp.web.SessionAware.extend(/** @lends openerp.web.Widget# */{ +openerp.web.Widget = openerp.web.CallbackEnabled.extend(/** @lends openerp.web.Widget# */{ /** * The name of the QWeb template that will be used for rendering. Must be * redefined in subclasses or the default render() method can not be used. @@ -814,7 +793,7 @@ openerp.web.Widget = openerp.web.SessionAware.extend(/** @lends openerp.web.Widg * Construct the widget and set its parent if a parent is given. * * @constructs openerp.web.Widget - * @extends openerp.web.SessionAware + * @extends openerp.web.CallbackEnabled * * @param {openerp.web.Widget} parent Binds the current instance to the given Widget instance. * When that widget is destroyed by calling stop(), the current instance will be @@ -825,7 +804,8 @@ openerp.web.Widget = openerp.web.SessionAware.extend(/** @lends openerp.web.Widg * for new components this argument should not be provided any more. */ init: function(parent, /** @deprecated */ element_id) { - this._super((parent || {}).session); + this._super(); + this.session = openerp.connection; // if given an element_id, try to get the associated DOM element and save // a reference in this.$element. Else just generate a unique identifier. this.element_id = element_id; @@ -964,7 +944,7 @@ openerp.web.Widget = openerp.web.SessionAware.extend(/** @lends openerp.web.Widg rpc: function(url, data, success, error) { var def = $.Deferred().then(success, error); var self = this; - this._super(url, data). then(function() { + openerp.connection.rpc(url, data). then(function() { if (!self.widget_is_stopped) def.resolve.apply(def, arguments); }, function() { @@ -1040,12 +1020,21 @@ openerp.web.TranslationDataBase = openerp.web.Class.extend(/** @lends openerp.we } }); +if ($.blockUI) { + $.blockUI.defaults.baseZ = 1100; + $.blockUI.defaults.message = '<img src="/web/static/src/img/throbber2.gif">'; +} + +/** Configure default qweb */ openerp.web._t = new openerp.web.TranslationDataBase().build_translation_function(); openerp.web.qweb = new QWeb2.Engine(); openerp.web.qweb.debug = (window.location.search.indexOf('?debug') !== -1); +openerp.web.qweb.default_dict = { + '_' : _ +} openerp.web.qweb.format_text_node = function(s) { // Note that 'this' is the Qweb Node of the text - var translation = this.node.parentElement.attributes['t-translation']; + var translation = this.node.parentNode.attributes['t-translation']; if (translation && translation.value === 'off') { return s; } @@ -1057,6 +1046,9 @@ openerp.web.qweb.format_text_node = function(s) { return tr === ts ? s : tr; } +/** Setup default connection */ +openerp.connection = new openerp.web.Connection(); + }; // vim:et fdc=0 fdl=0 foldnestmax=3 fdm=syntax: diff --git a/addons/web/static/src/js/data.js b/addons/web/static/src/js/data.js index 069506586ad..f4509c82a81 100644 --- a/addons/web/static/src/js/data.js +++ b/addons/web/static/src/js/data.js @@ -32,7 +32,7 @@ openerp.web.DataGroup = openerp.web.Widget.extend( /** @lends openerp.web.DataG * @constructs openerp.web.DataGroup * @extends openerp.web.Widget * - * @param {openerp.web.Session} session Current OpenERP session + * @param {openerp.web.Widget} parent widget * @param {String} model name of the model managed by this DataGroup * @param {Array} domain search domain for this DataGroup * @param {Object} context context of the DataGroup's searches @@ -785,11 +785,15 @@ openerp.web.ProxyDataSet = openerp.web.DataSetSearch.extend({ on_unlink: function(ids) {} }); -openerp.web.Model = openerp.web.SessionAware.extend({ - init: function(session, model_name) { - this._super(session); +openerp.web.Model = openerp.web.CallbackEnabled.extend({ + init: function(_, model_name) { + this._super(); this.model_name = model_name; }, + rpc: function() { + var c = openerp.connection; + return c.rpc.apply(c, arguments); + }, get_func: function(method_name) { var self = this; return function() { diff --git a/addons/web/static/src/js/data_import.js b/addons/web/static/src/js/data_import.js index 711e790dfaa..355c6c1b493 100644 --- a/addons/web/static/src/js/data_import.js +++ b/addons/web/static/src/js/data_import.js @@ -80,8 +80,8 @@ openerp.web.DataImport = openerp.web.Dialog.extend({ this.toggle_import_button(false); this.$element.find('#csvfile').change(this.on_autodetect_data); this.$element.find('fieldset').change(this.on_autodetect_data); - this.$element.find('fieldset legend').click(function() { - $(this).next().toggle(); + this.$element.delegate('fieldset legend', 'click', function() { + $(this).parent().toggleClass('oe-closed'); }); this.ready.push(new openerp.web.DataSet(this, this.model).call( 'fields_get', [], function (fields) { @@ -194,9 +194,11 @@ openerp.web.DataImport = openerp.web.Dialog.extend({ : with_headers ? results.records.slice(1) : results.records })); + this.$element.find('fieldset').addClass('oe-closed'); } else if (results['error']) { result_node.append(QWeb.render('ImportView.error', { 'error': results['error']})); + this.$element.find('fieldset').removeClass('oe-closed'); } else if (results['success']) { if (this.widget_parent.widget_parent.active_view == "list") { this.widget_parent.reload_content(); @@ -204,6 +206,11 @@ openerp.web.DataImport = openerp.web.Dialog.extend({ this.stop(); return; } + this.$element.find('form').removeClass('oe-import-no-result'); + + this.$element.delegate('.oe-m2o-drop-down-button', 'click', function () { + $(this).prev('input').focus(); + }); var self = this; this.ready.then(function () { diff --git a/addons/web/static/src/js/formats.js b/addons/web/static/src/js/formats.js index 3ab972f7a86..ca540844b7f 100644 --- a/addons/web/static/src/js/formats.js +++ b/addons/web/static/src/js/formats.js @@ -27,14 +27,8 @@ openerp.web.format_value = function (value, descriptor, value_if_empty) { return _.sprintf('%d', value); case 'float': var precision = descriptor.digits ? descriptor.digits[1] : 2; - var int_part = Math.floor(value); - var dec_part = _.sprintf( - '%.' + precision + 'f', - Math.abs(value) % 1).substring(2); - return _.sprintf('%d%s%s', - int_part, - openerp.web._t.database.parameters.decimal_point, - dec_part); + return _.sprintf('%.' + precision + 'f', value) + .replace('.', openerp.web._t.database.parameters.decimal_point); case 'float_time': return _.sprintf("%02d:%02d", Math.floor(value), diff --git a/addons/web/static/src/js/search.js b/addons/web/static/src/js/search.js index c7aa1e3cfe3..18e035a40b8 100644 --- a/addons/web/static/src/js/search.js +++ b/addons/web/static/src/js/search.js @@ -63,6 +63,7 @@ openerp.web.SearchView = openerp.web.Widget.extend(/** @lends openerp.web.Search rows.push(row); var filters = []; _.each(items, function (item) { + if (item.attrs.invisible === '1') { return; } if (filters.length && item.tag !== 'filter') { row.push( new openerp.web.search.FilterGroup( @@ -432,6 +433,7 @@ openerp.web.search.Widget = openerp.web.Widget.extend( /** @lends openerp.web.se * @param view the ancestor view of this widget */ init: function (view) { + this._super(view); this.view = view; }, /** @@ -472,10 +474,8 @@ openerp.web.search.Widget = openerp.web.Widget.extend( /** @lends openerp.web.se this._super(); }, render: function (defaults) { - return QWeb.render( - this.template, _.extend(this, { - defaults: defaults - })); + // FIXME + return this._super(_.extend(this, {defaults: defaults})); } }); openerp.web.search.add_expand_listener = function($root) { diff --git a/addons/web/static/src/js/view_editor.js b/addons/web/static/src/js/view_editor.js new file mode 100644 index 00000000000..71cda6fcc47 --- /dev/null +++ b/addons/web/static/src/js/view_editor.js @@ -0,0 +1,516 @@ +openerp.web.view_editor = function(openerp) { +var QWeb = openerp.web.qweb; +openerp.web.ViewEditor = openerp.web.Widget.extend({ + init: function(parent, element_id, dataset, view, options) { + this._super(parent); + this.element_id = element_id + this.parent = parent + this.dataset = dataset; + this.model = dataset.model; + this.xml_id = 0; + }, + start: function() { + this.init_view_editor(); + }, + init_view_editor: function() { + var self = this; + var action = { + name:'ViewEditor', + context:this.session.user_context, + domain: [["model", "=", this.dataset.model]], + res_model : 'ir.ui.view', + views : [[false, 'list']], + type: 'ir.actions.act_window', + target: "current", + limit : 80, + auto_search : true, + flags: { + sidebar: false, + deletable: false, + views_switcher: false, + action_buttons:false, + search_view:false, + pager:false, + radio: true + }, + }; + this.view_edit_dialog = new openerp.web.Dialog(this, { + modal: true, + title: 'ViewEditor', + width: 750, + height: 500, + buttons: { + "Create": function(){ + //to do + }, + "Edit": function(){ + self.xml_id=0; + self.get_data(); + }, + "Close": function(){ + self.view_edit_dialog.close(); + } + }, + }); + this.view_edit_dialog.start().open(); + var action_manager = new openerp.web.ActionManager(this); + action_manager.appendTo(this.view_edit_dialog); + action_manager.do_action(action); + }, + check_attr: function(xml, tag, level) { + var obj = {'child_id': [], 'id': this.xml_id++, 'level': level+1, 'att_list': [], 'name': ""}; + var render_name = "<" + tag; + obj.att_list.push(tag); + $(xml).each(function() { + _.each(this.attributes, function(attrs){ + if (tag != 'button') { + if (attrs.nodeName == "string" || attrs.nodeName == "name" || attrs.nodeName == "index") { + render_name += ' ' + attrs.nodeName + '=' + '"' + attrs.nodeValue + '"' ; + } + } else { + if (attrs.nodeName == "name") { + render_name += ' ' + attrs.nodeName + '=' + '"' + attrs.nodeValue + '"'; + } + } + obj.att_list.push( [attrs.nodeName,attrs.nodeValue] ); + }); + render_name+= ">"; + }); + obj.name = render_name; + return obj; + }, + save_object: function(val, parent_list, child_obj_list) { + var self = this; + var check_id = parent_list[0]; + var p_list = parent_list.slice(1); + if (val.child_id.length != 0) { + _.each(val.child_id, function(val, key) { + if (val.id == check_id) { + if (p_list.length!=0) { + self.save_object(val, p_list, child_obj_list); + } else { + val.child_id = child_obj_list; + return false; + } + } + }); + } else { + val.child_id = child_obj_list; + } + }, + xml_node_create: function(xml, root, parent_list, parent_id, main_object){ + var self = this; + var child_obj_list = []; + var children_list = $(xml).filter(root).children(); + var parents = $(children_list[0]).parents().get(); + _.each(children_list, function (child_node) { + child_obj_list.push(self.check_attr(child_node,child_node.tagName.toLowerCase(),parents.length)); + }); + if (children_list.length != 0) { + if (parents.length <= parent_list.length) { + parent_list.splice(parents.length - 1); + } + parent_list.push(parent_id); + self.save_object(main_object[0], parent_list.slice(1), child_obj_list); + } + for (var i = 0; i < children_list.length; i++) { + self.xml_node_create + (children_list[i], children_list[i].tagName.toLowerCase(), + parent_list, child_obj_list[i].id, main_object); + } + return main_object; + }, + parse_xml: function(arch, view_id) { + var root = $(arch).filter(":first")[0]; + var tag = root.tagName.toLowerCase(); + var obj ={'child_id':[],'id':this.xml_id++,'level':0,'att_list':[],'name':"<view view_id='"+view_id+"'>"}; + var root_object = this.check_attr(root,tag,0); + obj.child_id = this.xml_node_create(arch, tag, [], this.xml_id-1, [root_object], []) + return [obj]; + }, + get_data: function() { + var self = this; + var view_arch_list = []; + self.main_view_id =((this.view_edit_dialog.$element.find("input[name='radiogroup']:checked").parent()).parent()).attr('data-id'); + var ve_dataset = new openerp.web.DataSet(this, 'ir.ui.view'); + ve_dataset.read_ids([parseInt(self.main_view_id)], ['arch', 'type'], function (arch) { + one_object = self.parse_xml(arch[0].arch,self.main_view_id); + self.main_view_type = arch[0].type + view_arch_list.push({"view_id" : self.main_view_id, "arch" : arch[0].arch}); + dataset = new openerp.web.DataSetSearch(self, 'ir.ui.view', null, null); + dataset.read_slice([], {domain : [['inherit_id','=', parseInt(self.main_view_id)]]}, function (result) { + _.each(result, function(res) { + view_arch_list.push({"view_id":res.id,"arch":res.arch}); + self.inherit_view(one_object, res); + }); + return self.edit_view({"main_object": one_object, + "parent_child_id": self.parent_child_list(one_object, []), + "arch": view_arch_list}); + }); + }); + }, + parent_child_list : function(one_object, p_list) { + var self = this; + _.each(one_object , function(element){ + if(element.child_id.length != 0){ + p_list.push({"key":element.id,"value":_.pluck(element.child_id, 'id')}); + self.parent_child_list(element.child_id, p_list); + } + }); + return p_list; + }, + inherit_view : function(one_object, result) { + var self = this; + var root = $(result.arch).filter('*'); + var xml_list = []; + if (root[0].tagName.toLowerCase() == "data") { + xml_list = $(root[0]).children(); + } else { + xml_list.push(root[0]); + } + _.each(xml_list , function(xml){ + var parent_id; + var check_list = []; + var xpath_object = self.parse_xml(xml,result.id); + if (xml.tagName.toLowerCase() == "xpath" ) { + var part_expr = _.without($(xml).attr('expr').split("/"),""); + _.each(part_expr,function(part){ + check_list.push(_.without($.trim(part.replace(/[^a-zA-Z 0-9 _]+/g,'!')).split("!"),"")); + }); + } else { + var temp = []; + _.each(xpath_object[0].child_id[0].att_list, function(list){ + if(!_.include(list, "position")){ + temp.push(list); + } + }); + check_list = [_.flatten(temp)]; + } + self.full_path_search(check_list ,one_object ,xpath_object); + }); + }, + full_path_search: function(check_list ,val ,xpath_object) { + var self = this; + if(xpath_object.length!=0){ + var check = check_list[0]; + var obj; + switch (check.length) { + case 2: + if(parseInt(check[1])){ + var list_1 = _.select(val,function(element){ + var main_list = _.flatten(element.att_list); + return _.include(main_list, check[0]); + }); + obj = val[_.indexOf(val,list_1[parseInt(check[1])-1])]; + } else { + obj = _.detect(val, function(element){ + var main_list = _.flatten(element.att_list); + return _.include(main_list, check[0]); + }); + } + break; + case 3: + obj = _.detect(val,function(element){ + var main_list = _.flatten(element.att_list); + check = _.uniq(check); + var insert = _.intersection(main_list,check); + if(insert.length == check.length ){return element;} + }); + break; + case 1: + var list_1 = _.select(val,function(element){ + var main_list = _.flatten(element.att_list); + return _.include(main_list, check[0]); + }); + if(list_1.length != 0){ + (check_list.length == 1)? obj = list_1[0] : check_list.shift(); + } + break; + } + if(obj) { + check_list.shift(); + if (check_list.length !=0){ + self.full_path_search(check_list ,obj.child_id ,xpath_object); + } else { + var level = obj.level+1; + self.increase_level(xpath_object[0], level) + obj.child_id.push(xpath_object[0]); + xpath_object.pop(); + return; + } + } + else { + _.each(val,function(element){ + self.full_path_search(check_list ,element.child_id ,xpath_object); + }); + } + } + }, + increase_level: function(val, level) { + var self = this; + val.level = level; + _.each(val.child_id, function(val, key) { + self.increase_level(val, level + 1); + }); + }, + edit_view: function(one_object) { + var self = this; + this.edit_xml_dialog = new openerp.web.Dialog(this,{ + modal: true, + title: 'View Editor', + width: 750, + height: 500, + buttons: { + "Inherited View": function(){ + //todo + }, + "Preview": function(){ + var action = { + context:self.session.user_context, + res_model : self.model, + views : [[self.main_view_id, self.main_view_type]], + type: 'ir.actions.act_window', + target: "new", + flags: { + sidebar: false, + views_switcher: false, + action_buttons:false, + search_view:false, + pager:false, + }, + }; + var action_manager = new openerp.web.ActionManager(self); + action_manager.do_action(action); + }, + "Close": function(){ + self.edit_xml_dialog.close(); + } + } + }); + this.edit_xml_dialog.start().open(); + this.edit_xml_dialog.$element.html(QWeb.render('view_editor', { + 'data': one_object['main_object'], + })); + this.edit_xml_dialog.$element.find("tr[id^='viewedit-']").click(function() { + self.edit_xml_dialog.$element.find("tr[id^='viewedit-']").removeClass('ui-selected'); + $(this).addClass('ui-selected'); + }); + this.edit_xml_dialog.$element.find("img[id^='parentimg-']").click(function() { + if ($(this).attr('src') == '/web/static/src/img/collapse.gif') { + $(this).attr('src', '/web/static/src/img/expand.gif'); + self.on_expand(this); + } else { + $(this).attr('src', '/web/static/src/img/collapse.gif'); + var id = this.id.split('-')[1]; + self.on_collapse(this,one_object['parent_child_id'], one_object['main_object']); + } + }); + this.edit_xml_dialog.$element.find("img[id^='side-']").click(function() { + var side = $(this).closest("tr[id^='viewedit-']") + var id_tr = (side.attr('id')).split('-')[1]; + var img = side.find("img[id='parentimg-"+id_tr+"']").attr('src'); ; + var level = parseInt(side.attr('level')); + var list_shift =[]; + var last_tr; + var cur_tr = side; + list_shift.push(side); + var next_tr; + var ls = side; + var view_id; + var view_xml_id; + while(1){ + ls = ls.prev(); + if((self.edit_xml_dialog.$element.find(ls).find('a').text()).search("view_id") != -1 + && parseInt(ls.attr('level')) < level){ + view_id = parseInt(($(ls).find('a').text()).replace(/[^0-9]+/g,'')); + view_xml_id = (ls.attr('id')).split('-')[1]; + break; + } + } + switch (this.id) { + case "side-add": + break; + case "side-remove": + break; + case "side-edit": + break; + case "side-up": + while (1) { + var prev_tr = cur_tr.prev(); + if(level >= parseInt(prev_tr.attr('level')) || prev_tr.length == 0) { + last_tr = prev_tr; + break; + } + cur_tr = prev_tr; + } + if (img) { + while (1) { + next_tr = side.next(); + if ( parseInt(next_tr.attr('level')) <= level || next_tr.length == 0) { + break; + } else { + list_shift.push(next_tr); + side = next_tr; + } + } + } + if (last_tr.length != 0 && parseInt(last_tr.attr('level')) == level && + (self.edit_xml_dialog.$element.find(last_tr).find('a').text()).search("view_id") == -1) { + _.each(list_shift, function(rec) { + $(last_tr).before(rec); + }); + self.save_move_arch(one_object, view_id, view_xml_id, id_tr, level, "up"); + } + break; + case "side-down": + if (img) { + while (1) { + next_tr = cur_tr.next(); + if ( parseInt(next_tr.attr('level')) <= level || next_tr.length == 0) { + last_tr = next_tr; + break; + } else { + list_shift.push(next_tr); + cur_tr = next_tr; + } + } + } + else { + last_tr = cur_tr.next(); + } + if((self.edit_xml_dialog.$element.find(last_tr).find('a').text()).search("view_id") != -1){ + return; + } + if (last_tr.length != 0 && parseInt(last_tr.attr('level')) == level) { + var last_tr_id = (last_tr.attr('id')).split('-')[1]; + img = last_tr.find("img[id='parentimg-" + last_tr_id + "']").attr('src'); + if (img) { + self.edit_xml_dialog.$element.find("img[id='parentimg-" + last_tr_id + "']"). + attr('src', '/web/static/src/img/expand.gif'); + while (1) { + var next_tr = last_tr.next(); + if (next_tr.attr('level') <= level || next_tr.length == 0) break; + next_tr.hide(); + last_tr = next_tr; + } + } + list_shift.reverse(); + _.each(list_shift, function(rec) { + $(last_tr).after(rec); + }); + self.save_move_arch(one_object, view_id, view_xml_id, id_tr, level, "down"); + } + break; + } + }); + }, + save_move_arch: function(one_object, view_id, view_xml_id, id_tr, level, move_direct){ + var self = this; + var arch = _.detect(one_object['arch'],function(element){ + return element.view_id == view_id; + }); + var obj = self.get_view_object(view_xml_id, one_object['main_object'], []); + if(($(arch.arch).filter("data")).length != 0 && view_xml_id != 0){ + var check_list = _.flatten(obj[0].child_id[0].att_list); + arch.arch = _.detect($(arch.arch).children(), function(xml_child){ + var temp_obj = self.check_attr(xml_child, xml_child.tagName.toLowerCase()); + var main_list = _.flatten(temp_obj.att_list); + check_list = _.uniq(check_list); + var insert = _.intersection(main_list,check_list); + if(insert.length == check_list.length ){return xml_child;} + }); + } + return self.get_node(arch.arch, obj[0].child_id[0], parseInt(id_tr), [], parseInt(level), + parseInt(view_id), arch, move_direct); + }, + + get_view_object: function(view_xml_id, one_object,result){ + var self = this; + if(result.length==0){ + var check = _.detect(one_object , function(obj){ + return view_xml_id==obj.id; + }); + if(check){result.push(check);}; + _.each(one_object, function(obj){ + self.get_view_object(view_xml_id, obj.child_id, result); + }); + } + return result; + }, + get_node: function(arch1, obj, id, child_list, level, view_id, arch, move_direct){ + var self = this; + var children_list = $(arch1).children(); + var list_obj_xml = _.zip(children_list,obj.child_id); + if (id) { + if (obj.id == id) { + var id; + var parent = $(arch1).parents(); + var index = _.indexOf(child_list, obj) + var re_insert_obj = child_list.splice(index, 1); + if (move_direct == "down") { + var next = $(arch1).next(); + $(next).after(arch1); + child_list.splice(index+1, 0, re_insert_obj[0]); + } else { + var prev = $(arch1).prev(); + $(prev).before(arch1); + child_list.splice(index-1, 0, re_insert_obj[0]); + } + parent = parent[parent.length-1]; + var convert_to_utf = self.xml2Str(parent); + if (convert_to_utf) { + convert_to_utf = convert_to_utf.replace('xmlns="http://www.w3.org/1999/xhtml"', ""); + convert_to_utf = '<?xml version="1.0"?>' + convert_to_utf; + arch.arch = convert_to_utf; + dataset = new openerp.web.DataSet(this, 'ir.ui.view'); + dataset.write(parseInt(view_id),{"arch":convert_to_utf}, function(r) { + }); + } + } + if (obj.level <= level) { + _.each(list_obj_xml, function(child_node) { + self.get_node(child_node[0], child_node[1], id, obj.child_id, level, view_id, arch, move_direct); + }); + } + } + }, + xml2Str: function(xmlNode) { + try { + return (new XMLSerializer()).serializeToString(xmlNode); + } + catch (e) { + try { + return xmlNode.xml; + } + catch (e) { + return false; + } + } + + }, + on_expand: function(expand_img){ + var level = parseInt($(expand_img).closest("tr[id^='viewedit-']").attr('level')); + var cur_tr = $(expand_img).closest("tr[id^='viewedit-']"); + while (1) { + var nxt_tr = cur_tr.next(); + if (parseInt(nxt_tr.attr('level')) > level){ + cur_tr = nxt_tr; + nxt_tr.hide(); + } else return nxt_tr; + } + }, + on_collapse: function(collapse_img, parent_child_id, id, main_object) { + var self = this; + var id = collapse_img.id.split('-')[1]; + var datas = _.detect(parent_child_id,function(res) { + return res.key == id; + }); + _.each(datas.value, function(rec) { + var tr = self.edit_xml_dialog.$element.find("tr[id='viewedit-"+rec+"']"); + tr.find("img[id='parentimg-"+rec+"']").attr('src','/web/static/src/img/expand.gif'); + tr.show(); + }); + } + +}); +}; diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js index 2946df7166c..603e2abb008 100644 --- a/addons/web/static/src/js/view_form.js +++ b/addons/web/static/src/js/view_form.js @@ -10,6 +10,7 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# * view should be displayed (if there is one active). */ searchable: false, + readonly : false, form_template: "FormView", identifier_prefix: 'formview-', /** @@ -37,7 +38,7 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# this.dirty_for_user = false; this.default_focus_field = null; this.default_focus_button = null; - this.registry = openerp.web.form.widgets; + this.registry = this.readonly ? openerp.web.form.readonly : openerp.web.form.widgets; this.has_been_loaded = $.Deferred(); this.$form_header = null; this.translatable_fields = []; @@ -89,7 +90,7 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# this.fields_view = data; var frame = new (this.registry.get_object('frame'))(this, this.fields_view.arch); - this.rendered = QWeb.render(this.form_template, { 'frame': frame, 'view': this }); + this.rendered = QWeb.render(this.form_template, { 'frame': frame, 'widget': this }); } this.$element.html(this.rendered); _.each(this.widgets, function(w) { @@ -101,21 +102,11 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# self.on_pager_action(action); }); - this.$form_header.find('button.oe_form_button_save').click(this.do_save); - this.$form_header.find('button.oe_form_button_cancel').click(this.do_cancel); + this.$form_header.find('button.oe_form_button_save').click(this.do_save_then_readonly); this.$form_header.find('button.oe_form_button_new').click(this.on_button_new); this.$form_header.find('button.oe_form_button_duplicate').click(this.on_button_duplicate); - this.$form_header.find('button.oe_form_button_toggle').click(function () { - self.translatable_fields = []; - self.widgets = {}; - self.fields = {}; - self.$form_header.find('button').unbind('click'); - self.registry = self.registry === openerp.web.form.widgets - ? openerp.web.form.readonly - : openerp.web.form.widgets; - self.on_loaded(self.fields_view); - self.reload(); - }); + this.$form_header.find('button.oe_form_button_delete').click(this.on_button_delete); + this.$form_header.find('button.oe_form_button_toggle').click(this.on_toggle_readonly); if (this.options.sidebar && this.options.sidebar_id) { this.sidebar = new openerp.web.Sidebar(this, this.options.sidebar_id); @@ -127,6 +118,23 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# } this.has_been_loaded.resolve(); }, + on_toggle_readonly: function() { + var self = this; + self.translatable_fields = []; + self.widgets = {}; + self.fields = {}; + self.$form_header.find('button').unbind('click'); + self.readonly = !self.readonly; + self.registry = self.readonly ? openerp.web.form.readonly : openerp.web.form.widgets; + self.on_loaded(self.fields_view); + return self.reload(); + }, + do_set_readonly: function() { + return this.readonly ? $.Deferred().resolve() : this.on_toggle_readonly(); + }, + do_set_editable: function() { + return !this.readonly ? $.Deferred().resolve() : this.on_toggle_readonly(); + }, do_show: function () { var promise; if (this.dataset.index === null) { @@ -162,6 +170,8 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# this.$form_header.find('.oe_form_on_update').show(); this.$form_header.find('button.oe_form_button_new').show(); } + this.$form_header.find('.oe_form_on_readonly').toggle(this.readonly); + this.$form_header.find('.oe_form_on_editable').toggle(!this.readonly); this.dirty_for_user = false; this.datarecord = record; for (var f in this.fields) { @@ -342,14 +352,16 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# $.when(this.has_been_loaded).then(function() { if (self.can_be_discarded()) { var keys = _.keys(self.fields_view.fields); - if (keys.length) { - self.dataset.default_get(keys).then(self.on_record_loaded).then(function() { + $.when(self.do_set_editable()).then(function() { + if (keys.length) { + self.dataset.default_get(keys).then(self.on_record_loaded).then(function() { + def.resolve(); + }); + } else { + self.on_record_loaded({}); def.resolve(); - }); - } else { - self.on_record_loaded({}); - def.resolve(); - } + } + }); } }); return def.promise(); @@ -361,7 +373,20 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# if (self.can_be_discarded()) { self.dataset.call('copy', [self.datarecord.id, {}, self.dataset.context]).then(function(new_id) { return self.on_created({ result : new_id }); - }).then(function() { + }).then(self.do_set_editable).then(function() { + def.resolve(); + }); + } + }); + return def.promise(); + }, + on_button_delete: function() { + var self = this; + var def = $.Deferred(); + $.when(this.has_been_loaded).then(function() { + if (self.can_be_discarded() && self.datarecord.id) { + self.dataset.unlink([self.datarecord.id]).then(function() { + self.on_pager_action('next'); def.resolve(); }); } @@ -379,6 +404,9 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# * @param {Function} success callback on save success * @param {Boolean} [prepend_on_create=false] if ``do_save`` creates a new record, should that record be inserted at the start of the dataset (by default, records are added at the end) */ + do_save_then_readonly: function(success, prepend_on_create) { + return this.do_save(success, prepend_on_create).then(this.do_set_readonly); + }, do_save: function(success, prepend_on_create) { var self = this; var action = function() { @@ -426,10 +454,6 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# this.mutating_lock = this.mutating_lock.pipe(action, action); return this.mutating_lock; }, - switch_readonly: function() { - }, - switch_editable: function() { - }, on_invalid: function() { var msg = "<ul>"; _.each(this.fields, function(f) { @@ -487,9 +511,6 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# on_action: function (action) { console.debug('Executing action', action); }, - do_cancel: function () { - console.debug("Cancelling form"); - }, reload: function() { var self = this; var act = function() { @@ -715,6 +736,16 @@ openerp.web.form.Widget = openerp.web.Widget.extend(/** @lends openerp.web.form. this.invisible = this.modifiers['invisible'] === true; this.classname = 'oe_form_' + this.type; + this.align = parseFloat(this.node.attrs.align); + if (isNaN(this.align) || this.align === 1) { + this.align = 'right'; + } else if (this.align === 0) { + this.align = 'left'; + } else { + this.align = 'center'; + } + + this.width = this.node.attrs.width; }, start: function() { @@ -1044,8 +1075,7 @@ openerp.web.form.WidgetLabel = openerp.web.form.Widget.extend({ this._super(view, node); - // TODO fme: support for attrs.align - if (this.node.tag == 'label' && (this.node.attrs.colspan || (this.string && this.string.length > 32))) { + if (this.node.tag == 'label' && (this.align === 'left' || this.node.attrs.colspan || (this.string && this.string.length > 32))) { this.template = "WidgetParagraph"; this.colspan = parseInt(this.node.attrs.colspan || 1, 10); } else { @@ -1170,6 +1200,10 @@ openerp.web.form.Field = openerp.web.form.Widget.extend(/** @lends openerp.web.f openerp.web.form.FieldChar = openerp.web.form.Field.extend({ template: 'FieldChar', + init: function (view, node) { + this._super(view, node); + this.password = this.node.attrs.password === 'True' || this.node.attrs.password === '1'; + }, start: function() { this._super.apply(this, arguments); this.$element.find('input').change(this.on_ui_change); @@ -1419,11 +1453,7 @@ openerp.web.form.FieldBoolean = openerp.web.form.Field.extend({ start: function() { var self = this; this._super.apply(this, arguments); - this.$element.find('input').click(function() { - if ($(this).is(':checked') != self.value) { - self.on_ui_change(); - } - }); + this.$element.find('input').click(self.on_ui_change); }, set_value: function(value) { this._super.apply(this, arguments); @@ -1632,6 +1662,11 @@ openerp.web.form.FieldMany2One = openerp.web.form.Field.extend({ } else { $("#" + self.cm_id + " .oe_m2o_menu_item_mandatory").addClass("oe-m2o-disabled-cm"); } + if (!self.readonly) { + $("#" + self.cm_id + " .oe_m2o_menu_item_noreadonly").removeClass("oe-m2o-disabled-cm"); + } else { + $("#" + self.cm_id + " .oe_m2o_menu_item_noreadonly").addClass("oe-m2o-disabled-cm"); + } return true; }, menuStyle: {width: "200px"} }); @@ -1651,6 +1686,8 @@ openerp.web.form.FieldMany2One = openerp.web.form.Field.extend({ } }); this.$drop_down.click(function() { + if (self.readonly) + return; if (self.$input.autocomplete("widget").is(":visible")) { self.$input.autocomplete("close"); } else { @@ -1811,7 +1848,7 @@ openerp.web.form.FieldMany2One = openerp.web.form.Field.extend({ self.original_value = undefined; self._change_int_ext_value(rval); }; - if(typeof(value) === "number") { + if (value && !(value instanceof Array)) { var dataset = new openerp.web.DataSetStatic(this, this.field.relation, self.build_context()); dataset.name_get([value], function(data) { real_set_value(data[0]); @@ -1857,6 +1894,10 @@ openerp.web.form.FieldMany2One = openerp.web.form.Field.extend({ }, focus: function () { this.$input.focus(); + }, + update_dom: function() { + this._super.apply(this, arguments); + this.$input.attr('disabled', this.readonly); } }); @@ -1910,7 +1951,8 @@ openerp.web.form.FieldOne2Many = openerp.web.form.Field.extend({ multi_selection: false, init: function(view, node) { this._super(view, node); - this.is_started = $.Deferred(); + this.is_loaded = $.Deferred(); + this.initial_is_loaded = this.is_loaded; this.is_setted = $.Deferred(); this.form_last_update = $.Deferred(); this.init_form_last_update = this.form_last_update; @@ -1928,8 +1970,18 @@ openerp.web.form.FieldOne2Many = openerp.web.form.Field.extend({ self.on_ui_change(); }); + this.is_setted.then(function() { + self.load_views(); + }); + }, + is_readonly: function() { + return this.readonly || this.force_readonly; + }, + load_views: function() { + var self = this; + var modes = this.node.attrs.mode; - modes = !!modes ? modes.split(",") : ["tree", "form"]; + modes = !!modes ? modes.split(",") : ["tree"]; var views = []; _.each(modes, function(mode) { var view = { @@ -1942,25 +1994,38 @@ openerp.web.form.FieldOne2Many = openerp.web.form.Field.extend({ } if(view.view_type === "list") { view.options.selectable = self.multi_selection; + if (self.is_readonly()) { + view.options.addable = null; + view.options.deletable = null; + } } else if (view.view_type === "form") { view.options.not_interactible_on_create = true; } views.push(view); }); this.views = views; - + this.viewmanager = new openerp.web.ViewManager(this, this.dataset, views); this.viewmanager.registry = openerp.web.views.clone({ list: 'openerp.web.form.One2ManyListView', - form: 'openerp.web.form.One2ManyFormView' + form: 'openerp.web.FormView' }); var once = $.Deferred().then(function() { self.init_form_last_update.resolve(); }); + var def = $.Deferred().then(function() { + self.initial_is_loaded.resolve(); + }); this.viewmanager.on_controller_inited.add_last(function(view_type, controller) { if (view_type == "list") { controller.o2m = self; + if (self.is_readonly()) + controller.set_editable(false); } else if (view_type == "form") { + if (self.is_readonly()) { + controller.on_toggle_readonly(); + $(controller.$element.find(".oe_form_buttons")[0]).children().remove(); + } controller.on_record_loaded.add_last(function() { once.resolve(); }); @@ -1971,33 +2036,40 @@ openerp.web.form.FieldOne2Many = openerp.web.form.Field.extend({ } else if (view_type == "graph") { self.reload_current_view() } - self.is_started.resolve(); + def.resolve(); }); - this.viewmanager.on_mode_switch.add_first(function() { - self.save_form_view(); + this.viewmanager.on_mode_switch.add_first(function(n_mode, b, c, d, e) { + $.when(self.save_form_view()).then(function() { + if(n_mode === "list") + setTimeout(function() {self.reload_current_view();}, 0); + }); }); this.is_setted.then(function() { setTimeout(function () { self.viewmanager.appendTo(self.$element); }, 0); }); + return def; }, reload_current_view: function() { var self = this; - var view = self.viewmanager.views[self.viewmanager.active_view].controller; - if(self.viewmanager.active_view === "list") { - view.reload_content(); - } else if (self.viewmanager.active_view === "form") { - if (this.dataset.index === null && this.dataset.ids.length >= 1) { - this.dataset.index = 0; - } - var act = function() { - return view.do_show(); + self.is_loaded = self.is_loaded.pipe(function() { + var view = self.viewmanager.views[self.viewmanager.active_view].controller; + if(self.viewmanager.active_view === "list") { + return view.reload_content(); + } else if (self.viewmanager.active_view === "form") { + if (self.dataset.index === null && self.dataset.ids.length >= 1) { + self.dataset.index = 0; + } + var act = function() { + return view.do_show(); + } + self.form_last_update = self.form_last_update.pipe(act, act); + return self.form_last_update; + } else if (self.viewmanager.active_view === "graph") { + return view.do_search(self.build_domain(), self.dataset.get_context(), []); } - this.form_last_update = this.form_last_update.pipe(act, act);; - } else if (self.viewmanager.active_view === "graph") { - view.do_search(this.build_domain(), this.dataset.get_context(), []); - } + }); }, set_value: function(value) { value = value || []; @@ -2054,9 +2126,7 @@ openerp.web.form.FieldOne2Many = openerp.web.form.Field.extend({ if (this.dataset.index === null && this.dataset.ids.length > 0) { this.dataset.index = 0; } - $.when(this.is_started).then(function() { - self.reload_current_view(); - }); + self.reload_current_view(); this.is_setted.resolve(); }, get_value: function() { @@ -2120,7 +2190,18 @@ openerp.web.form.FieldOne2Many = openerp.web.form.Field.extend({ }, update_dom: function() { this._super.apply(this, arguments); - this.$element.toggleClass('disabled', this.readonly); + var self = this; + if (this.previous_readonly !== this.readonly) { + this.previous_readonly = this.readonly; + if (this.viewmanager) { + this.is_loaded = this.is_loaded.pipe(function() { + self.viewmanager.stop(); + return $.when(self.load_views()).then(function() { + self.reload_current_view(); + }); + }); + } + } } }); @@ -2131,9 +2212,6 @@ openerp.web.form.One2ManyDataSet = openerp.web.BufferedDataSet.extend({ } }); -openerp.web.form.One2ManyFormView = openerp.web.FormView.extend({ -}); - openerp.web.form.One2ManyListView = openerp.web.ListView.extend({ do_add_record: function () { if (this.options.editable) { @@ -2172,7 +2250,8 @@ openerp.web.form.One2ManyListView = openerp.web.ListView.extend({ read_function: function() { return self.o2m.dataset.read_ids.apply(self.o2m.dataset, arguments); }, - form_view_options: {'not_interactible_on_create':true} + form_view_options: {'not_interactible_on_create':true}, + readonly: self.o2m.is_readonly() }); pop.on_write.add(function(id, data) { self.o2m.dataset.write(id, data, {}, function(r) { @@ -2188,7 +2267,9 @@ openerp.web.form.FieldMany2Many = openerp.web.form.Field.extend({ init: function(view, node) { this._super(view, node); this.list_id = _.uniqueId("many2many"); - this.is_started = $.Deferred(); + this.is_loaded = $.Deferred(); + this.initial_is_loaded = this.is_loaded; + this.is_setted = $.Deferred(); }, start: function() { this._super.apply(this, arguments); @@ -2200,18 +2281,10 @@ openerp.web.form.FieldMany2Many = openerp.web.form.Field.extend({ this.dataset.on_unlink.add_last(function(ids) { self.on_ui_change(); }); - - this.list_view = new openerp.web.form.Many2ManyListView(this, this.dataset, false, { - 'addable': 'Add', - 'selectable': self.multi_selection - }); - this.list_view.m2m_field = this; - this.list_view.on_loaded.add_last(function() { - self.is_started.resolve(); + + this.is_setted.then(function() { + self.load_view(); }); - setTimeout(function () { - self.list_view.appendTo($("#" + self.list_id)); - }, 0); }, set_value: function(value) { value = value || []; @@ -2221,16 +2294,56 @@ openerp.web.form.FieldMany2Many = openerp.web.form.Field.extend({ this._super(value); this.dataset.set_ids(value); var self = this; - $.when(this.is_started).then(function() { - self.list_view.reload_content(); - }); + self.reload_content(); + this.is_setted.resolve(); }, get_value: function() { return [commands.replace_with(this.dataset.ids)]; }, validate: function() { this.invalid = false; - // TODO niv + }, + is_readonly: function() { + return this.readonly || this.force_readonly; + }, + load_view: function() { + var self = this; + this.list_view = new openerp.web.form.Many2ManyListView(this, this.dataset, false, { + 'addable': self.is_readonly() ? null : 'Add', + 'deletable': self.is_readonly() ? false : true, + 'selectable': self.multi_selection + }); + this.list_view.m2m_field = this; + var loaded = $.Deferred(); + this.list_view.on_loaded.add_last(function() { + self.initial_is_loaded.resolve(); + loaded.resolve(); + }); + setTimeout(function () { + self.list_view.appendTo($("#" + self.list_id)); + }, 0); + return loaded; + }, + reload_content: function() { + var self = this; + this.is_loaded = this.is_loaded.pipe(function() { + return self.list_view.reload_content(); + }); + }, + update_dom: function() { + this._super.apply(this, arguments); + var self = this; + if (this.previous_readonly !== this.readonly) { + this.previous_readonly = this.readonly; + if (this.list_view) { + this.is_loaded = this.is_loaded.pipe(function() { + self.list_view.stop(); + return $.when(self.load_view()).then(function() { + self.reload_content(); + }); + }); + } + } } }); @@ -2334,10 +2447,7 @@ openerp.web.form.SelectCreatePopup = openerp.web.OldWidget.extend(/** @lends ope this.searchview.stop(); } this.searchview = new openerp.web.SearchView(this, - this.dataset, false, { - "selectable": !this.options.disable_multiple_selection, - "deletable": false - }); + this.dataset, false, {}); this.searchview.on_search.add(function(domains, contexts, groupbys) { if (self.initial_ids) { self.do_search(domains.concat([[["id", "in", self.initial_ids]], self.domain]), @@ -2364,7 +2474,9 @@ openerp.web.form.SelectCreatePopup = openerp.web.OldWidget.extend(/** @lends ope }); self.view_list = new openerp.web.form.SelectCreateListView(self, self.dataset, false, - _.extend({'deletable': false}, self.options.list_view_options || {})); + _.extend({'deletable': false, + 'selectable': !self.options.disable_multiple_selection + }, self.options.list_view_options || {})); self.view_list.popup = self; self.view_list.appendTo($("#" + self.element_id + "_view_list")).pipe(function() { self.view_list.do_show(); @@ -2483,6 +2595,7 @@ openerp.web.form.FormOpenPopup = openerp.web.OldWidget.extend(/** @lends openerp * - read_function * - parent_view * - form_view_options + * - readonly */ show_element: function(model, row_id, context, options) { this.model = model; @@ -2522,7 +2635,13 @@ openerp.web.form.FormOpenPopup = openerp.web.OldWidget.extend(/** @lends openerp this.view_form.set_embedded_view(this.options.alternative_form_view); } this.view_form.appendTo(this.$element.find("#" + this.element_id + "_view_form")); + var once = $.Deferred().then(function() { + if (self.options.readonly) { + self.view_form.on_toggle_readonly(); + } + }); this.view_form.on_loaded.add_last(function() { + once.resolve(); var $buttons = self.view_form.$element.find(".oe_form_buttons"); $buttons.html(QWeb.render("FormOpenPopup.form.buttons")); var $nbutton = $buttons.find(".oe_formopenpopup-form-save"); @@ -2535,6 +2654,10 @@ openerp.web.form.FormOpenPopup = openerp.web.OldWidget.extend(/** @lends openerp $cbutton.click(function() { self.stop(); }); + if (self.options.readonly) { + $nbutton.hide(); + $cbutton.text(_t("Close")); + } self.view_form.do_show(); }); this.dataset.on_write.add(this.on_write); @@ -2817,17 +2940,21 @@ openerp.web.form.FieldStatus = openerp.web.form.Field.extend({ } }); -openerp.web.form.WidgetNotebookReadonly = openerp.web.form.WidgetNotebook.extend({ - template: 'WidgetNotebook.readonly' -}); openerp.web.form.FieldReadonly = openerp.web.form.Field.extend({ }); openerp.web.form.FieldCharReadonly = openerp.web.form.FieldReadonly.extend({ template: 'FieldChar.readonly', + init: function(view, node) { + this._super(view, node); + this.password = this.node.attrs.password === 'True' || this.node.attrs.password === '1'; + }, set_value: function (value) { this._super.apply(this, arguments); var show_value = openerp.web.format_value(value, this, ''); + if (this.password) { + show_value = new Array(show_value.length + 1).join('*'); + } this.$element.find('div').text(show_value); return show_value; } @@ -2855,7 +2982,7 @@ openerp.web.form.FieldUrlReadonly = openerp.web.form.FieldURIReadonly.extend({ }); openerp.web.form.FieldBooleanReadonly = openerp.web.form.FieldCharReadonly.extend({ set_value: function (value) { - this._super(value ? '\u2714' : '\u2718'); + this._super(value ? '\u2611' : '\u2610'); } }); openerp.web.form.FieldSelectionReadonly = openerp.web.form.FieldReadonly.extend({ @@ -2890,9 +3017,17 @@ openerp.web.form.FieldMany2OneReadonly = openerp.web.form.FieldCharReadonly.exte self.update_dom(); self.on_value_changed(); var real_set_value = function(rval) { - self.$element.find('div').text(rval ? rval[1] : ''); + self.value = rval; + var div = $(self.$element.find('div')); + div.html('<a href="javascript:void(0)"></a>'); + var a = $(div.find("a")); + a.text(rval ? rval[1] : ''); + a.click(function() { + var pop = new openerp.web.form.FormOpenPopup(self.view); + pop.show_element(self.field.relation, self.value[0],self.build_context(), {readonly:true}); + }); }; - if(typeof(value) === "number") { + if (value && !(value instanceof Array)) { var dataset = new openerp.web.DataSetStatic( this, this.field.relation, self.build_context()); dataset.name_get([value], function(data) { @@ -2937,8 +3072,14 @@ openerp.web.form.widgets = new openerp.web.Registry({ 'binary': 'openerp.web.form.FieldBinaryFile', 'statusbar': 'openerp.web.form.FieldStatus' }); + +openerp.web.form.FieldMany2ManyReadonly = openerp.web.form.FieldMany2Many.extend({ + force_readonly: true +}); +openerp.web.form.FieldOne2ManyReadonly = openerp.web.form.FieldOne2Many.extend({ + force_readonly: true +}); openerp.web.form.readonly = openerp.web.form.widgets.clone({ - 'notebook': 'openerp.web.form.WidgetNotebookReadonly', 'char': 'openerp.web.form.FieldCharReadonly', 'email': 'openerp.web.form.FieldEmailReadonly', 'url': 'openerp.web.form.FieldUrlReadonly', @@ -2948,6 +3089,9 @@ openerp.web.form.readonly = openerp.web.form.widgets.clone({ 'datetime': 'openerp.web.form.FieldCharReadonly', 'selection' : 'openerp.web.form.FieldSelectionReadonly', 'many2one': 'openerp.web.form.FieldMany2OneReadonly', + 'many2many' : 'openerp.web.form.FieldMany2ManyReadonly', + 'one2many' : 'openerp.web.form.FieldOne2ManyReadonly', + 'one2many_list' : 'openerp.web.form.FieldOne2ManyReadonly', 'boolean': 'openerp.web.form.FieldBooleanReadonly', 'float': 'openerp.web.form.FieldCharReadonly', 'integer': 'openerp.web.form.FieldCharReadonly', diff --git a/addons/web/static/src/js/view_list.js b/addons/web/static/src/js/view_list.js index d09ec1d3035..e891a6c7db7 100644 --- a/addons/web/static/src/js/view_list.js +++ b/addons/web/static/src/js/view_list.js @@ -11,7 +11,7 @@ openerp.web.ListView = openerp.web.View.extend( /** @lends openerp.web.ListView# // whether the column headers should be displayed 'header': true, // display addition button, with that label - 'addable': _t("New"), + 'addable': _t("Create"), // whether the list view can be sorted, note that once a view has been // sorted it can not be reordered anymore 'sortable': true, @@ -201,8 +201,15 @@ openerp.web.ListView = openerp.web.View.extend( /** @lends openerp.web.ListView# this.setup_columns(this.fields_view.fields, grouped); this.$element.html(QWeb.render("ListView", this)); - // Head hook + this.$element.find('.all-record-selector').click(function(){ + self.$element.find('.oe-record-selector input').prop('checked', + self.$element.find('.all-record-selector').prop('checked') || false); + var selection = self.groups.get_selection(); + $(self.groups).trigger( + 'selected', [selection.ids, selection.records]); + }); + this.$element.find('.oe-list-add') .click(this.do_add_record) .attr('disabled', grouped && this.options.editable); @@ -424,10 +431,13 @@ openerp.web.ListView = openerp.web.View.extend( /** @lends openerp.web.ListView# }, /** * re-renders the content of the list view + * + * @returns {$.Deferred} promise to content reloading */ reload_content: function () { var self = this; this.records.reset(); + var reloaded = $.Deferred(); this.$element.find('.oe-listview-content').append( this.groups.render(function () { if (self.dataset.index == null) { @@ -438,7 +448,9 @@ openerp.web.ListView = openerp.web.View.extend( /** @lends openerp.web.ListView# } } self.compute_aggregates(); + reloaded.resolve(); })); + return reloaded.promise(); }, /** * Handler for the result of eval_domain_and_context, actually perform the @@ -512,6 +524,17 @@ openerp.web.ListView = openerp.web.View.extend( /** @lends openerp.web.ListView# return field.name === name; }); if (!action) { return; } + + var c = new openerp.web.CompoundContext(); + c.set_eval_context(_.extend({ + active_id: id, + active_ids: [id], + active_model: this.dataset.model + }, this.records.get(id).toContext())); + if (action.context) { + c.add(action.context); + } + action.context = c; this.do_execute_action(action, this.dataset, id, callback); }, /** @@ -1201,6 +1224,10 @@ openerp.web.ListView.Groups = openerp.web.Class.extend( /** @lends openerp.web.L var options = { offset: page * limit, limit: limit }; //TODO xmo: investigate why we need to put the setTimeout setTimeout(function() {dataset.read_slice(fields, options , function (records) { + // FIXME: ignominious hacks, parents (aka form view) should not send two ListView#reload_content concurrently + if (self.records.length) { + self.records.reset(null, {silent: true}); + } if (!self.datagroup.openable) { view.configure_pager(dataset); } else { @@ -1430,6 +1457,25 @@ var Record = openerp.web.Class.extend(/** @lends Record# */{ } return {data: form_data}; + }, + /** + * Converts the current record to a format expected by context evaluations + * (identical to record.attributes, except m2o fields are their integer + * value rather than a pair) + */ + toContext: function () { + var output = {}, attrs = this.attributes; + for(var k in attrs) { + var val = attrs[k]; + if (typeof val !== 'object') { + output[k] = val; + } else if (val instanceof Array) { + output[k] = val[0]; + } else { + throw new Error("Can't convert value " + val + " to context"); + } + } + return output; } }); Record.include(Events); @@ -1541,7 +1587,8 @@ var Collection = openerp.web.Class.extend(/** @lends Collection# */{ * @param {Array} [records] * @returns this */ - reset: function (records) { + reset: function (records, options) { + options = options || {}; _(this._proxies).each(function (proxy) { proxy.reset(); }); @@ -1552,7 +1599,9 @@ var Collection = openerp.web.Class.extend(/** @lends Collection# */{ if (records) { this.add(records); } - this.trigger('reset', this); + if (!options.silent) { + this.trigger('reset', this); + } return this; }, /** diff --git a/addons/web/static/src/js/view_list_editable.js b/addons/web/static/src/js/view_list_editable.js index 4cc081a6266..dba0a1abba4 100644 --- a/addons/web/static/src/js/view_list_editable.js +++ b/addons/web/static/src/js/view_list_editable.js @@ -78,6 +78,17 @@ openerp.web.list_editable = function (openerp) { // tree/@editable takes priority on everything else if present. this.options.editable = data.arch.attrs.editable || this.options.editable; return this._super(data, grouped); + }, + /** + * Ensures the editable list is saved (saves any pending edition if + * needed, or tries to) + * + * Returns a deferred to the end of the saving. + * + * @returns {$.Deferred} + */ + ensure_saved: function () { + return this.groups.ensure_saved(); } }); @@ -86,6 +97,18 @@ openerp.web.list_editable = function (openerp) { new_record: function () { // TODO: handle multiple children this.children[null].new_record(); + }, + /** + * Ensures descendant editable List instances are all saved if they have + * pending editions. + * + * @returns {$.Deferred} + */ + ensure_saved: function () { + return $.when.apply(null, + _.invoke( + _.values(this.children), + 'ensure_saved')); } }); @@ -254,9 +277,11 @@ openerp.web.list_editable = function (openerp) { * sibling if asked. * * @param {Boolean} [edit_next=false] should the next row become editable + * @returns {$.Deferred} */ save_row: function (edit_next) { - var self = this; + //noinspection JSPotentiallyInvalidConstructorUsage + var self = this, done = $.Deferred(); this.edition_form.do_save(function (result) { if (result.created && !self.edition_id) { self.records.add({id: result.result}, @@ -267,28 +292,44 @@ openerp.web.list_editable = function (openerp) { next_record = self.records.at( self.records.indexOf(edited_record) + 1); - self.handle_onwrite(self.edition_id); - self.cancel_pending_edition().then(function () { - $(self).trigger('saved', [self.dataset]); - if (!edit_next) { - return; - } - if (result.created) { - self.new_record(); - return; - } - var next_record_id; - if (next_record) { - next_record_id = next_record.get('id'); - self.dataset.index = _(self.dataset.ids) - .indexOf(next_record_id); - } else { - self.dataset.index = 0; - next_record_id = self.records.at(0).get('id'); - } - self.edit_record(next_record_id); - }); - }, this.options.editable === 'top'); + $.when( + self.handle_onwrite(self.edition_id), + self.cancel_pending_edition().then(function () { + $(self).trigger('saved', [self.dataset]); + if (!edit_next) { + return; + } + if (result.created) { + self.new_record(); + return; + } + var next_record_id; + if (next_record) { + next_record_id = next_record.get('id'); + self.dataset.index = _(self.dataset.ids) + .indexOf(next_record_id); + } else { + self.dataset.index = 0; + next_record_id = self.records.at(0).get('id'); + } + self.edit_record(next_record_id); + })).then(function () { + done.resolve(); + }); + }, this.options.editable === 'top').fail(function () { + done.reject(); + }); + return done.promise(); + }, + /** + * If the current list is being edited, ensures it's saved + */ + ensure_saved: function () { + if (this.edition) { + return this.save_row(); + } + //noinspection JSPotentiallyInvalidConstructorUsage + return $.Deferred().resolve().promise(); }, /** * Cancels the edition of the row for the current dataset index diff --git a/addons/web/static/src/js/views.js b/addons/web/static/src/js/views.js index f402a51bf7e..62928401492 100644 --- a/addons/web/static/src/js/views.js +++ b/addons/web/static/src/js/views.js @@ -2,21 +2,21 @@ * OpenERP web library *---------------------------------------------------------*/ -openerp.web.views = function(db) { +openerp.web.views = function(session) { -var _t = db.web._t; +var _t = session.web._t; /** * Registry for all the client actions key: tag value: widget */ -db.web.client_actions = new db.web.Registry(); +session.web.client_actions = new session.web.Registry(); /** * Registry for all the main views */ -db.web.views = new db.web.Registry(); +session.web.views = new session.web.Registry(); -db.web.ActionManager = db.web.Widget.extend({ +session.web.ActionManager = session.web.Widget.extend({ identifier_prefix: "actionmanager", init: function(parent) { this._super(parent); @@ -93,20 +93,20 @@ db.web.ActionManager = db.web.Widget.extend({ ir_actions_act_window: function (action, on_close) { if (action.target === 'new') { if (this.dialog == null) { - this.dialog = new db.web.Dialog(this, { title: action.name, width: '80%' }); + this.dialog = new session.web.Dialog(this, { title: action.name, width: '80%' }); if(on_close) this.dialog.on_close.add(on_close); this.dialog.start(); } else { this.dialog_viewmanager.stop(); } - this.dialog_viewmanager = new db.web.ViewManagerAction(this, action); + this.dialog_viewmanager = new session.web.ViewManagerAction(this, action); this.dialog_viewmanager.appendTo(this.dialog.$element); this.dialog.open(); } else { this.dialog_stop(); this.content_stop(); - this.inner_viewmanager = new db.web.ViewManagerAction(this, action); + this.inner_viewmanager = new session.web.ViewManagerAction(this, action); this.inner_viewmanager.appendTo(this.$element); this.url_update(action); } @@ -124,7 +124,7 @@ db.web.ActionManager = db.web.Widget.extend({ if (this.dialog && action.context) { var model = action.context.active_model; if (model === 'base.module.upgrade' || model === 'base.setup.installer' || model === 'base.module.upgrade') { - db.webclient.do_reload(); + session.webclient.do_reload(); } } this.dialog_stop(); @@ -140,7 +140,7 @@ db.web.ActionManager = db.web.Widget.extend({ }, ir_actions_client: function (action) { this.content_stop(); - var ClientWidget = db.web.client_actions.get_object(action.tag); + var ClientWidget = session.web.client_actions.get_object(action.tag); (this.client_widget = new ClientWidget(this, action.params)).appendTo(this); }, ir_actions_report_xml: function(action) { @@ -164,12 +164,12 @@ db.web.ActionManager = db.web.Widget.extend({ } }); -db.web.ViewManager = db.web.Widget.extend(/** @lends db.web.ViewManager# */{ +session.web.ViewManager = session.web.Widget.extend(/** @lends session.web.ViewManager# */{ identifier_prefix: "viewmanager", template: "ViewManager", /** - * @constructs db.web.ViewManager - * @extends db.web.Widget + * @constructs session.web.ViewManager + * @extends session.web.Widget * * @param parent * @param dataset @@ -185,10 +185,10 @@ db.web.ViewManager = db.web.Widget.extend(/** @lends db.web.ViewManager# */{ this.views_src = _.map(views, function(x) {return x instanceof Array? {view_id: x[0], view_type: x[1]} : x;}); this.views = {}; this.flags = this.flags || {}; - this.registry = db.web.views; + this.registry = session.web.views; }, render: function() { - return db.web.qweb.render(this.template, { + return session.web.qweb.render(this.template, { self: this, prefix: this.element_id, views: this.views_src}); @@ -271,6 +271,10 @@ db.web.ViewManager = db.web.Widget.extend(/** @lends db.web.ViewManager# */{ } } } + $.when(view_promise).then(function () { + self.$element.find('.oe_view_title:first').text( + self.display_title()); + }); return view_promise; }, /** @@ -284,7 +288,7 @@ db.web.ViewManager = db.web.Widget.extend(/** @lends db.web.ViewManager# */{ if (this.searchview) { this.searchview.stop(); } - this.searchview = new db.web.SearchView( + this.searchview = new session.web.SearchView( this, this.dataset, view_id, search_defaults, this.flags.search_view === false); @@ -331,16 +335,24 @@ db.web.ViewManager = db.web.Widget.extend(/** @lends db.web.ViewManager# */{ /** * Called by children view after executing an action */ - on_action_executed: function () {} + on_action_executed: function () {}, + display_title: function () { + var view = this.views[this.active_view]; + if (view) { + // ick + return view.controller.fields_view.arch.attrs.string; + } + return ''; + } }); -db.web.ViewManagerAction = db.web.ViewManager.extend(/** @lends oepnerp.web.ViewManagerAction# */{ +session.web.ViewManagerAction = session.web.ViewManager.extend(/** @lends oepnerp.web.ViewManagerAction# */{ template:"ViewManagerAction", /** - * @constructs db.web.ViewManagerAction - * @extends db.web.ViewManager + * @constructs session.web.ViewManagerAction + * @extends session.web.ViewManager * - * @param {db.web.ActionManager} parent parent object/widget + * @param {session.web.ActionManager} parent parent object/widget * @param {Object} action descriptor for the action this viewmanager needs to manage its views. */ init: function(parent, action) { @@ -350,7 +362,7 @@ db.web.ViewManagerAction = db.web.ViewManager.extend(/** @lends oepnerp.web.View this._super(parent, null, action.views); this.session = parent.session; this.action = action; - var dataset = new db.web.DataSetSearch(this, action.res_model, action.context, action.domain); + var dataset = new session.web.DataSetSearch(this, action.res_model, action.context, action.domain); if (action.res_id) { dataset.ids.push(action.res_id); dataset.index = 0; @@ -400,12 +412,12 @@ db.web.ViewManagerAction = db.web.ViewManager.extend(/** @lends oepnerp.web.View this.$element.find('.oe_get_xml_view').click(function () { // TODO: add search view? - $('<pre>').text(db.web.json_node_to_xml( + $('<pre>').text(session.web.json_node_to_xml( self.views[self.active_view].controller.fields_view.arch, true)) .dialog({ width: '95%'}); }); if (this.action.help && !this.flags.low_profile) { - var Users = new db.web.DataSet(self, 'res.users'), + var Users = new session.web.DataSet(self, 'res.users'), header = this.$element.find('.oe-view-manager-header'); header.delegate('blockquote button', 'click', function() { var $this = $(this); @@ -444,6 +456,16 @@ db.web.ViewManagerAction = db.web.ViewManager.extend(/** @lends oepnerp.web.View if (!self.action.name && fvg) { self.$element.find('.oe_view_title').text(fvg.arch.attrs.string || fvg.name); } + + var $title = self.$element.find('.oe_view_title'), + $search_prefix = $title.find('span'); + if (controller.searchable !== false) { + if (!$search_prefix.length) { + $title.prepend('<span>' + _t("Search:") + '</span>'); + } + } else { + $search_prefix.remove(); + } }); }, shortcut_check : function(view) { @@ -451,7 +473,7 @@ db.web.ViewManagerAction = db.web.ViewManager.extend(/** @lends oepnerp.web.View var grandparent = this.widget_parent && this.widget_parent.widget_parent; // display shortcuts if on the first view for the action var $shortcut_toggle = this.$element.find('.oe-shortcut-toggle'); - if (!(grandparent instanceof db.web.WebClient) || + if (!(grandparent instanceof session.web.WebClient) || !(view.view_type === this.views_src[0].view_type && view.view_id === this.views_src[0].view_id)) { $shortcut_toggle.hide(); @@ -488,7 +510,7 @@ db.web.ViewManagerAction = db.web.ViewManager.extend(/** @lends oepnerp.web.View * Intercept do_action resolution from children views */ on_action_executed: function () { - return new db.web.DataSet(this, 'res.log') + return new session.web.DataSet(this, 'res.log') .call('get', [], this.do_display_log); }, /** @@ -512,10 +534,13 @@ db.web.ViewManagerAction = db.web.ViewManager.extend(/** @lends oepnerp.web.View return false; }); }); + }, + display_title: function () { + return this.action.name; } }); -db.web.Sidebar = db.web.Widget.extend({ +session.web.Sidebar = session.web.Widget.extend({ init: function(parent, element_id) { this._super(parent, element_id); this.items = {}; @@ -524,7 +549,7 @@ db.web.Sidebar = db.web.Widget.extend({ start: function() { this._super(this); var self = this; - this.$element.html(db.web.qweb.render('Sidebar')); + this.$element.html(session.web.qweb.render('Sidebar')); this.$element.find(".toggle-sidebar").click(function(e) { self.do_toggle(); }); @@ -544,7 +569,7 @@ db.web.Sidebar = db.web.Widget.extend({ { label: _t("Manage Views"), callback: this.call_default_on_sidebar, - title: _t("Manage views of the current object"), + title: _t("Manage views of the current object") }, { label: _t("Edit Workflow"), callback: this.call_default_on_sidebar, @@ -553,7 +578,7 @@ db.web.Sidebar = db.web.Widget.extend({ }, { label: _t("Customize Object"), callback: this.call_default_on_sidebar, - title: _t("Manage views of the current object"), + title: _t("Manage views of the current object") } ]); @@ -561,10 +586,10 @@ db.web.Sidebar = db.web.Widget.extend({ this.add_items('other', [ { label: _t("Import"), - callback: this.call_default_on_sidebar, + callback: this.call_default_on_sidebar }, { label: _t("Export"), - callback: this.call_default_on_sidebar, + callback: this.call_default_on_sidebar }, { label: _t("Translate"), callback: this.call_default_on_sidebar, @@ -601,10 +626,10 @@ db.web.Sidebar = db.web.Widget.extend({ if(!$section) { section_id = _.uniqueId(this.element_id + '_section_' + code + '_'); - var $section = $(db.web.qweb.render("Sidebar.section", { + var $section = $(session.web.qweb.render("Sidebar.section", { section_id: section_id, name: name, - classname: 'oe_sidebar_' + code, + classname: 'oe_sidebar_' + code })); $section.appendTo(this.$element.find('div.sidebar-actions')); this.sections[code] = $section; @@ -633,7 +658,7 @@ db.web.Sidebar = db.web.Widget.extend({ this.items[items[i].element_id] = items[i]; } - var $items = $(db.web.qweb.render("Sidebar.section.items", {items: items})); + var $items = $(session.web.qweb.render("Sidebar.section.items", {items: items})); $items.find('a.oe_sidebar_action_a').click(function() { var item = self.items[$(this).attr('id')]; @@ -687,7 +712,7 @@ db.web.Sidebar = db.web.Widget.extend({ } }); -db.web.TranslateDialog = db.web.Dialog.extend({ +session.web.TranslateDialog = session.web.Dialog.extend({ dialog_title: _t("Translations"), init: function(view) { // TODO fme: should add the language to fields_view_get because between the fields view get @@ -707,14 +732,14 @@ db.web.TranslateDialog = db.web.Dialog.extend({ this.translatable_fields_keys = _.map(this.view.translatable_fields || [], function(i) { return i.name }); this.languages = null; this.languages_loaded = $.Deferred(); - (new db.web.DataSetSearch(this, 'res.lang', this.view.dataset.get_context(), + (new session.web.DataSetSearch(this, 'res.lang', this.view.dataset.get_context(), [['translatable', '=', '1']])).read_slice(['code', 'name'], { sort: 'id' }, this.on_languages_loaded); }, start: function() { var self = this; this._super(); $.when(this.languages_loaded).then(function() { - self.$element.html(db.web.qweb.render('TranslateDialog', { widget: self })); + self.$element.html(session.web.qweb.render('TranslateDialog', { widget: self })); self.$element.tabs(); if (!(self.view.translatable_fields && self.view.translatable_fields.length)) { self.hide_tabs('fields'); @@ -819,7 +844,7 @@ db.web.TranslateDialog = db.web.Dialog.extend({ } }); -db.web.View = db.web.Widget.extend(/** @lends db.web.View# */{ +session.web.View = session.web.Widget.extend(/** @lends session.web.View# */{ template: "EmptyComponent", set_default_options: function(options) { this.options = options || {}; @@ -833,7 +858,7 @@ db.web.View = db.web.Widget.extend(/** @lends db.web.View# */{ }, open_translate_dialog: function(field) { if (!this.translate_dialog) { - this.translate_dialog = new db.web.TranslateDialog(this).start(); + this.translate_dialog = new session.web.TranslateDialog(this).start(); } this.translate_dialog.open(field); }, @@ -845,7 +870,7 @@ db.web.View = db.web.Widget.extend(/** @lends db.web.View# */{ * @param {String} [action_data.special=null] special action handlers (currently: only ``'cancel'``) * @param {String} [action_data.type='workflow'] the action type, if present, one of ``'object'``, ``'action'`` or ``'workflow'`` * @param {Object} [action_data.context=null] additional action context, to add to the current context - * @param {db.web.DataSet} dataset a dataset object used to communicate with the server + * @param {session.web.DataSet} dataset a dataset object used to communicate with the server * @param {Object} [record_id] the identifier of the object on which the action is to be applied * @param {Function} on_closed callback to execute when dialog is closed or when the action does not generate any result (no new action) */ @@ -857,12 +882,12 @@ db.web.View = db.web.Widget.extend(/** @lends db.web.View# */{ return self.widget_parent.on_action_executed.apply(null, arguments); } }; - var context = new db.web.CompoundContext(dataset.get_context(), action_data.context || {}); + var context = new session.web.CompoundContext(dataset.get_context(), action_data.context || {}); var handler = function (r) { var action = r.result; if (action && action.constructor == Object) { - var ncontext = new db.web.CompoundContext(context); + var ncontext = new session.web.CompoundContext(context); if (record_id) { ncontext.add({ active_id: record_id, @@ -899,7 +924,7 @@ db.web.View = db.web.Widget.extend(/** @lends db.web.View# */{ /** * Directly set a view to use instead of calling fields_view_get. This method must * be called before start(). When an embedded view is set, underlying implementations - * of db.web.View must use the provided view instead of any other one. + * of session.web.View must use the provided view instead of any other one. * * @param embedded_view A view. */ @@ -917,7 +942,8 @@ db.web.View = db.web.Widget.extend(/** @lends db.web.View# */{ }, on_sidebar_manage_views: function() { if (this.fields_view && this.fields_view.arch) { - $('<xmp>' + db.web.json_node_to_xml(this.fields_view.arch, true) + '</xmp>').dialog({ width: '95%', height: 600}); + var view_editor = new session.web.ViewEditor(this, this.$element, this.dataset, this.fields_view.arch); + view_editor.start(); } else { this.do_warn("Manage Views", "Could not find current view declaration"); } @@ -929,11 +955,11 @@ db.web.View = db.web.Widget.extend(/** @lends db.web.View# */{ console.log('Todo'); }, on_sidebar_import: function() { - var import_view = new db.web.DataImport(this, this.dataset); + var import_view = new session.web.DataImport(this, this.dataset); import_view.start(); }, on_sidebar_export: function() { - var export_view = new db.web.DataExport(this, this.dataset); + var export_view = new session.web.DataExport(this, this.dataset); export_view.start(); }, on_sidebar_translate: function() { @@ -943,19 +969,19 @@ db.web.View = db.web.Widget.extend(/** @lends db.web.View# */{ } }); -db.web.json_node_to_xml = function(node, single_quote, indent) { +session.web.json_node_to_xml = function(node, human_readable, indent) { // For debugging purpose, this function will convert a json node back to xml // Maybe usefull for xml view editor + indent = indent || 0; + var sindent = (human_readable ? (new Array(indent + 1).join('\t')) : ''), + r = sindent + '<' + node.tag, + cr = human_readable ? '\n' : ''; if (typeof(node) === 'string') { - return node; - } - else if (typeof(node.tag) !== 'string' || !node.children instanceof Array || !node.attrs instanceof Object) { + return sindent + node; + } else if (typeof(node.tag) !== 'string' || !node.children instanceof Array || !node.attrs instanceof Object) { throw("Node a json node"); } - indent = indent || 0; - var sindent = new Array(indent + 1).join('\t'), - r = sindent + '<' + node.tag; for (var attr in node.attrs) { var vattr = node.attrs[attr]; if (typeof(vattr) !== 'string') { @@ -963,19 +989,19 @@ db.web.json_node_to_xml = function(node, single_quote, indent) { vattr = JSON.stringify(vattr); } vattr = vattr.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"'); - if (single_quote) { + if (human_readable) { vattr = vattr.replace(/"/g, "'"); } r += ' ' + attr + '="' + vattr + '"'; } if (node.children && node.children.length) { - r += '>\n'; + r += '>' + cr; var childs = []; for (var i = 0, ii = node.children.length; i < ii; i++) { - childs.push(db.web.json_node_to_xml(node.children[i], single_quote, indent + 1)); + childs.push(session.web.json_node_to_xml(node.children[i], human_readable, indent + 1)); } - r += childs.join('\n'); - r += '\n' + sindent + '</' + node.tag + '>'; + r += childs.join(cr); + r += cr + sindent + '</' + node.tag + '>'; return r; } else { return r + '/>'; diff --git a/addons/web/static/src/xml/base.xml b/addons/web/static/src/xml/base.xml index 7720ae2d38b..1fc98ba34ee 100644 --- a/addons/web/static/src/xml/base.xml +++ b/addons/web/static/src/xml/base.xml @@ -415,6 +415,9 @@ <tr> <td class="view-manager-main-content"> <div class="oe-view-manager-header"> + <h2 class="oe_view_title" t-if="self.flags.display_title !== false"> + <t t-esc="self.display_title()"/> + </h2> <div class="oe_vm_switch"> <t t-if="views.length != 1" t-foreach="views" t-as="view"> <button type="button" t-att-data-view-type="view.view_type"> @@ -452,9 +455,6 @@ <button t-if="self.session.debug" class="oe_get_xml_view"> View#<span></span> </button> - <h2 class="oe_view_title" t-if="self.flags.display_title !== false"> - <t t-if="self.flags.display_title !== false" t-esc="self.action.name"/> - </h2> </t> <t t-jquery=".oe-view-manager-header" t-operation="after"> <ul class="oe-view-manager-logs"></ul> @@ -473,8 +473,6 @@ <h2><t t-esc="name"/></h2> </div> </t> - - <t t-name="Sidebar.section.items"> <li t-foreach="items" t-as="item" t-att-class="item.classname"> <a class="oe_sidebar_action_a" t-att-id="item.element_id" t-att-title="item.title" href="#"> @@ -551,6 +549,7 @@ </span> </td> </tr> + <table t-name="ListView" class="oe-listview-content"> <t t-set="columns_count" t-value="visible_columns.length + (options.selectable ? 1 : 0) + (options.deletable ? 1 : 0)"/> <thead class="ui-widget-header"> @@ -568,21 +567,7 @@ Delete </button> </td> - <th t-if="options.pager !== false" class="oe-list-pager"> - <button type="button" disabled="disabled" - data-pager-action="first">First</button> - <button type="button" disabled="disabled" - data-pager-action="previous" - ><</button> - - <span class="oe-pager-state"> - </span> - - <button type="button" disabled="disabled" - data-pager-action="next">></button> - <button type="button" disabled="disabled" - data-pager-action="last">Last</button> - </th> + <t t-call="Listview.navigation.button"/> </tr> </table> </th> @@ -593,7 +578,8 @@ <t t-esc="column.string"/> </th> </t> - <th t-if="options.selectable" width="1"/> + <th t-if="options.selectable" width="1" > + <input type="checkbox" class="all-record-selector"/> </th> <t t-foreach="columns" t-as="column"> <th t-if="!column.meta and column.invisible !== '1'" t-att-data-id="column.id" t-att-class="((options.sortable and column.tag !== 'button') ? 'oe-sortable' : null)"> @@ -612,8 +598,26 @@ </td> <td t-if="options.deletable"/> </tr> + <tr> + <t t-call="Listview.navigation.button"/> + </tr> </tfoot> </table> +<th t-name="Listview.navigation.button" t-if="options.pager !== false" + class="oe-list-pager" t-att-colspan="columns_count"> + <button type="button" disabled="disabled" + data-pager-action="first">First</button> + <button type="button" disabled="disabled" + data-pager-action="previous"><</button> + + <span class="oe-pager-state"> + </span> + + <button type="button" disabled="disabled" + data-pager-action="next">></button> + <button type="button" disabled="disabled" + data-pager-action="last">Last</button> +</th> <t t-name="ListView.rows" t-foreach="records.length" t-as="index"> <t t-call="ListView.row"> <t t-set="record" t-value="records.at(index)"/> @@ -628,9 +632,18 @@ </td> </t> - <th t-if="options.selectable" class="oe-record-selector" width="1"> - <input type="checkbox"/> - </th> + <t t-if="options.radio"> + <th t-if="options.selectable" class="oe-record-selector" width="1"> + <input type="radio" name ="radiogroup"/> + </th> + </t> + <t t-if="!options.radio"> + <th t-if="options.selectable" class="oe-record-selector" width="1"> + <input type="checkbox"/> + </th> + </t> + + <t t-foreach="columns" t-as="column"> <t t-set="align" t-value="column.type === 'integer' or column.type == 'float'"/> <td t-if="!column.meta and column.invisible !== '1'" t-att-title="column.help" @@ -646,18 +659,20 @@ <t t-name="ListView.row.form"> <t t-raw="frame.render()"/> </t> + <t t-name="FormView"> <div class="oe_form_header"> - <div class="oe_form_buttons" t-if="view.options.action_buttons !== false"> - <button type="button" class="oe_form_button_save"> - <span class="oe_form_on_update">Save</span> - <span class="oe_form_on_create">Create</span> + <div class="oe_form_buttons" t-if="widget.options.action_buttons !== false"> + <button type="button" class="oe_form_button_save oe_form_on_editable">Save</button> + <button type="button" class="oe_form_button_toggle"> + <span class="oe_form_on_editable">Cancel</span> + <span class="oe_form_on_readonly">Edit</span> </button> - <button type="button" class="oe_form_button_new">New</button> - <button type="button" class="oe_form_button_duplicate oe_form_on_update">Duplicate</button> - <button type="button" class="oe_form_button_toggle">Readonly/Editable</button> + <button type="button" class="oe_form_button_new oe_form_on_readonly">Create</button> + <button type="button" class="oe_form_button_duplicate oe_form_on_readonly">Duplicate</button> + <button type="button" class="oe_form_button_delete oe_form_on_readonly">Delete</button> </div> - <div class="oe_form_pager" t-if="view.options.pager !== false"> + <div class="oe_form_pager" t-if="widget.options.pager !== false"> <button type="button" data-pager-action="first">First</button> <button type="button" data-pager-action="previous"><<</button> @@ -740,12 +755,6 @@ <t t-call="WidgetFrame"/> </div> </t> -<t t-name="WidgetNotebook.readonly"> - <t t-foreach="widget.pages" t-as="page"> - <h3><t t-esc="page.string"/></h3> - <t t-raw="page.render()"/> - </t> -</t> <t t-name="WidgetSeparator"> <div t-if="widget.orientation !== 'vertical'" t-att-class="'separator ' + widget.orientation"> <t t-esc="widget.string"/> @@ -753,7 +762,7 @@ </t> <t t-name="WidgetLabel"> <label t-att-for="widget.element_id" - t-att-class="'oe_label' + (widget.help ? '_help' : '')" + t-attf-class="oe_label#{widget.help ? '_help' : ''} oe_align_#{widget.align}" t-att-title="widget.help"> <t t-esc="widget.string"/> <span t-if="widget.help">?</span> @@ -761,10 +770,10 @@ </label> </t> <t t-name="WidgetParagraph"> - <p class="oe_form_paragraph"><t t-esc="widget.string"/></p> + <p t-attf-class="oe_form_paragraph oe_align_#{widget.align}"><t t-esc="widget.string"/></p> </t> <t t-name="FieldChar"> - <input type="text" size="1" + <input t-att-type="widget.password ? 'password' : 'text'" size="1" t-att-name="widget.name" t-att-id="widget.element_id" t-attf-class="field_#{widget.type}" @@ -855,9 +864,9 @@ </t> <t t-name="FieldMany2One.context_menu"> <ul> - <li t-att-id="widget.cm_id + '_open'" style="color:grey">Open...</li> - <li t-att-id="widget.cm_id + '_create'">Create...</li> - <li t-att-id="widget.cm_id + '_search'" class="oe_m2o_menu_item_mandatory">Search...</li> + <li t-att-id="widget.cm_id + '_open'" style="color:grey" class="oe_m2o_menu_item_mandatory">Open...</li> + <li t-att-id="widget.cm_id + '_create'" class="oe_m2o_menu_item_noreadonly">Create...</li> + <li t-att-id="widget.cm_id + '_search'" class="oe_m2o_menu_item_noreadonly">Search...</li> <t t-set="i" t-value="0"/> <t t-foreach="widget.related_entries" t-as="entry"> <li t-att-id="widget.cm_id + '_related_' + i" style="color:grey" class="oe_m2o_menu_item_mandatory"> @@ -1002,6 +1011,7 @@ <span t-if="widget.string"><t t-esc="widget.string"/></span> </button> </t> + <t t-name="SearchView"> <form class="oe_forms"> <t t-call="SearchView.render_lines"/> @@ -1271,6 +1281,55 @@ .unwrap(); </t> </t> +<t t-name="view_editor"> + <table class="oe_view_editor"> + <t t-call="view_editor.row"/> + </table> +</t> +<tr t-name="view_editor.row" class="oe_view_editor_row" t-att-id="'viewedit-' + rec.id" t-att-level="rec.level" t-foreach="data" t-as="rec"> + <td class="oe_view_editor_colum" width="85%"> + <table class="oe_view_editor_tree_grid"> + <tr> + <td width="16px" t-att-style="'background-position: ' + 20*rec.level + 'px; padding-left: ' + 20*rec.level + 'px'"> + <img t-if="rec.child_id.length" t-att-id="'parentimg-' + rec.id" + src="/web/static/src/img/collapse.gif" width="16" height="16" border="0"/> + </td> + <td style="cursor: pointer;"> + <a style="text-decoration:none" href="javascript:void(0);"> <t t-esc="rec.name"/> </a> + </td> + </tr> + </table> + </td> + <td align="left" class="oe_view_editor_colum" width="15%"> + <table width="100%"> + <tr> + <td width="20%"> + <img t-if="rec.att_list.length" + id="side-add" src="/web/static/src/img/icons/gtk-add.png" style="cursor: pointer;"/> + </td> + <td width="20%"> + <img id="side-remove" src="/web/static/src/img/icons/gtk-remove.png" style="cursor: pointer;"/> + </td> + <td width="20%"> + <img t-if="rec.att_list.length" + id="side-edit" src="/web/static/src/img/icons/gtk-edit.png" style="cursor: pointer;"/> + </td> + <td width="20%"> + <img t-if="rec.att_list.length" + id="side-up" src="/web/static/src/img/icons/gtk-go-up.png" style="cursor: pointer;"/> + </td> + <td width="20%"> + <img t-if="rec.att_list.length" + id="side-down" src="/web/static/src/img/icons/gtk-go-down.png" style="cursor: pointer;"/> + </td> + </tr> + </table> + </td> + <t t-if="rec.child_id.length"> + <t t-set="data" t-value="rec.child_id"/> + <t t-call="view_editor.row"/> + </t> +</tr> <t t-name="ExportView"> <a id="exportview" href="javascript: void(0)" style="text-decoration: none;color: #3D3D3D;">Export</a> @@ -1405,7 +1464,8 @@ <a id="importview" href="javascript: void(0)" style="text-decoration: none;color: #3D3D3D;">Import</a> </t> <t t-name="ImportDataView"> -<form name="import_data" id="import_data" action="" method="post" enctype="multipart/form-data"> +<form name="import_data" id="import_data" action="" method="post" enctype="multipart/form-data" + class="oe-import oe-import-no-result"> <input type="hidden" name="session_id" t-att-value="session.session_id"/> <h2 class="separator horizontal">1. Import a .CSV file</h2> <p>Select a .CSV file to import. If you need a sample of file to import, @@ -1415,11 +1475,11 @@ <label for="csvfile">CSV File:</label> <input type="file" id="csvfile" size="50" name="csvfile"/> </p> - <h2 class="separator horizontal">2. Check your file format</h2> - <div id="result"></div> - <fieldset> - <legend style="cursor:pointer;">Import Options</legend> - <table style="display:none"> + <h2 class="separator horizontal oe-import-result">2. Check your file format</h2> + <div id="result" class="oe-import-result"></div> + <fieldset class="oe-closed oe-import-result"> + <legend>Import Options</legend> + <table> <tr> <td colspan="4"> <label for="file_has_headers">Does your file have titles?</label> @@ -1449,22 +1509,24 @@ </fieldset> </form> </t> -<table t-name="ImportView.result" - class="oe_import_grid" width="100%" style="margin: 5px 0;"> - <tr t-if="headers" class="oe_import_grid-header"> - <td t-foreach="headers" t-as="header" class="oe_import_grid-cell"> - <t t-esc="header"/></td> - </tr> - <tr> - <td t-foreach="records[0]" t-as="column"> - <input class="sel_fields"/> - </td> - </tr> - <tr t-foreach="records" t-as="record" class="oe_import_grid-row"> - <td t-foreach="record" t-as="cell" class="oe_import_grid-cell"> - <t t-esc="cell"/></td> - </tr> -</table> +<t t-name="ImportView.result"> + <table class="oe_import_grid" width="100%" style="margin: 5px 0;"> + <tr t-if="headers" class="oe_import_grid-header"> + <td t-foreach="headers" t-as="header" class="oe_import_grid-cell"> + <t t-esc="header"/></td> + </tr> + <tr> + <td t-foreach="records[0]" t-as="column"> + <input class="sel_fields" placeholder="--- Don't Import ---"/><span class="oe-m2o-drop-down-button"> + <img src="/web/static/src/img/down-arrow.png" /></span> + </td> + </tr> + <tr t-foreach="records" t-as="record" class="oe_import_grid-row"> + <td t-foreach="record" t-as="cell" class="oe_import_grid-cell"> + <t t-esc="cell"/></td> + </tr> + </table> +</t> <t t-name="ImportView.error"> <p style="white-space:pre-line;">The import failed due to:<t t-esc="error.message"/></p> <t t-if="error.preview"> diff --git a/addons/web/static/test/formats.js b/addons/web/static/test/formats.js index 3c3c6b06e72..8fc5abed42e 100644 --- a/addons/web/static/test/formats.js +++ b/addons/web/static/test/formats.js @@ -39,6 +39,8 @@ $(document).ready(function () { '1.000000'); equal(openerp.web.format_value(1, {type: 'float'}), '1.00'); + equal(openerp.web.format_value(-11.25, {type: 'float'}), + "-11.25"); }); test("parse_datetime", function () { var val = openerp.web.str_to_datetime("2009-05-04 12:34:23"); diff --git a/addons/web_calendar/__openerp__.py b/addons/web_calendar/__openerp__.py index 1eba26065f5..5b09e70cba8 100644 --- a/addons/web_calendar/__openerp__.py +++ b/addons/web_calendar/__openerp__.py @@ -11,5 +11,8 @@ "css": ['static/lib/dhtmlxScheduler/codebase/dhtmlxscheduler.css', 'static/lib/dhtmlxScheduler/codebase/ext/dhtmlxscheduler_ext.css' ], + 'qweb' : [ + "static/src/xml/*.xml", + ], 'active': True } diff --git a/addons/web_calendar/po/ar.po b/addons/web_calendar/po/ar.po new file mode 100644 index 00000000000..33e04220c2c --- /dev/null +++ b/addons/web_calendar/po/ar.po @@ -0,0 +1,22 @@ +# Arabic translation for openerp-web +# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011 +# This file is distributed under the same license as the openerp-web package. +# FIRST AUTHOR <EMAIL@ADDRESS>, 2011. +# +msgid "" +msgstr "" +"Project-Id-Version: openerp-web\n" +"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n" +"POT-Creation-Date: 2011-10-07 10:38+0200\n" +"PO-Revision-Date: 2011-11-03 15:02+0000\n" +"Last-Translator: kifcaliph <kifcaliph@hotmail.com>\n" +"Language-Team: Arabic <ar@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: 2011-11-04 05:32+0000\n" +"X-Generator: Launchpad (build 14231)\n" + +#: addons/web_calendar/static/src/xml/web_calendar.xml:0 +msgid " " +msgstr " " diff --git a/addons/web_calendar/po/da.po b/addons/web_calendar/po/da.po index a064b4cdc1f..68e2b21a673 100644 --- a/addons/web_calendar/po/da.po +++ b/addons/web_calendar/po/da.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-10-12 04:44+0000\n" -"X-Generator: Launchpad (build 14124)\n" +"X-Launchpad-Export-Date: 2011-11-01 05:09+0000\n" +"X-Generator: Launchpad (build 14197)\n" #: addons/web_calendar/static/src/xml/web_calendar.xml:0 msgid " " diff --git a/addons/web_calendar/po/de.po b/addons/web_calendar/po/de.po index c0719196cb2..27e0168a44e 100644 --- a/addons/web_calendar/po/de.po +++ b/addons/web_calendar/po/de.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-10-11 05:42+0000\n" -"X-Generator: Launchpad (build 14123)\n" +"X-Launchpad-Export-Date: 2011-11-01 05:09+0000\n" +"X-Generator: Launchpad (build 14197)\n" #: addons/web_calendar/static/src/xml/web_calendar.xml:0 msgid " " diff --git a/addons/web_calendar/po/es.po b/addons/web_calendar/po/es.po index 25e6c8c24d6..9e0c5f32f98 100644 --- a/addons/web_calendar/po/es.po +++ b/addons/web_calendar/po/es.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-10-19 06:05+0000\n" -"X-Generator: Launchpad (build 14157)\n" +"X-Launchpad-Export-Date: 2011-11-01 05:09+0000\n" +"X-Generator: Launchpad (build 14197)\n" #: addons/web_calendar/static/src/xml/web_calendar.xml:0 msgid " " diff --git a/addons/web_calendar/po/es_EC.po b/addons/web_calendar/po/es_EC.po index 2aea3aa063f..6b9cf2145dd 100644 --- a/addons/web_calendar/po/es_EC.po +++ b/addons/web_calendar/po/es_EC.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-10-08 05:30+0000\n" -"X-Generator: Launchpad (build 14110)\n" +"X-Launchpad-Export-Date: 2011-11-01 05:09+0000\n" +"X-Generator: Launchpad (build 14197)\n" #: addons/web_calendar/static/src/xml/web_calendar.xml:0 msgid " " diff --git a/addons/web_calendar/po/et.po b/addons/web_calendar/po/et.po index f9086495da6..b08c52fbfc7 100644 --- a/addons/web_calendar/po/et.po +++ b/addons/web_calendar/po/et.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-10-11 05:42+0000\n" -"X-Generator: Launchpad (build 14123)\n" +"X-Launchpad-Export-Date: 2011-11-01 05:09+0000\n" +"X-Generator: Launchpad (build 14197)\n" #: addons/web_calendar/static/src/xml/web_calendar.xml:0 msgid " " diff --git a/addons/web_calendar/po/fr.po b/addons/web_calendar/po/fr.po index 7679850c593..5f04d2d7182 100644 --- a/addons/web_calendar/po/fr.po +++ b/addons/web_calendar/po/fr.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-10-24 05:18+0000\n" -"X-Generator: Launchpad (build 14185)\n" +"X-Launchpad-Export-Date: 2011-11-01 05:09+0000\n" +"X-Generator: Launchpad (build 14197)\n" #: addons/web_calendar/static/src/xml/web_calendar.xml:0 msgid " " diff --git a/addons/web_calendar/po/gl.po b/addons/web_calendar/po/gl.po index 73ecf153937..7705a7cda2f 100644 --- a/addons/web_calendar/po/gl.po +++ b/addons/web_calendar/po/gl.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-10-20 04:48+0000\n" -"X-Generator: Launchpad (build 14165)\n" +"X-Launchpad-Export-Date: 2011-11-01 05:09+0000\n" +"X-Generator: Launchpad (build 14197)\n" #: addons/web_calendar/static/src/xml/web_calendar.xml:0 msgid " " diff --git a/addons/web_calendar/po/it.po b/addons/web_calendar/po/it.po index 29bbe86b507..5b98572ab45 100644 --- a/addons/web_calendar/po/it.po +++ b/addons/web_calendar/po/it.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-10-09 05:22+0000\n" -"X-Generator: Launchpad (build 14110)\n" +"X-Launchpad-Export-Date: 2011-11-01 05:09+0000\n" +"X-Generator: Launchpad (build 14197)\n" #: addons/web_calendar/static/src/xml/web_calendar.xml:0 msgid " " diff --git a/addons/web_calendar/po/nl_BE.po b/addons/web_calendar/po/nl_BE.po index ecb2d565787..b071632ea47 100644 --- a/addons/web_calendar/po/nl_BE.po +++ b/addons/web_calendar/po/nl_BE.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-10-08 05:30+0000\n" -"X-Generator: Launchpad (build 14110)\n" +"X-Launchpad-Export-Date: 2011-11-01 05:09+0000\n" +"X-Generator: Launchpad (build 14197)\n" #: addons/web_calendar/static/src/xml/web_calendar.xml:0 msgid " " diff --git a/addons/web_calendar/po/sk.po b/addons/web_calendar/po/sk.po index 168ca1d2adf..f879c6b13f1 100644 --- a/addons/web_calendar/po/sk.po +++ b/addons/web_calendar/po/sk.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-10-24 05:18+0000\n" -"X-Generator: Launchpad (build 14185)\n" +"X-Launchpad-Export-Date: 2011-11-01 05:09+0000\n" +"X-Generator: Launchpad (build 14197)\n" #: addons/web_calendar/static/src/xml/web_calendar.xml:0 msgid " " diff --git a/addons/web_calendar/po/sl.po b/addons/web_calendar/po/sl.po index 40f8f43a756..80c32b8728b 100644 --- a/addons/web_calendar/po/sl.po +++ b/addons/web_calendar/po/sl.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-10-20 04:48+0000\n" -"X-Generator: Launchpad (build 14165)\n" +"X-Launchpad-Export-Date: 2011-11-01 05:09+0000\n" +"X-Generator: Launchpad (build 14197)\n" #: addons/web_calendar/static/src/xml/web_calendar.xml:0 msgid " " diff --git a/addons/web_calendar/static/src/js/calendar.js b/addons/web_calendar/static/src/js/calendar.js index a5fd8bcac9c..982fc60e1c4 100644 --- a/addons/web_calendar/static/src/js/calendar.js +++ b/addons/web_calendar/static/src/js/calendar.js @@ -5,7 +5,6 @@ openerp.web_calendar = function(openerp) { var _t = openerp.web._t; var QWeb = openerp.web.qweb; -QWeb.add_template('/web_calendar/static/src/xml/web_calendar.xml'); openerp.web.views.add('calendar', 'openerp.web_calendar.CalendarView'); openerp.web_calendar.CalendarView = openerp.web.View.extend({ // Dhtmlx scheduler ? diff --git a/addons/web_dashboard/__openerp__.py b/addons/web_dashboard/__openerp__.py index 7a527511b03..68c73731c71 100644 --- a/addons/web_dashboard/__openerp__.py +++ b/addons/web_dashboard/__openerp__.py @@ -7,5 +7,8 @@ 'static/src/js/dashboard.js' ], "css": ['static/src/css/dashboard.css'], + 'qweb' : [ + "static/src/xml/*.xml", + ], 'active': True } diff --git a/addons/web_dashboard/po/ar.po b/addons/web_dashboard/po/ar.po new file mode 100644 index 00000000000..0e2cf4dfcf2 --- /dev/null +++ b/addons/web_dashboard/po/ar.po @@ -0,0 +1,46 @@ +# Arabic translation for openerp-web +# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011 +# This file is distributed under the same license as the openerp-web package. +# FIRST AUTHOR <EMAIL@ADDRESS>, 2011. +# +msgid "" +msgstr "" +"Project-Id-Version: openerp-web\n" +"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n" +"POT-Creation-Date: 2011-10-07 10:39+0200\n" +"PO-Revision-Date: 2011-11-03 15:09+0000\n" +"Last-Translator: kifcaliph <kifcaliph@hotmail.com>\n" +"Language-Team: Arabic <ar@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: 2011-11-04 05:32+0000\n" +"X-Generator: Launchpad (build 14231)\n" + +#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0 +msgid "Reset" +msgstr "إستعادة" + +#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0 +msgid "Undo" +msgstr "تراجع" + +#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0 +msgid "Add Widget" +msgstr "أضف أداة" + +#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0 +msgid "Change layout" +msgstr "تغيير المخطط" + +#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0 +msgid "Choose dashboard layout" +msgstr "اختر مخطط للعرض" + +#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0 +msgid "progress:" +msgstr "التقدم:" + +#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0 +msgid "%" +msgstr "%" diff --git a/addons/web_dashboard/po/da.po b/addons/web_dashboard/po/da.po index 8df0abb1499..312ceaa7327 100644 --- a/addons/web_dashboard/po/da.po +++ b/addons/web_dashboard/po/da.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-10-12 04:44+0000\n" -"X-Generator: Launchpad (build 14124)\n" +"X-Launchpad-Export-Date: 2011-11-01 05:09+0000\n" +"X-Generator: Launchpad (build 14197)\n" #: addons/web_dashboard/static/src/xml/web_dashboard.xml:0 msgid "Reset" diff --git a/addons/web_dashboard/po/de.po b/addons/web_dashboard/po/de.po index 6e2b8e003a3..1fecf9c9550 100644 --- a/addons/web_dashboard/po/de.po +++ b/addons/web_dashboard/po/de.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-10-11 05:42+0000\n" -"X-Generator: Launchpad (build 14123)\n" +"X-Launchpad-Export-Date: 2011-11-01 05:09+0000\n" +"X-Generator: Launchpad (build 14197)\n" #: addons/web_dashboard/static/src/xml/web_dashboard.xml:0 msgid "Reset" diff --git a/addons/web_dashboard/po/es.po b/addons/web_dashboard/po/es.po index 8cd91812416..9686bc1b517 100644 --- a/addons/web_dashboard/po/es.po +++ b/addons/web_dashboard/po/es.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-10-19 06:05+0000\n" -"X-Generator: Launchpad (build 14157)\n" +"X-Launchpad-Export-Date: 2011-11-01 05:09+0000\n" +"X-Generator: Launchpad (build 14197)\n" #: addons/web_dashboard/static/src/xml/web_dashboard.xml:0 msgid "Reset" diff --git a/addons/web_dashboard/po/es_EC.po b/addons/web_dashboard/po/es_EC.po index 11cf8918d7f..24ae8287a6d 100644 --- a/addons/web_dashboard/po/es_EC.po +++ b/addons/web_dashboard/po/es_EC.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-10-08 05:30+0000\n" -"X-Generator: Launchpad (build 14110)\n" +"X-Launchpad-Export-Date: 2011-11-01 05:09+0000\n" +"X-Generator: Launchpad (build 14197)\n" #: addons/web_dashboard/static/src/xml/web_dashboard.xml:0 msgid "Reset" diff --git a/addons/web_dashboard/po/et.po b/addons/web_dashboard/po/et.po index 381db624021..06fccba4842 100644 --- a/addons/web_dashboard/po/et.po +++ b/addons/web_dashboard/po/et.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-10-11 05:42+0000\n" -"X-Generator: Launchpad (build 14123)\n" +"X-Launchpad-Export-Date: 2011-11-01 05:09+0000\n" +"X-Generator: Launchpad (build 14197)\n" #: addons/web_dashboard/static/src/xml/web_dashboard.xml:0 msgid "Reset" diff --git a/addons/web_dashboard/po/fr.po b/addons/web_dashboard/po/fr.po index b02d061cdd2..a8c0e7ba530 100644 --- a/addons/web_dashboard/po/fr.po +++ b/addons/web_dashboard/po/fr.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-10-24 05:18+0000\n" -"X-Generator: Launchpad (build 14185)\n" +"X-Launchpad-Export-Date: 2011-11-01 05:09+0000\n" +"X-Generator: Launchpad (build 14197)\n" #: addons/web_dashboard/static/src/xml/web_dashboard.xml:0 msgid "Reset" diff --git a/addons/web_dashboard/po/gl.po b/addons/web_dashboard/po/gl.po index b7a081aff6f..16edea4823f 100644 --- a/addons/web_dashboard/po/gl.po +++ b/addons/web_dashboard/po/gl.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-10-20 04:48+0000\n" -"X-Generator: Launchpad (build 14165)\n" +"X-Launchpad-Export-Date: 2011-11-01 05:09+0000\n" +"X-Generator: Launchpad (build 14197)\n" #: addons/web_dashboard/static/src/xml/web_dashboard.xml:0 msgid "Reset" diff --git a/addons/web_dashboard/po/it.po b/addons/web_dashboard/po/it.po index 2986cb8ccd0..90e98cd48bc 100644 --- a/addons/web_dashboard/po/it.po +++ b/addons/web_dashboard/po/it.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-10-08 05:30+0000\n" -"X-Generator: Launchpad (build 14110)\n" +"X-Launchpad-Export-Date: 2011-11-01 05:09+0000\n" +"X-Generator: Launchpad (build 14197)\n" #: addons/web_dashboard/static/src/xml/web_dashboard.xml:0 msgid "Reset" diff --git a/addons/web_dashboard/po/nl_BE.po b/addons/web_dashboard/po/nl_BE.po index 40dcc0438a7..57a9fdadbf5 100644 --- a/addons/web_dashboard/po/nl_BE.po +++ b/addons/web_dashboard/po/nl_BE.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-10-08 05:30+0000\n" -"X-Generator: Launchpad (build 14110)\n" +"X-Launchpad-Export-Date: 2011-11-01 05:09+0000\n" +"X-Generator: Launchpad (build 14197)\n" #: addons/web_dashboard/static/src/xml/web_dashboard.xml:0 msgid "Reset" diff --git a/addons/web_dashboard/po/pl.po b/addons/web_dashboard/po/pl.po new file mode 100644 index 00000000000..256945c9030 --- /dev/null +++ b/addons/web_dashboard/po/pl.po @@ -0,0 +1,46 @@ +# Polish translation for openerp-web +# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011 +# This file is distributed under the same license as the openerp-web package. +# FIRST AUTHOR <EMAIL@ADDRESS>, 2011. +# +msgid "" +msgstr "" +"Project-Id-Version: openerp-web\n" +"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n" +"POT-Creation-Date: 2011-10-07 10:39+0200\n" +"PO-Revision-Date: 2011-11-04 16:28+0000\n" +"Last-Translator: Grzegorz Grzelak (OpenGLOBE.pl) <grzegorz@openglobe.pl>\n" +"Language-Team: Polish <pl@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: 2011-11-05 06:04+0000\n" +"X-Generator: Launchpad (build 14231)\n" + +#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0 +msgid "Reset" +msgstr "Przywróć" + +#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0 +msgid "Undo" +msgstr "Cofnij" + +#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0 +msgid "Add Widget" +msgstr "Dodaj kontrolkę" + +#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0 +msgid "Change layout" +msgstr "Zmień układ" + +#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0 +msgid "Choose dashboard layout" +msgstr "Wybierz układ konsoli" + +#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0 +msgid "progress:" +msgstr "postęp:" + +#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0 +msgid "%" +msgstr "" diff --git a/addons/web_dashboard/po/sk.po b/addons/web_dashboard/po/sk.po index d2c2b2160a0..a9e11093ef1 100644 --- a/addons/web_dashboard/po/sk.po +++ b/addons/web_dashboard/po/sk.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-10-24 05:18+0000\n" -"X-Generator: Launchpad (build 14185)\n" +"X-Launchpad-Export-Date: 2011-11-01 05:09+0000\n" +"X-Generator: Launchpad (build 14197)\n" #: addons/web_dashboard/static/src/xml/web_dashboard.xml:0 msgid "Reset" diff --git a/addons/web_dashboard/po/sl.po b/addons/web_dashboard/po/sl.po index 9eee401c427..01a5bf45deb 100644 --- a/addons/web_dashboard/po/sl.po +++ b/addons/web_dashboard/po/sl.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-10-20 04:48+0000\n" -"X-Generator: Launchpad (build 14165)\n" +"X-Launchpad-Export-Date: 2011-11-01 05:09+0000\n" +"X-Generator: Launchpad (build 14197)\n" #: addons/web_dashboard/static/src/xml/web_dashboard.xml:0 msgid "Reset" diff --git a/addons/web_dashboard/static/src/js/dashboard.js b/addons/web_dashboard/static/src/js/dashboard.js index 923b43ce034..e629a4a6ef5 100644 --- a/addons/web_dashboard/static/src/js/dashboard.js +++ b/addons/web_dashboard/static/src/js/dashboard.js @@ -1,6 +1,5 @@ openerp.web_dashboard = function(openerp) { var QWeb = openerp.web.qweb; -QWeb.add_template('/web_dashboard/static/src/xml/web_dashboard.xml'); if (!openerp.web_dashboard) { /** @namespace */ @@ -468,7 +467,7 @@ openerp.web_dashboard.ApplicationTiles = openerp.web.View.extend({ [['name', '=', module_name], ['state', '=', 'uninstalled']]); var Upgrade = new openerp.web.DataSet(this, 'base.module.upgrade'); - $.blockUI({message:'<img src="/web/static/src/img/throbber2.gif">'}); + $.blockUI(); Modules.read_slice(['id'], {}, function (records) { if (!(records.length === 1)) { $.unblockUI(); return; } Modules.call('state_update', diff --git a/addons/web_dashboard/static/src/xml/web_dashboard.xml b/addons/web_dashboard/static/src/xml/web_dashboard.xml index 87222baa5fd..77eab4b7e28 100644 --- a/addons/web_dashboard/static/src/xml/web_dashboard.xml +++ b/addons/web_dashboard/static/src/xml/web_dashboard.xml @@ -30,7 +30,7 @@ </t> <t t-name="DashBoard.action"> <div t-att-data-id="action.attrs.name" class="oe-dashboard-action"> - <h2 t-attf-class="oe-dashboard-action-header oe_view_title #{action.attrs.string ? '' : 'oe-dashboard-action-header-empty'}"> + <h2 t-attf-class="oe-dashboard-action-header #{action.attrs.string ? '' : 'oe-dashboard-action-header-empty'}"> <input class="oe-dashboard-action-input" type="text" name="title" value="" style="display: none"/> <t t-esc="action.attrs.string"/> <t t-if="!action.attrs.string">&nbsp;</t> diff --git a/addons/web_default_home/po/ar.po b/addons/web_default_home/po/ar.po new file mode 100644 index 00000000000..48260328d70 --- /dev/null +++ b/addons/web_default_home/po/ar.po @@ -0,0 +1,38 @@ +# Arabic translation for openerp-web +# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011 +# This file is distributed under the same license as the openerp-web package. +# FIRST AUTHOR <EMAIL@ADDRESS>, 2011. +# +msgid "" +msgstr "" +"Project-Id-Version: openerp-web\n" +"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n" +"POT-Creation-Date: 2011-10-07 10:39+0200\n" +"PO-Revision-Date: 2011-11-08 05:50+0000\n" +"Last-Translator: Ahmad Khayyat <Unknown>\n" +"Language-Team: Arabic <ar@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: 2011-11-08 06:12+0000\n" +"X-Generator: Launchpad (build 14231)\n" + +#: addons/web_default_home/static/src/xml/web_default_home.xml:0 +msgid "Welcome to your new OpenERP instance." +msgstr "أهلاً و مرحباً بك في OpenERP" + +#: addons/web_default_home/static/src/xml/web_default_home.xml:0 +msgid "Remember to bookmark this page." +msgstr "لا تنس إدراج هذه الصفحة ضمن المفضلات" + +#: addons/web_default_home/static/src/xml/web_default_home.xml:0 +msgid "Remember your login:" +msgstr "تذكر كلمة المرور" + +#: addons/web_default_home/static/src/xml/web_default_home.xml:0 +msgid "Choose the first OpenERP Application you want to install.." +msgstr "اختر أول تطبيق OpenERP تود تثبيته" + +#: addons/web_default_home/static/src/xml/web_default_home.xml:0 +msgid "Install" +msgstr "تثبيت" diff --git a/addons/web_default_home/po/da.po b/addons/web_default_home/po/da.po new file mode 100644 index 00000000000..989daa78361 --- /dev/null +++ b/addons/web_default_home/po/da.po @@ -0,0 +1,38 @@ +# Danish translation for openerp-web +# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011 +# This file is distributed under the same license as the openerp-web package. +# FIRST AUTHOR <EMAIL@ADDRESS>, 2011. +# +msgid "" +msgstr "" +"Project-Id-Version: openerp-web\n" +"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n" +"POT-Creation-Date: 2011-10-07 10:39+0200\n" +"PO-Revision-Date: 2011-10-11 14:02+0000\n" +"Last-Translator: Jonas Mortensen <Unknown>\n" +"Language-Team: Danish <da@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: 2011-11-01 05:09+0000\n" +"X-Generator: Launchpad (build 14197)\n" + +#: addons/web_default_home/static/src/xml/web_default_home.xml:0 +msgid "Welcome to your new OpenERP instance." +msgstr "Velkommen til din nye OpenERP instans." + +#: addons/web_default_home/static/src/xml/web_default_home.xml:0 +msgid "Remember to bookmark this page." +msgstr "Husk at tilføje denne side til dine favoritter." + +#: addons/web_default_home/static/src/xml/web_default_home.xml:0 +msgid "Remember your login:" +msgstr "Husk dit log ind:" + +#: addons/web_default_home/static/src/xml/web_default_home.xml:0 +msgid "Choose the first OpenERP Application you want to install.." +msgstr "Vælg den første OpenERP Applikation som du ønsker at installere." + +#: addons/web_default_home/static/src/xml/web_default_home.xml:0 +msgid "Install" +msgstr "Installér" diff --git a/addons/web_default_home/po/de.po b/addons/web_default_home/po/de.po new file mode 100644 index 00000000000..2363aea8505 --- /dev/null +++ b/addons/web_default_home/po/de.po @@ -0,0 +1,38 @@ +# German translation for openerp-web +# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011 +# This file is distributed under the same license as the openerp-web package. +# FIRST AUTHOR <EMAIL@ADDRESS>, 2011. +# +msgid "" +msgstr "" +"Project-Id-Version: openerp-web\n" +"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n" +"POT-Creation-Date: 2011-10-07 10:39+0200\n" +"PO-Revision-Date: 2011-10-10 12:40+0000\n" +"Last-Translator: Felix Schubert <Unknown>\n" +"Language-Team: German <de@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: 2011-11-01 05:10+0000\n" +"X-Generator: Launchpad (build 14197)\n" + +#: addons/web_default_home/static/src/xml/web_default_home.xml:0 +msgid "Welcome to your new OpenERP instance." +msgstr "Willkommen zu Ihrer neuen OpenERP Instanz." + +#: addons/web_default_home/static/src/xml/web_default_home.xml:0 +msgid "Remember to bookmark this page." +msgstr "Denken Sie daran ein Lesezeichen für diese Seite zu setzen." + +#: addons/web_default_home/static/src/xml/web_default_home.xml:0 +msgid "Remember your login:" +msgstr "Anmeldung speichern" + +#: addons/web_default_home/static/src/xml/web_default_home.xml:0 +msgid "Choose the first OpenERP Application you want to install.." +msgstr "Wählen Sie die erste OpenERP Anwendung die Sie installieren möchten." + +#: addons/web_default_home/static/src/xml/web_default_home.xml:0 +msgid "Install" +msgstr "Installieren" diff --git a/addons/web_default_home/po/es.po b/addons/web_default_home/po/es.po index 4f35e5b6345..5120f12015d 100644 --- a/addons/web_default_home/po/es.po +++ b/addons/web_default_home/po/es.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-10-19 06:05+0000\n" -"X-Generator: Launchpad (build 14157)\n" +"X-Launchpad-Export-Date: 2011-11-01 05:10+0000\n" +"X-Generator: Launchpad (build 14197)\n" #: addons/web_default_home/static/src/xml/web_default_home.xml:0 msgid "Welcome to your new OpenERP instance." diff --git a/addons/web_default_home/po/es_EC.po b/addons/web_default_home/po/es_EC.po new file mode 100644 index 00000000000..077b51cbeee --- /dev/null +++ b/addons/web_default_home/po/es_EC.po @@ -0,0 +1,38 @@ +# Spanish (Ecuador) translation for openerp-web +# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011 +# This file is distributed under the same license as the openerp-web package. +# FIRST AUTHOR <EMAIL@ADDRESS>, 2011. +# +msgid "" +msgstr "" +"Project-Id-Version: openerp-web\n" +"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n" +"POT-Creation-Date: 2011-10-07 10:39+0200\n" +"PO-Revision-Date: 2011-10-07 16:00+0000\n" +"Last-Translator: Cristian Salamea (Gnuthink) <ovnicraft@gmail.com>\n" +"Language-Team: Spanish (Ecuador) <es_EC@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: 2011-11-01 05:10+0000\n" +"X-Generator: Launchpad (build 14197)\n" + +#: addons/web_default_home/static/src/xml/web_default_home.xml:0 +msgid "Welcome to your new OpenERP instance." +msgstr "Bienvenido a tu nueva instancia de OpenERP" + +#: addons/web_default_home/static/src/xml/web_default_home.xml:0 +msgid "Remember to bookmark this page." +msgstr "Recuerda marcar esta página" + +#: addons/web_default_home/static/src/xml/web_default_home.xml:0 +msgid "Remember your login:" +msgstr "Recordar tu inicio de sesión" + +#: addons/web_default_home/static/src/xml/web_default_home.xml:0 +msgid "Choose the first OpenERP Application you want to install.." +msgstr "Escoge la primea Aplicación OpenERP que deseas instalar..." + +#: addons/web_default_home/static/src/xml/web_default_home.xml:0 +msgid "Install" +msgstr "Instalar" diff --git a/addons/web_default_home/po/et.po b/addons/web_default_home/po/et.po new file mode 100644 index 00000000000..a2dedb192d4 --- /dev/null +++ b/addons/web_default_home/po/et.po @@ -0,0 +1,38 @@ +# Estonian translation for openerp-web +# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011 +# This file is distributed under the same license as the openerp-web package. +# FIRST AUTHOR <EMAIL@ADDRESS>, 2011. +# +msgid "" +msgstr "" +"Project-Id-Version: openerp-web\n" +"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n" +"POT-Creation-Date: 2011-10-07 10:39+0200\n" +"PO-Revision-Date: 2011-10-10 19:29+0000\n" +"Last-Translator: Aare Vesi <Unknown>\n" +"Language-Team: Estonian <et@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: 2011-11-01 05:09+0000\n" +"X-Generator: Launchpad (build 14197)\n" + +#: addons/web_default_home/static/src/xml/web_default_home.xml:0 +msgid "Welcome to your new OpenERP instance." +msgstr "" + +#: addons/web_default_home/static/src/xml/web_default_home.xml:0 +msgid "Remember to bookmark this page." +msgstr "" + +#: addons/web_default_home/static/src/xml/web_default_home.xml:0 +msgid "Remember your login:" +msgstr "" + +#: addons/web_default_home/static/src/xml/web_default_home.xml:0 +msgid "Choose the first OpenERP Application you want to install.." +msgstr "" + +#: addons/web_default_home/static/src/xml/web_default_home.xml:0 +msgid "Install" +msgstr "Paigalda" diff --git a/addons/web_default_home/po/fr.po b/addons/web_default_home/po/fr.po index ec8855f86cf..e1b15ca7021 100644 --- a/addons/web_default_home/po/fr.po +++ b/addons/web_default_home/po/fr.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-10-24 05:18+0000\n" -"X-Generator: Launchpad (build 14185)\n" +"X-Launchpad-Export-Date: 2011-11-01 05:09+0000\n" +"X-Generator: Launchpad (build 14197)\n" #: addons/web_default_home/static/src/xml/web_default_home.xml:0 msgid "Welcome to your new OpenERP instance." diff --git a/addons/web_default_home/po/gl.po b/addons/web_default_home/po/gl.po index 4069197dec9..5783af8a2fb 100644 --- a/addons/web_default_home/po/gl.po +++ b/addons/web_default_home/po/gl.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-10-20 04:48+0000\n" -"X-Generator: Launchpad (build 14165)\n" +"X-Launchpad-Export-Date: 2011-11-01 05:10+0000\n" +"X-Generator: Launchpad (build 14197)\n" #: addons/web_default_home/static/src/xml/web_default_home.xml:0 msgid "Welcome to your new OpenERP instance." diff --git a/addons/web_default_home/po/it.po b/addons/web_default_home/po/it.po new file mode 100644 index 00000000000..a9f3a86854b --- /dev/null +++ b/addons/web_default_home/po/it.po @@ -0,0 +1,38 @@ +# Italian translation for openerp-web +# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011 +# This file is distributed under the same license as the openerp-web package. +# FIRST AUTHOR <EMAIL@ADDRESS>, 2011. +# +msgid "" +msgstr "" +"Project-Id-Version: openerp-web\n" +"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n" +"POT-Creation-Date: 2011-10-07 10:39+0200\n" +"PO-Revision-Date: 2011-10-08 13:41+0000\n" +"Last-Translator: Nicola Riolini - Micronaet <Unknown>\n" +"Language-Team: Italian <it@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: 2011-11-01 05:10+0000\n" +"X-Generator: Launchpad (build 14197)\n" + +#: addons/web_default_home/static/src/xml/web_default_home.xml:0 +msgid "Welcome to your new OpenERP instance." +msgstr "Benvenuto nella nuova istanza di OpenERP" + +#: addons/web_default_home/static/src/xml/web_default_home.xml:0 +msgid "Remember to bookmark this page." +msgstr "Ricordarsi di aggiungere ai preferiti questa pagina" + +#: addons/web_default_home/static/src/xml/web_default_home.xml:0 +msgid "Remember your login:" +msgstr "Ricordare il proprio login:" + +#: addons/web_default_home/static/src/xml/web_default_home.xml:0 +msgid "Choose the first OpenERP Application you want to install.." +msgstr "Scegliere la prima applicazione OpenERP che volete installare..." + +#: addons/web_default_home/static/src/xml/web_default_home.xml:0 +msgid "Install" +msgstr "Installa" diff --git a/addons/web_default_home/po/nl_BE.po b/addons/web_default_home/po/nl_BE.po new file mode 100644 index 00000000000..1f046075120 --- /dev/null +++ b/addons/web_default_home/po/nl_BE.po @@ -0,0 +1,38 @@ +# Dutch (Belgium) translation for openerp-web +# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011 +# This file is distributed under the same license as the openerp-web package. +# FIRST AUTHOR <EMAIL@ADDRESS>, 2011. +# +msgid "" +msgstr "" +"Project-Id-Version: openerp-web\n" +"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n" +"POT-Creation-Date: 2011-10-07 10:39+0200\n" +"PO-Revision-Date: 2011-10-07 09:07+0000\n" +"Last-Translator: Niels Huylebroeck <Unknown>\n" +"Language-Team: Dutch (Belgium) <nl_BE@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: 2011-11-01 05:10+0000\n" +"X-Generator: Launchpad (build 14197)\n" + +#: addons/web_default_home/static/src/xml/web_default_home.xml:0 +msgid "Welcome to your new OpenERP instance." +msgstr "Welkom bij uw nieuwe OpenERP." + +#: addons/web_default_home/static/src/xml/web_default_home.xml:0 +msgid "Remember to bookmark this page." +msgstr "Gelieve een bookmark voor deze pagina te maken." + +#: addons/web_default_home/static/src/xml/web_default_home.xml:0 +msgid "Remember your login:" +msgstr "Vergeet je login niet:" + +#: addons/web_default_home/static/src/xml/web_default_home.xml:0 +msgid "Choose the first OpenERP Application you want to install.." +msgstr "Kies welke OpenERP Applicatie je wilt installeren..." + +#: addons/web_default_home/static/src/xml/web_default_home.xml:0 +msgid "Install" +msgstr "Installeer" diff --git a/addons/web_default_home/po/pl.po b/addons/web_default_home/po/pl.po new file mode 100644 index 00000000000..3eec2b0ab49 --- /dev/null +++ b/addons/web_default_home/po/pl.po @@ -0,0 +1,38 @@ +# Polish translation for openerp-web +# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011 +# This file is distributed under the same license as the openerp-web package. +# FIRST AUTHOR <EMAIL@ADDRESS>, 2011. +# +msgid "" +msgstr "" +"Project-Id-Version: openerp-web\n" +"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n" +"POT-Creation-Date: 2011-10-07 10:39+0200\n" +"PO-Revision-Date: 2011-11-04 16:30+0000\n" +"Last-Translator: Grzegorz Grzelak (OpenGLOBE.pl) <grzegorz@openglobe.pl>\n" +"Language-Team: Polish <pl@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: 2011-11-05 06:04+0000\n" +"X-Generator: Launchpad (build 14231)\n" + +#: addons/web_default_home/static/src/xml/web_default_home.xml:0 +msgid "Welcome to your new OpenERP instance." +msgstr "Witamy w twojej nowej instancji OpenERP." + +#: addons/web_default_home/static/src/xml/web_default_home.xml:0 +msgid "Remember to bookmark this page." +msgstr "Pamiętaj o dodaniu tej strony do zakładek." + +#: addons/web_default_home/static/src/xml/web_default_home.xml:0 +msgid "Remember your login:" +msgstr "Zapamiętaj twój login:" + +#: addons/web_default_home/static/src/xml/web_default_home.xml:0 +msgid "Choose the first OpenERP Application you want to install.." +msgstr "Wybierz pierwszą aplikację OpenERP do instalacji." + +#: addons/web_default_home/static/src/xml/web_default_home.xml:0 +msgid "Install" +msgstr "Instaluj" diff --git a/addons/web_default_home/po/sk.po b/addons/web_default_home/po/sk.po new file mode 100644 index 00000000000..bf766fb65b0 --- /dev/null +++ b/addons/web_default_home/po/sk.po @@ -0,0 +1,38 @@ +# Slovak translation for openerp-web +# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011 +# This file is distributed under the same license as the openerp-web package. +# FIRST AUTHOR <EMAIL@ADDRESS>, 2011. +# +msgid "" +msgstr "" +"Project-Id-Version: openerp-web\n" +"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n" +"POT-Creation-Date: 2011-10-07 10:39+0200\n" +"PO-Revision-Date: 2011-11-01 13:27+0000\n" +"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" +"Language-Team: Slovak <sk@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: 2011-11-02 05:05+0000\n" +"X-Generator: Launchpad (build 14214)\n" + +#: addons/web_default_home/static/src/xml/web_default_home.xml:0 +msgid "Welcome to your new OpenERP instance." +msgstr "" + +#: addons/web_default_home/static/src/xml/web_default_home.xml:0 +msgid "Remember to bookmark this page." +msgstr "" + +#: addons/web_default_home/static/src/xml/web_default_home.xml:0 +msgid "Remember your login:" +msgstr "" + +#: addons/web_default_home/static/src/xml/web_default_home.xml:0 +msgid "Choose the first OpenERP Application you want to install.." +msgstr "" + +#: addons/web_default_home/static/src/xml/web_default_home.xml:0 +msgid "Install" +msgstr "" diff --git a/addons/web_default_home/po/sl.po b/addons/web_default_home/po/sl.po index d9f10a9e92f..2f9d918cb49 100644 --- a/addons/web_default_home/po/sl.po +++ b/addons/web_default_home/po/sl.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-10-20 04:48+0000\n" -"X-Generator: Launchpad (build 14165)\n" +"X-Launchpad-Export-Date: 2011-11-01 05:10+0000\n" +"X-Generator: Launchpad (build 14197)\n" #: addons/web_default_home/static/src/xml/web_default_home.xml:0 msgid "Welcome to your new OpenERP instance." diff --git a/addons/web_diagram/__openerp__.py b/addons/web_diagram/__openerp__.py index 584c0a16e66..cd9eb719934 100644 --- a/addons/web_diagram/__openerp__.py +++ b/addons/web_diagram/__openerp__.py @@ -13,5 +13,8 @@ 'css' : [ "static/src/css/base_diagram.css", ], + 'qweb' : [ + "static/src/xml/*.xml", + ], 'active': True, } diff --git a/addons/web_diagram/controllers/main.py b/addons/web_diagram/controllers/main.py index 51861c17b5f..55047804725 100644 --- a/addons/web_diagram/controllers/main.py +++ b/addons/web_diagram/controllers/main.py @@ -93,7 +93,6 @@ class DiagramView(View): n.update( id=act['id'], color='white', - shape='ellipse', options={} ) for color, expr in bgcolors.items(): @@ -107,12 +106,5 @@ class DiagramView(View): for i, fld in enumerate(visible_node_fields): n['options'][node_fields_string[i]] = act[fld] - #to relate m2o field of transition to corresponding o2m in activity - in_transition_field_id = fields.search([('relation', '=', connector), ('relation_field', '=', des_node), ('model', '=', node)], 0, 0, 0, req.session.context) - in_transition_field = fields.read(in_transition_field_id[0], ['name'], req.session.context)['name'] - - out_transition_field_id = fields.search([('relation', '=', connector), ('relation_field', '=', src_node), ('model', '=', node)], 0, 0, 0, req.session.context) - out_transition_field = fields.read(out_transition_field_id[0], ['name'], req.session.context)['name'] - id_model = req.session.model(model).read([id],['name'], req.session.context)[0]['name'] - return dict(nodes=nodes, conn=connectors, id_model = id_model) + return dict(nodes=nodes, conn=connectors, id_model=id_model) diff --git a/addons/web_diagram/po/ar.po b/addons/web_diagram/po/ar.po new file mode 100644 index 00000000000..af8c6ab7213 --- /dev/null +++ b/addons/web_diagram/po/ar.po @@ -0,0 +1,54 @@ +# Arabic translation for openerp-web +# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011 +# This file is distributed under the same license as the openerp-web package. +# FIRST AUTHOR <EMAIL@ADDRESS>, 2011. +# +msgid "" +msgstr "" +"Project-Id-Version: openerp-web\n" +"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n" +"POT-Creation-Date: 2011-10-07 10:39+0200\n" +"PO-Revision-Date: 2011-11-03 15:11+0000\n" +"Last-Translator: kifcaliph <kifcaliph@hotmail.com>\n" +"Language-Team: Arabic <ar@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: 2011-11-04 05:32+0000\n" +"X-Generator: Launchpad (build 14231)\n" + +#: addons/web_diagram/static/src/xml/base_diagram.xml:0 +msgid "New Node" +msgstr "طرف جديد" + +#: addons/web_diagram/static/src/xml/base_diagram.xml:0 +msgid "New Edge" +msgstr "حافة جديدة" + +#: addons/web_diagram/static/src/xml/base_diagram.xml:0 +msgid "Show Grid:" +msgstr "عرض الشبكة" + +#: addons/web_diagram/static/src/xml/base_diagram.xml:0 +msgid "First" +msgstr "الأول" + +#: addons/web_diagram/static/src/xml/base_diagram.xml:0 +msgid "<<" +msgstr ">>" + +#: addons/web_diagram/static/src/xml/base_diagram.xml:0 +msgid "0" +msgstr "0" + +#: addons/web_diagram/static/src/xml/base_diagram.xml:0 +msgid "/" +msgstr "/" + +#: addons/web_diagram/static/src/xml/base_diagram.xml:0 +msgid ">>" +msgstr ">>" + +#: addons/web_diagram/static/src/xml/base_diagram.xml:0 +msgid "Last" +msgstr "الأخير" diff --git a/addons/web_diagram/po/da.po b/addons/web_diagram/po/da.po index e91754b6da3..b0a68cf641c 100644 --- a/addons/web_diagram/po/da.po +++ b/addons/web_diagram/po/da.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-10-12 04:44+0000\n" -"X-Generator: Launchpad (build 14124)\n" +"X-Launchpad-Export-Date: 2011-11-01 05:10+0000\n" +"X-Generator: Launchpad (build 14197)\n" #: addons/web_diagram/static/src/xml/base_diagram.xml:0 msgid "New Node" diff --git a/addons/web_diagram/po/de.po b/addons/web_diagram/po/de.po index 2aa5e23eb13..1a511d763ba 100644 --- a/addons/web_diagram/po/de.po +++ b/addons/web_diagram/po/de.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-10-11 05:42+0000\n" -"X-Generator: Launchpad (build 14123)\n" +"X-Launchpad-Export-Date: 2011-11-01 05:10+0000\n" +"X-Generator: Launchpad (build 14197)\n" #: addons/web_diagram/static/src/xml/base_diagram.xml:0 msgid "New Node" diff --git a/addons/web_diagram/po/es.po b/addons/web_diagram/po/es.po index 192c69b6428..465cc16f401 100644 --- a/addons/web_diagram/po/es.po +++ b/addons/web_diagram/po/es.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-10-19 06:05+0000\n" -"X-Generator: Launchpad (build 14157)\n" +"X-Launchpad-Export-Date: 2011-11-01 05:10+0000\n" +"X-Generator: Launchpad (build 14197)\n" #: addons/web_diagram/static/src/xml/base_diagram.xml:0 msgid "New Node" diff --git a/addons/web_diagram/po/es_EC.po b/addons/web_diagram/po/es_EC.po index 0aff9dc73a0..3faa86e9bc5 100644 --- a/addons/web_diagram/po/es_EC.po +++ b/addons/web_diagram/po/es_EC.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-10-08 05:30+0000\n" -"X-Generator: Launchpad (build 14110)\n" +"X-Launchpad-Export-Date: 2011-11-01 05:10+0000\n" +"X-Generator: Launchpad (build 14197)\n" #: addons/web_diagram/static/src/xml/base_diagram.xml:0 msgid "New Node" diff --git a/addons/web_diagram/po/et.po b/addons/web_diagram/po/et.po index f2f3816fafa..5f8e394d816 100644 --- a/addons/web_diagram/po/et.po +++ b/addons/web_diagram/po/et.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-10-11 05:42+0000\n" -"X-Generator: Launchpad (build 14123)\n" +"X-Launchpad-Export-Date: 2011-11-01 05:10+0000\n" +"X-Generator: Launchpad (build 14197)\n" #: addons/web_diagram/static/src/xml/base_diagram.xml:0 msgid "New Node" diff --git a/addons/web_diagram/po/gl.po b/addons/web_diagram/po/gl.po index 0aca25055d3..27f4dc017fa 100644 --- a/addons/web_diagram/po/gl.po +++ b/addons/web_diagram/po/gl.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-10-20 04:48+0000\n" -"X-Generator: Launchpad (build 14165)\n" +"X-Launchpad-Export-Date: 2011-11-01 05:10+0000\n" +"X-Generator: Launchpad (build 14197)\n" #: addons/web_diagram/static/src/xml/base_diagram.xml:0 msgid "New Node" diff --git a/addons/web_diagram/po/it.po b/addons/web_diagram/po/it.po index f9ab13eaec5..c3ced470ca6 100644 --- a/addons/web_diagram/po/it.po +++ b/addons/web_diagram/po/it.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-10-09 05:22+0000\n" -"X-Generator: Launchpad (build 14110)\n" +"X-Launchpad-Export-Date: 2011-11-01 05:10+0000\n" +"X-Generator: Launchpad (build 14197)\n" #: addons/web_diagram/static/src/xml/base_diagram.xml:0 msgid "New Node" diff --git a/addons/web_diagram/po/nl_BE.po b/addons/web_diagram/po/nl_BE.po index 6f574501bba..4d2999c099d 100644 --- a/addons/web_diagram/po/nl_BE.po +++ b/addons/web_diagram/po/nl_BE.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-10-08 05:30+0000\n" -"X-Generator: Launchpad (build 14110)\n" +"X-Launchpad-Export-Date: 2011-11-01 05:10+0000\n" +"X-Generator: Launchpad (build 14197)\n" #: addons/web_diagram/static/src/xml/base_diagram.xml:0 msgid "New Node" diff --git a/addons/web_diagram/po/pl.po b/addons/web_diagram/po/pl.po new file mode 100644 index 00000000000..f36f3853850 --- /dev/null +++ b/addons/web_diagram/po/pl.po @@ -0,0 +1,54 @@ +# Polish translation for openerp-web +# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011 +# This file is distributed under the same license as the openerp-web package. +# FIRST AUTHOR <EMAIL@ADDRESS>, 2011. +# +msgid "" +msgstr "" +"Project-Id-Version: openerp-web\n" +"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n" +"POT-Creation-Date: 2011-10-07 10:39+0200\n" +"PO-Revision-Date: 2011-11-04 16:24+0000\n" +"Last-Translator: Grzegorz Grzelak (OpenGLOBE.pl) <grzegorz@openglobe.pl>\n" +"Language-Team: Polish <pl@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: 2011-11-05 06:04+0000\n" +"X-Generator: Launchpad (build 14231)\n" + +#: addons/web_diagram/static/src/xml/base_diagram.xml:0 +msgid "New Node" +msgstr "Nowy węzeł" + +#: addons/web_diagram/static/src/xml/base_diagram.xml:0 +msgid "New Edge" +msgstr "Nowa linia" + +#: addons/web_diagram/static/src/xml/base_diagram.xml:0 +msgid "Show Grid:" +msgstr "Pokaż siatkę" + +#: addons/web_diagram/static/src/xml/base_diagram.xml:0 +msgid "First" +msgstr "Pierwsze" + +#: addons/web_diagram/static/src/xml/base_diagram.xml:0 +msgid "<<" +msgstr "" + +#: addons/web_diagram/static/src/xml/base_diagram.xml:0 +msgid "0" +msgstr "" + +#: addons/web_diagram/static/src/xml/base_diagram.xml:0 +msgid "/" +msgstr "" + +#: addons/web_diagram/static/src/xml/base_diagram.xml:0 +msgid ">>" +msgstr "" + +#: addons/web_diagram/static/src/xml/base_diagram.xml:0 +msgid "Last" +msgstr "Ostatnie" diff --git a/addons/web_diagram/po/sl.po b/addons/web_diagram/po/sl.po index 9cce3a3564e..6766b54fb3c 100644 --- a/addons/web_diagram/po/sl.po +++ b/addons/web_diagram/po/sl.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-10-20 04:48+0000\n" -"X-Generator: Launchpad (build 14165)\n" +"X-Launchpad-Export-Date: 2011-11-01 05:10+0000\n" +"X-Generator: Launchpad (build 14197)\n" #: addons/web_diagram/static/src/xml/base_diagram.xml:0 msgid "New Node" diff --git a/addons/web_diagram/static/lib/js/dracula_graffle.js b/addons/web_diagram/static/lib/js/dracula_graffle.js index 9d4fd2099e8..2b03ad16c79 100644 --- a/addons/web_diagram/static/lib/js/dracula_graffle.js +++ b/addons/web_diagram/static/lib/js/dracula_graffle.js @@ -71,7 +71,7 @@ Raphael.fn.connection = function (obj1, obj2, style) { x3 = [0, 0, 0, 0, x4, x4, x4 - dx, x4 + dx][res[1]].toFixed(3), y3 = [0, 0, 0, 0, y1 + dy, y1 - dy, y4, y4][res[1]].toFixed(3); /* assemble path and arrow */ - var path = ["M", x1.toFixed(3), y1.toFixed(3), "C", x2, y2, x3, y3, x4.toFixed(3), y4.toFixed(3)].join(","); + var path = ["M", x1.toFixed(3), y1.toFixed(3), "C", x2, y2, x3, y3, x4.toFixed(3), y4.toFixed(3)]; /* arrow */ if(style && style.directed) { /* magnitude, length of the last path vector */ @@ -83,15 +83,16 @@ Raphael.fn.connection = function (obj1, obj2, style) { {x:(norm(x4-x3)+norm(y4-y3)+x4).toFixed(3), y:(norm(y4-y3)+norm(x4-x3)+y4).toFixed(3)}, {x:(norm(x4-x3)-norm(y4-y3)+x4).toFixed(3), y:(norm(y4-y3)-norm(x4-x3)+y4).toFixed(3)} ]; - path = path + ",M"+arr[0].x+","+arr[0].y+",L"+x4+","+y4+",L"+arr[1].x+","+arr[1].y; + path.push("M", arr[0].x, arr[0].y, "L", x4, y4, "L", arr[1].x, arr[1].y, "L", arr[0].x, arr[0].y); } + var svgpath = path.join(' '); /* function to be used for moving existent path(s), e.g. animate() or attr() */ var move = "attr"; /* applying path(s) */ - edge.fg && edge.fg[move]({path:path}) - || (edge.fg = selfRef.path(path).attr({stroke: style && style.stroke || "#000", fill: "none"}).toBack()); - edge.bg && edge.bg[move]({path:path}) - || style && style.fill && (edge.bg = style.fill.split && selfRef.path(path).attr({stroke: style.fill.split("|")[0], fill: "none", "stroke-width": style.fill.split("|")[1] || 3}).toBack()); + edge.fg && edge.fg[move]({path:svgpath}) + || (edge.fg = selfRef.path(svgpath).attr({stroke: style && style.stroke || "#000", fill: "none"}).toBack()); + edge.bg && edge.bg[move]({path:svgpath}) + || style && style.fill && (edge.bg = style.fill.split && selfRef.path(svgpath).attr({stroke: style.fill.split("|")[0], fill: "none", "stroke-width": style.fill.split("|")[1] || 3}).toBack()); /* setting label */ style && style.label && (edge.label && edge.label.attr({x:(x1+x4)/2, y:(y1+y4)/2}) diff --git a/addons/web_diagram/static/lib/js/dracula_graph.js b/addons/web_diagram/static/lib/js/dracula_graph.js index df9945882a7..28269986e78 100644 --- a/addons/web_diagram/static/lib/js/dracula_graph.js +++ b/addons/web_diagram/static/lib/js/dracula_graph.js @@ -160,13 +160,11 @@ Graph.Renderer.Raphael = function(element, graph, width, height) { */ this.isDrag = false; this.dragger = function (e) { - if(e.detail < 2) { - this.dx = e.clientX; - this.dy = e.clientY; - selfRef.isDrag = this; - this.set && this.set.animate({"fill-opacity": .1}, 200) && this.set.toFront(); - e.preventDefault && e.preventDefault(); - } + this.dx = e.clientX; + this.dy = e.clientY; + selfRef.isDrag = this; + this.set && this.set.animate({"fill-opacity": .1}, 200); + e.preventDefault && e.preventDefault(); }; var d = document.getElementById(element); @@ -378,6 +376,8 @@ Graph.Layout.Spring.prototype = { }, layoutRepulsive: function(node1, node2) { + if (typeof node1 == 'undefined' || typeof node2 == 'undefined') + return; var dx = node2.layoutPosX - node1.layoutPosX; var dy = node2.layoutPosY - node1.layoutPosY; var d2 = dx * dx + dy * dy; diff --git a/addons/web_diagram/static/lib/js/raphael-min.js b/addons/web_diagram/static/lib/js/raphael-min.js index 8718b5bc749..e69ea16a809 100644 --- a/addons/web_diagram/static/lib/js/raphael-min.js +++ b/addons/web_diagram/static/lib/js/raphael-min.js @@ -1,7 +1,8 @@ -/* - * Raphael 1.3.1 - JavaScript Vector Library - * - * Copyright (c) 2008 - 2009 Dmitry Baranovskiy (http://raphaeljs.com) - * Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license. - */ -Raphael=(function(){var a=/[, ]+/,aO=/^(circle|rect|path|ellipse|text|image)$/,L=document,au=window,l={was:"Raphael" in au,is:au.Raphael},an=function(){if(an.is(arguments[0],"array")){var d=arguments[0],e=w[aW](an,d.splice(0,3+an.is(d[0],al))),S=e.set();for(var R=0,a0=d[m];R<a0;R++){var E=d[R]||{};aO.test(E.type)&&S[f](e[E.type]().attr(E));}return S;}return w[aW](an,arguments);},aT=function(){},aL="appendChild",aW="apply",aS="concat",at="",am=" ",z="split",F="click dblclick mousedown mousemove mouseout mouseover mouseup"[z](am),Q="hasOwnProperty",az="join",m="length",aY="prototype",aZ=String[aY].toLowerCase,ab=Math,g=ab.max,aI=ab.min,al="number",aA="toString",aw=Object[aY][aA],aQ={},aM=ab.pow,f="push",aU=/^(?=[\da-f]$)/,c=/^url\(['"]?([^\)]+)['"]?\)$/i,x=/^\s*((#[a-f\d]{6})|(#[a-f\d]{3})|rgb\(\s*([\d\.]+\s*,\s*[\d\.]+\s*,\s*[\d\.]+)\s*\)|rgb\(\s*([\d\.]+%\s*,\s*[\d\.]+%\s*,\s*[\d\.]+%)\s*\)|hs[bl]\(\s*([\d\.]+\s*,\s*[\d\.]+\s*,\s*[\d\.]+)\s*\)|hs[bl]\(\s*([\d\.]+%\s*,\s*[\d\.]+%\s*,\s*[\d\.]+%)\s*\))\s*$/i,O=ab.round,v="setAttribute",W=parseFloat,G=parseInt,aN=String[aY].toUpperCase,j={"clip-rect":"0 0 1e9 1e9",cursor:"default",cx:0,cy:0,fill:"#fff","fill-opacity":1,font:'10px "Arial"',"font-family":'"Arial"',"font-size":"10","font-style":"normal","font-weight":400,gradient:0,height:0,href:"http://raphaeljs.com/",opacity:1,path:"M0,0",r:0,rotation:0,rx:0,ry:0,scale:"1 1",src:"",stroke:"#000","stroke-dasharray":"","stroke-linecap":"butt","stroke-linejoin":"butt","stroke-miterlimit":0,"stroke-opacity":1,"stroke-width":1,target:"_blank","text-anchor":"middle",title:"Raphael",translation:"0 0",width:0,x:0,y:0},Z={along:"along","clip-rect":"csv",cx:al,cy:al,fill:"colour","fill-opacity":al,"font-size":al,height:al,opacity:al,path:"path",r:al,rotation:"csv",rx:al,ry:al,scale:"csv",stroke:"colour","stroke-opacity":al,"stroke-width":al,translation:"csv",width:al,x:al,y:al},aP="replace";an.version="1.3.1";an.type=(au.SVGAngle||L.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1")?"SVG":"VML");if(an.type=="VML"){var ag=document.createElement("div");ag.innerHTML="<!--[if vml]><br><br><![endif]-->";if(ag.childNodes[m]!=2){return null;}}an.svg=!(an.vml=an.type=="VML");aT[aY]=an[aY];an._id=0;an._oid=0;an.fn={};an.is=function(e,d){d=aZ.call(d);return((d=="object"||d=="undefined")&&typeof e==d)||(e==null&&d=="null")||aZ.call(aw.call(e).slice(8,-1))==d;};an.setWindow=function(d){au=d;L=au.document;};var aD=function(e){if(an.vml){var d=/^\s+|\s+$/g;aD=aj(function(R){var S;R=(R+at)[aP](d,at);try{var a0=new ActiveXObject("htmlfile");a0.write("<body>");a0.close();S=a0.body;}catch(a2){S=createPopup().document.body;}var i=S.createTextRange();try{S.style.color=R;var a1=i.queryCommandValue("ForeColor");a1=((a1&255)<<16)|(a1&65280)|((a1&16711680)>>>16);return"#"+("000000"+a1[aA](16)).slice(-6);}catch(a2){return"none";}});}else{var E=L.createElement("i");E.title="Rapha\xebl Colour Picker";E.style.display="none";L.body[aL](E);aD=aj(function(i){E.style.color=i;return L.defaultView.getComputedStyle(E,at).getPropertyValue("color");});}return aD(e);};an.hsb2rgb=aj(function(a3,a1,a7){if(an.is(a3,"object")&&"h" in a3&&"s" in a3&&"b" in a3){a7=a3.b;a1=a3.s;a3=a3.h;}var R,S,a8;if(a7==0){return{r:0,g:0,b:0,hex:"#000"};}if(a3>1||a1>1||a7>1){a3/=255;a1/=255;a7/=255;}var a0=~~(a3*6),a4=(a3*6)-a0,E=a7*(1-a1),e=a7*(1-(a1*a4)),a9=a7*(1-(a1*(1-a4)));R=[a7,e,E,E,a9,a7,a7][a0];S=[a9,a7,a7,e,E,E,a9][a0];a8=[E,E,a9,a7,a7,e,E][a0];R*=255;S*=255;a8*=255;var a5={r:R,g:S,b:a8},d=(~~R)[aA](16),a2=(~~S)[aA](16),a6=(~~a8)[aA](16);d=d[aP](aU,"0");a2=a2[aP](aU,"0");a6=a6[aP](aU,"0");a5.hex="#"+d+a2+a6;return a5;},an);an.rgb2hsb=aj(function(d,e,a1){if(an.is(d,"object")&&"r" in d&&"g" in d&&"b" in d){a1=d.b;e=d.g;d=d.r;}if(an.is(d,"string")){var a3=an.getRGB(d);d=a3.r;e=a3.g;a1=a3.b;}if(d>1||e>1||a1>1){d/=255;e/=255;a1/=255;}var a0=g(d,e,a1),i=aI(d,e,a1),R,E,S=a0;if(i==a0){return{h:0,s:0,b:a0};}else{var a2=(a0-i);E=a2/a0;if(d==a0){R=(e-a1)/a2;}else{if(e==a0){R=2+((a1-d)/a2);}else{R=4+((d-e)/a2);}}R/=6;R<0&&R++;R>1&&R--;}return{h:R,s:E,b:S};},an);var aE=/,?([achlmqrstvxz]),?/gi;an._path2string=function(){return this.join(",")[aP](aE,"$1");};function aj(E,e,d){function i(){var R=Array[aY].slice.call(arguments,0),a0=R[az]("\u25ba"),S=i.cache=i.cache||{},a1=i.count=i.count||[];if(S[Q](a0)){return d?d(S[a0]):S[a0];}a1[m]>=1000&&delete S[a1.shift()];a1[f](a0);S[a0]=E[aW](e,R);return d?d(S[a0]):S[a0];}return i;}an.getRGB=aj(function(d){if(!d||!!((d=d+at).indexOf("-")+1)){return{r:-1,g:-1,b:-1,hex:"none",error:1};}if(d=="none"){return{r:-1,g:-1,b:-1,hex:"none"};}!(({hs:1,rg:1})[Q](d.substring(0,2))||d.charAt()=="#")&&(d=aD(d));var S,i,E,a2,a3,a0=d.match(x);if(a0){if(a0[2]){a2=G(a0[2].substring(5),16);E=G(a0[2].substring(3,5),16);i=G(a0[2].substring(1,3),16);}if(a0[3]){a2=G((a3=a0[3].charAt(3))+a3,16);E=G((a3=a0[3].charAt(2))+a3,16);i=G((a3=a0[3].charAt(1))+a3,16);}if(a0[4]){a0=a0[4][z](/\s*,\s*/);i=W(a0[0]);E=W(a0[1]);a2=W(a0[2]);}if(a0[5]){a0=a0[5][z](/\s*,\s*/);i=W(a0[0])*2.55;E=W(a0[1])*2.55;a2=W(a0[2])*2.55;}if(a0[6]){a0=a0[6][z](/\s*,\s*/);i=W(a0[0]);E=W(a0[1]);a2=W(a0[2]);return an.hsb2rgb(i,E,a2);}if(a0[7]){a0=a0[7][z](/\s*,\s*/);i=W(a0[0])*2.55;E=W(a0[1])*2.55;a2=W(a0[2])*2.55;return an.hsb2rgb(i,E,a2);}a0={r:i,g:E,b:a2};var e=(~~i)[aA](16),R=(~~E)[aA](16),a1=(~~a2)[aA](16);e=e[aP](aU,"0");R=R[aP](aU,"0");a1=a1[aP](aU,"0");a0.hex="#"+e+R+a1;return a0;}return{r:-1,g:-1,b:-1,hex:"none",error:1};},an);an.getColor=function(e){var i=this.getColor.start=this.getColor.start||{h:0,s:1,b:e||0.75},d=this.hsb2rgb(i.h,i.s,i.b);i.h+=0.075;if(i.h>1){i.h=0;i.s-=0.2;i.s<=0&&(this.getColor.start={h:0,s:1,b:i.b});}return d.hex;};an.getColor.reset=function(){delete this.start;};an.parsePathString=aj(function(d){if(!d){return null;}var i={a:7,c:6,h:1,l:2,m:2,q:4,s:4,t:2,v:1,z:0},e=[];if(an.is(d,"array")&&an.is(d[0],"array")){e=av(d);}if(!e[m]){(d+at)[aP](/([achlmqstvz])[\s,]*((-?\d*\.?\d*(?:e[-+]?\d+)?\s*,?\s*)+)/ig,function(R,E,a1){var a0=[],S=aZ.call(E);a1[aP](/(-?\d*\.?\d*(?:e[-+]?\d+)?)\s*,?\s*/ig,function(a3,a2){a2&&a0[f](+a2);});while(a0[m]>=i[S]){e[f]([E][aS](a0.splice(0,i[S])));if(!i[S]){break;}}});}e[aA]=an._path2string;return e;});an.findDotsAtSegment=function(e,d,be,bc,a0,R,a2,a1,a8){var a6=1-a8,a5=aM(a6,3)*e+aM(a6,2)*3*a8*be+a6*3*a8*a8*a0+aM(a8,3)*a2,a3=aM(a6,3)*d+aM(a6,2)*3*a8*bc+a6*3*a8*a8*R+aM(a8,3)*a1,ba=e+2*a8*(be-e)+a8*a8*(a0-2*be+e),a9=d+2*a8*(bc-d)+a8*a8*(R-2*bc+d),bd=be+2*a8*(a0-be)+a8*a8*(a2-2*a0+be),bb=bc+2*a8*(R-bc)+a8*a8*(a1-2*R+bc),a7=(1-a8)*e+a8*be,a4=(1-a8)*d+a8*bc,E=(1-a8)*a0+a8*a2,i=(1-a8)*R+a8*a1,S=(90-ab.atan((ba-bd)/(a9-bb))*180/ab.PI);(ba>bd||a9<bb)&&(S+=180);return{x:a5,y:a3,m:{x:ba,y:a9},n:{x:bd,y:bb},start:{x:a7,y:a4},end:{x:E,y:i},alpha:S};};var U=aj(function(a5){if(!a5){return{x:0,y:0,width:0,height:0};}a5=H(a5);var a2=0,a1=0,R=[],e=[],E;for(var S=0,a4=a5[m];S<a4;S++){E=a5[S];if(E[0]=="M"){a2=E[1];a1=E[2];R[f](a2);e[f](a1);}else{var a0=aC(a2,a1,E[1],E[2],E[3],E[4],E[5],E[6]);R=R[aS](a0.min.x,a0.max.x);e=e[aS](a0.min.y,a0.max.y);a2=E[5];a1=E[6];}}var d=aI[aW](0,R),a3=aI[aW](0,e);return{x:d,y:a3,width:g[aW](0,R)-d,height:g[aW](0,e)-a3};}),av=function(a0){var E=[];if(!an.is(a0,"array")||!an.is(a0&&a0[0],"array")){a0=an.parsePathString(a0);}for(var e=0,R=a0[m];e<R;e++){E[e]=[];for(var d=0,S=a0[e][m];d<S;d++){E[e][d]=a0[e][d];}}E[aA]=an._path2string;return E;},ad=aj(function(R){if(!an.is(R,"array")||!an.is(R&&R[0],"array")){R=an.parsePathString(R);}var a4=[],a6=0,a5=0,a9=0,a8=0,E=0;if(R[0][0]=="M"){a6=R[0][1];a5=R[0][2];a9=a6;a8=a5;E++;a4[f](["M",a6,a5]);}for(var a1=E,ba=R[m];a1<ba;a1++){var d=a4[a1]=[],a7=R[a1];if(a7[0]!=aZ.call(a7[0])){d[0]=aZ.call(a7[0]);switch(d[0]){case"a":d[1]=a7[1];d[2]=a7[2];d[3]=a7[3];d[4]=a7[4];d[5]=a7[5];d[6]=+(a7[6]-a6).toFixed(3);d[7]=+(a7[7]-a5).toFixed(3);break;case"v":d[1]=+(a7[1]-a5).toFixed(3);break;case"m":a9=a7[1];a8=a7[2];default:for(var a0=1,a2=a7[m];a0<a2;a0++){d[a0]=+(a7[a0]-((a0%2)?a6:a5)).toFixed(3);}}}else{d=a4[a1]=[];if(a7[0]=="m"){a9=a7[1]+a6;a8=a7[2]+a5;}for(var S=0,e=a7[m];S<e;S++){a4[a1][S]=a7[S];}}var a3=a4[a1][m];switch(a4[a1][0]){case"z":a6=a9;a5=a8;break;case"h":a6+=+a4[a1][a3-1];break;case"v":a5+=+a4[a1][a3-1];break;default:a6+=+a4[a1][a3-2];a5+=+a4[a1][a3-1];}}a4[aA]=an._path2string;return a4;},0,av),r=aj(function(R){if(!an.is(R,"array")||!an.is(R&&R[0],"array")){R=an.parsePathString(R);}var a3=[],a5=0,a4=0,a8=0,a7=0,E=0;if(R[0][0]=="M"){a5=+R[0][1];a4=+R[0][2];a8=a5;a7=a4;E++;a3[0]=["M",a5,a4];}for(var a1=E,a9=R[m];a1<a9;a1++){var d=a3[a1]=[],a6=R[a1];if(a6[0]!=aN.call(a6[0])){d[0]=aN.call(a6[0]);switch(d[0]){case"A":d[1]=a6[1];d[2]=a6[2];d[3]=a6[3];d[4]=a6[4];d[5]=a6[5];d[6]=+(a6[6]+a5);d[7]=+(a6[7]+a4);break;case"V":d[1]=+a6[1]+a4;break;case"H":d[1]=+a6[1]+a5;break;case"M":a8=+a6[1]+a5;a7=+a6[2]+a4;default:for(var a0=1,a2=a6[m];a0<a2;a0++){d[a0]=+a6[a0]+((a0%2)?a5:a4);}}}else{for(var S=0,e=a6[m];S<e;S++){a3[a1][S]=a6[S];}}switch(d[0]){case"Z":a5=a8;a4=a7;break;case"H":a5=d[1];break;case"V":a4=d[1];break;default:a5=a3[a1][a3[a1][m]-2];a4=a3[a1][a3[a1][m]-1];}}a3[aA]=an._path2string;return a3;},null,av),aX=function(e,E,d,i){return[e,E,d,i,d,i];},aK=function(e,E,a0,R,d,i){var S=1/3,a1=2/3;return[S*e+a1*a0,S*E+a1*R,S*d+a1*a0,S*i+a1*R,d,i];},K=function(a9,bE,bi,bg,ba,a4,S,a8,bD,bb){var R=ab.PI,bf=R*120/180,d=R/180*(+ba||0),bm=[],bj,bA=aj(function(bF,bI,i){var bH=bF*ab.cos(i)-bI*ab.sin(i),bG=bF*ab.sin(i)+bI*ab.cos(i);return{x:bH,y:bG};});if(!bb){bj=bA(a9,bE,-d);a9=bj.x;bE=bj.y;bj=bA(a8,bD,-d);a8=bj.x;bD=bj.y;var e=ab.cos(R/180*ba),a6=ab.sin(R/180*ba),bo=(a9-a8)/2,bn=(bE-bD)/2;bi=g(bi,ab.abs(bo));bg=g(bg,ab.abs(bn));var by=(bo*bo)/(bi*bi)+(bn*bn)/(bg*bg);if(by>1){bi=ab.sqrt(by)*bi;bg=ab.sqrt(by)*bg;}var E=bi*bi,br=bg*bg,bt=(a4==S?-1:1)*ab.sqrt(ab.abs((E*br-E*bn*bn-br*bo*bo)/(E*bn*bn+br*bo*bo))),bd=bt*bi*bn/bg+(a9+a8)/2,bc=bt*-bg*bo/bi+(bE+bD)/2,a3=ab.asin(((bE-bc)/bg).toFixed(7)),a2=ab.asin(((bD-bc)/bg).toFixed(7));a3=a9<bd?R-a3:a3;a2=a8<bd?R-a2:a2;a3<0&&(a3=R*2+a3);a2<0&&(a2=R*2+a2);if(S&&a3>a2){a3=a3-R*2;}if(!S&&a2>a3){a2=a2-R*2;}}else{a3=bb[0];a2=bb[1];bd=bb[2];bc=bb[3];}var a7=a2-a3;if(ab.abs(a7)>bf){var be=a2,bh=a8,a5=bD;a2=a3+bf*(S&&a2>a3?1:-1);a8=bd+bi*ab.cos(a2);bD=bc+bg*ab.sin(a2);bm=K(a8,bD,bi,bg,ba,0,S,bh,a5,[a2,be,bd,bc]);}a7=a2-a3;var a1=ab.cos(a3),bC=ab.sin(a3),a0=ab.cos(a2),bB=ab.sin(a2),bp=ab.tan(a7/4),bs=4/3*bi*bp,bq=4/3*bg*bp,bz=[a9,bE],bx=[a9+bs*bC,bE-bq*a1],bw=[a8+bs*bB,bD-bq*a0],bu=[a8,bD];bx[0]=2*bz[0]-bx[0];bx[1]=2*bz[1]-bx[1];if(bb){return[bx,bw,bu][aS](bm);}else{bm=[bx,bw,bu][aS](bm)[az]()[z](",");var bk=[];for(var bv=0,bl=bm[m];bv<bl;bv++){bk[bv]=bv%2?bA(bm[bv-1],bm[bv],d).y:bA(bm[bv],bm[bv+1],d).x;}return bk;}},M=function(e,d,E,i,a2,a1,a0,S,a3){var R=1-a3;return{x:aM(R,3)*e+aM(R,2)*3*a3*E+R*3*a3*a3*a2+aM(a3,3)*a0,y:aM(R,3)*d+aM(R,2)*3*a3*i+R*3*a3*a3*a1+aM(a3,3)*S};},aC=aj(function(i,d,R,E,a9,a8,a5,a2){var a7=(a9-2*R+i)-(a5-2*a9+R),a4=2*(R-i)-2*(a9-R),a1=i-R,a0=(-a4+ab.sqrt(a4*a4-4*a7*a1))/2/a7,S=(-a4-ab.sqrt(a4*a4-4*a7*a1))/2/a7,a3=[d,a2],a6=[i,a5],e;ab.abs(a0)>1000000000000&&(a0=0.5);ab.abs(S)>1000000000000&&(S=0.5);if(a0>0&&a0<1){e=M(i,d,R,E,a9,a8,a5,a2,a0);a6[f](e.x);a3[f](e.y);}if(S>0&&S<1){e=M(i,d,R,E,a9,a8,a5,a2,S);a6[f](e.x);a3[f](e.y);}a7=(a8-2*E+d)-(a2-2*a8+E);a4=2*(E-d)-2*(a8-E);a1=d-E;a0=(-a4+ab.sqrt(a4*a4-4*a7*a1))/2/a7;S=(-a4-ab.sqrt(a4*a4-4*a7*a1))/2/a7;ab.abs(a0)>1000000000000&&(a0=0.5);ab.abs(S)>1000000000000&&(S=0.5);if(a0>0&&a0<1){e=M(i,d,R,E,a9,a8,a5,a2,a0);a6[f](e.x);a3[f](e.y);}if(S>0&&S<1){e=M(i,d,R,E,a9,a8,a5,a2,S);a6[f](e.x);a3[f](e.y);}return{min:{x:aI[aW](0,a6),y:aI[aW](0,a3)},max:{x:g[aW](0,a6),y:g[aW](0,a3)}};}),H=aj(function(a9,a4){var R=r(a9),a5=a4&&r(a4),a6={x:0,y:0,bx:0,by:0,X:0,Y:0,qx:null,qy:null},d={x:0,y:0,bx:0,by:0,X:0,Y:0,qx:null,qy:null},a0=function(ba,bb){var i,bc;if(!ba){return["C",bb.x,bb.y,bb.x,bb.y,bb.x,bb.y];}!(ba[0] in {T:1,Q:1})&&(bb.qx=bb.qy=null);switch(ba[0]){case"M":bb.X=ba[1];bb.Y=ba[2];break;case"A":ba=["C"][aS](K[aW](0,[bb.x,bb.y][aS](ba.slice(1))));break;case"S":i=bb.x+(bb.x-(bb.bx||bb.x));bc=bb.y+(bb.y-(bb.by||bb.y));ba=["C",i,bc][aS](ba.slice(1));break;case"T":bb.qx=bb.x+(bb.x-(bb.qx||bb.x));bb.qy=bb.y+(bb.y-(bb.qy||bb.y));ba=["C"][aS](aK(bb.x,bb.y,bb.qx,bb.qy,ba[1],ba[2]));break;case"Q":bb.qx=ba[1];bb.qy=ba[2];ba=["C"][aS](aK(bb.x,bb.y,ba[1],ba[2],ba[3],ba[4]));break;case"L":ba=["C"][aS](aX(bb.x,bb.y,ba[1],ba[2]));break;case"H":ba=["C"][aS](aX(bb.x,bb.y,ba[1],bb.y));break;case"V":ba=["C"][aS](aX(bb.x,bb.y,bb.x,ba[1]));break;case"Z":ba=["C"][aS](aX(bb.x,bb.y,bb.X,bb.Y));break;}return ba;},e=function(ba,bb){if(ba[bb][m]>7){ba[bb].shift();var bc=ba[bb];while(bc[m]){ba.splice(bb++,0,["C"][aS](bc.splice(0,6)));}ba.splice(bb,1);a7=g(R[m],a5&&a5[m]||0);}},E=function(be,bd,bb,ba,bc){if(be&&bd&&be[bc][0]=="M"&&bd[bc][0]!="M"){bd.splice(bc,0,["M",ba.x,ba.y]);bb.bx=0;bb.by=0;bb.x=be[bc][1];bb.y=be[bc][2];a7=g(R[m],a5&&a5[m]||0);}};for(var a2=0,a7=g(R[m],a5&&a5[m]||0);a2<a7;a2++){R[a2]=a0(R[a2],a6);e(R,a2);a5&&(a5[a2]=a0(a5[a2],d));a5&&e(a5,a2);E(R,a5,a6,d,a2);E(a5,R,d,a6,a2);var a1=R[a2],a8=a5&&a5[a2],S=a1[m],a3=a5&&a8[m];a6.x=a1[S-2];a6.y=a1[S-1];a6.bx=W(a1[S-4])||a6.x;a6.by=W(a1[S-3])||a6.y;d.bx=a5&&(W(a8[a3-4])||d.x);d.by=a5&&(W(a8[a3-3])||d.y);d.x=a5&&a8[a3-2];d.y=a5&&a8[a3-1];}return a5?[R,a5]:R;},null,av),p=aj(function(a4){var a3=[];for(var a0=0,a5=a4[m];a0<a5;a0++){var e={},a2=a4[a0].match(/^([^:]*):?([\d\.]*)/);e.color=an.getRGB(a2[1]);if(e.color.error){return null;}e.color=e.color.hex;a2[2]&&(e.offset=a2[2]+"%");a3[f](e);}for(var a0=1,a5=a3[m]-1;a0<a5;a0++){if(!a3[a0].offset){var E=W(a3[a0-1].offset||0),R=0;for(var S=a0+1;S<a5;S++){if(a3[S].offset){R=a3[S].offset;break;}}if(!R){R=100;S=a5;}R=W(R);var a1=(R-E)/(S-a0+1);for(;a0<S;a0++){E+=a1;a3[a0].offset=E+"%";}}}return a3;}),ao=function(){var i,e,R,E,d;if(an.is(arguments[0],"string")||an.is(arguments[0],"object")){if(an.is(arguments[0],"string")){i=L.getElementById(arguments[0]);}else{i=arguments[0];}if(i.tagName){if(arguments[1]==null){return{container:i,width:i.style.pixelWidth||i.offsetWidth,height:i.style.pixelHeight||i.offsetHeight};}else{return{container:i,width:arguments[1],height:arguments[2]};}}}else{if(an.is(arguments[0],al)&&arguments[m]>3){return{container:1,x:arguments[0],y:arguments[1],width:arguments[2],height:arguments[3]};}}},aG=function(d,i){var e=this;for(var E in i){if(i[Q](E)&&!(E in d)){switch(typeof i[E]){case"function":(function(R){d[E]=d===e?R:function(){return R[aW](e,arguments);};})(i[E]);break;case"object":d[E]=d[E]||{};aG.call(this,d[E],i[E]);break;default:d[E]=i[E];break;}}}},ak=function(d,e){d==e.top&&(e.top=d.prev);d==e.bottom&&(e.bottom=d.next);d.next&&(d.next.prev=d.prev);d.prev&&(d.prev.next=d.next);},Y=function(d,e){if(e.top===d){return;}ak(d,e);d.next=null;d.prev=e.top;e.top.next=d;e.top=d;},k=function(d,e){if(e.bottom===d){return;}ak(d,e);d.next=e.bottom;d.prev=null;e.bottom.prev=d;e.bottom=d;},A=function(e,d,i){ak(e,i);d==i.top&&(i.top=e);d.next&&(d.next.prev=e);e.next=d.next;e.prev=d;d.next=e;},aq=function(e,d,i){ak(e,i);d==i.bottom&&(i.bottom=e);d.prev&&(d.prev.next=e);e.prev=d.prev;d.prev=e;e.next=d;},s=function(d){return function(){throw new Error("Rapha\xebl: you are calling to method \u201c"+d+"\u201d of removed object");};},ar=/^r(?:\(([^,]+?)\s*,\s*([^\)]+?)\))?/;if(an.svg){aT[aY].svgns="http://www.w3.org/2000/svg";aT[aY].xlink="http://www.w3.org/1999/xlink";var O=function(d){return +d+(~~d===d)*0.5;},V=function(S){for(var e=0,E=S[m];e<E;e++){if(aZ.call(S[e][0])!="a"){for(var d=1,R=S[e][m];d<R;d++){S[e][d]=O(S[e][d]);}}else{S[e][6]=O(S[e][6]);S[e][7]=O(S[e][7]);}}return S;},aJ=function(i,d){if(d){for(var e in d){if(d[Q](e)){i[v](e,d[e]);}}}else{return L.createElementNS(aT[aY].svgns,i);}};an[aA]=function(){return"Your browser supports SVG.\nYou are running Rapha\xebl "+this.version;};var q=function(d,E){var e=aJ("path");E.canvas&&E.canvas[aL](e);var i=new ax(e,E);i.type="path";aa(i,{fill:"none",stroke:"#000",path:d});return i;};var b=function(E,a7,d){var a4="linear",a1=0.5,S=0.5,a9=E.style;a7=(a7+at)[aP](ar,function(bb,i,bc){a4="radial";if(i&&bc){a1=W(i);S=W(bc);var ba=((S>0.5)*2-1);aM(a1-0.5,2)+aM(S-0.5,2)>0.25&&(S=ab.sqrt(0.25-aM(a1-0.5,2))*ba+0.5)&&S!=0.5&&(S=S.toFixed(5)-0.00001*ba);}return at;});a7=a7[z](/\s*\-\s*/);if(a4=="linear"){var a0=a7.shift();a0=-W(a0);if(isNaN(a0)){return null;}var R=[0,0,ab.cos(a0*ab.PI/180),ab.sin(a0*ab.PI/180)],a6=1/(g(ab.abs(R[2]),ab.abs(R[3]))||1);R[2]*=a6;R[3]*=a6;if(R[2]<0){R[0]=-R[2];R[2]=0;}if(R[3]<0){R[1]=-R[3];R[3]=0;}}var a3=p(a7);if(!a3){return null;}var e=aJ(a4+"Gradient");e.id="r"+(an._id++)[aA](36);aJ(e,a4=="radial"?{fx:a1,fy:S}:{x1:R[0],y1:R[1],x2:R[2],y2:R[3]});d.defs[aL](e);for(var a2=0,a8=a3[m];a2<a8;a2++){var a5=aJ("stop");aJ(a5,{offset:a3[a2].offset?a3[a2].offset:!a2?"0%":"100%","stop-color":a3[a2].color||"#fff"});e[aL](a5);}aJ(E,{fill:"url(#"+e.id+")",opacity:1,"fill-opacity":1});a9.fill=at;a9.opacity=1;a9.fillOpacity=1;return 1;};var N=function(e){var d=e.getBBox();aJ(e.pattern,{patternTransform:an.format("translate({0},{1})",d.x,d.y)});};var aa=function(a6,bf){var a9={"":[0],none:[0],"-":[3,1],".":[1,1],"-.":[3,1,1,1],"-..":[3,1,1,1,1,1],". ":[1,3],"- ":[4,3],"--":[8,3],"- .":[4,3,1,3],"--.":[8,3,1,3],"--..":[8,3,1,3,1,3]},bb=a6.node,a7=a6.attrs,a3=a6.rotate(),S=function(bm,bl){bl=a9[aZ.call(bl)];if(bl){var bj=bm.attrs["stroke-width"]||"1",bh={round:bj,square:bj,butt:0}[bm.attrs["stroke-linecap"]||bf["stroke-linecap"]]||0,bk=[];var bi=bl[m];while(bi--){bk[bi]=bl[bi]*bj+((bi%2)?1:-1)*bh;}aJ(bb,{"stroke-dasharray":bk[az](",")});}};bf[Q]("rotation")&&(a3=bf.rotation);var a2=(a3+at)[z](a);if(!(a2.length-1)){a2=null;}else{a2[1]=+a2[1];a2[2]=+a2[2];}W(a3)&&a6.rotate(0,true);for(var ba in bf){if(bf[Q](ba)){if(!j[Q](ba)){continue;}var a8=bf[ba];a7[ba]=a8;switch(ba){case"rotation":a6.rotate(a8,true);break;case"href":case"title":case"target":var bd=bb.parentNode;if(aZ.call(bd.tagName)!="a"){var E=aJ("a");bd.insertBefore(E,bb);E[aL](bb);bd=E;}bd.setAttributeNS(a6.paper.xlink,ba,a8);break;case"cursor":bb.style.cursor=a8;break;case"clip-rect":var e=(a8+at)[z](a);if(e[m]==4){a6.clip&&a6.clip.parentNode.parentNode.removeChild(a6.clip.parentNode);var i=aJ("clipPath"),bc=aJ("rect");i.id="r"+(an._id++)[aA](36);aJ(bc,{x:e[0],y:e[1],width:e[2],height:e[3]});i[aL](bc);a6.paper.defs[aL](i);aJ(bb,{"clip-path":"url(#"+i.id+")"});a6.clip=bc;}if(!a8){var be=L.getElementById(bb.getAttribute("clip-path")[aP](/(^url\(#|\)$)/g,at));be&&be.parentNode.removeChild(be);aJ(bb,{"clip-path":at});delete a6.clip;}break;case"path":if(a8&&a6.type=="path"){a7.path=V(r(a8));aJ(bb,{d:a7.path});}break;case"width":bb[v](ba,a8);if(a7.fx){ba="x";a8=a7.x;}else{break;}case"x":if(a7.fx){a8=-a7.x-(a7.width||0);}case"rx":if(ba=="rx"&&a6.type=="rect"){break;}case"cx":a2&&(ba=="x"||ba=="cx")&&(a2[1]+=a8-a7[ba]);bb[v](ba,O(a8));a6.pattern&&N(a6);break;case"height":bb[v](ba,a8);if(a7.fy){ba="y";a8=a7.y;}else{break;}case"y":if(a7.fy){a8=-a7.y-(a7.height||0);}case"ry":if(ba=="ry"&&a6.type=="rect"){break;}case"cy":a2&&(ba=="y"||ba=="cy")&&(a2[2]+=a8-a7[ba]);bb[v](ba,O(a8));a6.pattern&&N(a6);break;case"r":if(a6.type=="rect"){aJ(bb,{rx:a8,ry:a8});}else{bb[v](ba,a8);}break;case"src":if(a6.type=="image"){bb.setAttributeNS(a6.paper.xlink,"href",a8);}break;case"stroke-width":bb.style.strokeWidth=a8;bb[v](ba,a8);if(a7["stroke-dasharray"]){S(a6,a7["stroke-dasharray"]);}break;case"stroke-dasharray":S(a6,a8);break;case"translation":var a0=(a8+at)[z](a);a0[0]=+a0[0]||0;a0[1]=+a0[1]||0;if(a2){a2[1]+=a0[0];a2[2]+=a0[1];}t.call(a6,a0[0],a0[1]);break;case"scale":var a0=(a8+at)[z](a);a6.scale(+a0[0]||1,+a0[1]||+a0[0]||1,+a0[2]||null,+a0[3]||null);break;case"fill":var R=(a8+at).match(c);if(R){var i=aJ("pattern"),a5=aJ("image");i.id="r"+(an._id++)[aA](36);aJ(i,{x:0,y:0,patternUnits:"userSpaceOnUse",height:1,width:1});aJ(a5,{x:0,y:0});a5.setAttributeNS(a6.paper.xlink,"href",R[1]);i[aL](a5);var bg=L.createElement("img");bg.style.cssText="position:absolute;left:-9999em;top-9999em";bg.onload=function(){aJ(i,{width:this.offsetWidth,height:this.offsetHeight});aJ(a5,{width:this.offsetWidth,height:this.offsetHeight});L.body.removeChild(this);a6.paper.safari();};L.body[aL](bg);bg.src=R[1];a6.paper.defs[aL](i);bb.style.fill="url(#"+i.id+")";aJ(bb,{fill:"url(#"+i.id+")"});a6.pattern=i;a6.pattern&&N(a6);break;}if(!an.getRGB(a8).error){delete bf.gradient;delete a7.gradient;!an.is(a7.opacity,"undefined")&&an.is(bf.opacity,"undefined")&&aJ(bb,{opacity:a7.opacity});!an.is(a7["fill-opacity"],"undefined")&&an.is(bf["fill-opacity"],"undefined")&&aJ(bb,{"fill-opacity":a7["fill-opacity"]});}else{if((({circle:1,ellipse:1})[Q](a6.type)||(a8+at).charAt()!="r")&&b(bb,a8,a6.paper)){a7.gradient=a8;a7.fill="none";break;}}case"stroke":bb[v](ba,an.getRGB(a8).hex);break;case"gradient":(({circle:1,ellipse:1})[Q](a6.type)||(a8+at).charAt()!="r")&&b(bb,a8,a6.paper);break;case"opacity":case"fill-opacity":if(a7.gradient){var d=L.getElementById(bb.getAttribute("fill")[aP](/^url\(#|\)$/g,at));if(d){var a1=d.getElementsByTagName("stop");a1[a1[m]-1][v]("stop-opacity",a8);}break;}default:ba=="font-size"&&(a8=G(a8,10)+"px");var a4=ba[aP](/(\-.)/g,function(bh){return aN.call(bh.substring(1));});bb.style[a4]=a8;bb[v](ba,a8);break;}}}D(a6,bf);if(a2){a6.rotate(a2.join(am));}else{W(a3)&&a6.rotate(a3,true);}};var h=1.2;var D=function(d,R){if(d.type!="text"||!(R[Q]("text")||R[Q]("font")||R[Q]("font-size")||R[Q]("x")||R[Q]("y"))){return;}var a3=d.attrs,e=d.node,a5=e.firstChild?G(L.defaultView.getComputedStyle(e.firstChild,at).getPropertyValue("font-size"),10):10;if(R[Q]("text")){a3.text=R.text;while(e.firstChild){e.removeChild(e.firstChild);}var E=(R.text+at)[z]("\n");for(var S=0,a4=E[m];S<a4;S++){if(E[S]){var a1=aJ("tspan");S&&aJ(a1,{dy:a5*h,x:a3.x});a1[aL](L.createTextNode(E[S]));e[aL](a1);}}}else{var E=e.getElementsByTagName("tspan");for(var S=0,a4=E[m];S<a4;S++){S&&aJ(E[S],{dy:a5*h,x:a3.x});}}aJ(e,{y:a3.y});var a0=d.getBBox(),a2=a3.y-(a0.y+a0.height/2);a2&&isFinite(a2)&&aJ(e,{y:a3.y+a2});};var ax=function(e,d){var E=0,i=0;this[0]=e;this.id=an._oid++;this.node=e;e.raphael=this;this.paper=d;this.attrs=this.attrs||{};this.transformations=[];this._={tx:0,ty:0,rt:{deg:0,cx:0,cy:0},sx:1,sy:1};!d.bottom&&(d.bottom=this);this.prev=d.top;d.top&&(d.top.next=this);d.top=this;this.next=null;};ax[aY].rotate=function(e,d,E){if(this.removed){return this;}if(e==null){if(this._.rt.cx){return[this._.rt.deg,this._.rt.cx,this._.rt.cy][az](am);}return this._.rt.deg;}var i=this.getBBox();e=(e+at)[z](a);if(e[m]-1){d=W(e[1]);E=W(e[2]);}e=W(e[0]);if(d!=null){this._.rt.deg=e;}else{this._.rt.deg+=e;}(E==null)&&(d=null);this._.rt.cx=d;this._.rt.cy=E;d=d==null?i.x+i.width/2:d;E=E==null?i.y+i.height/2:E;if(this._.rt.deg){this.transformations[0]=an.format("rotate({0} {1} {2})",this._.rt.deg,d,E);this.clip&&aJ(this.clip,{transform:an.format("rotate({0} {1} {2})",-this._.rt.deg,d,E)});}else{this.transformations[0]=at;this.clip&&aJ(this.clip,{transform:at});}aJ(this.node,{transform:this.transformations[az](am)});return this;};ax[aY].hide=function(){!this.removed&&(this.node.style.display="none");return this;};ax[aY].show=function(){!this.removed&&(this.node.style.display="");return this;};ax[aY].remove=function(){if(this.removed){return;}ak(this,this.paper);this.node.parentNode.removeChild(this.node);for(var d in this){delete this[d];}this.removed=true;};ax[aY].getBBox=function(){if(this.removed){return this;}if(this.type=="path"){return U(this.attrs.path);}if(this.node.style.display=="none"){this.show();var E=true;}var a1={};try{a1=this.node.getBBox();}catch(S){}finally{a1=a1||{};}if(this.type=="text"){a1={x:a1.x,y:Infinity,width:0,height:0};for(var d=0,R=this.node.getNumberOfChars();d<R;d++){var a0=this.node.getExtentOfChar(d);(a0.y<a1.y)&&(a1.y=a0.y);(a0.y+a0.height-a1.y>a1.height)&&(a1.height=a0.y+a0.height-a1.y);(a0.x+a0.width-a1.x>a1.width)&&(a1.width=a0.x+a0.width-a1.x);}}E&&this.hide();return a1;};ax[aY].attr=function(){if(this.removed){return this;}if(arguments[m]==0){var R={};for(var E in this.attrs){if(this.attrs[Q](E)){R[E]=this.attrs[E];}}this._.rt.deg&&(R.rotation=this.rotate());(this._.sx!=1||this._.sy!=1)&&(R.scale=this.scale());R.gradient&&R.fill=="none"&&(R.fill=R.gradient)&&delete R.gradient;return R;}if(arguments[m]==1&&an.is(arguments[0],"string")){if(arguments[0]=="translation"){return t.call(this);}if(arguments[0]=="rotation"){return this.rotate();}if(arguments[0]=="scale"){return this.scale();}if(arguments[0]=="fill"&&this.attrs.fill=="none"&&this.attrs.gradient){return this.attrs.gradient;}return this.attrs[arguments[0]];}if(arguments[m]==1&&an.is(arguments[0],"array")){var d={};for(var e in arguments[0]){if(arguments[0][Q](e)){d[arguments[0][e]]=this.attrs[arguments[0][e]];}}return d;}if(arguments[m]==2){var S={};S[arguments[0]]=arguments[1];aa(this,S);}else{if(arguments[m]==1&&an.is(arguments[0],"object")){aa(this,arguments[0]);}}return this;};ax[aY].toFront=function(){if(this.removed){return this;}this.node.parentNode[aL](this.node);var d=this.paper;d.top!=this&&Y(this,d);return this;};ax[aY].toBack=function(){if(this.removed){return this;}if(this.node.parentNode.firstChild!=this.node){this.node.parentNode.insertBefore(this.node,this.node.parentNode.firstChild);k(this,this.paper);var d=this.paper;}return this;};ax[aY].insertAfter=function(d){if(this.removed){return this;}var e=d.node;if(e.nextSibling){e.parentNode.insertBefore(this.node,e.nextSibling);}else{e.parentNode[aL](this.node);}A(this,d,this.paper);return this;};ax[aY].insertBefore=function(d){if(this.removed){return this;}var e=d.node;e.parentNode.insertBefore(this.node,e);aq(this,d,this.paper);return this;};var P=function(e,d,S,R){d=O(d);S=O(S);var E=aJ("circle");e.canvas&&e.canvas[aL](E);var i=new ax(E,e);i.attrs={cx:d,cy:S,r:R,fill:"none",stroke:"#000"};i.type="circle";aJ(E,i.attrs);return i;};var aF=function(i,d,a1,e,S,a0){d=O(d);a1=O(a1);var R=aJ("rect");i.canvas&&i.canvas[aL](R);var E=new ax(R,i);E.attrs={x:d,y:a1,width:e,height:S,r:a0||0,rx:a0||0,ry:a0||0,fill:"none",stroke:"#000"};E.type="rect";aJ(R,E.attrs);return E;};var ai=function(e,d,a0,S,R){d=O(d);a0=O(a0);var E=aJ("ellipse");e.canvas&&e.canvas[aL](E);var i=new ax(E,e);i.attrs={cx:d,cy:a0,rx:S,ry:R,fill:"none",stroke:"#000"};i.type="ellipse";aJ(E,i.attrs);return i;};var o=function(i,a0,d,a1,e,S){var R=aJ("image");aJ(R,{x:d,y:a1,width:e,height:S,preserveAspectRatio:"none"});R.setAttributeNS(i.xlink,"href",a0);i.canvas&&i.canvas[aL](R);var E=new ax(R,i);E.attrs={x:d,y:a1,width:e,height:S,src:a0};E.type="image";return E;};var X=function(e,d,S,R){var E=aJ("text");aJ(E,{x:d,y:S,"text-anchor":"middle"});e.canvas&&e.canvas[aL](E);var i=new ax(E,e);i.attrs={x:d,y:S,"text-anchor":"middle",text:R,font:j.font,stroke:"none",fill:"#000"};i.type="text";aa(i,i.attrs);return i;};var aV=function(e,d){this.width=e||this.width;this.height=d||this.height;this.canvas[v]("width",this.width);this.canvas[v]("height",this.height);return this;};var w=function(){var E=ao[aW](null,arguments),i=E&&E.container,e=E.x,a0=E.y,R=E.width,d=E.height;if(!i){throw new Error("SVG container not found.");}var S=aJ("svg");R=R||512;d=d||342;aJ(S,{xmlns:"http://www.w3.org/2000/svg",version:1.1,width:R,height:d});if(i==1){S.style.cssText="position:absolute;left:"+e+"px;top:"+a0+"px";L.body[aL](S);}else{if(i.firstChild){i.insertBefore(S,i.firstChild);}else{i[aL](S);}}i=new aT;i.width=R;i.height=d;i.canvas=S;aG.call(i,i,an.fn);i.clear();return i;};aT[aY].clear=function(){var d=this.canvas;while(d.firstChild){d.removeChild(d.firstChild);}this.bottom=this.top=null;(this.desc=aJ("desc"))[aL](L.createTextNode("Created with Rapha\xebl"));d[aL](this.desc);d[aL](this.defs=aJ("defs"));};aT[aY].remove=function(){this.canvas.parentNode&&this.canvas.parentNode.removeChild(this.canvas);for(var d in this){this[d]=s(d);}};}if(an.vml){var aH=function(a8){var a5=/[ahqstv]/ig,a0=r;(a8+at).match(a5)&&(a0=H);a5=/[clmz]/g;if(a0==r&&!(a8+at).match(a5)){var e={M:"m",L:"l",C:"c",Z:"x",m:"t",l:"r",c:"v",z:"x"},R=/([clmz]),?([^clmz]*)/gi,S=/-?[^,\s-]+/g;var a4=(a8+at)[aP](R,function(a9,bb,i){var ba=[];i[aP](S,function(bc){ba[f](O(bc));});return e[bb]+ba;});return a4;}var a6=a0(a8),E,a4=[],d;for(var a2=0,a7=a6[m];a2<a7;a2++){E=a6[a2];d=aZ.call(a6[a2][0]);d=="z"&&(d="x");for(var a1=1,a3=E[m];a1<a3;a1++){d+=O(E[a1])+(a1!=a3-1?",":at);}a4[f](d);}return a4[az](am);};an[aA]=function(){return"Your browser doesn\u2019t support SVG. Falling down to VML.\nYou are running Rapha\xebl "+this.version;};var q=function(d,S){var E=ah("group");E.style.cssText="position:absolute;left:0;top:0;width:"+S.width+"px;height:"+S.height+"px";E.coordsize=S.coordsize;E.coordorigin=S.coordorigin;var i=ah("shape"),e=i.style;e.width=S.width+"px";e.height=S.height+"px";i.coordsize=this.coordsize;i.coordorigin=this.coordorigin;E[aL](i);var R=new ax(i,E,S);R.isAbsolute=true;R.type="path";R.path=[];R.Path=at;d&&aa(R,{fill:"none",stroke:"#000",path:d});S.canvas[aL](E);return R;};var aa=function(a3,a8){a3.attrs=a3.attrs||{};var a6=a3.node,a9=a3.attrs,a0=a6.style,E,bd=a3;for(var a1 in a8){if(a8[Q](a1)){a9[a1]=a8[a1];}}a8.href&&(a6.href=a8.href);a8.title&&(a6.title=a8.title);a8.target&&(a6.target=a8.target);a8.cursor&&(a0.cursor=a8.cursor);if(a8.path&&a3.type=="path"){a9.path=a8.path;a6.path=aH(a9.path);}if(a8.rotation!=null){a3.rotate(a8.rotation,true);}if(a8.translation){E=(a8.translation+at)[z](a);t.call(a3,E[0],E[1]);if(a3._.rt.cx!=null){a3._.rt.cx+=+E[0];a3._.rt.cy+=+E[1];a3.setBox(a3.attrs,E[0],E[1]);}}if(a8.scale){E=(a8.scale+at)[z](a);a3.scale(+E[0]||1,+E[1]||+E[0]||1,+E[2]||null,+E[3]||null);}if("clip-rect" in a8){var d=(a8["clip-rect"]+at)[z](a);if(d[m]==4){d[2]=+d[2]+(+d[0]);d[3]=+d[3]+(+d[1]);var a2=a6.clipRect||L.createElement("div"),bc=a2.style,S=a6.parentNode;bc.clip=an.format("rect({1}px {2}px {3}px {0}px)",d);if(!a6.clipRect){bc.position="absolute";bc.top=0;bc.left=0;bc.width=a3.paper.width+"px";bc.height=a3.paper.height+"px";S.parentNode.insertBefore(a2,S);a2[aL](S);a6.clipRect=a2;}}if(!a8["clip-rect"]){a6.clipRect&&(a6.clipRect.style.clip=at);}}if(a3.type=="image"&&a8.src){a6.src=a8.src;}if(a3.type=="image"&&a8.opacity){a6.filterOpacity=" progid:DXImageTransform.Microsoft.Alpha(opacity="+(a8.opacity*100)+")";a0.filter=(a6.filterMatrix||at)+(a6.filterOpacity||at);}a8.font&&(a0.font=a8.font);a8["font-family"]&&(a0.fontFamily='"'+a8["font-family"][z](",")[0][aP](/^['"]+|['"]+$/g,at)+'"');a8["font-size"]&&(a0.fontSize=a8["font-size"]);a8["font-weight"]&&(a0.fontWeight=a8["font-weight"]);a8["font-style"]&&(a0.fontStyle=a8["font-style"]);if(a8.opacity!=null||a8["stroke-width"]!=null||a8.fill!=null||a8.stroke!=null||a8["stroke-width"]!=null||a8["stroke-opacity"]!=null||a8["fill-opacity"]!=null||a8["stroke-dasharray"]!=null||a8["stroke-miterlimit"]!=null||a8["stroke-linejoin"]!=null||a8["stroke-linecap"]!=null){a6=a3.shape||a6;var a7=(a6.getElementsByTagName("fill")&&a6.getElementsByTagName("fill")[0]),ba=false;!a7&&(ba=a7=ah("fill"));if("fill-opacity" in a8||"opacity" in a8){var e=((+a9["fill-opacity"]+1||2)-1)*((+a9.opacity+1||2)-1);e<0&&(e=0);e>1&&(e=1);a7.opacity=e;}a8.fill&&(a7.on=true);if(a7.on==null||a8.fill=="none"){a7.on=false;}if(a7.on&&a8.fill){var i=a8.fill.match(c);if(i){a7.src=i[1];a7.type="tile";}else{a7.color=an.getRGB(a8.fill).hex;a7.src=at;a7.type="solid";if(an.getRGB(a8.fill).error&&(bd.type in {circle:1,ellipse:1}||(a8.fill+at).charAt()!="r")&&b(bd,a8.fill)){a9.fill="none";a9.gradient=a8.fill;}}}ba&&a6[aL](a7);var R=(a6.getElementsByTagName("stroke")&&a6.getElementsByTagName("stroke")[0]),bb=false;!R&&(bb=R=ah("stroke"));if((a8.stroke&&a8.stroke!="none")||a8["stroke-width"]||a8["stroke-opacity"]!=null||a8["stroke-dasharray"]||a8["stroke-miterlimit"]||a8["stroke-linejoin"]||a8["stroke-linecap"]){R.on=true;}(a8.stroke=="none"||R.on==null||a8.stroke==0||a8["stroke-width"]==0)&&(R.on=false);R.on&&a8.stroke&&(R.color=an.getRGB(a8.stroke).hex);var e=((+a9["stroke-opacity"]+1||2)-1)*((+a9.opacity+1||2)-1),a4=(W(a8["stroke-width"])||1)*0.75;e<0&&(e=0);e>1&&(e=1);a8["stroke-width"]==null&&(a4=a9["stroke-width"]);a8["stroke-width"]&&(R.weight=a4);a4&&a4<1&&(e*=a4)&&(R.weight=1);R.opacity=e;a8["stroke-linejoin"]&&(R.joinstyle=a8["stroke-linejoin"]||"miter");R.miterlimit=a8["stroke-miterlimit"]||8;a8["stroke-linecap"]&&(R.endcap=a8["stroke-linecap"]=="butt"?"flat":a8["stroke-linecap"]=="square"?"square":"round");if(a8["stroke-dasharray"]){var a5={"-":"shortdash",".":"shortdot","-.":"shortdashdot","-..":"shortdashdotdot",". ":"dot","- ":"dash","--":"longdash","- .":"dashdot","--.":"longdashdot","--..":"longdashdotdot"};R.dashstyle=a5[Q](a8["stroke-dasharray"])?a5[a8["stroke-dasharray"]]:at;}bb&&a6[aL](R);}if(bd.type=="text"){var a0=bd.paper.span.style;a9.font&&(a0.font=a9.font);a9["font-family"]&&(a0.fontFamily=a9["font-family"]);a9["font-size"]&&(a0.fontSize=a9["font-size"]);a9["font-weight"]&&(a0.fontWeight=a9["font-weight"]);a9["font-style"]&&(a0.fontStyle=a9["font-style"]);bd.node.string&&(bd.paper.span.innerHTML=(bd.node.string+at)[aP](/</g,"<")[aP](/&/g,"&")[aP](/\n/g,"<br>"));bd.W=a9.w=bd.paper.span.offsetWidth;bd.H=a9.h=bd.paper.span.offsetHeight;bd.X=a9.x;bd.Y=a9.y+O(bd.H/2);switch(a9["text-anchor"]){case"start":bd.node.style["v-text-align"]="left";bd.bbx=O(bd.W/2);break;case"end":bd.node.style["v-text-align"]="right";bd.bbx=-O(bd.W/2);break;default:bd.node.style["v-text-align"]="center";break;}}};var b=function(d,a1){d.attrs=d.attrs||{};var a2=d.attrs,a4=d.node.getElementsByTagName("fill"),S="linear",a0=".5 .5";d.attrs.gradient=a1;a1=(a1+at)[aP](ar,function(a6,a7,i){S="radial";if(a7&&i){a7=W(a7);i=W(i);aM(a7-0.5,2)+aM(i-0.5,2)>0.25&&(i=ab.sqrt(0.25-aM(a7-0.5,2))*((i>0.5)*2-1)+0.5);a0=a7+am+i;}return at;});a1=a1[z](/\s*\-\s*/);if(S=="linear"){var e=a1.shift();e=-W(e);if(isNaN(e)){return null;}}var R=p(a1);if(!R){return null;}d=d.shape||d.node;a4=a4[0]||ah("fill");if(R[m]){a4.on=true;a4.method="none";a4.type=(S=="radial")?"gradientradial":"gradient";a4.color=R[0].color;a4.color2=R[R[m]-1].color;var a5=[];for(var E=0,a3=R[m];E<a3;E++){R[E].offset&&a5[f](R[E].offset+am+R[E].color);}a4.colors&&(a4.colors.value=a5[m]?a5[az](","):"0% "+a4.color);if(S=="radial"){a4.focus="100%";a4.focussize=a0;a4.focusposition=a0;}else{a4.angle=(270-e)%360;}}return 1;};var ax=function(R,a0,d){var S=0,i=0,e=0,E=1;this[0]=R;this.id=an._oid++;this.node=R;R.raphael=this;this.X=0;this.Y=0;this.attrs={};this.Group=a0;this.paper=d;this._={tx:0,ty:0,rt:{deg:0},sx:1,sy:1};!d.bottom&&(d.bottom=this);this.prev=d.top;d.top&&(d.top.next=this);d.top=this;this.next=null;};ax[aY].rotate=function(e,d,i){if(this.removed){return this;}if(e==null){if(this._.rt.cx){return[this._.rt.deg,this._.rt.cx,this._.rt.cy][az](am);}return this._.rt.deg;}e=(e+at)[z](a);if(e[m]-1){d=W(e[1]);i=W(e[2]);}e=W(e[0]);if(d!=null){this._.rt.deg=e;}else{this._.rt.deg+=e;}i==null&&(d=null);this._.rt.cx=d;this._.rt.cy=i;this.setBox(this.attrs,d,i);this.Group.style.rotation=this._.rt.deg;return this;};ax[aY].setBox=function(bb,e,d){if(this.removed){return this;}var a5=this.Group.style,R=(this.shape&&this.shape.style)||this.node.style;bb=bb||{};for(var a9 in bb){if(bb[Q](a9)){this.attrs[a9]=bb[a9];}}e=e||this._.rt.cx;d=d||this._.rt.cy;var a7=this.attrs,a1,a0,a2,ba;switch(this.type){case"circle":a1=a7.cx-a7.r;a0=a7.cy-a7.r;a2=ba=a7.r*2;break;case"ellipse":a1=a7.cx-a7.rx;a0=a7.cy-a7.ry;a2=a7.rx*2;ba=a7.ry*2;break;case"rect":case"image":a1=+a7.x;a0=+a7.y;a2=a7.width||0;ba=a7.height||0;break;case"text":this.textpath.v=["m",O(a7.x),", ",O(a7.y-2),"l",O(a7.x)+1,", ",O(a7.y-2)][az](at);a1=a7.x-O(this.W/2);a0=a7.y-this.H/2;a2=this.W;ba=this.H;break;case"path":if(!this.attrs.path){a1=0;a0=0;a2=this.paper.width;ba=this.paper.height;}else{var a8=U(this.attrs.path);a1=a8.x;a0=a8.y;a2=a8.width;ba=a8.height;}break;default:a1=0;a0=0;a2=this.paper.width;ba=this.paper.height;break;}e=(e==null)?a1+a2/2:e;d=(d==null)?a0+ba/2:d;var E=e-this.paper.width/2,a4=d-this.paper.height/2;if(this.type=="path"||this.type=="text"){(a5.left!=E+"px")&&(a5.left=E+"px");(a5.top!=a4+"px")&&(a5.top=a4+"px");this.X=this.type=="text"?a1:-E;this.Y=this.type=="text"?a0:-a4;this.W=a2;this.H=ba;(R.left!=-E+"px")&&(R.left=-E+"px");(R.top!=-a4+"px")&&(R.top=-a4+"px");}else{(a5.left!=E+"px")&&(a5.left=E+"px");(a5.top!=a4+"px")&&(a5.top=a4+"px");this.X=a1;this.Y=a0;this.W=a2;this.H=ba;(a5.width!=this.paper.width+"px")&&(a5.width=this.paper.width+"px");(a5.height!=this.paper.height+"px")&&(a5.height=this.paper.height+"px");(R.left!=a1-E+"px")&&(R.left=a1-E+"px");(R.top!=a0-a4+"px")&&(R.top=a0-a4+"px");(R.width!=a2+"px")&&(R.width=a2+"px");(R.height!=ba+"px")&&(R.height=ba+"px");var S=(+bb.r||0)/aI(a2,ba);if(this.type=="rect"&&this.arcsize.toFixed(4)!=S.toFixed(4)&&(S||this.arcsize)){var a6=ah("roundrect"),bc={},a9=0,a3=this.events&&this.events[m];a6.arcsize=S;a6.raphael=this;this.Group[aL](a6);this.Group.removeChild(this.node);this[0]=this.node=a6;this.arcsize=S;for(var a9 in a7){bc[a9]=a7[a9];}delete bc.scale;this.attr(bc);if(this.events){for(;a9<a3;a9++){this.events[a9].unbind=ae(this.node,this.events[a9].name,this.events[a9].f,this);}}}}};ax[aY].hide=function(){!this.removed&&(this.Group.style.display="none");return this;};ax[aY].show=function(){!this.removed&&(this.Group.style.display="block");return this;};ax[aY].getBBox=function(){if(this.removed){return this;}if(this.type=="path"){return U(this.attrs.path);}return{x:this.X+(this.bbx||0),y:this.Y,width:this.W,height:this.H};};ax[aY].remove=function(){if(this.removed){return;}ak(this,this.paper);this.node.parentNode.removeChild(this.node);this.Group.parentNode.removeChild(this.Group);this.shape&&this.shape.parentNode.removeChild(this.shape);for(var d in this){delete this[d];}this.removed=true;};ax[aY].attr=function(){if(this.removed){return this;}if(arguments[m]==0){var E={};for(var e in this.attrs){if(this.attrs[Q](e)){E[e]=this.attrs[e];}}this._.rt.deg&&(E.rotation=this.rotate());(this._.sx!=1||this._.sy!=1)&&(E.scale=this.scale());E.gradient&&E.fill=="none"&&(E.fill=E.gradient)&&delete E.gradient;return E;}if(arguments[m]==1&&an.is(arguments[0],"string")){if(arguments[0]=="translation"){return t.call(this);}if(arguments[0]=="rotation"){return this.rotate();}if(arguments[0]=="scale"){return this.scale();}if(arguments[0]=="fill"&&this.attrs.fill=="none"&&this.attrs.gradient){return this.attrs.gradient;}return this.attrs[arguments[0]];}if(this.attrs&&arguments[m]==1&&an.is(arguments[0],"array")){var d={};for(var e=0,R=arguments[0][m];e<R;e++){d[arguments[0][e]]=this.attrs[arguments[0][e]];}return d;}var S;if(arguments[m]==2){S={};S[arguments[0]]=arguments[1];}arguments[m]==1&&an.is(arguments[0],"object")&&(S=arguments[0]);if(S){if(S.text&&this.type=="text"){this.node.string=S.text;}aa(this,S);if(S.gradient&&(({circle:1,ellipse:1})[Q](this.type)||(S.gradient+at).charAt()!="r")){b(this,S.gradient);}(this.type!="path"||this._.rt.deg)&&this.setBox(this.attrs);}return this;};ax[aY].toFront=function(){!this.removed&&this.Group.parentNode[aL](this.Group);this.paper.top!=this&&Y(this,this.paper);return this;};ax[aY].toBack=function(){if(this.removed){return this;}if(this.Group.parentNode.firstChild!=this.Group){this.Group.parentNode.insertBefore(this.Group,this.Group.parentNode.firstChild);k(this,this.paper);}return this;};ax[aY].insertAfter=function(d){if(this.removed){return this;}if(d.Group.nextSibling){d.Group.parentNode.insertBefore(this.Group,d.Group.nextSibling);}else{d.Group.parentNode[aL](this.Group);}A(this,d,this.paper);return this;};ax[aY].insertBefore=function(d){if(this.removed){return this;}d.Group.parentNode.insertBefore(this.Group,d.Group);aq(this,d,this.paper);return this;};var P=function(e,d,a1,S){var R=ah("group"),a0=ah("oval"),i=a0.style;R.style.cssText="position:absolute;left:0;top:0;width:"+e.width+"px;height:"+e.height+"px";R.coordsize=e.coordsize;R.coordorigin=e.coordorigin;R[aL](a0);var E=new ax(a0,R,e);E.type="circle";aa(E,{stroke:"#000",fill:"none"});E.attrs.cx=d;E.attrs.cy=a1;E.attrs.r=S;E.setBox({x:d-S,y:a1-S,width:S*2,height:S*2});e.canvas[aL](R);return E;},aF=function(e,a1,a0,a2,E,d){var R=ah("group"),i=ah("roundrect"),a3=(+d||0)/(aI(a2,E));R.style.cssText="position:absolute;left:0;top:0;width:"+e.width+"px;height:"+e.height+"px";R.coordsize=e.coordsize;R.coordorigin=e.coordorigin;R[aL](i);i.arcsize=a3;var S=new ax(i,R,e);S.type="rect";aa(S,{stroke:"#000"});S.arcsize=a3;S.setBox({x:a1,y:a0,width:a2,height:E,r:d});e.canvas[aL](R);return S;},ai=function(d,a2,a1,i,e){var R=ah("group"),E=ah("oval"),a0=E.style;R.style.cssText="position:absolute;left:0;top:0;width:"+d.width+"px;height:"+d.height+"px";R.coordsize=d.coordsize;R.coordorigin=d.coordorigin;R[aL](E);var S=new ax(E,R,d);S.type="ellipse";aa(S,{stroke:"#000"});S.attrs.cx=a2;S.attrs.cy=a1;S.attrs.rx=i;S.attrs.ry=e;S.setBox({x:a2-i,y:a1-e,width:i*2,height:e*2});d.canvas[aL](R);return S;},o=function(e,d,a2,a1,a3,E){var R=ah("group"),i=ah("image"),a0=i.style;R.style.cssText="position:absolute;left:0;top:0;width:"+e.width+"px;height:"+e.height+"px";R.coordsize=e.coordsize;R.coordorigin=e.coordorigin;i.src=d;R[aL](i);var S=new ax(i,R,e);S.type="image";S.attrs.src=d;S.attrs.x=a2;S.attrs.y=a1;S.attrs.w=a3;S.attrs.h=E;S.setBox({x:a2,y:a1,width:a3,height:E});e.canvas[aL](R);return S;},X=function(e,a2,a1,a3){var R=ah("group"),E=ah("shape"),a0=E.style,a4=ah("path"),d=a4.style,i=ah("textpath");R.style.cssText="position:absolute;left:0;top:0;width:"+e.width+"px;height:"+e.height+"px";R.coordsize=e.coordsize;R.coordorigin=e.coordorigin;a4.v=an.format("m{0},{1}l{2},{1}",O(a2),O(a1),O(a2)+1);a4.textpathok=true;a0.width=e.width;a0.height=e.height;i.string=a3+at;i.on=true;E[aL](i);E[aL](a4);R[aL](E);var S=new ax(i,R,e);S.shape=E;S.textpath=a4;S.type="text";S.attrs.text=a3;S.attrs.x=a2;S.attrs.y=a1;S.attrs.w=1;S.attrs.h=1;aa(S,{font:j.font,stroke:"none",fill:"#000"});S.setBox();e.canvas[aL](R);return S;},aV=function(i,d){var e=this.canvas.style;i==+i&&(i+="px");d==+d&&(d+="px");e.width=i;e.height=d;e.clip="rect(0 "+i+" "+d+" 0)";return this;},ah;L.createStyleSheet().addRule(".rvml","behavior:url(#default#VML)");try{!L.namespaces.rvml&&L.namespaces.add("rvml","urn:schemas-microsoft-com:vml");ah=function(d){return L.createElement("<rvml:"+d+' class="rvml">');};}catch(af){ah=function(d){return L.createElement("<"+d+' xmlns="urn:schemas-microsoft.com:vml" class="rvml">');};}var w=function(){var i=ao[aW](null,arguments),d=i.container,a2=i.height,a3,e=i.width,a1=i.x,a0=i.y;if(!d){throw new Error("VML container not found.");}var R=new aT,S=R.canvas=L.createElement("div"),E=S.style;e=e||512;a2=a2||342;e==+e&&(e+="px");a2==+a2&&(a2+="px");R.width=1000;R.height=1000;R.coordsize="1000 1000";R.coordorigin="0 0";R.span=L.createElement("span");R.span.style.cssText="position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;display:inline;";S[aL](R.span);E.cssText=an.format("width:{0};height:{1};position:absolute;clip:rect(0 {0} {1} 0);overflow:hidden",e,a2);if(d==1){L.body[aL](S);E.left=a1+"px";E.top=a0+"px";}else{d.style.width=e;d.style.height=a2;if(d.firstChild){d.insertBefore(S,d.firstChild);}else{d[aL](S);}}aG.call(R,R,an.fn);return R;};aT[aY].clear=function(){this.canvas.innerHTML=at;this.span=L.createElement("span");this.span.style.cssText="position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;display:inline;";this.canvas[aL](this.span);this.bottom=this.top=null;};aT[aY].remove=function(){this.canvas.parentNode.removeChild(this.canvas);for(var d in this){this[d]=s(d);}};}if((/^Apple|^Google/).test(navigator.vendor)&&!(navigator.userAgent.indexOf("Version/4.0")+1)){aT[aY].safari=function(){var d=this.rect(-99,-99,this.width+99,this.height+99);setTimeout(function(){d.remove();});};}else{aT[aY].safari=function(){};}var ae=(function(){if(L.addEventListener){return function(R,i,e,d){var E=function(S){return e.call(d,S);};R.addEventListener(i,E,false);return function(){R.removeEventListener(i,E,false);return true;};};}else{if(L.attachEvent){return function(S,E,i,e){var R=function(a0){return i.call(e,a0||au.event);};S.attachEvent("on"+E,R);var d=function(){S.detachEvent("on"+E,R);return true;};return d;};}}})();for(var ac=F[m];ac--;){(function(d){ax[aY][d]=function(e){if(an.is(e,"function")){this.events=this.events||[];this.events.push({name:d,f:e,unbind:ae(this.shape||this.node,d,e,this)});}return this;};ax[aY]["un"+d]=function(E){var i=this.events,e=i[m];while(e--){if(i[e].name==d&&i[e].f==E){i[e].unbind();i.splice(e,1);!i.length&&delete this.events;return this;}}return this;};})(F[ac]);}ax[aY].hover=function(e,d){return this.mouseover(e).mouseout(d);};ax[aY].unhover=function(e,d){return this.unmouseover(e).unmouseout(d);};aT[aY].circle=function(d,i,e){return P(this,d||0,i||0,e||0);};aT[aY].rect=function(d,R,e,i,E){return aF(this,d||0,R||0,e||0,i||0,E||0);};aT[aY].ellipse=function(d,E,i,e){return ai(this,d||0,E||0,i||0,e||0);};aT[aY].path=function(d){d&&!an.is(d,"string")&&!an.is(d[0],"array")&&(d+=at);return q(an.format[aW](an,arguments),this);};aT[aY].image=function(E,d,R,e,i){return o(this,E||"about:blank",d||0,R||0,e||0,i||0);};aT[aY].text=function(d,i,e){return X(this,d||0,i||0,e||at);};aT[aY].set=function(d){arguments[m]>1&&(d=Array[aY].splice.call(arguments,0,arguments[m]));return new T(d);};aT[aY].setSize=aV;aT[aY].top=aT[aY].bottom=null;aT[aY].raphael=an;function u(){return this.x+am+this.y;}ax[aY].scale=function(a6,a5,E,e){if(a6==null&&a5==null){return{x:this._.sx,y:this._.sy,toString:u};}a5=a5||a6;!+a5&&(a5=a6);var ba,a8,a9,a7,bm=this.attrs;if(a6!=0){var a4=this.getBBox(),a1=a4.x+a4.width/2,R=a4.y+a4.height/2,bl=a6/this._.sx,bk=a5/this._.sy;E=(+E||E==0)?E:a1;e=(+e||e==0)?e:R;var a3=~~(a6/ab.abs(a6)),a0=~~(a5/ab.abs(a5)),be=this.node.style,bo=E+(a1-E)*bl,bn=e+(R-e)*bk;switch(this.type){case"rect":case"image":var a2=bm.width*a3*bl,bd=bm.height*a0*bk;this.attr({height:bd,r:bm.r*aI(a3*bl,a0*bk),width:a2,x:bo-a2/2,y:bn-bd/2});break;case"circle":case"ellipse":this.attr({rx:bm.rx*a3*bl,ry:bm.ry*a0*bk,r:bm.r*aI(a3*bl,a0*bk),cx:bo,cy:bn});break;case"path":var bg=ad(bm.path),bh=true;for(var bj=0,bc=bg[m];bj<bc;bj++){var bf=bg[bj],bi,S=aN.call(bf[0]);if(S=="M"&&bh){continue;}else{bh=false;}if(S=="A"){bf[bg[bj][m]-2]*=bl;bf[bg[bj][m]-1]*=bk;bf[1]*=a3*bl;bf[2]*=a0*bk;bf[5]=+(a3+a0?!!+bf[5]:!+bf[5]);}else{if(S=="H"){for(bi=1,jj=bf[m];bi<jj;bi++){bf[bi]*=bl;}}else{if(S=="V"){for(bi=1,jj=bf[m];bi<jj;bi++){bf[bi]*=bk;}}else{for(bi=1,jj=bf[m];bi<jj;bi++){bf[bi]*=(bi%2)?bl:bk;}}}}}var d=U(bg),ba=bo-d.x-d.width/2,a8=bn-d.y-d.height/2;bg[0][1]+=ba;bg[0][2]+=a8;this.attr({path:bg});break;}if(this.type in {text:1,image:1}&&(a3!=1||a0!=1)){if(this.transformations){this.transformations[2]="scale("[aS](a3,",",a0,")");this.node[v]("transform",this.transformations[az](am));ba=(a3==-1)?-bm.x-(a2||0):bm.x;a8=(a0==-1)?-bm.y-(bd||0):bm.y;this.attr({x:ba,y:a8});bm.fx=a3-1;bm.fy=a0-1;}else{this.node.filterMatrix=" progid:DXImageTransform.Microsoft.Matrix(M11="[aS](a3,", M12=0, M21=0, M22=",a0,", Dx=0, Dy=0, sizingmethod='auto expand', filtertype='bilinear')");be.filter=(this.node.filterMatrix||at)+(this.node.filterOpacity||at);}}else{if(this.transformations){this.transformations[2]=at;this.node[v]("transform",this.transformations[az](am));bm.fx=0;bm.fy=0;}else{this.node.filterMatrix=at;be.filter=(this.node.filterMatrix||at)+(this.node.filterOpacity||at);}}bm.scale=[a6,a5,E,e][az](am);this._.sx=a6;this._.sy=a5;}return this;};ax[aY].clone=function(){var d=this.attr();delete d.scale;delete d.translation;return this.paper[this.type]().attr(d);};var aB=function(d,e){return function(a9,S,a0){a9=H(a9);var a5,a4,E,a1,R="",a8={},a6,a3=0;for(var a2=0,a7=a9.length;a2<a7;a2++){E=a9[a2];if(E[0]=="M"){a5=+E[1];a4=+E[2];}else{a1=n(a5,a4,E[1],E[2],E[3],E[4],E[5],E[6]);if(a3+a1>S){if(e&&!a8.start){a6=an.findDotsAtSegment(a5,a4,E[1],E[2],E[3],E[4],E[5],E[6],(S-a3)/a1);R+=["C",a6.start.x,a6.start.y,a6.m.x,a6.m.y,a6.x,a6.y];if(a0){return R;}a8.start=R;R=["M",a6.x,a6.y+"C",a6.n.x,a6.n.y,a6.end.x,a6.end.y,E[5],E[6]][az]();a3+=a1;a5=+E[5];a4=+E[6];continue;}if(!d&&!e){a6=an.findDotsAtSegment(a5,a4,E[1],E[2],E[3],E[4],E[5],E[6],(S-a3)/a1);return{x:a6.x,y:a6.y,alpha:a6.alpha};}}a3+=a1;a5=+E[5];a4=+E[6];}R+=E;}a8.end=R;a6=d?a3:e?a8:an.findDotsAtSegment(a5,a4,E[1],E[2],E[3],E[4],E[5],E[6],1);a6.alpha&&(a6={x:a6.x,y:a6.y,alpha:a6.alpha});return a6;};},n=aj(function(E,d,a0,S,a6,a5,a4,a3){var R={x:0,y:0},a2=0;for(var a1=0;a1<1.01;a1+=0.01){var e=M(E,d,a0,S,a6,a5,a4,a3,a1);a1&&(a2+=ab.sqrt(aM(R.x-e.x,2)+aM(R.y-e.y,2)));R=e;}return a2;});var ap=aB(1),C=aB(),J=aB(0,1);ax[aY].getTotalLength=function(){if(this.type!="path"){return;}return ap(this.attrs.path);};ax[aY].getPointAtLength=function(d){if(this.type!="path"){return;}return C(this.attrs.path,d);};ax[aY].getSubpath=function(i,e){if(this.type!="path"){return;}if(ab.abs(this.getTotalLength()-e)<0.000001){return J(this.attrs.path,i).end;}var d=J(this.attrs.path,e,1);return i?J(d,i).end:d;};an.easing_formulas={linear:function(d){return d;},"<":function(d){return aM(d,3);},">":function(d){return aM(d-1,3)+1;},"<>":function(d){d=d*2;if(d<1){return aM(d,3)/2;}d-=2;return(aM(d,3)+2)/2;},backIn:function(e){var d=1.70158;return e*e*((d+1)*e-d);},backOut:function(e){e=e-1;var d=1.70158;return e*e*((d+1)*e+d)+1;},elastic:function(i){if(i==0||i==1){return i;}var e=0.3,d=e/4;return aM(2,-10*i)*ab.sin((i-d)*(2*ab.PI)/e)+1;},bounce:function(E){var e=7.5625,i=2.75,d;if(E<(1/i)){d=e*E*E;}else{if(E<(2/i)){E-=(1.5/i);d=e*E*E+0.75;}else{if(E<(2.5/i)){E-=(2.25/i);d=e*E*E+0.9375;}else{E-=(2.625/i);d=e*E*E+0.984375;}}}return d;}};var I={length:0},aR=function(){var a2=+new Date;for(var be in I){if(be!="length"&&I[Q](be)){var bj=I[be];if(bj.stop){delete I[be];I[m]--;continue;}var a0=a2-bj.start,bb=bj.ms,ba=bj.easing,bf=bj.from,a7=bj.diff,E=bj.to,a6=bj.t,a9=bj.prev||0,a1=bj.el,R=bj.callback,a8={},d;if(a0<bb){var S=an.easing_formulas[ba]?an.easing_formulas[ba](a0/bb):a0/bb;for(var bc in bf){if(bf[Q](bc)){switch(Z[bc]){case"along":d=S*bb*a7[bc];E.back&&(d=E.len-d);var bd=C(E[bc],d);a1.translate(a7.sx-a7.x||0,a7.sy-a7.y||0);a7.x=bd.x;a7.y=bd.y;a1.translate(bd.x-a7.sx,bd.y-a7.sy);E.rot&&a1.rotate(a7.r+bd.alpha,bd.x,bd.y);break;case"number":d=+bf[bc]+S*bb*a7[bc];break;case"colour":d="rgb("+[B(O(bf[bc].r+S*bb*a7[bc].r)),B(O(bf[bc].g+S*bb*a7[bc].g)),B(O(bf[bc].b+S*bb*a7[bc].b))][az](",")+")";break;case"path":d=[];for(var bh=0,a5=bf[bc][m];bh<a5;bh++){d[bh]=[bf[bc][bh][0]];for(var bg=1,bi=bf[bc][bh][m];bg<bi;bg++){d[bh][bg]=+bf[bc][bh][bg]+S*bb*a7[bc][bh][bg];}d[bh]=d[bh][az](am);}d=d[az](am);break;case"csv":switch(bc){case"translation":var a4=a7[bc][0]*(a0-a9),a3=a7[bc][1]*(a0-a9);a6.x+=a4;a6.y+=a3;d=a4+am+a3;break;case"rotation":d=+bf[bc][0]+S*bb*a7[bc][0];bf[bc][1]&&(d+=","+bf[bc][1]+","+bf[bc][2]);break;case"scale":d=[+bf[bc][0]+S*bb*a7[bc][0],+bf[bc][1]+S*bb*a7[bc][1],(2 in E[bc]?E[bc][2]:at),(3 in E[bc]?E[bc][3]:at)][az](am);break;case"clip-rect":d=[];var bh=4;while(bh--){d[bh]=+bf[bc][bh]+S*bb*a7[bc][bh];}break;}break;}a8[bc]=d;}}a1.attr(a8);a1._run&&a1._run.call(a1);}else{if(E.along){var bd=C(E.along,E.len*!E.back);a1.translate(a7.sx-(a7.x||0)+bd.x-a7.sx,a7.sy-(a7.y||0)+bd.y-a7.sy);E.rot&&a1.rotate(a7.r+bd.alpha,bd.x,bd.y);}(a6.x||a6.y)&&a1.translate(-a6.x,-a6.y);E.scale&&(E.scale=E.scale+at);a1.attr(E);delete I[be];I[m]--;a1.in_animation=null;an.is(R,"function")&&R.call(a1);}bj.prev=a0;}}an.svg&&a1&&a1.paper.safari();I[m]&&setTimeout(aR);},B=function(d){return d>255?255:(d<0?0:d);},t=function(d,i){if(d==null){return{x:this._.tx,y:this._.ty,toString:u};}this._.tx+=+d;this._.ty+=+i;switch(this.type){case"circle":case"ellipse":this.attr({cx:+d+this.attrs.cx,cy:+i+this.attrs.cy});break;case"rect":case"image":case"text":this.attr({x:+d+this.attrs.x,y:+i+this.attrs.y});break;case"path":var e=ad(this.attrs.path);e[0][1]+=+d;e[0][2]+=+i;this.attr({path:e});break;}return this;};ax[aY].animateWith=function(e,i,d,R,E){I[e.id]&&(i.start=I[e.id].start);return this.animate(i,d,R,E);};ax[aY].animateAlong=ay();ax[aY].animateAlongBack=ay(1);function ay(d){return function(E,i,e,S){var R={back:d};an.is(e,"function")?(S=e):(R.rot=e);E&&E.constructor==ax&&(E=E.attrs.path);E&&(R.along=E);return this.animate(R,i,S);};}ax[aY].onAnimation=function(d){this._run=d||0;return this;};ax[aY].animate=function(be,a5,a4,E){if(an.is(a4,"function")||!a4){E=a4||null;}var a9={},e={},a2={};for(var a6 in be){if(be[Q](a6)){if(Z[Q](a6)){a9[a6]=this.attr(a6);(a9[a6]==null)&&(a9[a6]=j[a6]);e[a6]=be[a6];switch(Z[a6]){case"along":var bc=ap(be[a6]),a7=C(be[a6],bc*!!be.back),R=this.getBBox();a2[a6]=bc/a5;a2.tx=R.x;a2.ty=R.y;a2.sx=a7.x;a2.sy=a7.y;e.rot=be.rot;e.back=be.back;e.len=bc;be.rot&&(a2.r=W(this.rotate())||0);break;case"number":a2[a6]=(e[a6]-a9[a6])/a5;break;case"colour":a9[a6]=an.getRGB(a9[a6]);var a8=an.getRGB(e[a6]);a2[a6]={r:(a8.r-a9[a6].r)/a5,g:(a8.g-a9[a6].g)/a5,b:(a8.b-a9[a6].b)/a5};break;case"path":var S=H(a9[a6],e[a6]);a9[a6]=S[0];var a3=S[1];a2[a6]=[];for(var bb=0,a1=a9[a6][m];bb<a1;bb++){a2[a6][bb]=[0];for(var ba=1,bd=a9[a6][bb][m];ba<bd;ba++){a2[a6][bb][ba]=(a3[bb][ba]-a9[a6][bb][ba])/a5;}}break;case"csv":var d=(be[a6]+at)[z](a),a0=(a9[a6]+at)[z](a);switch(a6){case"translation":a9[a6]=[0,0];a2[a6]=[d[0]/a5,d[1]/a5];break;case"rotation":a9[a6]=(a0[1]==d[1]&&a0[2]==d[2])?a0:[0,d[1],d[2]];a2[a6]=[(d[0]-a9[a6][0])/a5,0,0];break;case"scale":be[a6]=d;a9[a6]=(a9[a6]+at)[z](a);a2[a6]=[(d[0]-a9[a6][0])/a5,(d[1]-a9[a6][1])/a5,0,0];break;case"clip-rect":a9[a6]=(a9[a6]+at)[z](a);a2[a6]=[];var bb=4;while(bb--){a2[a6][bb]=(d[bb]-a9[a6][bb])/a5;}break;}e[a6]=d;}}}}this.stop();this.in_animation=1;I[this.id]={start:be.start||+new Date,ms:a5,easing:a4,from:a9,diff:a2,to:e,el:this,callback:E,t:{x:0,y:0}};++I[m]==1&&aR();return this;};ax[aY].stop=function(){I[this.id]&&I[m]--;delete I[this.id];return this;};ax[aY].translate=function(d,e){return this.attr({translation:d+" "+e});};ax[aY][aA]=function(){return"Rapha\xebl\u2019s object";};an.ae=I;var T=function(d){this.items=[];this[m]=0;if(d){for(var e=0,E=d[m];e<E;e++){if(d[e]&&(d[e].constructor==ax||d[e].constructor==T)){this[this.items[m]]=this.items[this.items[m]]=d[e];this[m]++;}}}};T[aY][f]=function(){var R,d;for(var e=0,E=arguments[m];e<E;e++){R=arguments[e];if(R&&(R.constructor==ax||R.constructor==T)){d=this.items[m];this[d]=this.items[d]=R;this[m]++;}}return this;};T[aY].pop=function(){delete this[this[m]--];return this.items.pop();};for(var y in ax[aY]){if(ax[aY][Q](y)){T[aY][y]=(function(d){return function(){for(var e=0,E=this.items[m];e<E;e++){this.items[e][d][aW](this.items[e],arguments);}return this;};})(y);}}T[aY].attr=function(e,a0){if(e&&an.is(e,"array")&&an.is(e[0],"object")){for(var d=0,S=e[m];d<S;d++){this.items[d].attr(e[d]);}}else{for(var E=0,R=this.items[m];E<R;E++){this.items[E].attr[aW](this.items[E],arguments);}}return this;};T[aY].animate=function(S,e,a2,a1){(an.is(a2,"function")||!a2)&&(a1=a2||null);var d=this.items[m],E=d,a0=this,R;a1&&(R=function(){!--d&&a1.call(a0);});this.items[--E].animate(S,e,a2||R,R);while(E--){this.items[E].animateWith(this.items[d-1],S,e,a2||R,R);}return this;};T[aY].insertAfter=function(e){var d=this.items[m];while(d--){this.items[d].insertAfter(e);}return this;};T[aY].getBBox=function(){var d=[],a0=[],e=[],R=[];for(var E=this.items[m];E--;){var S=this.items[E].getBBox();d[f](S.x);a0[f](S.y);e[f](S.x+S.width);R[f](S.y+S.height);}d=aI[aW](0,d);a0=aI[aW](0,a0);return{x:d,y:a0,width:g[aW](0,e)-d,height:g[aW](0,R)-a0};};an.registerFont=function(e){if(!e.face){return e;}this.fonts=this.fonts||{};var E={w:e.w,face:{},glyphs:{}},i=e.face["font-family"];for(var a0 in e.face){if(e.face[Q](a0)){E.face[a0]=e.face[a0];}}if(this.fonts[i]){this.fonts[i][f](E);}else{this.fonts[i]=[E];}if(!e.svg){E.face["units-per-em"]=G(e.face["units-per-em"],10);for(var R in e.glyphs){if(e.glyphs[Q](R)){var S=e.glyphs[R];E.glyphs[R]={w:S.w,k:{},d:S.d&&"M"+S.d[aP](/[mlcxtrv]/g,function(a1){return{l:"L",c:"C",x:"z",t:"m",r:"l",v:"c"}[a1]||"M";})+"z"};if(S.k){for(var d in S.k){if(S[Q](d)){E.glyphs[R].k[d]=S.k[d];}}}}}}return e;};aT[aY].getFont=function(a2,a3,e,R){R=R||"normal";e=e||"normal";a3=+a3||{normal:400,bold:700,lighter:300,bolder:800}[a3]||400;var S=an.fonts[a2];if(!S){var E=new RegExp("(^|\\s)"+a2[aP](/[^\w\d\s+!~.:_-]/g,at)+"(\\s|$)","i");for(var d in an.fonts){if(an.fonts[Q](d)){if(E.test(d)){S=an.fonts[d];break;}}}}var a0;if(S){for(var a1=0,a4=S[m];a1<a4;a1++){a0=S[a1];if(a0.face["font-weight"]==a3&&(a0.face["font-style"]==e||!a0.face["font-style"])&&a0.face["font-stretch"]==R){break;}}}return a0;};aT[aY].print=function(R,E,d,a1,a2,bb){bb=bb||"middle";var a7=this.set(),ba=(d+at)[z](at),a8=0,a4=at,bc;an.is(a1,"string")&&(a1=this.getFont(a1));if(a1){bc=(a2||16)/a1.face["units-per-em"];var e=a1.face.bbox.split(a),a0=+e[0],a3=+e[1]+(bb=="baseline"?e[3]-e[1]+(+a1.face.descent):(e[3]-e[1])/2);for(var a6=0,S=ba[m];a6<S;a6++){var a5=a6&&a1.glyphs[ba[a6-1]]||{},a9=a1.glyphs[ba[a6]];a8+=a6?(a5.w||a1.w)+(a5.k&&a5.k[ba[a6]]||0):0;a9&&a9.d&&a7[f](this.path(a9.d).attr({fill:"#000",stroke:"none",translation:[a8,0]}));}a7.scale(bc,bc,a0,a3).translate(R-a0,E-a3);}return a7;};an.format=function(i){var e=an.is(arguments[1],"array")?[0][aS](arguments[1]):arguments,d=/\{(\d+)\}/g;i&&an.is(i,"string")&&e[m]-1&&(i=i[aP](d,function(R,E){return e[++E]==null?at:e[E];}));return i||at;};an.ninja=function(){var d=Raphael;if(l.was){Raphael=l.is;}else{delete Raphael;}return d;};an.el=ax[aY];return an;})();
\ No newline at end of file +// ┌─────────────────────────────────────────────────────────────────────┐ \\ +// │ Raphaël 2.0 - JavaScript Vector Library │ \\ +// ├─────────────────────────────────────────────────────────────────────┤ \\ +// │ Copyright (c) 2008-2011 Dmitry Baranovskiy (http://raphaeljs.com) │ \\ +// │ Copyright (c) 2008-2011 Sencha Labs (http://sencha.com) │ \\ +// │ Licensed under the MIT (http://raphaeljs.com/license.html) license. │ \\ +// └─────────────────────────────────────────────────────────────────────┘ \\ +(function(a){var b="0.3.2",c="hasOwnProperty",d=/[\.\/]/,e="*",f=function(){},g=function(a,b){return a-b},h,i,j={n:{}},k=function(a,b){var c=j,d=i,e=Array.prototype.slice.call(arguments,2),f=k.listeners(a),l=0,m=!1,n,o=[],p={},q=[],r=[];h=a,i=0;for(var s=0,t=f.length;s<t;s++)"zIndex"in f[s]&&(o.push(f[s].zIndex),f[s].zIndex<0&&(p[f[s].zIndex]=f[s]));o.sort(g);while(o[l]<0){n=p[o[l++]],q.push(n.apply(b,e));if(i){i=d;return q}}for(s=0;s<t;s++){n=f[s];if("zIndex"in n)if(n.zIndex==o[l]){q.push(n.apply(b,e));if(i){i=d;return q}do{l++,n=p[o[l]],n&&q.push(n.apply(b,e));if(i){i=d;return q}}while(n)}else p[n.zIndex]=n;else{q.push(n.apply(b,e));if(i){i=d;return q}}}i=d;return q.length?q:null};k.listeners=function(a){var b=a.split(d),c=j,f,g,h,i,k,l,m,n,o=[c],p=[];for(i=0,k=b.length;i<k;i++){n=[];for(l=0,m=o.length;l<m;l++){c=o[l].n,g=[c[b[i]],c[e]],h=2;while(h--)f=g[h],f&&(n.push(f),p=p.concat(f.f||[]))}o=n}return p},k.on=function(a,b){var c=a.split(d),e=j;for(var g=0,h=c.length;g<h;g++)e=e.n,!e[c[g]]&&(e[c[g]]={n:{}}),e=e[c[g]];e.f=e.f||[];for(g=0,h=e.f.length;g<h;g++)if(e.f[g]==b)return f;e.f.push(b);return function(a){+a==+a&&(b.zIndex=+a)}},k.stop=function(){i=1},k.nt=function(a){if(a)return(new RegExp("(?:\\.|\\/|^)"+a+"(?:\\.|\\/|$)")).test(h);return h},k.unbind=function(a,b){var f=a.split(d),g,h,i,k=[j];for(var l=0,m=f.length;l<m;l++)for(var n=0;n<k.length;n+=i.length-2){i=[n,1],g=k[n].n;if(f[l]!=e)g[f[l]]&&i.push(g[f[l]]);else for(h in g)g[c](h)&&i.push(g[h]);k.splice.apply(k,i)}for(l=0,m=k.length;l<m;l++){g=k[l];while(g.n){if(b){if(g.f){for(n=0,jj=g.f.length;n<jj;n++)if(g.f[n]==b){g.f.splice(n,1);break}!g.f.length&&delete g.f}for(h in g.n)if(g.n[c](h)&&g.n[h].f){var o=g.n[h].f;for(n=0,jj=o.length;n<jj;n++)if(o[n]==b){o.splice(n,1);break}!o.length&&delete g.n[h].f}}else{delete g.f;for(h in g.n)g.n[c](h)&&g.n[h].f&&delete g.n[h].f}g=g.n}}},k.version=b,k.toString=function(){return"You are running Eve "+b},typeof module!="undefined"&&module.exports?module.exports=k:a.eve=k})(this),function(){function cr(b,d,e,f,h,i){e=Q(e);var j,k,l,m=[],o,p,q,t=b.ms,u={},v={},w={};if(f)for(y=0,z=cl.length;y<z;y++){var x=cl[y];if(x.el.id==d.id&&x.anim==b){x.percent!=e?(cl.splice(y,1),l=1):k=x,d.attr(x.totalOrigin);break}}else f=+v;for(var y=0,z=b.percents.length;y<z;y++){if(b.percents[y]==e||b.percents[y]>f*b.top){e=b.percents[y],p=b.percents[y-1]||0,t=t/b.top*(e-p),o=b.percents[y+1],j=b.anim[e];break}f&&d.attr(b.anim[b.percents[y]])}if(!!j){if(!k){for(attr in j)if(j[g](attr))if(U[g](attr)||d.paper.customAttributes[g](attr)){u[attr]=d.attr(attr),u[attr]==null&&(u[attr]=T[attr]),v[attr]=j[attr];switch(U[attr]){case C:w[attr]=(v[attr]-u[attr])/t;break;case"colour":u[attr]=a.getRGB(u[attr]);var A=a.getRGB(v[attr]);w[attr]={r:(A.r-u[attr].r)/t,g:(A.g-u[attr].g)/t,b:(A.b-u[attr].b)/t};break;case"path":var B=bG(u[attr],v[attr]),D=B[1];u[attr]=B[0],w[attr]=[];for(y=0,z=u[attr].length;y<z;y++){w[attr][y]=[0];for(var E=1,F=u[attr][y].length;E<F;E++)w[attr][y][E]=(D[y][E]-u[attr][y][E])/t}break;case"transform":var G=d._,H=bQ(G[attr],v[attr]);if(H){u[attr]=H.from,v[attr]=H.to,w[attr]=[],w[attr].real=!0;for(y=0,z=u[attr].length;y<z;y++){w[attr][y]=[u[attr][y][0]];for(E=1,F=u[attr][y].length;E<F;E++)w[attr][y][E]=(v[attr][y][E]-u[attr][y][E])/t}}else{var I=d.matrix||new bR,J={_:{transform:G.transform},getBBox:function(){return d.getBBox(1)}};u[attr]=[I.a,I.b,I.c,I.d,I.e,I.f],bO(J,v[attr]),v[attr]=J._.transform,w[attr]=[(J.matrix.a-I.a)/t,(J.matrix.b-I.b)/t,(J.matrix.c-I.c)/t,(J.matrix.d-I.d)/t,(J.matrix.e-I.e)/t,(J.matrix.e-I.f)/t]}break;case"csv":var K=r(j[attr])[s](c),L=r(u[attr])[s](c);if(attr=="clip-rect"){u[attr]=L,w[attr]=[],y=L.length;while(y--)w[attr][y]=(K[y]-u[attr][y])/t}v[attr]=K;break;default:K=[][n](j[attr]),L=[][n](u[attr]),w[attr]=[],y=d.paper.customAttributes[attr].length;while(y--)w[attr][y]=((K[y]||0)-(L[y]||0))/t}}var M=j.easing,O=a.easing_formulas[M];if(!O){O=r(M).match(N);if(O&&O.length==5){var P=O;O=function(a){return cp(a,+P[1],+P[2],+P[3],+P[4],t)}}else O=be}q=j.start||b.start||+(new Date),x={anim:b,percent:e,timestamp:q,start:q+(b.del||0),status:0,initstatus:f||0,stop:!1,ms:t,easing:O,from:u,diff:w,to:v,el:d,callback:j.callback,prev:p,next:o,repeat:i||b.times,origin:d.attr(),totalOrigin:h},cl.push(x);if(f&&!k&&!l){x.stop=!0,x.start=new Date-t*f;if(cl.length==1)return cn()}l&&(x.start=new Date-x.ms*f),cl.length==1&&cm(cn)}else k.initstatus=f,k.start=new Date-k.ms*f;eve("anim.start."+d.id,d,b)}}function cq(a,b){var c=[],d={};this.ms=b,this.times=1;if(a){for(var e in a)a[g](e)&&(d[Q(e)]=a[e],c.push(Q(e)));c.sort(bc)}this.anim=d,this.top=c[c.length-1],this.percents=c}function cp(a,b,c,d,e,f){function o(a,b){var c,d,e,f,j,k;for(e=a,k=0;k<8;k++){f=m(e)-a;if(z(f)<b)return e;j=(3*i*e+2*h)*e+g;if(z(j)<1e-6)break;e=e-f/j}c=0,d=1,e=a;if(e<c)return c;if(e>d)return d;while(c<d){f=m(e);if(z(f-a)<b)return e;a>f?c=e:d=e,e=(d-c)/2+c}return e}function n(a,b){var c=o(a,b);return((l*c+k)*c+j)*c}function m(a){return((i*a+h)*a+g)*a}var g=3*b,h=3*(d-b)-g,i=1-g-h,j=3*c,k=3*(e-c)-j,l=1-j-k;return n(a,1/(200*f))}function cd(){return this.x+q+this.y+q+this.width+" × "+this.height}function cc(){return this.x+q+this.y}function bR(a,b,c,d,e,f){a!=null?(this.a=+a,this.b=+b,this.c=+c,this.d=+d,this.e=+e,this.f=+f):(this.a=1,this.b=0,this.c=0,this.d=1,this.e=0,this.f=0)}function bw(a){var b=[];for(var c=0,d=a.length;d-2>c;c+=2){var e=[{x:+a[c],y:+a[c+1]},{x:+a[c],y:+a[c+1]},{x:+a[c+2],y:+a[c+3]},{x:+a[c+4],y:+a[c+5]}];d-4==c?(e[0]={x:+a[c-2],y:+a[c-1]},e[3]=e[2]):c&&(e[0]={x:+a[c-2],y:+a[c-1]}),b.push(["C",(-e[0].x+6*e[1].x+e[2].x)/6,(-e[0].y+6*e[1].y+e[2].y)/6,(e[1].x+6*e[2].x-e[3].x)/6,(e[1].y+6*e[2].y-e[3].y)/6,e[2].x,e[2].y])}return b}function bv(){return this.hex}function bt(a,b,c){function d(){var e=Array.prototype.slice.call(arguments,0),f=e.join("␀"),h=d.cache=d.cache||{},i=d.count=d.count||[];if(h[g](f)){bs(i,f);return c?c(h[f]):h[f]}i.length>=1e3&&delete h[i.shift()],i.push(f),h[f]=a[m](b,e);return c?c(h[f]):h[f]}return d}function bs(a,b){for(var c=0,d=a.length;c<d;c++)if(a[c]===b)return a.push(a.splice(c,1)[0])}function a(c){if(a.is(c,"function"))return b?c():eve.on("DOMload",c);if(a.is(c,E)){var e=c,f=a._engine.create[m](a,e.splice(0,3+a.is(e[0],C))),h=f.set(),i=0,j=e.length,k;for(;i<j;i++)k=e[i]||{},d[g](k.type)&&h.push(f[k.type]().attr(k));return h}var l=Array.prototype.slice.call(arguments,0);if(a.is(l[l.length-1],"function")){var n=l.pop();return b?n.call(a._engine.create[m](a,l)):eve.on("DOMload",function(){n.call(a._engine.create[m](a,l))})}return a._engine.create[m](a,arguments)}a.version="2.0.0",a.eve=eve;var b,c=/[, ]+/,d={circle:1,rect:1,path:1,ellipse:1,text:1,image:1},e=/\{(\d+)\}/g,f="prototype",g="hasOwnProperty",h={doc:document,win:window},i={was:Object.prototype[g].call(h.win,"Raphael"),is:h.win.Raphael},j=function(){this.ca=this.customAttributes={}},k,l="appendChild",m="apply",n="concat",o="createTouch"in h.doc,p="",q=" ",r=String,s="split",t="click dblclick mousedown mousemove mouseout mouseover mouseup touchstart touchmove touchend touchcancel"[s](q),u={mousedown:"touchstart",mousemove:"touchmove",mouseup:"touchend"},v=r.prototype.toLowerCase,w=Math,x=w.max,y=w.min,z=w.abs,A=w.pow,B=w.PI,C="number",D="string",E="array",F="toString",G="fill",H=Object.prototype.toString,I={},J="push",K=a._ISURL=/^url\(['"]?([^\)]+?)['"]?\)$/i,L=/^\s*((#[a-f\d]{6})|(#[a-f\d]{3})|rgba?\(\s*([\d\.]+%?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+%?(?:\s*,\s*[\d\.]+%?)?)\s*\)|hsba?\(\s*([\d\.]+(?:deg|\xb0|%)?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+(?:%?\s*,\s*[\d\.]+)?)%?\s*\)|hsla?\(\s*([\d\.]+(?:deg|\xb0|%)?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+(?:%?\s*,\s*[\d\.]+)?)%?\s*\))\s*$/i,M={NaN:1,Infinity:1,"-Infinity":1},N=/^(?:cubic-)?bezier\(([^,]+),([^,]+),([^,]+),([^\)]+)\)/,O=w.round,P="setAttribute",Q=parseFloat,R=parseInt,S=r.prototype.toUpperCase,T=a._availableAttrs={"arrow-end":"none","arrow-start":"none",blur:0,"clip-rect":"0 0 1e9 1e9",cursor:"default",cx:0,cy:0,fill:"#fff","fill-opacity":1,font:'10px "Arial"',"font-family":'"Arial"',"font-size":"10","font-style":"normal","font-weight":400,gradient:0,height:0,href:"http://raphaeljs.com/",opacity:1,path:"M0,0",r:0,rx:0,ry:0,src:"",stroke:"#000","stroke-dasharray":"","stroke-linecap":"butt","stroke-linejoin":"butt","stroke-miterlimit":0,"stroke-opacity":1,"stroke-width":1,target:"_blank","text-anchor":"middle",title:"Raphael",transform:"",width:0,x:0,y:0},U=a._availableAnimAttrs={blur:C,"clip-rect":"csv",cx:C,cy:C,fill:"colour","fill-opacity":C,"font-size":C,height:C,opacity:C,path:"path",r:C,rx:C,ry:C,stroke:"colour","stroke-opacity":C,"stroke-width":C,transform:"transform",width:C,x:C,y:C},V=/\s*,\s*/,W={hs:1,rg:1},X=/,?([achlmqrstvxz]),?/gi,Y=/([achlmrqstvz])[\s,]*((-?\d*\.?\d*(?:e[\-+]?\d+)?\s*,?\s*)+)/ig,Z=/([rstm])[\s,]*((-?\d*\.?\d*(?:e[\-+]?\d+)?\s*,?\s*)+)/ig,$=/(-?\d*\.?\d*(?:e[\-+]?\d+)?)\s*,?\s*/ig,_=a._radial_gradient=/^r(?:\(([^,]+?)\s*,\s*([^\)]+?)\))?/,ba={},bb=function(a,b){return a.key-b.key},bc=function(a,b){return Q(a)-Q(b)},bd=function(){},be=function(a){return a},bf=a._rectPath=function(a,b,c,d,e){if(e)return[["M",a+e,b],["l",c-e*2,0],["a",e,e,0,0,1,e,e],["l",0,d-e*2],["a",e,e,0,0,1,-e,e],["l",e*2-c,0],["a",e,e,0,0,1,-e,-e],["l",0,e*2-d],["a",e,e,0,0,1,e,-e],["z"]];return[["M",a,b],["l",c,0],["l",0,d],["l",-c,0],["z"]]},bg=function(a,b,c,d){d==null&&(d=c);return[["M",a,b],["m",0,-d],["a",c,d,0,1,1,0,2*d],["a",c,d,0,1,1,0,-2*d],["z"]]},bh=a._getPath={path:function(a){return a.attr("path")},circle:function(a){var b=a.attrs;return bg(b.cx,b.cy,b.r)},ellipse:function(a){var b=a.attrs;return bg(b.cx,b.cy,b.rx,b.ry)},rect:function(a){var b=a.attrs;return bf(b.x,b.y,b.width,b.height,b.r)},image:function(a){var b=a.attrs;return bf(b.x,b.y,b.width,b.height)},text:function(a){var b=a._getBBox();return bf(b.x,b.y,b.width,b.height)}},bi=a.mapPath=function(a,b){if(!b)return a;var c,d,e,f,g;a=bG(a);for(e=0,ii=a.length;e<ii;e++){g=a[e];for(f=1,jj=g.length;f<jj;f+=2)c=b.x(g[f],g[f+1]),d=b.y(g[f],g[f+1]),g[f]=c,g[f+1]=d}return a};a._g=h,a.type=h.win.SVGAngle||h.doc.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1")?"SVG":"VML";if(a.type=="VML"){var bj=h.doc.createElement("div"),bk;bj.innerHTML='<v:shape adj="1"/>',bk=bj.firstChild,bk.style.behavior="url(#default#VML)";if(!bk||typeof bk.adj!="object")return a.type=p;bj=null}a.svg=!(a.vml=a.type=="VML"),a._Paper=j,a.fn=k=j.prototype=a.prototype,a._id=0,a._oid=0,a.is=function(a,b){b=v.call(b);if(b=="finite")return!M[g](+a);if(b=="array")return a instanceof Array;return b=="null"&&a===null||b==typeof a&&a!==null||b=="object"&&a===Object(a)||b=="array"&&Array.isArray&&Array.isArray(a)||H.call(a).slice(8,-1).toLowerCase()==b},a.angle=function(b,c,d,e,f,g){if(f==null){var h=b-d,i=c-e;if(!h&&!i)return 0;return(180+w.atan2(-i,-h)*180/B+360)%360}return a.angle(b,c,f,g)-a.angle(d,e,f,g)},a.rad=function(a){return a%360*B/180},a.deg=function(a){return a*180/B%360},a.snapTo=function(b,c,d){d=a.is(d,"finite")?d:10;if(a.is(b,E)){var e=b.length;while(e--)if(z(b[e]-c)<=d)return b[e]}else{b=+b;var f=c%b;if(f<d)return c-f;if(f>b-d)return c-f+b}return c};var bl=a.createUUID=function(a,b){return function(){return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(a,b).toUpperCase()}}(/[xy]/g,function(a){var b=w.random()*16|0,c=a=="x"?b:b&3|8;return c.toString(16)});a.setWindow=function(b){eve("setWindow",a,h.win,b),h.win=b,h.doc=h.win.document,initWin&&initWin(h.win)};var bm=function(b){if(a.vml){var c=/^\s+|\s+$/g,d;try{var e=new ActiveXObject("htmlfile");e.write("<body>"),e.close(),d=e.body}catch(f){d=createPopup().document.body}var g=d.createTextRange();bm=bt(function(a){try{d.style.color=r(a).replace(c,p);var b=g.queryCommandValue("ForeColor");b=(b&255)<<16|b&65280|(b&16711680)>>>16;return"#"+("000000"+b.toString(16)).slice(-6)}catch(e){return"none"}})}else{var i=h.doc.createElement("i");i.title="Raphaël Colour Picker",i.style.display="none",h.doc.body.appendChild(i),bm=bt(function(a){i.style.color=a;return h.doc.defaultView.getComputedStyle(i,p).getPropertyValue("color")})}return bm(b)},bn=function(){return"hsb("+[this.h,this.s,this.b]+")"},bo=function(){return"hsl("+[this.h,this.s,this.l]+")"},bp=function(){return this.hex},bq=function(b,c,d){c==null&&a.is(b,"object")&&"r"in b&&"g"in b&&"b"in b&&(d=b.b,c=b.g,b=b.r);if(c==null&&a.is(b,D)){var e=a.getRGB(b);b=e.r,c=e.g,d=e.b}if(b>1||c>1||d>1)b/=255,c/=255,d/=255;return[b,c,d]},br=function(b,c,d,e){b*=255,c*=255,d*=255;var f={r:b,g:c,b:d,hex:a.rgb(b,c,d),toString:bp};a.is(e,"finite")&&(f.opacity=e);return f};a.color=function(b){var c;a.is(b,"object")&&"h"in b&&"s"in b&&"b"in b?(c=a.hsb2rgb(b),b.r=c.r,b.g=c.g,b.b=c.b,b.hex=c.hex):a.is(b,"object")&&"h"in b&&"s"in b&&"l"in b?(c=a.hsl2rgb(b),b.r=c.r,b.g=c.g,b.b=c.b,b.hex=c.hex):(a.is(b,"string")&&(b=a.getRGB(b)),a.is(b,"object")&&"r"in b&&"g"in b&&"b"in b?(c=a.rgb2hsl(b),b.h=c.h,b.s=c.s,b.l=c.l,c=a.rgb2hsb(b),b.v=c.b):(b={hex:"none"},crl.r=b.g=b.b=b.h=b.s=b.v=b.l=-1)),b.toString=bp;return b},a.hsb2rgb=function(a,b,c,d){this.is(a,"object")&&"h"in a&&"s"in a&&"b"in a&&(c=a.b,b=a.s,a=a.h,d=a.o),a*=360;var e,f,g,h,i;a=a%360/60,i=c*b,h=i*(1-z(a%2-1)),e=f=g=c-i,a=~~a,e+=[i,h,0,0,h,i][a],f+=[h,i,i,h,0,0][a],g+=[0,0,h,i,i,h][a];return br(e,f,g,d)},a.hsl2rgb=function(a,b,c,d){this.is(a,"object")&&"h"in a&&"s"in a&&"l"in a&&(c=a.l,b=a.s,a=a.h);if(a>1||b>1||c>1)a/=360,b/=100,c/=100;a*=360;var e,f,g,h,i;a=a%360/60,i=2*b*(c<.5?c:1-c),h=i*(1-z(a%2-1)),e=f=g=c-i/2,a=~~a,e+=[i,h,0,0,h,i][a],f+=[h,i,i,h,0,0][a],g+=[0,0,h,i,i,h][a];return br(e,f,g,d)},a.rgb2hsb=function(a,b,c){c=bq(a,b,c),a=c[0],b=c[1],c=c[2];var d,e,f,g;f=x(a,b,c),g=f-y(a,b,c),d=g==0?null:f==a?(b-c)/g:f==b?(c-a)/g+2:(a-b)/g+4,d=(d+360)%6*60/360,e=g==0?0:g/f;return{h:d,s:e,b:f,toString:bn}},a.rgb2hsl=function(a,b,c){c=bq(a,b,c),a=c[0],b=c[1],c=c[2];var d,e,f,g,h,i;g=x(a,b,c),h=y(a,b,c),i=g-h,d=i==0?null:g==a?(b-c)/i:g==b?(c-a)/i+2:(a-b)/i+4,d=(d+360)%6*60/360,f=(g+h)/2,e=i==0?0:f<.5?i/(2*f):i/(2-2*f);return{h:d,s:e,l:f,toString:bo}},a._path2string=function(){return this.join(",").replace(X,"$1")};var bu=a._preload=function(a,b){var c=h.doc.createElement("img");c.style.cssText="position:absolute;left:-9999em;top-9999em",c.onload=function(){b.call(this),this.onload=null,h.doc.body.removeChild(this)},c.onerror=function(){h.doc.body.removeChild(this)},h.doc.body.appendChild(c),c.src=a};a.getRGB=bt(function(b){if(!b||!!((b=r(b)).indexOf("-")+1))return{r:-1,g:-1,b:-1,hex:"none",error:1,toString:bv};if(b=="none")return{r:-1,g:-1,b:-1,hex:"none",toString:bv};!W[g](b.toLowerCase().substring(0,2))&&b.charAt()!="#"&&(b=bm(b));var c,d,e,f,h,i,j,k=b.match(L);if(k){k[2]&&(f=R(k[2].substring(5),16),e=R(k[2].substring(3,5),16),d=R(k[2].substring(1,3),16)),k[3]&&(f=R((i=k[3].charAt(3))+i,16),e=R((i=k[3].charAt(2))+i,16),d=R((i=k[3].charAt(1))+i,16)),k[4]&&(j=k[4][s](V),d=Q(j[0]),j[0].slice(-1)=="%"&&(d*=2.55),e=Q(j[1]),j[1].slice(-1)=="%"&&(e*=2.55),f=Q(j[2]),j[2].slice(-1)=="%"&&(f*=2.55),k[1].toLowerCase().slice(0,4)=="rgba"&&(h=Q(j[3])),j[3]&&j[3].slice(-1)=="%"&&(h/=100));if(k[5]){j=k[5][s](V),d=Q(j[0]),j[0].slice(-1)=="%"&&(d*=2.55),e=Q(j[1]),j[1].slice(-1)=="%"&&(e*=2.55),f=Q(j[2]),j[2].slice(-1)=="%"&&(f*=2.55),(j[0].slice(-3)=="deg"||j[0].slice(-1)=="°")&&(d/=360),k[1].toLowerCase().slice(0,4)=="hsba"&&(h=Q(j[3])),j[3]&&j[3].slice(-1)=="%"&&(h/=100);return a.hsb2rgb(d,e,f,h)}if(k[6]){j=k[6][s](V),d=Q(j[0]),j[0].slice(-1)=="%"&&(d*=2.55),e=Q(j[1]),j[1].slice(-1)=="%"&&(e*=2.55),f=Q(j[2]),j[2].slice(-1)=="%"&&(f*=2.55),(j[0].slice(-3)=="deg"||j[0].slice(-1)=="°")&&(d/=360),k[1].toLowerCase().slice(0,4)=="hsla"&&(h=Q(j[3])),j[3]&&j[3].slice(-1)=="%"&&(h/=100);return a.hsl2rgb(d,e,f,h)}k={r:d,g:e,b:f,toString:bv},k.hex="#"+(16777216|f|e<<8|d<<16).toString(16).slice(1),a.is(h,"finite")&&(k.opacity=h);return k}return{r:-1,g:-1,b:-1,hex:"none",error:1,toString:bv}},a),a.hsb=bt(function(b,c,d){return a.hsb2rgb(b,c,d).hex}),a.hsl=bt(function(b,c,d){return a.hsl2rgb(b,c,d).hex}),a.rgb=bt(function(a,b,c){return"#"+(16777216|c|b<<8|a<<16).toString(16).slice(1)}),a.getColor=function(a){var b=this.getColor.start=this.getColor.start||{h:0,s:1,b:a||.75},c=this.hsb2rgb(b.h,b.s,b.b);b.h+=.075,b.h>1&&(b.h=0,b.s-=.2,b.s<=0&&(this.getColor.start={h:0,s:1,b:b.b}));return c.hex},a.getColor.reset=function(){delete this.start},a.parsePathString=bt(function(b){if(!b)return null;var c={a:7,c:6,h:1,l:2,m:2,r:4,q:4,s:4,t:2,v:1,z:0},d=[];a.is(b,E)&&a.is(b[0],E)&&(d=by(b)),d.length||r(b).replace(Y,function(a,b,e){var f=[],g=b.toLowerCase();e.replace($,function(a,b){b&&f.push(+b)}),g=="m"&&f.length>2&&(d.push([b][n](f.splice(0,2))),g="l",b=b=="m"?"l":"L");if(g=="r")d.push([b][n](f));else while(f.length>=c[g]){d.push([b][n](f.splice(0,c[g])));if(!c[g])break}}),d.toString=a._path2string;return d}),a.parseTransformString=bt(function(b){if(!b)return null;var c={r:3,s:4,t:2,m:6},d=[];a.is(b,E)&&a.is(b[0],E)&&(d=by(b)),d.length||r(b).replace(Z,function(a,b,c){var e=[],f=v.call(b);c.replace($,function(a,b){b&&e.push(+b)}),d.push([b][n](e))}),d.toString=a._path2string;return d}),a.findDotsAtSegment=function(a,b,c,d,e,f,g,h,i){var j=1-i,k=A(j,3),l=A(j,2),m=i*i,n=m*i,o=k*a+l*3*i*c+j*3*i*i*e+n*g,p=k*b+l*3*i*d+j*3*i*i*f+n*h,q=a+2*i*(c-a)+m*(e-2*c+a),r=b+2*i*(d-b)+m*(f-2*d+b),s=c+2*i*(e-c)+m*(g-2*e+c),t=d+2*i*(f-d)+m*(h-2*f+d),u=j*a+i*c,v=j*b+i*d,x=j*e+i*g,y=j*f+i*h,z=90-w.atan2(q-s,r-t)*180/B;(q>s||r<t)&&(z+=180);return{x:o,y:p,m:{x:q,y:r},n:{x:s,y:t},start:{x:u,y:v},end:{x:x,y:y},alpha:z}};var bx=bt(function(a){if(!a)return{x:0,y:0,width:0,height:0};a=bG(a);var b=0,c=0,d=[],e=[],f;for(var g=0,h=a.length;g<h;g++){f=a[g];if(f[0]=="M")b=f[1],c=f[2],d.push(b),e.push(c);else{var i=bF(b,c,f[1],f[2],f[3],f[4],f[5],f[6]);d=d[n](i.min.x,i.max.x),e=e[n](i.min.y,i.max.y),b=f[5],c=f[6]}}var j=y[m](0,d),k=y[m](0,e);return{x:j,y:k,width:x[m](0,d)-j,height:x[m](0,e)-k}},null,function(a){return{x:a.x,y:a.y,width:a.width,height:a.height}}),by=function(b){var c=[];if(!a.is(b,E)||!a.is(b&&b[0],E))b=a.parsePathString(b);for(var d=0,e=b.length;d<e;d++){c[d]=[];for(var f=0,g=b[d].length;f<g;f++)c[d][f]=b[d][f]}c.toString=a._path2string;return c},bz=a._pathToRelative=bt(function(b){if(!a.is(b,E)||!a.is(b&&b[0],E))b=a.parsePathString(b);var c=[],d=0,e=0,f=0,g=0,h=0;b[0][0]=="M"&&(d=b[0][1],e=b[0][2],f=d,g=e,h++,c.push(["M",d,e]));for(var i=h,j=b.length;i<j;i++){var k=c[i]=[],l=b[i];if(l[0]!=v.call(l[0])){k[0]=v.call(l[0]);switch(k[0]){case"a":k[1]=l[1],k[2]=l[2],k[3]=l[3],k[4]=l[4],k[5]=l[5],k[6]=+(l[6]-d).toFixed(3),k[7]=+(l[7]-e).toFixed(3);break;case"v":k[1]=+(l[1]-e).toFixed(3);break;case"m":f=l[1],g=l[2];default:for(var m=1,n=l.length;m<n;m++)k[m]=+(l[m]-(m%2?d:e)).toFixed(3)}}else{k=c[i]=[],l[0]=="m"&&(f=l[1]+d,g=l[2]+e);for(var o=0,p=l.length;o<p;o++)c[i][o]=l[o]}var q=c[i].length;switch(c[i][0]){case"z":d=f,e=g;break;case"h":d+=+c[i][q-1];break;case"v":e+=+c[i][q-1];break;default:d+=+c[i][q-2],e+=+c[i][q-1]}}c.toString=a._path2string;return c},0,by),bA=a._pathToAbsolute=bt(function(b){if(!a.is(b,E)||!a.is(b&&b[0],E))b=a.parsePathString(b);if(!b||!b.length)return[["M",0,0]];var c=[],d=0,e=0,f=0,g=0,h=0;b[0][0]=="M"&&(d=+b[0][1],e=+b[0][2],f=d,g=e,h++,c[0]=["M",d,e]);for(var i,j,k=h,l=b.length;k<l;k++){c.push(i=[]),j=b[k];if(j[0]!=S.call(j[0])){i[0]=S.call(j[0]);switch(i[0]){case"A":i[1]=j[1],i[2]=j[2],i[3]=j[3],i[4]=j[4],i[5]=j[5],i[6]=+(j[6]+d),i[7]=+(j[7]+e);break;case"V":i[1]=+j[1]+e;break;case"H":i[1]=+j[1]+d;break;case"R":var m=[d,e][n](j.slice(1));for(var o=2,p=m.length;o<p;o++)m[o]=+m[o]+d,m[++o]=+m[o]+e;c.pop(),c=c[n](bw(m));break;case"M":f=+j[1]+d,g=+j[2]+e;default:for(o=1,p=j.length;o<p;o++)i[o]=+j[o]+(o%2?d:e)}}else if(j[0]=="R")m=[d,e][n](j.slice(1)),c.pop(),c=c[n](bw(m)),i=["R"][n](j.slice(-2));else for(var q=0,r=j.length;q<r;q++)i[q]=j[q];switch(i[0]){case"Z":d=f,e=g;break;case"H":d=i[1];break;case"V":e=i[1];break;case"M":f=i[i.length-2],g=i[i.length-1];default:d=i[i.length-2],e=i[i.length-1]}}c.toString=a._path2string;return c},null,by),bB=function(a,b,c,d){return[a,b,c,d,c,d]},bC=function(a,b,c,d,e,f){var g=1/3,h=2/3;return[g*a+h*c,g*b+h*d,g*e+h*c,g*f+h*d,e,f]},bD=function(a,b,c,d,e,f,g,h,i,j){var k=B*120/180,l=B/180*(+e||0),m=[],o,p=bt(function(a,b,c){var d=a*w.cos(c)-b*w.sin(c),e=a*w.sin(c)+b*w.cos(c);return{x:d,y:e}});if(!j){o=p(a,b,-l),a=o.x,b=o.y,o=p(h,i,-l),h=o.x,i=o.y;var q=w.cos(B/180*e),r=w.sin(B/180*e),t=(a-h)/2,u=(b-i)/2,v=t*t/(c*c)+u*u/(d*d);v>1&&(v=w.sqrt(v),c=v*c,d=v*d);var x=c*c,y=d*d,A=(f==g?-1:1)*w.sqrt(z((x*y-x*u*u-y*t*t)/(x*u*u+y*t*t))),C=A*c*u/d+(a+h)/2,D=A*-d*t/c+(b+i)/2,E=w.asin(((b-D)/d).toFixed(9)),F=w.asin(((i-D)/d).toFixed(9));E=a<C?B-E:E,F=h<C?B-F:F,E<0&&(E=B*2+E),F<0&&(F=B*2+F),g&&E>F&&(E=E-B*2),!g&&F>E&&(F=F-B*2)}else E=j[0],F=j[1],C=j[2],D=j[3];var G=F-E;if(z(G)>k){var H=F,I=h,J=i;F=E+k*(g&&F>E?1:-1),h=C+c*w.cos(F),i=D+d*w.sin(F),m=bD(h,i,c,d,e,0,g,I,J,[F,H,C,D])}G=F-E;var K=w.cos(E),L=w.sin(E),M=w.cos(F),N=w.sin(F),O=w.tan(G/4),P=4/3*c*O,Q=4/3*d*O,R=[a,b],S=[a+P*L,b-Q*K],T=[h+P*N,i-Q*M],U=[h,i];S[0]=2*R[0]-S[0],S[1]=2*R[1]-S[1];if(j)return[S,T,U][n](m);m=[S,T,U][n](m).join()[s](",");var V=[];for(var W=0,X=m.length;W<X;W++)V[W]=W%2?p(m[W-1],m[W],l).y:p(m[W],m[W+1],l).x;return V},bE=function(a,b,c,d,e,f,g,h,i){var j=1-i;return{x:A(j,3)*a+A(j,2)*3*i*c+j*3*i*i*e+A(i,3)*g,y:A(j,3)*b+A(j,2)*3*i*d+j*3*i*i*f+A(i,3)*h}},bF=bt(function(a,b,c,d,e,f,g,h){var i=e-2*c+a-(g-2*e+c),j=2*(c-a)-2*(e-c),k=a-c,l=(-j+w.sqrt(j*j-4*i*k))/2/i,n=(-j-w.sqrt(j*j-4*i*k))/2/i,o=[b,h],p=[a,g],q;z(l)>"1e12"&&(l=.5),z(n)>"1e12"&&(n=.5),l>0&&l<1&&(q=bE(a,b,c,d,e,f,g,h,l),p.push(q.x),o.push(q.y)),n>0&&n<1&&(q=bE(a,b,c,d,e,f,g,h,n),p.push(q.x),o.push(q.y)),i=f-2*d+b-(h-2*f+d),j=2*(d-b)-2*(f-d),k=b-d,l=(-j+w.sqrt(j*j-4*i*k))/2/i,n=(-j-w.sqrt(j*j-4*i*k))/2/i,z(l)>"1e12"&&(l=.5),z(n)>"1e12"&&(n=.5),l>0&&l<1&&(q=bE(a,b,c,d,e,f,g,h,l),p.push(q.x),o.push(q.y)),n>0&&n<1&&(q=bE(a,b,c,d,e,f,g,h,n),p.push(q.x),o.push(q.y));return{min:{x:y[m](0,p),y:y[m](0,o)},max:{x:x[m](0,p),y:x[m](0,o)}}}),bG=a._path2curve=bt(function(a,b){var c=bA(a),d=b&&bA(b),e={x:0,y:0,bx:0,by:0,X:0,Y:0,qx:null,qy:null},f={x:0,y:0,bx:0,by:0,X:0,Y:0,qx:null,qy:null},g=function(a,b){var c,d;if(!a)return["C",b.x,b.y,b.x,b.y,b.x,b.y];!(a[0]in{T:1,Q:1})&&(b.qx=b.qy=null);switch(a[0]){case"M":b.X=a[1],b.Y=a[2];break;case"A":a=["C"][n](bD[m](0,[b.x,b.y][n](a.slice(1))));break;case"S":c=b.x+(b.x-(b.bx||b.x)),d=b.y+(b.y-(b.by||b.y)),a=["C",c,d][n](a.slice(1));break;case"T":b.qx=b.x+(b.x-(b.qx||b.x)),b.qy=b.y+(b.y-(b.qy||b.y)),a=["C"][n](bC(b.x,b.y,b.qx,b.qy,a[1],a[2]));break;case"Q":b.qx=a[1],b.qy=a[2],a=["C"][n](bC(b.x,b.y,a[1],a[2],a[3],a[4]));break;case"L":a=["C"][n](bB(b.x,b.y,a[1],a[2]));break;case"H":a=["C"][n](bB(b.x,b.y,a[1],b.y));break;case"V":a=["C"][n](bB(b.x,b.y,b.x,a[1]));break;case"Z":a=["C"][n](bB(b.x,b.y,b.X,b.Y))}return a},h=function(a,b){if(a[b].length>7){a[b].shift();var e=a[b];while(e.length)a.splice(b++,0,["C"][n](e.splice(0,6)));a.splice(b,1),k=x(c.length,d&&d.length||0)}},i=function(a,b,e,f,g){a&&b&&a[g][0]=="M"&&b[g][0]!="M"&&(b.splice(g,0,["M",f.x,f.y]),e.bx=0,e.by=0,e.x=a[g][1],e.y=a[g][2],k=x(c.length,d&&d.length||0))};for(var j=0,k=x(c.length,d&&d.length||0);j<k;j++){c[j]=g(c[j],e),h(c,j),d&&(d[j]=g(d[j],f)),d&&h(d,j),i(c,d,e,f,j),i(d,c,f,e,j);var l=c[j],o=d&&d[j],p=l.length,q=d&&o.length;e.x=l[p-2],e.y=l[p-1],e.bx=Q(l[p-4])||e.x,e.by=Q(l[p-3])||e.y,f.bx=d&&(Q(o[q-4])||f.x),f.by=d&&(Q(o[q-3])||f.y),f.x=d&&o[q-2],f.y=d&&o[q-1]}return d?[c,d]:c},null,by),bH=a._parseDots=bt(function(b){var c=[];for(var d=0,e=b.length;d<e;d++){var f={},g=b[d].match(/^([^:]*):?([\d\.]*)/);f.color=a.getRGB(g[1]);if(f.color.error)return null;f.color=f.color.hex,g[2]&&(f.offset=g[2]+"%"),c.push(f)}for(d=1,e=c.length-1;d<e;d++)if(!c[d].offset){var h=Q(c[d-1].offset||0),i=0;for(var j=d+1;j<e;j++)if(c[j].offset){i=c[j].offset;break}i||(i=100,j=e),i=Q(i);var k=(i-h)/(j-d+1);for(;d<j;d++)h+=k,c[d].offset=h+"%"}return c}),bI=a._tear=function(a,b){a==b.top&&(b.top=a.prev),a==b.bottom&&(b.bottom=a.next),a.next&&(a.next.prev=a.prev),a.prev&&(a.prev.next=a.next)},bJ=a._tofront=function(a,b){b.top!==a&&(bI(a,b),a.next=null,a.prev=b.top,b.top.next=a,b.top=a)},bK=a._toback=function(a,b){b.bottom!==a&&(bI(a,b),a.next=b.bottom,a.prev=null,b.bottom.prev=a,b.bottom=a)},bL=a._insertafter=function(a,b,c){bI(a,c),b==c.top&&(c.top=a),b.next&&(b.next.prev=a),a.next=b.next,a.prev=b,b.next=a},bM=a._insertbefore=function(a,b,c){bI(a,c),b==c.bottom&&(c.bottom=a),b.prev&&(b.prev.next=a),a.prev=b.prev,b.prev=a,a.next=b},bN=function(a){return function(){throw new Error("Raphaël: you are calling to method “"+a+"” of removed object")}},bO=a._extractTransform=function(b,c){if(c==null)return b._.transform;c=r(c).replace(/\.{3}|\u2026/g,b._.transform||p);var d=a.parseTransformString(c),e=0,f=0,g=0,h=1,i=1,j=b._,k=new bR;j.transform=d||[];if(d)for(var l=0,m=d.length;l<m;l++){var n=d[l],o=n.length,q=r(n[0]).toLowerCase(),s=n[0]!=q,t=s?k.invert():0,u,v,w,x,y;q=="t"&&o==3?s?(u=t.x(0,0),v=t.y(0,0),w=t.x(n[1],n[2]),x=t.y(n[1],n[2]),k.translate(w-u,x-v)):k.translate(n[1],n[2]):q=="r"?o==2?(y=y||b.getBBox(1),k.rotate(n[1],y.x+y.width/2,y.y+y.height/2),e+=n[1]):o==4&&(s?(w=t.x(n[2],n[3]),x=t.y(n[2],n[3]),k.rotate(n[1],w,x)):k.rotate(n[1],n[2],n[3]),e+=n[1]):q=="s"?o==2||o==3?(y=y||b.getBBox(1),k.scale(n[1],n[o-1],y.x+y.width/2,y.y+y.height/2),h*=n[1],i*=n[o-1]):o==5&&(s?(w=t.x(n[3],n[4]),x=t.y(n[3],n[4]),k.scale(n[1],n[2],w,x)):k.scale(n[1],n[2],n[3],n[4]),h*=n[1],i*=n[2]):q=="m"&&o==7&&k.add(n[1],n[2],n[3],n[4],n[5],n[6]),j.dirtyT=1,b.matrix=k}b.matrix=k,j.sx=h,j.sy=i,j.deg=e,j.dx=f=k.e,j.dy=g=k.f,h==1&&i==1&&!e&&j.bbox?(j.bbox.x+=+f,j.bbox.y+=+g):j.dirtyT=1},bP=function(a){var b=a[0];switch(b.toLowerCase()){case"t":return[b,0,0];case"m":return[b,1,0,0,1,0,0];case"r":return a.length==4?[b,0,a[2],a[3]]:[b,0];case"s":return a.length==5?[b,1,1,a[3],a[4]]:a.length==3?[b,1,1]:[b,1]}},bQ=a._equaliseTransform=function(b,c){c=r(c).replace(/\.{3}|\u2026/g,b),b=a.parseTransformString(b)||[],c=a.parseTransformString(c)||[];var d=x(b.length,c.length),e=[],f=[],g=0,h,i,j,k;for(;g<d;g++){j=b[g]||bP(c[g]),k=c[g]||bP(j);if(j[0]!=k[0]||j[0].toLowerCase()=="r"&&(j[2]!=k[2]||j[3]!=k[3])||j[0].toLowerCase()=="s"&&(j[3]!=k[3]||j[4]!=k[4]))return;e[g]=[],f[g]=[];for(h=0,i=x(j.length,k.length);h<i;h++)h in j&&(e[g][h]=j[h]),h in k&&(f[g][h]=k[h])}return{from:e,to:f}};a._getContainer=function(b,c,d,e){var f;f=e==null&&!a.is(b,"object")?h.doc.getElementById(b):b;if(f!=null){if(f.tagName)return c==null?{container:f,width:f.style.pixelWidth||f.offsetWidth,height:f.style.pixelHeight||f.offsetHeight}:{container:f,width:c,height:d};return{container:1,x:b,y:c,width:d,height:e}}},a.pathToRelative=bz,a._engine={},a.path2curve=bG,a.matrix=function(a,b,c,d,e,f){return new bR(a,b,c,d,e,f)},function(b){function d(a){var b=w.sqrt(c(a));a[0]&&(a[0]/=b),a[1]&&(a[1]/=b)}function c(a){return a[0]*a[0]+a[1]*a[1]}b.add=function(a,b,c,d,e,f){var g=[[],[],[]],h=[[this.a,this.c,this.e],[this.b,this.d,this.f],[0,0,1]],i=[[a,c,e],[b,d,f],[0,0,1]],j,k,l,m;a&&a instanceof bR&&(i=[[a.a,a.c,a.e],[a.b,a.d,a.f],[0,0,1]]);for(j=0;j<3;j++)for(k=0;k<3;k++){m=0;for(l=0;l<3;l++)m+=h[j][l]*i[l][k];g[j][k]=m}this.a=g[0][0],this.b=g[1][0],this.c=g[0][1],this.d=g[1][1],this.e=g[0][2],this.f=g[1][2]},b.invert=function(){var a=this,b=a.a*a.d-a.b*a.c;return new bR(a.d/b,-a.b/b,-a.c/b,a.a/b,(a.c*a.f-a.d*a.e)/b,(a.b*a.e-a.a*a.f)/b)},b.clone=function(){return new bR(this.a,this.b,this.c,this.d,this.e,this.f)},b.translate=function(a,b){this.add(1,0,0,1,a,b)},b.scale=function(a,b,c,d){b==null&&(b=a),(c||d)&&this.add(1,0,0,1,c,d),this.add(a,0,0,b,0,0),(c||d)&&this.add(1,0,0,1,-c,-d)},b.rotate=function(b,c,d){b=a.rad(b),c=c||0,d=d||0;var e=+w.cos(b).toFixed(9),f=+w.sin(b).toFixed(9);this.add(e,f,-f,e,c,d),this.add(1,0,0,1,-c,-d)},b.x=function(a,b){return a*this.a+b*this.c+this.e},b.y=function(a,b){return a*this.b+b*this.d+this.f},b.get=function(a){return+this[r.fromCharCode(97+a)].toFixed(4)},b.toString=function(){return a.svg?"matrix("+[this.get(0),this.get(1),this.get(2),this.get(3),this.get(4),this.get(5)].join()+")":[this.get(0),this.get(2),this.get(1),this.get(3),0,0].join()},b.toFilter=function(){return"progid:DXImageTransform.Microsoft.Matrix(M11="+this.get(0)+", M12="+this.get(2)+", M21="+this.get(1)+", M22="+this.get(3)+", Dx="+this.get(4)+", Dy="+this.get(5)+", sizingmethod='auto expand')"},b.offset=function(){return[this.e.toFixed(4),this.f.toFixed(4)]},b.split=function(){var b={};b.dx=this.e,b.dy=this.f;var e=[[this.a,this.c],[this.b,this.d]];b.scalex=w.sqrt(c(e[0])),d(e[0]),b.shear=e[0][0]*e[1][0]+e[0][1]*e[1][1],e[1]=[e[1][0]-e[0][0]*b.shear,e[1][1]-e[0][1]*b.shear],b.scaley=w.sqrt(c(e[1])),d(e[1]),b.shear/=b.scaley;var f=-e[0][1],g=e[1][1];g<0?(b.rotate=a.deg(w.acos(g)),f<0&&(b.rotate=360-b.rotate)):b.rotate=a.deg(w.asin(f)),b.isSimple=!+b.shear.toFixed(9)&&(b.scalex.toFixed(9)==b.scaley.toFixed(9)||!b.rotate),b.isSuperSimple=!+b.shear.toFixed(9)&&b.scalex.toFixed(9)==b.scaley.toFixed(9)&&!b.rotate,b.noRotation=!+b.shear.toFixed(9)&&!b.rotate;return b},b.toTransformString=function(a){var b=a||this[s]();return b.isSimple?"t"+[b.dx,b.dy]+"s"+[b.scalex,b.scaley,0,0]+"r"+[b.rotate,0,0]:"m"+[this.get(0),this.get(1),this.get(2),this.get(3),this.get(4),this.get(5)]}}(bR.prototype);var bS=navigator.userAgent.match(/Version\/(.*?)\s/)||navigator.userAgent.match(/Chrome\/(\d+)/);navigator.vendor=="Apple Computer, Inc."&&(bS&&bS[1]<4||navigator.platform.slice(0,2)=="iP")||navigator.vendor=="Google Inc."&&bS&&bS[1]<8?k.safari=function(){var a=this.rect(-99,-99,this.width+99,this.height+99).attr({stroke:"none"});setTimeout(function(){a.remove()})}:k.safari=bd;var bT=function(){this.returnValue=!1},bU=function(){return this.originalEvent.preventDefault()},bV=function(){this.cancelBubble=!0},bW=function(){return this.originalEvent.stopPropagation()},bX=function(){if(h.doc.addEventListener)return function(a,b,c,d){var e=o&&u[b]?u[b]:b,f=function(e){var f=h.doc.documentElement.scrollTop||h.doc.body.scrollTop,i=h.doc.documentElement.scrollLeft||h.doc.body.scrollLeft,j=e.clientX+i,k=e.clientY+f;if(o&&u[g](b))for(var l=0,m=e.targetTouches&&e.targetTouches.length;l<m;l++)if(e.targetTouches[l].target==a){var n=e;e=e.targetTouches[l],e.originalEvent=n,e.preventDefault=bU,e.stopPropagation=bW;break}return c.call(d,e,j,k)};a.addEventListener(e,f,!1);return function(){a.removeEventListener(e,f,!1);return!0}};if(h.doc.attachEvent)return function(a,b,c,d){var e=function(a){a=a||h.win.event;var b=h.doc.documentElement.scrollTop||h.doc.body.scrollTop,e=h.doc.documentElement.scrollLeft||h.doc.body.scrollLeft,f=a.clientX+e,g=a.clientY+b;a.preventDefault=a.preventDefault||bT,a.stopPropagation=a.stopPropagation||bV;return c.call(d,a,f,g)};a.attachEvent("on"+b,e);var f=function(){a.detachEvent("on"+b,e);return!0};return f}}(),bY=[],bZ=function(a){var b=a.clientX,c=a.clientY,d=h.doc.documentElement.scrollTop||h.doc.body.scrollTop,e=h.doc.documentElement.scrollLeft||h.doc.body.scrollLeft,f,g=bY.length;while(g--){f=bY[g];if(o){var i=a.touches.length,j;while(i--){j=a.touches[i];if(j.identifier==f.el._drag.id){b=j.clientX,c=j.clientY,(a.originalEvent?a.originalEvent:a).preventDefault();break}}}else a.preventDefault();var k=f.el.node,l,m=k.nextSibling,n=k.parentNode,p=k.style.display;h.win.opera&&n.removeChild(k),k.style.display="none",l=f.el.paper.getElementByPoint(b,c),k.style.display=p,h.win.opera&&(m?n.insertBefore(k,m):n.appendChild(k)),l&&eve("drag.over."+f.el.id,f.el,l),b+=e,c+=d,eve("drag.move."+f.el.id,f.move_scope||f.el,b-f.el._drag.x,c-f.el._drag.y,b,c,a)}},b$=function(b){a.unmousemove(bZ).unmouseup(b$);var c=bY.length,d;while(c--)d=bY[c],d.el._drag={},eve("drag.end."+d.el.id,d.end_scope||d.start_scope||d.move_scope||d.el,b);bY=[]},b_=a.el={};for(var ca=t.length;ca--;)(function(b){a[b]=b_[b]=function(c,d){a.is(c,"function")&&(this.events=this.events||[],this.events.push({name:b,f:c,unbind:bX(this.shape||this.node||h.doc,b,c,d||this)}));return this},a["un"+b]=b_["un"+b]=function(a){var c=this.events,d=c.length;while(d--)if(c[d].name==b&&c[d].f==a){c[d].unbind(),c.splice(d,1),!c.length&&delete this.events;return this}return this}})(t[ca]);b_.data=function(b,c){var d=ba[this.id]=ba[this.id]||{};if(arguments.length==1){if(a.is(b,"object")){for(var e in b)b[g](e)&&this.data(e,b[e]);return this}eve("data.get."+this.id,this,d[b],b);return d[b]}d[b]=c,eve("data.set."+this.id,this,c,b);return this},b_.removeData=function(a){a==null?ba[this.id]={}:ba[this.id]&&delete ba[this.id][a];return this},b_.hover=function(a,b,c,d){return this.mouseover(a,c).mouseout(b,d||c)},b_.unhover=function(a,b){return this.unmouseover(a).unmouseout(b)},b_.drag=function(b,c,d,e,f,g){function i(i){(i.originalEvent||i).preventDefault();var j=h.doc.documentElement.scrollTop||h.doc.body.scrollTop,k=h.doc.documentElement.scrollLeft||h.doc.body.scrollLeft;this._drag.x=i.clientX+k,this._drag.y=i.clientY+j,this._drag.id=i.identifier,!bY.length&&a.mousemove(bZ).mouseup(b$),bY.push({el:this,move_scope:e,start_scope:f,end_scope:g}),c&&eve.on("drag.start."+this.id,c),b&&eve.on("drag.move."+this.id,b),d&&eve.on("drag.end."+this.id,d),eve("drag.start."+this.id,f||e||this,i.clientX+k,i.clientY+j,i)}this._drag={},this.mousedown(i);return this},b_.onDragOver=function(a){a?eve.on("drag.over."+this.id,a):eve.unbind("drag.over."+this.id)},b_.undrag=function(){var b=bY.length;while(b--)bY[b].el==this&&(a.unmousedown(bY[b].start),bY.splice(b++,1),eve.unbind("drag.*."+this.id));!bY.length&&a.unmousemove(bZ).unmouseup(b$)},k.circle=function(b,c,d){var e=a._engine.circle(this,b||0,c||0,d||0);this.__set__&&this.__set__.push(e);return e},k.rect=function(b,c,d,e,f){var g=a._engine.rect(this,b||0,c||0,d||0,e||0,f||0);this.__set__&&this.__set__.push(g);return g},k.ellipse=function(b,c,d,e){var f=a._engine.ellipse(this,b||0,c||0,d||0,e||0);this.__set__&&this.__set__.push(f);return f},k.path=function(b){b&&!a.is(b,D)&&!a.is(b[0],E)&&(b+=p);var c=a._engine.path(a.format[m](a,arguments),this);this.__set__&&this.__set__.push(c);return c},k.image=function(b,c,d,e,f){var g=a._engine.image(this,b||"about:blank",c||0,d||0,e||0,f||0);this.__set__&&this.__set__.push(g);return g},k.text=function(b,c,d){var e=a._engine.text(this,b||0,c||0,r(d));this.__set__&&this.__set__.push(e);return e},k.set=function(b){!a.is(b,"array")&&(b=Array.prototype.splice.call(arguments,0,arguments.length));var c=new cs(b);this.__set__&&this.__set__.push(c);return c},k.setStart=function(a){this.__set__=a||this.set()},k.setFinish=function(a){var b=this.__set__;delete this.__set__;return b},k.setSize=function(b,c){return a._engine.setSize.call(this,b,c)},k.setViewBox=function(b,c,d,e,f){return a._engine.setViewBox.call(this,b,c,d,e,f)},k.top=k.bottom=null,k.raphael=a;var cb=function(a){var b=a.getBoundingClientRect(),c=a.ownerDocument,d=c.body,e=c.documentElement,f=e.clientTop||d.clientTop||0,g=e.clientLeft||d.clientLeft||0,i=b.top+(h.win.pageYOffset||e.scrollTop||d.scrollTop)-f,j=b.left+(h.win.pageXOffset||e.scrollLeft||d.scrollLeft)-g;return{y:i,x:j}};k.getElementByPoint=function(a,b){var c=this,d=c.canvas,e=h.doc.elementFromPoint(a,b);if(h.win.opera&&e.tagName=="svg"){var f=cb(d),g=d.createSVGRect();g.x=a-f.x,g.y=b-f.y,g.width=g.height=1;var i=d.getIntersectionList(g,null);i.length&&(e=i[i.length-1])}if(!e)return null;while(e.parentNode&&e!=d.parentNode&&!e.raphael)e=e.parentNode;e==c.canvas.parentNode&&(e=d),e=e&&e.raphael?c.getById(e.raphaelid):null;return e},k.getById=function(a){var b=this.bottom;while(b){if(b.id==a)return b;b=b.next}return null},k.forEach=function(a,b){var c=this.bottom;while(c){if(a.call(b,c)===!1)return this;c=c.next}return this},b_.getBBox=function(a){if(this.removed)return{};var b=this._;if(a){if(b.dirty||!b.bboxwt)this.realPath=bh[this.type](this),b.bboxwt=bx(this.realPath),b.bboxwt.toString=cd,b.dirty=0;return b.bboxwt}if(b.dirty||b.dirtyT||!b.bbox){if(b.dirty||!this.realPath)b.bboxwt=0,this.realPath=bh[this.type](this);b.bbox=bx(bi(this.realPath,this.matrix)),b.bbox.toString=cd,b.dirty=b.dirtyT=0}return b.bbox},b_.clone=function(){if(this.removed)return null;var a=this.paper[this.type]().attr(this.attr());this.__set__&&this.__set__.push(a);return a},b_.glow=function(a){if(this.type=="text")return null;a=a||{};var b={width:(a.width||10)+(+this.attr("stroke-width")||1),fill:a.fill||!1,opacity:a.opacity||.5,offsetx:a.offsetx||0,offsety:a.offsety||0,color:a.color||"#000"},c=b.width/2,d=this.paper,e=d.set(),f=this.realPath||bh[this.type](this);f=this.matrix?bi(f,this.matrix):f;for(var g=1;g<c+1;g++)e.push(d.path(f).attr({stroke:b.color,fill:b.fill?b.color:"none","stroke-linejoin":"round","stroke-linecap":"round","stroke-width":+(b.width/c*g).toFixed(3),opacity:+(b.opacity/c).toFixed(3)}));return e.insertBefore(this).translate(b.offsetx,b.offsety)};var ce={},cf=function(b,c,d,e,f,g,h,i,j){var k=0,l=100,m=[b,c,d,e,f,g,h,i].join(),n=ce[m],o,p;!n&&(ce[m]=n={data:[]}),n.timer&&clearTimeout(n.timer),n.timer=setTimeout(function(){delete ce[m]},2e3);if(j!=null&&!n.precision){var q=cf(b,c,d,e,f,g,h,i);n.precision=~~q*10,n.data=[]}l=n.precision||l;for(var r=0;r<l+1;r++){n.data[r*l]?p=n.data[r*l]:(p=a.findDotsAtSegment(b,c,d,e,f,g,h,i,r/l),n.data[r*l]=p),r&&(k+=A(A(o.x-p.x,2)+A(o.y-p.y,2),.5));if(j!=null&&k>=j)return p;o=p}if(j==null)return k},cg=function(b,c){return function(d,e,f){d=bG(d);var g,h,i,j,k="",l={},m,n=0;for(var o=0,p=d.length;o<p;o++){i=d[o];if(i[0]=="M")g=+i[1],h=+i[2];else{j=cf(g,h,i[1],i[2],i[3],i[4],i[5],i[6]);if(n+j>e){if(c&&!l.start){m=cf(g,h,i[1],i[2],i[3],i[4],i[5],i[6],e-n),k+=["C"+m.start.x,m.start.y,m.m.x,m.m.y,m.x,m.y];if(f)return k;l.start=k,k=["M"+m.x,m.y+"C"+m.n.x,m.n.y,m.end.x,m.end.y,i[5],i[6]].join(),n+=j,g=+i[5],h=+i[6];continue}if(!b&&!c){m=cf(g,h,i[1],i[2],i[3],i[4],i[5],i[6],e-n);return{x:m.x,y:m.y,alpha:m.alpha}}}n+=j,g=+i[5],h=+i[6]}k+=i.shift()+i}l.end=k,m=b?n:c?l:a.findDotsAtSegment(g,h,i[0],i[1],i[2],i[3],i[4],i[5],1),m.alpha&&(m={x:m.x,y:m.y,alpha:m.alpha});return m}},ch=cg(1),ci=cg(),cj=cg(0,1);a.getTotalLength=ch,a.getPointAtLength=ci,a.getSubpath=function(a,b,c){if(this.getTotalLength(a)-c<1e-6)return cj(a,b).end;var d=cj(a,c,1);return b?cj(d,b).end:d},b_.getTotalLength=function(){if(this.type=="path"){if(this.node.getTotalLength)return this.node.getTotalLength();return ch(this.attrs.path)}},b_.getPointAtLength=function(a){if(this.type=="path")return ci(this.attrs.path,a)},b_.getSubpath=function(b,c){if(this.type=="path")return a.getSubpath(this.attrs.path,b,c)};var ck=a.easing_formulas={linear:function(a){return a},"<":function(a){return A(a,1.7)},">":function(a){return A(a,.48)},"<>":function(a){var b=.48-a/1.04,c=w.sqrt(.1734+b*b),d=c-b,e=A(z(d),1/3)*(d<0?-1:1),f=-c-b,g=A(z(f),1/3)*(f<0?-1:1),h=e+g+.5;return(1-h)*3*h*h+h*h*h},backIn:function(a){var b=1.70158;return a*a*((b+1)*a-b)},backOut:function(a){a=a-1;var b=1.70158;return a*a*((b+1)*a+b)+1},elastic:function(a){if(a==!!a)return a;return A(2,-10*a)*w.sin((a-.075)*2*B/.3)+1},bounce:function(a){var b=7.5625,c=2.75,d;a<1/c?d=b*a*a:a<2/c?(a-=1.5/c,d=b*a*a+.75):a<2.5/c?(a-=2.25/c,d=b*a*a+.9375):(a-=2.625/c,d=b*a*a+.984375);return d}};ck.easeIn=ck["ease-in"]=ck["<"],ck.easeOut=ck["ease-out"]=ck[">"],ck.easeInOut=ck["ease-in-out"]=ck["<>"],ck["back-in"]=ck.backIn,ck["back-out"]=ck.backOut;var cl=[],cm=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(a){setTimeout(a,16)},cn=function(){var b=+(new Date),c=0;for(;c<cl.length;c++){var d=cl[c];if(d.el.removed||d.paused)continue;var e=b-d.start,f=d.ms,h=d.easing,i=d.from,j=d.diff,k=d.to,l=d.t,m=d.el,o={},p,r={},s;d.initstatus?(e=(d.initstatus*d.anim.top-d.prev)/(d.percent-d.prev)*f,d.status=d.initstatus,delete d.initstatus,d.stop&&cl.splice(c--,1)):d.status=(d.prev+(d.percent-d.prev)*(e/f))/d.anim.top;if(e<0)continue;if(e<f){var t=h(e/f);for(var u in i)if(i[g](u)){switch(U[u]){case C:p=+i[u]+t*f*j[u];break;case"colour":p="rgb("+[co(O(i[u].r+t*f*j[u].r)),co(O(i[u].g+t*f*j[u].g)),co(O(i[u].b+t*f*j[u].b))].join(",")+")";break;case"path":p=[];for(var v=0,w=i[u].length;v<w;v++){p[v]=[i[u][v][0]];for(var x=1,y=i[u][v].length;x<y;x++)p[v][x]=+i[u][v][x]+t*f*j[u][v][x];p[v]=p[v].join(q)}p=p.join(q);break;case"transform":if(j[u].real){p=[];for(v=0,w=i[u].length;v<w;v++){p[v]=[i[u][v][0]];for(x=1,y=i[u][v].length;x<y;x++)p[v][x]=i[u][v][x]+t*f*j[u][v][x]}}else{var z=function(a){return+i[u][a]+t*f*j[u][a]};p=[["m",z(0),z(1),z(2),z(3),z(4),z(5)]]}break;case"csv":if(u=="clip-rect"){p=[],v=4;while(v--)p[v]=+i[u][v]+t*f*j[u][v]}break;default:var A=[][n](i[u]);p=[],v=m.paper.customAttributes[u].length;while(v--)p[v]=+A[v]+t*f*j[u][v]}o[u]=p}m.attr(o),function(a,b,c){setTimeout(function(){eve("anim.frame."+a,b,c)})}(m.id,m,d.anim)}else{(function(b,c,d){setTimeout(function(){eve("anim.frame."+c.id,c,d),eve("anim.finish."+c.id,c,d),a.is(b,"function")&&b.call(c)})})(d.callback,m,d.anim),m.attr(k),cl.splice(c--,1);if(d.repeat>1&&!d.next){for(s in k)k[g](s)&&(r[s]=d.totalOrigin[s]);d.el.attr(r),cr(d.anim,d.el,d.anim.percents[0],null,d.totalOrigin,d.repeat-1)}d.next&&!d.stop&&cr(d.anim,d.el,d.next,null,d.totalOrigin,d.repeat)}}a.svg&&m&&m.paper&&m.paper.safari(),cl.length&&cm(cn)},co=function(a){return a>255?255:a<0?0:a};b_.animateWith=function(b,c,d,e,f,g){var h=d?a.animation(d,e,f,g):c;status=b.status(c);return this.animate(h).status(h,status*c.ms/h.ms)},b_.onAnimation=function(a){a?eve.on("anim.frame."+this.id,a):eve.unbind("anim.frame."+this.id);return this},cq.prototype.delay=function(a){var b=new cq(this.anim,this.ms);b.times=this.times,b.del=+a||0;return b},cq.prototype.repeat=function(a){var b=new cq(this.anim,this.ms);b.del=this.del,b.times=w.floor(x(a,0))||1;return b},a.animation=function(b,c,d,e){if(b instanceof cq)return b;if(a.is(d,"function")||!d)e=e||d||null,d=null;b=Object(b),c=+c||0;var f={},h,i;for(i in b)b[g](i)&&Q(i)!=i&&Q(i)+"%"!=i&&(h=!0,f[i]=b[i]);if(!h)return new cq(b,c);d&&(f.easing=d),e&&(f.callback=e);return new cq({100:f},c)},b_.animate=function(b,c,d,e){var f=this;if(f.removed){e&&e.call(f);return f}var g=b instanceof cq?b:a.animation(b,c,d,e);cr(g,f,g.percents[0],null,f.attr());return f},b_.setTime=function(a,b){a&&b!=null&&this.status(a,y(b,a.ms)/a.ms);return this},b_.status=function(a,b){var c=[],d=0,e,f;if(b!=null){cr(a,this,-1,y(b,1));return this}e=cl.length;for(;d<e;d++){f=cl[d];if(f.el.id==this.id&&(!a||f.anim==a)){if(a)return f.status;c.push({anim:f.anim,status:f.status})}}if(a)return 0;return c},b_.pause=function(a){for(var b=0;b<cl.length;b++)cl[b].el.id==this.id&&(!a||cl[b].anim==a)&&eve("anim.pause."+this.id,this,cl[b].anim)!==!1&&(cl[b].paused=!0);return this},b_.resume=function(a){for(var b=0;b<cl.length;b++)if(cl[b].el.id==this.id&&(!a||cl[b].anim==a)){var c=cl[b];eve("anim.resume."+this.id,this,c.anim)!==!1&&(delete c.paused,this.status(c.anim,c.status))}return this},b_.stop=function(a){for(var b=0;b<cl.length;b++)cl[b].el.id==this.id&&(!a||cl[b].anim==a)&&eve("anim.stop."+this.id,this,cl[b].anim)!==!1&&cl.splice(b--,1);return this},b_.toString=function(){return"Raphaël’s object"};var cs=function(a){this.items=[],this.length=0,this.type="set";if(a)for(var b=0,c=a.length;b<c;b++)a[b]&&(a[b].constructor==b_.constructor||a[b].constructor==cs)&&(this[this.items.length]=this.items[this.items.length]=a[b],this.length++)},ct=cs.prototype;ct.push=function(){var a,b;for(var c=0,d=arguments.length;c<d;c++)a=arguments[c],a&&(a.constructor==b_.constructor||a.constructor==cs)&&(b=this.items.length,this[b]=this.items[b]=a,this.length++);return this},ct.pop=function(){this.length&&delete this[this.length--];return this.items.pop()},ct.forEach=function(a,b){for(var c=0,d=this.items.length;c<d;c++)if(a.call(b,this.items[c],c)===!1)return this;return this};for(var cu in b_)b_[g](cu)&&(ct[cu]=function(a){return function(){var b=arguments;return this.forEach(function(c){c[a][m](c,b)})}}(cu));ct.attr=function(b,c){if(b&&a.is(b,E)&&a.is(b[0],"object"))for(var d=0,e=b.length;d<e;d++)this.items[d].attr(b[d]);else for(var f=0,g=this.items.length;f<g;f++)this.items[f].attr(b,c);return this},ct.clear=function(){while(this.length)this.pop()},ct.splice=function(a,b,c){a=a<0?x(this.length+a,0):a,b=x(0,y(this.length-a,b));var d=[],e=[],f=[],g;for(g=2;g<arguments.length;g++)f.push(arguments[g]);for(g=0;g<b;g++)e.push(this[a+g]);for(;g<this.length-a;g++)d.push(this[a+g]);var h=f.length;for(g=0;g<h+d.length;g++)this.items[a+g]=this[a+g]=g<h?f[g]:d[g-h];g=this.items.length=this.length-=b-h;while(this[g])delete this[g++];return new cs(e)},ct.exclude=function(a){for(var b=0,c=this.length;b<c;b++)if(this[b]==a){this.splice(b,1);return!0}},ct.animate=function(b,c,d,e){(a.is(d,"function")||!d)&&(e=d||null);var f=this.items.length,g=f,h,i=this,j;if(!f)return this;e&&(j=function(){!--f&&e.call(i)}),d=a.is(d,D)?d:j;var k=a.animation(b,c,d,j);h=this.items[--g].animate(k);while(g--)this.items[g]&&!this.items[g].removed&&this.items[g].animateWith(h,k);return this},ct.insertAfter=function(a){var b=this.items.length;while(b--)this.items[b].insertAfter(a);return this},ct.getBBox=function(){var a=[],b=[],c=[],d=[];for(var e=this.items.length;e--;)if(!this.items[e].removed){var f=this.items[e].getBBox();a.push(f.x),b.push(f.y),c.push(f.x+f.width),d.push(f.y+f.height)}a=y[m](0,a),b=y[m](0,b);return{x:a,y:b,width:x[m](0,c)-a,height:x[m](0,d)-b}},ct.clone=function(a){a=new cs;for(var b=0,c=this.items.length;b<c;b++)a.push(this.items[b].clone());return a},ct.toString=function(){return"Raphaël‘s set"},a.registerFont=function(a){if(!a.face)return a;this.fonts=this.fonts||{};var b={w:a.w,face:{},glyphs:{}},c=a.face["font-family"];for(var d in a.face)a.face[g](d)&&(b.face[d]=a.face[d]);this.fonts[c]?this.fonts[c].push(b):this.fonts[c]=[b];if(!a.svg){b.face["units-per-em"]=R(a.face["units-per-em"],10);for(var e in a.glyphs)if(a.glyphs[g](e)){var f=a.glyphs[e];b.glyphs[e]={w:f.w,k:{},d:f.d&&"M"+f.d.replace(/[mlcxtrv]/g,function(a){return{l:"L",c:"C",x:"z",t:"m",r:"l",v:"c"}[a]||"M"})+"z"};if(f.k)for(var h in f.k)f[g](h)&&(b.glyphs[e].k[h]=f.k[h])}}return a},k.getFont=function(b,c,d,e){e=e||"normal",d=d||"normal",c=+c||{normal:400,bold:700,lighter:300,bolder:800}[c]||400;if(!!a.fonts){var f=a.fonts[b];if(!f){var h=new RegExp("(^|\\s)"+b.replace(/[^\w\d\s+!~.:_-]/g,p)+"(\\s|$)","i");for(var i in a.fonts)if(a.fonts[g](i)&&h.test(i)){f=a.fonts[i];break}}var j;if(f)for(var k=0,l=f.length;k<l;k++){j=f[k];if(j.face["font-weight"]==c&&(j.face["font-style"]==d||!j.face["font-style"])&&j.face["font-stretch"]==e)break}return j}},k.print=function(b,d,e,f,g,h,i){h=h||"middle",i=x(y(i||0,1),-1);var j=this.set(),k=r(e)[s](p),l=0,m=p,n;a.is(f,e)&&(f=this.getFont(f));if(f){n=(g||16)/f.face["units-per-em"];var o=f.face.bbox[s](c),q=+o[0],t=+o[1]+(h=="baseline"?o[3]-o[1]+ +f.face.descent:(o[3]-o[1])/2);for(var u=0,v=k.length;u<v;u++){var w=u&&f.glyphs[k[u-1]]||{},z=f.glyphs[k[u]];l+=u?(w.w||f.w)+(w.k&&w.k[k[u]]||0)+f.w*i:0,z&&z.d&&j.push(this.path(z.d).attr({fill:"#000",stroke:"none",transform:[["t",l*n,0]]}))}j.transform(["...s",n,n,q,t,"t",(b-q)/n,(d-t)/n])}return j},a.format=function(b,c){var d=a.is(c,E)?[0][n](c):arguments;b&&a.is(b,D)&&d.length-1&&(b=b.replace(e,function(a,b){return d[++b]==null?p:d[b]}));return b||p},a.fullfill=function(){var a=/\{([^\}]+)\}/g,b=/(?:(?:^|\.)(.+?)(?=\[|\.|$|\()|\[('|")(.+?)\2\])(\(\))?/g,c=function(a,c,d){var e=d;c.replace(b,function(a,b,c,d,f){b=b||d,e&&(b in e&&(e=e[b]),typeof e=="function"&&f&&(e=e()))}),e=(e==null||e==d?a:e)+"";return e};return function(b,d){return String(b).replace(a,function(a,b){return c(a,b,d)})}}(),a.ninja=function(){i.was?h.win.Raphael=i.is:delete Raphael;return a},a.st=ct,function(b,c,d){function e(){/in/.test(b.readyState)?setTimeout(e,9):a.eve("DOMload")}b.readyState==null&&b.addEventListener&&(b.addEventListener(c,d=function(){b.removeEventListener(c,d,!1),b.readyState="complete"},!1),b.readyState="loading"),e()}(document,"DOMContentLoaded"),i.was?h.win.Raphael=a:Raphael=a,eve.on("DOMload",function(){b=!0})}(),window.Raphael.svg&&function(a){var b="hasOwnProperty",c=String,d=parseFloat,e=parseInt,f=Math,g=f.max,h=f.abs,i=f.pow,j=/[, ]+/,k=a.eve,l="",m=" ",n="http://www.w3.org/1999/xlink",o={block:"M5,0 0,2.5 5,5z",classic:"M5,0 0,2.5 5,5 3.5,3 3.5,2z",diamond:"M2.5,0 5,2.5 2.5,5 0,2.5z",open:"M6,1 1,3.5 6,6",oval:"M2.5,0A2.5,2.5,0,0,1,2.5,5 2.5,2.5,0,0,1,2.5,0z"},p={};a.toString=function(){return"Your browser supports SVG.\nYou are running Raphaël "+this.version};var q=function(d,e){if(e){typeof d=="string"&&(d=q(d));for(var f in e)e[b](f)&&(f.substring(0,6)=="xlink:"?d.setAttributeNS(n,f.substring(6),c(e[f])):d.setAttribute(f,c(e[f])))}else d=a._g.doc.createElementNS("http://www.w3.org/2000/svg",d),d.style&&(d.style.webkitTapHighlightColor="rgba(0,0,0,0)");return d},r={},s=/^url\(#(.*)\)$/,t=function(b,c){var d=b.getAttribute("fill");d=d&&d.match(s),d&&!--r[d[1]]&&(delete r[d[1]],c.defs.removeChild(a._g.doc.getElementById(d[1])))},u=function(b,e){var j="linear",k=b.id+e,m=.5,n=.5,o=b.node,p=b.paper,r=o.style,s=a._g.doc.getElementById(k);if(!s){e=c(e).replace(a._radial_gradient,function(a,b,c){j="radial";if(b&&c){m=d(b),n=d(c);var e=(n>.5)*2-1;i(m-.5,2)+i(n-.5,2)>.25&&(n=f.sqrt(.25-i(m-.5,2))*e+.5)&&n!=.5&&(n=n.toFixed(5)-1e-5*e)}return l}),e=e.split(/\s*\-\s*/);if(j=="linear"){var t=e.shift();t=-d(t);if(isNaN(t))return null;var u=[0,0,f.cos(a.rad(t)),f.sin(a.rad(t))],v=1/(g(h(u[2]),h(u[3]))||1);u[2]*=v,u[3]*=v,u[2]<0&&(u[0]=-u[2],u[2]=0),u[3]<0&&(u[1]=-u[3],u[3]=0)}var w=a._parseDots(e);if(!w)return null;b.gradient&&(p.defs.removeChild(b.gradient),delete b.gradient),k=k.replace(/[\(\)\s,\xb0#]/g,"-"),s=q(j+"Gradient",{id:k}),b.gradient=s,q(s,j=="radial"?{fx:m,fy:n}:{x1:u[0],y1:u[1],x2:u[2],y2:u[3],gradientTransform:b.matrix.invert()}),p.defs.appendChild(s);for(var x=0,y=w.length;x<y;x++)s.appendChild(q("stop",{offset:w[x].offset?w[x].offset:x?"100%":"0%","stop-color":w[x].color||"#fff"}))}q(o,{fill:"url(#"+k+")",opacity:1,"fill-opacity":1}),r.fill=l,r.opacity=1,r.fillOpacity=1;return 1},v=function(a){var b=a.getBBox(1);q(a.pattern,{patternTransform:a.matrix.invert()+" translate("+b.x+","+b.y+")"})},w=function(d,e,f){if(d.type=="path"){var g=c(e).toLowerCase().split("-"),h=d.paper,i=f?"end":"start",j=d.node,k=d.attrs,l=k["stroke-width"],n=g.length,r="classic",s,t,u,v,w,x=3,y=3,z=5;while(n--)switch(g[n]){case"block":case"classic":case"oval":case"diamond":case"open":case"none":r=g[n];break;case"wide":y=5;break;case"narrow":y=2;break;case"long":x=5;break;case"short":x=2}r=="open"?(x+=2,y+=2,z+=2,u=1,v=f?4:1,w={fill:"none",stroke:k.stroke}):(v=u=x/2,w={fill:k.stroke,stroke:"none"}),d._.arrows?f?(d._.arrows.endPath&&p[d._.arrows.endPath]--,d._.arrows.endMarker&&p[d._.arrows.endMarker]--):(d._.arrows.startPath&&p[d._.arrows.startPath]--,d._.arrows.startMarker&&p[d._.arrows.startMarker]--):d._.arrows={};if(r!="none"){var A="raphael-marker-"+r,B="raphael-marker-"+i+r+x+y;a._g.doc.getElementById(A)?p[A]++:(h.defs.appendChild(q(q("path"),{"stroke-linecap":"round",d:o[r],id:A})),p[A]=1);var C=a._g.doc.getElementById(B),D;C?(p[B]++,D=C.getElementsByTagName("use")[0]):(C=q(q("marker"),{id:B,markerHeight:y,markerWidth:x,orient:"auto",refX:v,refY:y/2}),D=q(q("use"),{"xlink:href":"#"+A,transform:(f?" rotate(180 "+x/2+" "+y/2+") ":m)+"scale("+x/z+","+y/z+")","stroke-width":1/((x/z+y/z)/2)}),C.appendChild(D),h.defs.appendChild(C),p[B]=1),q(D,w);var E=u*(r!="diamond"&&r!="oval");f?(s=d._.arrows.startdx*l||0,t=a.getTotalLength(k.path)-E*l):(s=E*l,t=a.getTotalLength(k.path)-(d._.arrows.enddx*l||0)),w={},w["marker-"+i]="url(#"+B+")";if(t||s)w.d=Raphael.getSubpath(k.path,s,t);q(j,w),d._.arrows[i+"Path"]=A,d._.arrows[i+"Marker"]=B,d._.arrows[i+"dx"]=E,d._.arrows[i+"Type"]=r,d._.arrows[i+"String"]=e}else f?(s=d._.arrows.startdx*l||0,t=a.getTotalLength(k.path)-s):(s=0,t=a.getTotalLength(k.path)-(d._.arrows.enddx*l||0)),d._.arrows[i+"Path"]&&q(j,{d:Raphael.getSubpath(k.path,s,t)}),delete d._.arrows[i+"Path"],delete d._.arrows[i+"Marker"],delete d._.arrows[i+"dx"],delete d._.arrows[i+"Type"],delete d._.arrows[i+"String"];for(w in p)if(p[b](w)&&!p[w]){var F=a._g.doc.getElementById(w);F&&F.parentNode.removeChild(F)}}},x={"":[0],none:[0],"-":[3,1],".":[1,1],"-.":[3,1,1,1],"-..":[3,1,1,1,1,1],". ":[1,3],"- ":[4,3],"--":[8,3],"- .":[4,3,1,3],"--.":[8,3,1,3],"--..":[8,3,1,3,1,3]},y=function(a,b,d){b=x[c(b).toLowerCase()];if(b){var e=a.attrs["stroke-width"]||"1",f={round:e,square:e,butt:0}[a.attrs["stroke-linecap"]||d["stroke-linecap"]]||0,g=[],h=b.length;while(h--)g[h]=b[h]*e+(h%2?1:-1)*f;q(a.node,{"stroke-dasharray":g.join(",")})}},z=function(d,f){var i=d.node,k=d.attrs,m=i.style.visibility;i.style.visibility="hidden";for(var o in f)if(f[b](o)){if(!a._availableAttrs[b](o))continue;var p=f[o];k[o]=p;switch(o){case"blur":d.blur(p);break;case"href":case"title":case"target":var r=i.parentNode;if(r.tagName.toLowerCase()!="a"){var s=q("a");r.insertBefore(s,i),s.appendChild(i),r=s}o=="target"&&p=="blank"?r.setAttributeNS(n,"show","new"):r.setAttributeNS(n,o,p);break;case"cursor":i.style.cursor=p;break;case"transform":d.transform(p);break;case"arrow-start":w(d,p);break;case"arrow-end":w(d,p,1);break;case"clip-rect":var t=c(p).split(j);if(t.length==4){d.clip&&d.clip.parentNode.parentNode.removeChild(d.clip.parentNode);var x=q("clipPath"),z=q("rect");x.id=a.createUUID(),q(z,{x:t[0],y:t[1],width:t[2],height:t[3]}),x.appendChild(z),d.paper.defs.appendChild(x),q(i,{"clip-path":"url(#"+x.id+")"}),d.clip=z}if(!p){var A=a._g.doc.getElementById(i.getAttribute("clip-path").replace(/(^url\(#|\)$)/g,l));A&&A.parentNode.removeChild(A),q(i,{"clip-path":l}),delete d.clip}break;case"path":d.type=="path"&&(q(i,{d:p?k.path=a._pathToAbsolute(p):"M0,0"}),d._.dirty=1,d._.arrows&&("startString"in d._.arrows&&w(d,d._.arrows.startString),"endString"in d._.arrows&&w(d,d._.arrows.endString,1)));break;case"width":i.setAttribute(o,p),d._.dirty=1;if(k.fx)o="x",p=k.x;else break;case"x":k.fx&&(p=-k.x-(k.width||0));case"rx":if(o=="rx"&&d.type=="rect")break;case"cx":i.setAttribute(o,p),d.pattern&&v(d),d._.dirty=1;break;case"height":i.setAttribute(o,p),d._.dirty=1;if(k.fy)o="y",p=k.y;else break;case"y":k.fy&&(p=-k.y-(k.height||0));case"ry":if(o=="ry"&&d.type=="rect")break;case"cy":i.setAttribute(o,p),d.pattern&&v(d),d._.dirty=1;break;case"r":d.type=="rect"?q(i,{rx:p,ry:p}):i.setAttribute(o,p),d._.dirty=1;break;case"src":d.type=="image"&&i.setAttributeNS(n,"href",p);break;case"stroke-width":if(d._.sx!=1||d._.sy!=1)p/=g(h(d._.sx),h(d._.sy))||1;d.paper._vbSize&&(p*=d.paper._vbSize),i.setAttribute(o,p),k["stroke-dasharray"]&&y(d,k["stroke-dasharray"],f),d._.arrows&&("startString"in d._.arrows&&w(d,d._.arrows.startString),"endString"in d._.arrows&&w(d,d._.arrows.endString,1));break;case"stroke-dasharray":y(d,p,f);break;case"fill":var C=c(p).match(a._ISURL);if(C){x=q("pattern");var D=q("image");x.id=a.createUUID(),q(x,{x:0,y:0,patternUnits:"userSpaceOnUse",height:1,width:1}),q(D,{x:0,y:0,"xlink:href":C[1]}),x.appendChild(D),function(b){a._preload(C[1],function(){var a=this.offsetWidth,c=this.offsetHeight;q(b,{width:a,height:c}),q(D,{width:a,height:c}),d.paper.safari()})}(x),d.paper.defs.appendChild(x),i.style.fill="url(#"+x.id+")",q(i,{fill:"url(#"+x.id+")"}),d.pattern=x,d.pattern&&v(d);break}var E=a.getRGB(p);if(!E.error)delete f.gradient,delete k.gradient,!a.is(k.opacity,"undefined")&&a.is(f.opacity,"undefined")&&q(i,{opacity:k.opacity}),!a.is(k["fill-opacity"],"undefined")&&a.is(f["fill-opacity"],"undefined")&&q(i,{"fill-opacity":k["fill-opacity"]});else if((d.type=="circle"||d.type=="ellipse"||c(p).charAt()!="r")&&u(d,p)){if("opacity"in k||"fill-opacity"in k){var F=a._g.doc.getElementById(i.getAttribute("fill").replace(/^url\(#|\)$/g,l));if(F){var G=F.getElementsByTagName("stop");q(G[G.length-1],{"stop-opacity":("opacity"in k?k.opacity:1)*("fill-opacity"in k?k["fill-opacity"]:1)})}}k.gradient=p,k.fill="none";break}E[b]("opacity")&&q(i,{"fill-opacity":E.opacity>1?E.opacity/100:E.opacity});case"stroke":E=a.getRGB(p),i.setAttribute(o,E.hex),o=="stroke"&&E[b]("opacity")&&q(i,{"stroke-opacity":E.opacity>1?E.opacity/100:E.opacity}),o=="stroke"&&d._.arrows&&("startString"in d._.arrows&&w(d,d._.arrows.startString),"endString"in d._.arrows&&w(d,d._.arrows.endString,1));break;case"gradient":(d.type=="circle"||d.type=="ellipse"||c(p).charAt()!="r")&&u(d,p);break;case"opacity":k.gradient&&!k[b]("stroke-opacity")&&q(i,{"stroke-opacity":p>1?p/100:p});case"fill-opacity":if(k.gradient){F=a._g.doc.getElementById(i.getAttribute("fill").replace(/^url\(#|\)$/g,l)),F&&(G=F.getElementsByTagName("stop"),q(G[G.length-1],{"stop-opacity":p}));break};default:o=="font-size"&&(p=e(p,10)+"px");var H=o.replace(/(\-.)/g,function(a){return a.substring(1).toUpperCase()});i.style[H]=p,d._.dirty=1,i.setAttribute(o,p)}}B(d,f),i.style.visibility=m},A=1.2,B=function(d,f){if(d.type=="text"&&!!(f[b]("text")||f[b]("font")||f[b]("font-size")||f[b]("x")||f[b]("y"))){var g=d.attrs,h=d.node,i=h.firstChild?e(a._g.doc.defaultView.getComputedStyle(h.firstChild,l).getPropertyValue("font-size"),10):10;if(f[b]("text")){g.text=f.text;while(h.firstChild)h.removeChild(h.firstChild);var j=c(f.text).split("\n"),k=[],m;for(var n=0,o=j.length;n<o;n++)m=q("tspan"),n&&q(m,{dy:i*A,x:g.x}),m.appendChild(a._g.doc.createTextNode(j[n])),h.appendChild(m),k[n]=m}else{k=h.getElementsByTagName("tspan");for(n=0,o=k.length;n<o;n++)n?q(k[n],{dy:i*A,x:g.x}):q(k[0],{dy:0})}q(h,{x:g.x,y:g.y}),d._.dirty=1;var p=d._getBBox(),r=g.y-(p.y+p.height/2);r&&a.is(r,"finite")&&q(k[0],{dy:r})}},C=function(b,c){var d=0,e=0;this[0]=this.node=b,b.raphael=!0,this.id=a._oid++,b.raphaelid=this.id,this.matrix=a.matrix(),this.realPath=null,this.paper=c,this.attrs=this.attrs||{},this._={transform:[],sx:1,sy:1,deg:0,dx:0,dy:0,dirty:1},!c.bottom&&(c.bottom=this),this.prev=c.top,c.top&&(c.top.next=this),c.top=this,this.next=null},D=a.el;C.prototype=D,D.constructor=C,a._engine.path=function(a,b){var c=q("path");b.canvas&&b.canvas.appendChild(c);var d=new C(c,b);d.type="path",z(d,{fill:"none",stroke:"#000",path:a});return d},D.rotate=function(a,b,e){if(this.removed)return this;a=c(a).split(j),a.length-1&&(b=d(a[1]),e=d(a[2])),a=d(a[0]),e==null&&(b=e);if(b==null||e==null){var f=this.getBBox(1);b=f.x+f.width/2,e=f.y+f.height/2}this.transform(this._.transform.concat([["r",a,b,e]]));return this},D.scale=function(a,b,e,f){if(this.removed)return this;a=c(a).split(j),a.length-1&&(b=d(a[1]),e=d(a[2]),f=d(a[3])),a=d(a[0]),b==null&&(b=a),f==null&&(e=f);if(e==null||f==null)var g=this.getBBox(1);e=e==null?g.x+g.width/2:e,f=f==null?g.y+g.height/2:f,this.transform(this._.transform.concat([["s",a,b,e,f]]));return this},D.translate=function(a,b){if(this.removed)return this;a=c(a).split(j),a.length-1&&(b=d(a[1])),a=d(a[0])||0,b=+b||0,this.transform(this._.transform.concat([["t",a,b]]));return this},D.transform=function(c){var d=this._;if(c==null)return d.transform;a._extractTransform(this,c),this.clip&&q(this.clip,{transform:this.matrix.invert()}),this.pattern&&v(this),this.node&&q(this.node,{transform:this.matrix});if(d.sx!=1||d.sy!=1){var e=this.attrs[b]("stroke-width")?this.attrs["stroke-width"]:1;this.attr({"stroke-width":e})}return this},D.hide=function(){!this.removed&&this.paper.safari(this.node.style.display="none");return this},D.show=function(){!this.removed&&this.paper.safari(this.node.style.display="");return this},D.remove=function(){if(!this.removed){this.paper.__set__&&this.paper.__set__.exclude(this),k.unbind("*.*."+this.id),a._tear(this,this.paper),this.node.parentNode.removeChild(this.node);for(var b in this)delete this[b];this.removed=!0}},D._getBBox=function(){if(this.node.style.display=="none"){this.show();var a=!0}var b={};try{b=this.node.getBBox()}catch(c){}finally{b=b||{}}a&&this.hide();return b},D.attr=function(c,d){if(this.removed)return this;if(c==null){var e={};for(var f in this.attrs)this.attrs[b](f)&&(e[f]=this.attrs[f]);e.gradient&&e.fill=="none"&&(e.fill=e.gradient)&&delete e.gradient,e.transform=this._.transform;return e}if(d==null&&a.is(c,"string")){if(c=="fill"&&this.attrs.fill=="none"&&this.attrs.gradient)return this.attrs.gradient;if(c=="transform")return this._.transform;var g=c.split(j),h={};for(var i=0,l=g.length;i<l;i++)c=g[i],c in this.attrs?h[c]=this.attrs[c]:a.is(this.paper.customAttributes[c],"function")?h[c]=this.paper.customAttributes[c].def:h[c]=a._availableAttrs[c];return l-1?h:h[g[0]]}if(d==null&&a.is(c,"array")){h={};for(i=0,l=c.length;i<l;i++)h[c[i]]=this.attr(c[i]);return h}if(d!=null){var m={};m[c]=d}else c!=null&&a.is(c,"object")&&(m=c);for(var n in m)k("attr."+n+"."+this.id,this,m[n]);for(n in this.paper.customAttributes)if(this.paper.customAttributes[b](n)&&m[b](n)&&a.is(this.paper.customAttributes[n],"function")){var o=this.paper.customAttributes[n].apply(this,[].concat(m[n]));this.attrs[n]=m[n];for(var p in o)o[b](p)&&(m[p]=o[p])}z(this,m);return this},D.toFront=function(){if(this.removed)return this;this.node.parentNode.appendChild(this.node);var b=this.paper;b.top!=this&&a._tofront(this,b);return this},D.toBack=function(){if(this.removed)return this;if(this.node.parentNode.firstChild!=this.node){this.node.parentNode.insertBefore(this.node,this.node.parentNode.firstChild),a._toback(this,this.paper);var b=this.paper}return this},D.insertAfter=function(b){if(this.removed)return this;var c=b.node||b[b.length-1].node;c.nextSibling?c.parentNode.insertBefore(this.node,c.nextSibling):c.parentNode.appendChild(this.node),a._insertafter(this,b,this.paper);return this},D.insertBefore=function(b){if(this.removed)return this;var c=b.node||b[0].node;c.parentNode.insertBefore(this.node,c),a._insertbefore(this,b,this.paper);return this},D.blur=function(b){var c=this;if(+b!==0){var d=q("filter"),e=q("feGaussianBlur");c.attrs.blur=b,d.id=a.createUUID(),q(e,{stdDeviation:+b||1.5}),d.appendChild(e),c.paper.defs.appendChild(d),c._blur=d,q(c.node,{filter:"url(#"+d.id+")"})}else c._blur&&(c._blur.parentNode.removeChild(c._blur),delete c._blur,delete c.attrs.blur),c.node.removeAttribute("filter")},a._engine.circle=function(a,b,c,d){var e=q("circle");a.canvas&&a.canvas.appendChild(e);var f=new C(e,a);f.attrs={cx:b,cy:c,r:d,fill:"none",stroke:"#000"},f.type="circle",q(e,f.attrs);return f},a._engine.rect=function(a,b,c,d,e,f){var g=q("rect");a.canvas&&a.canvas.appendChild(g);var h=new C(g,a);h.attrs={x:b,y:c,width:d,height:e,r:f||0,rx:f||0,ry:f||0,fill:"none",stroke:"#000"},h.type="rect",q(g,h.attrs);return h},a._engine.ellipse=function(a,b,c,d,e){var f=q("ellipse");a.canvas&&a.canvas.appendChild(f);var g=new C(f,a);g.attrs={cx:b,cy:c,rx:d,ry:e,fill:"none",stroke:"#000"},g.type="ellipse",q(f,g.attrs);return g},a._engine.image=function(a,b,c,d,e,f){var g=q("image");q(g,{x:c,y:d,width:e,height:f,preserveAspectRatio:"none"}),g.setAttributeNS(n,"href",b),a.canvas&&a.canvas.appendChild(g);var h=new C(g,a);h.attrs={x:c,y:d,width:e,height:f,src:b},h.type="image";return h},a._engine.text=function(b,c,d,e){var f=q("text");b.canvas&&b.canvas.appendChild(f);var g=new C(f,b);g.attrs={x:c,y:d,"text-anchor":"middle",text:e,font:a._availableAttrs.font,stroke:"none",fill:"#000"},g.type="text",z(g,g.attrs);return g},a._engine.setSize=function(a,b){this.width=a||this.width,this.height=b||this.height,this.canvas.setAttribute("width",this.width),this.canvas.setAttribute("height",this.height),this._viewBox&&this.setViewBox.apply(this,this._viewBox);return this},a._engine.create=function(){var b=a._getContainer.apply(0,arguments),c=b&&b.container,d=b.x,e=b.y,f=b.width,g=b.height;if(!c)throw new Error("SVG container not found.");var h=q("svg"),i="overflow:hidden;",j;d=d||0,e=e||0,f=f||512,g=g||342,q(h,{height:g,version:1.1,width:f,xmlns:"http://www.w3.org/2000/svg"}),c==1?(h.style.cssText=i+"position:absolute;left:"+d+"px;top:"+e+"px",a._g.doc.body.appendChild(h),j=1):(h.style.cssText=i+"position:relative",c.firstChild?c.insertBefore(h,c.firstChild):c.appendChild(h)),c=new a._Paper,c.width=f,c.height=g,c.canvas=h,c.clear(),c._left=c._top=0,j&&(c.renderfix=function(){}),c.renderfix();return c},a._engine.setViewBox=function(a,b,c,d,e){k("setViewBox",this,this._viewBox,[a,b,c,d,e]);var f=g(c/this.width,d/this.height),h=this.top,i=e?"meet":"xMinYMin",j,l;a==null?(this._vbSize&&(f=1),delete this._vbSize,j="0 0 "+this.width+m+this.height):(this._vbSize=f,j=a+m+b+m+c+m+d),q(this.canvas,{viewBox:j,preserveAspectRatio:i});while(f&&h)l="stroke-width"in h.attrs?h.attrs["stroke-width"]:1,h.attr({"stroke-width":l}),h._.dirty=1,h._.dirtyT=1,h=h.prev;this._viewBox=[a,b,c,d,!!e];return this},a.prototype.renderfix=function(){var a=this.canvas,b=a.style,c=a.getScreenCTM()||a.createSVGMatrix(),d=-c.e%1,e=-c.f%1;if(d||e)d&&(this._left=(this._left+d)%1,b.left=this._left+"px"),e&&(this._top=(this._top+e)%1,b.top=this._top+"px")},a.prototype.clear=function(){a.eve("clear",this);var b=this.canvas;while(b.firstChild)b.removeChild(b.firstChild);this.bottom=this.top=null,(this.desc=q("desc")).appendChild(a._g.doc.createTextNode("Created with Raphaël "+a.version)),b.appendChild(this.desc),b.appendChild(this.defs=q("defs"))},a.prototype.remove=function(){k("remove",this),this.canvas.parentNode&&this.canvas.parentNode.removeChild(this.canvas);for(var a in this)this[a]=removed(a)};var E=a.st;for(var F in D)D[b](F)&&!E[b](F)&&(E[F]=function(a){return function(){var b=arguments;return this.forEach(function(c){c[a].apply(c,b)})}}(F))}(window.Raphael),window.Raphael.vml&&function(a){var b="hasOwnProperty",c=String,d=parseFloat,e=Math,f=e.round,g=e.max,h=e.min,i=e.abs,j="fill",k=/[, ]+/,l=a.eve,m=" progid:DXImageTransform.Microsoft",n=" ",o="",p={M:"m",L:"l",C:"c",Z:"x",m:"t",l:"r",c:"v",z:"x"},q=/([clmz]),?([^clmz]*)/gi,r=/ progid:\S+Blur\([^\)]+\)/g,s=/-?[^,\s-]+/g,t="position:absolute;left:0;top:0;width:1px;height:1px",u=21600,v={path:1,rect:1,image:1},w={circle:1,ellipse:1},x=function(b){var d=/[ahqstv]/ig,e=a._pathToAbsolute;c(b).match(d)&&(e=a._path2curve),d=/[clmz]/g;if(e==a._pathToAbsolute&&!c(b).match(d)){var g=c(b).replace(q,function(a,b,c){var d=[],e=b.toLowerCase()=="m",g=p[b];c.replace(s,function(a){e&&d.length==2&&(g+=d+p[b=="m"?"l":"L"],d=[]),d.push(f(a*u))});return g+d});return g}var h=e(b),i,j;g=[];for(var k=0,l=h.length;k<l;k++){i=h[k],j=h[k][0].toLowerCase(),j=="z"&&(j="x");for(var m=1,r=i.length;m<r;m++)j+=f(i[m]*u)+(m!=r-1?",":o);g.push(j)}return g.join(n)},y=function(b,c,d){var e=a.matrix();e.rotate(-b,.5,.5);return{dx:e.x(c,d),dy:e.y(c,d)}},z=function(a,b,c,d,e,f){var g=a._,h=a.matrix,k=g.fillpos,l=a.node,m=l.style,o=1,p="",q,r=u/b,s=u/c;m.visibility="hidden";if(!!b&&!!c){l.coordsize=i(r)+n+i(s),m.rotation=f*(b*c<0?-1:1);if(f){var t=y(f,d,e);d=t.dx,e=t.dy}b<0&&(p+="x"),c<0&&(p+=" y")&&(o=-1),m.flip=p,l.coordorigin=d*-r+n+e*-s;if(k||g.fillsize){var v=l.getElementsByTagName(j);v=v&&v[0],l.removeChild(v),k&&(t=y(f,h.x(k[0],k[1]),h.y(k[0],k[1])),v.position=t.dx*o+n+t.dy*o),g.fillsize&&(v.size=g.fillsize[0]*i(b)+n+g.fillsize[1]*i(c)),l.appendChild(v)}m.visibility="visible"}};a.toString=function(){return"Your browser doesn’t support SVG. Falling down to VML.\nYou are running Raphaël "+this.version},addArrow=function(a,b,d){var e=c(b).toLowerCase().split("-"),f=d?"end":"start",g=e.length,h="classic",i="medium",j="medium";while(g--)switch(e[g]){case"block":case"classic":case"oval":case"diamond":case"open":case"none":h=e[g];break;case"wide":case"narrow":j=e[g];break;case"long":case"short":i=e[g]}var k=a.node.getElementsByTagName("stroke")[0];k[f+"arrow"]=h,k[f+"arrowlength"]=i,k[f+"arrowwidth"]=j},setFillAndStroke=function(e,i){e.attrs=e.attrs||{};var l=e.node,m=e.attrs,p=l.style,q,r=v[e.type]&&(i.x!=m.x||i.y!=m.y||i.width!=m.width||i.height!=m.height||i.cx!=m.cx||i.cy!=m.cy||i.rx!=m.rx||i.ry!=m.ry||i.r!=m.r),s=w[e.type]&&(m.cx!=i.cx||m.cy!=i.cy||m.r!=i.r||m.rx!=i.rx||m.ry!=i.ry),t=e;for(var y in i)i[b](y)&&(m[y]=i[y]);r&&(m.path=a._getPath[e.type](e),e._.dirty=1),i.href&&(l.href=i.href),i.title&&(l.title=i.title),i.target&&(l.target=i.target),i.cursor&&(p.cursor=i.cursor),"blur"in i&&e.blur(i.blur);if(i.path&&e.type=="path"||r)l.path=x(~c(m.path).toLowerCase().indexOf("r")?a._pathToAbsolute(m.path):m.path),e.type=="image"&&(e._.fillpos=[m.x,m.y],e._.fillsize=[m.width,m.height],z(e,1,1,0,0,0));"transform"in i&&e.transform(i.transform);if(s){var A=+m.cx,C=+m.cy,D=+m.rx||+m.r||0,E=+m.ry||+m.r||0;l.path=a.format("ar{0},{1},{2},{3},{4},{1},{4},{1}x",f((A-D)*u),f((C-E)*u),f((A+D)*u),f((C+E)*u),f(A*u))}if("clip-rect"in i){var F=c(i["clip-rect"]).split(k);if(F.length==4){F[2]=+F[2]+ +F[0],F[3]=+F[3]+ +F[1];var G=l.clipRect||a._g.doc.createElement("div"),H=G.style;H.clip=a.format("rect({1}px {2}px {3}px {0}px)",F),l.clipRect||(H.position="absolute",H.top=0,H.left=0,H.width=e.paper.width+"px",H.height=e.paper.height+"px",l.parentNode.insertBefore(G,l),G.appendChild(l),l.clipRect=G)}i["clip-rect"]||l.clipRect&&(l.clipRect.style.clip=o)}if(e.textpath){var I=e.textpath.style;i.font&&(I.font=i.font),i["font-family"]&&(I.fontFamily='"'+i["font-family"].split(",")[0].replace(/^['"]+|['"]+$/g,o)+'"'),i["font-size"]&&(I.fontSize=i["font-size"]),i["font-weight"]&&(I.fontWeight=i["font-weight"]),i["font-style"]&&(I.fontStyle=i["font-style"])}"arrow-start"in i&&addArrow(t,i["arrow-start"]),"arrow-end"in i&&addArrow(t,i["arrow-end"],1);if(i.opacity!=null||i["stroke-width"]!=null||i.fill!=null||i.src!=null||i.stroke!=null||i["stroke-width"]!=null||i["stroke-opacity"]!=null||i["fill-opacity"]!=null||i["stroke-dasharray"]!=null||i["stroke-miterlimit"]!=null||i["stroke-linejoin"]!=null||i["stroke-linecap"]!=null){var J=l.getElementsByTagName(j),K=!1;J=J&&J[0],!J&&(K=J=B(j)),e.type=="image"&&i.src&&(J.src=i.src),i.fill&&(J.on=!0);if(J.on==null||i.fill=="none"||i.fill===null)J.on=!1;if(J.on&&i.fill){var L=c(i.fill).match(a._ISURL);if(L){J.parentNode==l&&l.removeChild(J),J.rotate=!0,J.src=L[1],J.type="tile";var M=e.getBBox(1);J.position=M.x+n+M.y,e._.fillpos=[M.x,M.y],a._preload(L[1],function(){e._.fillsize=[this.offsetWidth,this.offsetHeight]})}else J.color=a.getRGB(i.fill).hex,J.src=o,J.type="solid",a.getRGB(i.fill).error&&(t.type in{circle:1,ellipse:1}||c(i.fill).charAt()!="r")&&addGradientFill(t,i.fill,J)&&(m.fill="none",m.gradient=i.fill,J.rotate=!1)}if("fill-opacity"in i||"opacity"in i){var N=((+m["fill-opacity"]+1||2)-1)*((+m.opacity+1||2)-1)*((+a.getRGB(i.fill).o+1||2)-1);N=h(g(N,0),1),J.opacity=N,J.src&&(J.color="none")}l.appendChild(J);var O=l.getElementsByTagName("stroke")&&l.getElementsByTagName("stroke")[0],P=!1;!O&&(P=O=B("stroke"));if(i.stroke&&i.stroke!="none"||i["stroke-width"]||i["stroke-opacity"]!=null||i["stroke-dasharray"]||i["stroke-miterlimit"]||i["stroke-linejoin"]||i["stroke-linecap"])O.on=!0;(i.stroke=="none"||i.stroke===null||O.on==null||i.stroke==0||i["stroke-width"]==0)&&(O.on=!1);var Q=a.getRGB(i.stroke);O.on&&i.stroke&&(O.color=Q.hex),N=((+m["stroke-opacity"]+1||2)-1)*((+m.opacity+1||2)-1)*((+Q.o+1||2)-1);var T=(d(i["stroke-width"])||1)*.75;N=h(g(N,0),1),i["stroke-width"]==null&&(T=m["stroke-width"]),i["stroke-width"]&&(O.weight=T),T&&T<1&&(N*=T)&&(O.weight=1),O.opacity=N,i["stroke-linejoin"]&&(O.joinstyle=i["stroke-linejoin"]||"miter"),O.miterlimit=i["stroke-miterlimit"]||8,i["stroke-linecap"]&&(O.endcap=i["stroke-linecap"]=="butt"?"flat":i["stroke-linecap"]=="square"?"square":"round");if(i["stroke-dasharray"]){var U={"-":"shortdash",".":"shortdot","-.":"shortdashdot","-..":"shortdashdotdot",". ":"dot","- ":"dash","--":"longdash","- .":"dashdot","--.":"longdashdot","--..":"longdashdotdot"};O.dashstyle=U[b](i["stroke-dasharray"])?U[i["stroke-dasharray"]]:o}P&&l.appendChild(O)}if(t.type=="text"){t.paper.canvas.style.display=o;var V=t.paper.span,W=100,X=m.font&&m.font.match(/\d+(?:\.\d*)?(?=px)/);p=V.style,m.font&&(p.font=m.font),m["font-family"]&&(p.fontFamily=m["font-family"]),m["font-weight"]&&(p.fontWeight=m["font-weight"]),m["font-style"]&&(p.fontStyle=m["font-style"]),X=d(X?X[0]:m["font-size"]),p.fontSize=X*W+"px",t.textpath.string&&(V.innerHTML=c(t.textpath.string).replace(/</g,"<").replace(/&/g,"&").replace(/\n/g,"<br>"));var Y=V.getBoundingClientRect();t.W=m.w=(Y.right-Y.left)/W,t.H=m.h=(Y.bottom-Y.top)/W,t.X=m.x,t.Y=m.y+t.H/2,("x"in i||"y"in i)&&(t.path.v=a.format("m{0},{1}l{2},{1}",f(m.x*u),f(m.y*u),f(m.x*u)+1));var Z=["x","y","text","font","font-family","font-weight","font-style","font-size"];for(var $=0,_=Z.length;$<_;$++)if(Z[$]in i){t._.dirty=1;break}switch(m["text-anchor"]){case"start":t.textpath.style["v-text-align"]="left",t.bbx=t.W/2;break;case"end":t.textpath.style["v-text-align"]="right",t.bbx=-t.W/2;break;default:t.textpath.style["v-text-align"]="center",t.bbx=0}t.textpath.style["v-text-kern"]=!0}},addGradientFill=function(b,f,g){b.attrs=b.attrs||{};var h=b.attrs,i=Math.pow,j,k,l="linear",m=".5 .5";b.attrs.gradient=f,f=c(f).replace(a._radial_gradient,function(a,b,c){l="radial",b&&c&&(b=d(b),c=d(c),i(b-.5,2)+i(c-.5,2)>.25&&(c=e.sqrt(.25-i(b-.5,2))*((c>.5)*2-1)+.5),m=b+n+c);return o}),f=f.split(/\s*\-\s*/);if(l=="linear"){var p=f.shift();p=-d(p);if(isNaN(p))return null}var q=a._parseDots(f);if(!q)return null;b=b.shape||b.node;if(q.length){b.removeChild(g),g.on=!0,g.method="none",g.color=q[0].color,g.color2=q[q.length-1].color;var r=[];for(var s=0,t=q.length;s<t;s++)q[s].offset&&r.push(q[s].offset+n+q[s].color);g.colors=r.length?r.join():"0% "+g.color,l=="radial"?(g.type="gradientTitle",g.focus="100%",g.focussize="0 0",g.focusposition=m,g.angle=0):(g.type="gradient",g.angle=(270-p)%360),b.appendChild(g)}return 1},Element=function(b,c){this[0]=this.node=b,b.raphael=!0,this.id=a._oid++,b.raphaelid=this.id,this.X=0,this.Y=0,this.attrs={},this.paper=c,this.matrix=a.matrix(),this._={transform:[],sx:1,sy:1,dx:0,dy:0,deg:0,dirty:1,dirtyT:1},!c.bottom&&(c.bottom=this),this.prev=c.top,c.top&&(c.top.next=this),c.top=this,this.next=null};var A=a.el;Element.prototype=A,A.constructor=Element,A.transform=function(b){if(b==null)return this._.transform;var d=this.paper._viewBoxShift,e=d?"s"+[d.scale,d.scale]+"-1-1t"+[d.dx,d.dy]:o,f;d&&(f=b=c(b).replace(/\.{3}|\u2026/g,this._.transform||o)),a._extractTransform(this,e+b);var g=this.matrix.clone(),h=this.skew,i=this.node,j,k=~c(this.attrs.fill).indexOf("-"),l=!c(this.attrs.fill).indexOf("url(");g.translate(-0.5,-0.5);if(l||k||this.type=="image"){h.matrix="1 0 0 1",h.offset="0 0",j=g.split();if(k&&j.noRotation||!j.isSimple){i.style.filter=g.toFilter();var m=this.getBBox(),p=this.getBBox(1),q=m.x-p.x,r=m.y-p.y;i.coordorigin=q*-u+n+r*-u,z(this,1,1,q,r,0)}else i.style.filter=o,z(this,j.scalex,j.scaley,j.dx,j.dy,j.rotate)}else i.style.filter=o,h.matrix=c(g),h.offset=g.offset();f&&(this._.transform=f);return this},A.rotate=function(a,b,e){if(this.removed)return this;if(a!=null){a=c(a).split(k),a.length-1&&(b=d(a[1]),e=d(a[2])),a=d(a[0]),e==null&&(b=e);if(b==null||e==null){var f=this.getBBox(1);b=f.x+f.width/2,e=f.y+f.height/2}this._.dirtyT=1,this.transform(this._.transform.concat([["r",a,b,e]]));return this}},A.translate=function(a,b){if(this.removed)return this;a=c(a).split(k),a.length-1&&(b=d(a[1])),a=d(a[0])||0,b=+b||0,this._.bbox&&(this._.bbox.x+=a,this._.bbox.y+=b),this.transform(this._.transform.concat([["t",a,b]]));return this},A.scale=function(a,b,e,f){if(this.removed)return this;a=c(a).split(k),a.length-1&&(b=d(a[1]),e=d(a[2]),f=d(a[3]),isNaN(e)&&(e=null),isNaN(f)&&(f=null)),a=d(a[0]),b==null&&(b=a),f==null&&(e=f);if(e==null||f==null)var g=this.getBBox(1);e=e==null?g.x+g.width/2:e,f=f==null?g.y+g.height/2:f,this.transform(this._.transform.concat([["s",a,b,e,f]])),this._.dirtyT=1;return this},A.hide=function(){!this.removed&&(this.node.style.display="none");return this},A.show=function(){!this.removed&&(this.node.style.display=o);return this},A._getBBox=function(){if(this.removed)return{};return this.type=="text"?{x:this.X+(this.bbx||0)-this.W/2,y:this.Y-this.H,width:this.W,height:this.H}:pathDimensions(this.attrs.path)},A.remove=function(){if(!this.removed){this.paper.__set__&&this.paper.__set__.exclude(this),a.eve.unbind("*.*."+this.id),a._tear(this,this.paper),this.node.parentNode.removeChild(this.node),this.shape&&this.shape.parentNode.removeChild(this.shape);for(var b in this)delete this[b];this.removed=!0}},A.attr=function(c,d){if(this.removed)return this;if(c==null){var e={};for(var f in this.attrs)this.attrs[b](f)&&(e[f]=this.attrs[f]);e.gradient&&e.fill=="none"&&(e.fill=e.gradient)&&delete e.gradient,e.transform=this._.transform;return e}if(d==null&&a.is(c,"string")){if(c==j&&this.attrs.fill=="none"&&this.attrs.gradient)return this.attrs.gradient;var g=c.split(k),h={};for(var i=0,m=g.length;i<m;i++)c=g[i],c in this.attrs?h[c]=this.attrs[c]:a.is(this.paper.customAttributes[c],"function")?h[c]=this.paper.customAttributes[c].def:h[c]=a._availableAttrs[c];return m-1?h:h[g[0]]}if(this.attrs&&d==null&&a.is(c,"array")){h={};for(i=0,m=c.length;i<m;i++)h[c[i]]=this.attr(c[i]);return h}var n;d!=null&&(n={},n[c]=d),d==null&&a.is(c,"object")&&(n=c);for(var o in n)l("attr."+o+"."+this.id,this,n[o]);if(n){for(o in this.paper.customAttributes)if(this.paper.customAttributes[b](o)&&n[b](o)&&a.is(this.paper.customAttributes[o],"function")){var p=this.paper.customAttributes[o].apply(this,[].concat(n[o]));this.attrs[o]=n[o];for(var q in p)p[b](q)&&(n[q]=p[q])}n.text&&this.type=="text"&&(this.textpath.string=n.text),setFillAndStroke(this,n)}return this},A.toFront=function(){!this.removed&&this.node.parentNode.appendChild(this.node),this.paper&&this.paper.top!=this&&a._tofront(this,this.paper);return this},A.toBack=function(){if(this.removed)return this;this.node.parentNode.firstChild!=this.node&&(this.node.parentNode.insertBefore(this.node,this.node.parentNode.firstChild),a._toback(this,this.paper));return this},A.insertAfter=function(b){if(this.removed)return this;b.constructor==a.st.constructor&&(b=b[b.length-1]),b.node.nextSibling?b.node.parentNode.insertBefore(this.node,b.node.nextSibling):b.node.parentNode.appendChild(this.node),a._insertafter(this,b,this.paper);return this},A.insertBefore=function(b){if(this.removed)return this;b.constructor==a.st.constructor&&(b=b[0]),b.node.parentNode.insertBefore(this.node,b.node),a._insertbefore(this,b,this.paper);return this},A.blur=function(b){var c=this.node.runtimeStyle,d=c.filter;d=d.replace(r,o),+b!==0?(this.attrs.blur=b,c.filter=d+n+m+".Blur(pixelradius="+(+b||1.5)+")",c.margin=a.format("-{0}px 0 0 -{0}px",f(+b||1.5))):(c.filter=d,c.margin=0,delete this.attrs.blur)},a._engine.path=function(a,b){var c=B("shape");c.style.cssText=t,c.coordsize=u+n+u,c.coordorigin=b.coordorigin;var d=new Element(c,b),e={fill:"none",stroke:"#000"};a&&(e.path=a),d.type="path",d.path=[],d.Path=o,setFillAndStroke(d,e),b.canvas.appendChild(c);var f=B("skew");f.on=!0,c.appendChild(f),d.skew=f,d.transform(o);return d},a._engine.rect=function(b,c,d,e,f,g){var h=a._rectPath(c,d,e,f,g),i=b.path(h),j=i.attrs;i.X=j.x=c,i.Y=j.y=d,i.W=j.width=e,i.H=j.height=f,j.r=g,j.path=h,i.type="rect";return i},a._engine.ellipse=function(a,b,c,d,e){var f=a.path(),g=f.attrs;f.X=b-d,f.Y=c-e,f.W=d*2,f.H=e*2,f.type="ellipse",setFillAndStroke(f,{cx:b,cy:c,rx:d,ry:e});return f},a._engine.circle=function(a,b,c,d){var e=a.path(),f=e.attrs;e.X=b-d,e.Y=c-d,e.W=e.H=d*2,e.type="circle",setFillAndStroke(e,{cx:b,cy:c,r:d});return e},a._engine.image=function(b,c,d,e,f,g){var h=a._rectPath(d,e,f,g),i=b.path(h).attr({stroke:"none"}),k=i.attrs,l=i.node,m=l.getElementsByTagName(j)[0];k.src=c,i.X=k.x=d,i.Y=k.y=e,i.W=k.width=f,i.H=k.height=g,k.path=h,i.type="image",m.parentNode==l&&l.removeChild(m),m.rotate=!0,m.src=c,m.type="tile",i._.fillpos=[d,e],i._.fillsize=[f,g],l.appendChild(m),z(i,1,1,0,0,0);return i},a._engine.text=function(b,d,e,g){var h=B("shape"),i=B("path"),j=B("textpath");d=d||0,e=e||0,g=g||"",i.v=a.format("m{0},{1}l{2},{1}",f(d*u),f(e*u),f(d*u)+1),i.textpathok=!0,j.string=c(g),j.on=!0,h.style.cssText=t,h.coordsize=u+n+u,h.coordorigin="0 0";var k=new Element(h,b),l={fill:"#000",stroke:"none",font:a._availableAttrs.font,text:g};k.shape=h,k.path=i,k.textpath=j,k.type="text",k.attrs.text=c(g),k.attrs.x=d,k.attrs.y=e,k.attrs.w=1,k.attrs.h=1,setFillAndStroke(k,l),h.appendChild(j),h.appendChild(i),b.canvas.appendChild(h);var m=B("skew");m.on=!0,h.appendChild(m),k.skew=m,k.transform(o);return k},a._engine.setSize=function(a,b){var c=this.canvas.style;this.width=a,this.height=b,a==+a&&(a+="px"),b==+b&&(b+="px"),c.width=a,c.height=b,c.clip="rect(0 "+a+" "+b+" 0)",this._viewBox&&setViewBox.apply(this,this._viewBox);return this},a._engine.setViewBox=function(b,c,d,e,f){a.eve("setViewBox",this,this._viewBox,[b,c,d,e,f]);var h=this.width,i=this.height,j=1/g(d/h,e/i),k,l;f&&(k=i/e,l=h/d,d*k<h&&(b-=(h-d*k)/2/k),e*l<i&&(c-=(i-e*l)/2/l)),this._viewBox=[b,c,d,e,!!f],this._viewBoxShift={dx:-b,dy:-c,scale:j},this.forEach(function(a){a.transform("...")});return this};var B,C=function(a){var b=a.document;b.createStyleSheet().addRule(".rvml","behavior:url(#default#VML)");try{!b.namespaces.rvml&&b.namespaces.add("rvml","urn:schemas-microsoft-com:vml"),B=function(a){return b.createElement("<rvml:"+a+' class="rvml">')}}catch(c){B=function(a){return b.createElement("<"+a+' xmlns="urn:schemas-microsoft.com:vml" class="rvml">')}}};C(a._g.win),a._engine.create=function(){var b=a._getContainer.apply(0,arguments),c=b.container,d=b.height,e,f=b.width,g=b.x,h=b.y;if(!c)throw new Error("VML container not found.");var i=new a._Paper,j=i.canvas=a._g.doc.createElement("div"),k=j.style;g=g||0,h=h||0,f=f||512,d=d||342,i.width=f,i.height=d,f==+f&&(f+="px"),d==+d&&(d+="px"),i.coordsize=u*1e3+n+u*1e3,i.coordorigin="0 0",i.span=a._g.doc.createElement("span"),i.span.style.cssText="position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;",j.appendChild(i.span),k.cssText=a.format("top:0;left:0;width:{0};height:{1};display:inline-block;position:relative;clip:rect(0 {0} {1} 0);overflow:hidden",f,d),c==1?(a._g.doc.body.appendChild(j),k.left=g+"px",k.top=h+"px",k.position="absolute"):c.firstChild?c.insertBefore(j,c.firstChild):c.appendChild(j),i.renderfix=function(){};return i},a.prototype.clear=function(){a.eve("clear",this),this.canvas.innerHTML=o,this.span=a._g.doc.createElement("span"),this.span.style.cssText="position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;display:inline;",this.canvas.appendChild(this.span),this.bottom=this.top=null},a.prototype.remove=function(){a.eve("remove",this),this.canvas.parentNode.removeChild(this.canvas);for(var b in this)this[b]=removed(b);return!0};var D=a.st;for(var E in A)A[b](E)&&!D[b](E)&&(D[E]=function(a){return function(){var b=arguments;return this.forEach(function(c){c[a].apply(c,b)})}}(E))}(window.Raphael)
\ No newline at end of file diff --git a/addons/web_diagram/static/src/css/base_diagram.css b/addons/web_diagram/static/src/css/base_diagram.css index 9ba2f6b0c83..0dd8483fdc4 100644 --- a/addons/web_diagram/static/src/css/base_diagram.css +++ b/addons/web_diagram/static/src/css/base_diagram.css @@ -1,13 +1,3 @@ -.openerp .diagram { - border: 1px solid #999; - -moz-border-radius: 8px; - -webkit-border-radius: 8px; -} - -.openerp .show_grid { - background: url("/web_diagram/static/src/img/grid.jpg") repeat; -} - .openerp .oe_diagram_pager { text-align: right; white-space: nowrap; diff --git a/addons/web_diagram/static/src/js/diagram.js b/addons/web_diagram/static/src/js/diagram.js index b4aa62fd8f0..e4fb3ef5b75 100644 --- a/addons/web_diagram/static/src/js/diagram.js +++ b/addons/web_diagram/static/src/js/diagram.js @@ -4,7 +4,6 @@ openerp.web_diagram = function (openerp) { var QWeb = openerp.web.qweb; -QWeb.add_template('/web_diagram/static/src/xml/base_diagram.xml'); openerp.web.views.add('diagram', 'openerp.web.DiagramView'); openerp.web.DiagramView = openerp.web.View.extend({ searchable: false, @@ -54,11 +53,6 @@ openerp.web.DiagramView = openerp.web.View.extend({ // New Node,Edge this.$element.find('#new_node.oe_diagram_button_new').click(function(){self.add_edit_node(null, self.node);}); - this.$element.find('#new_edge.oe_diagram_button_new').click(function(){self.add_edit_node(null, self.connector);}); - - this.$element.find('#toggle_grid').click(function() { - self.$element.find('.diagram').toggleClass('show_grid'); - }); if(this.id) { self.get_diagram_info(); @@ -113,8 +107,25 @@ openerp.web.DiagramView = openerp.web.View.extend({ this.get_diagram_info(); } }, - + select_node: function (node, element) { + if (!this.selected_node) { + this.selected_node = node; + element.attr('stroke', 'red'); + return; + } + // Re-click selected node, deselect it + if (node.id === this.selected_node.id) { + this.selected_node = null; + element.attr('stroke', 'black'); + return; + } + this.add_edit_node(null, this.connector, { + act_from: this.selected_node.id, + act_to: node.id + }); + }, draw_diagram: function(result) { + this.selected_node = null; var diagram = new Graph(); this.active_model = result['id_model']; @@ -125,34 +136,33 @@ openerp.web.DiagramView = openerp.web.View.extend({ //Custom logic var self = this; var renderer = function(r, n) { - var node; - var set; - var shape = n.node.shape; - if(shape == 'rectangle') - shape = 'rect'; - node = r[shape](n.node.x, n.node.y).attr({ + var shape = (n.node.shape === 'rectangle') ? 'rect' : 'ellipse'; + + var node = r[shape](n.node.x, n.node.y).attr({ "fill": n.node.color - }).dblclick(function() { - self.add_edit_node(n.node.id, self.node); }); - set = r.set() - .push(node) - .push( - r.text(n.node.x, n.node.y, (n.label || n.id)) - .attr({"cursor":"pointer"}) - .dblclick(function() { - self.add_edit_node(n.node.id, self.node); - }) - ); - node.attr({cursor: "pointer"}); - - if(shape == "ellipse") - node.attr({rx: "40", ry: "20"}); - else if(shape == 'rect') { + + var nodes = r.set(node, r.text(n.node.x, n.node.y, (n.label || n.id))) + .attr("cursor", "pointer") + .dblclick(function() { + self.add_edit_node(n.node.id, self.node); + }) + .mousedown(function () { node.moved = false; }) + .mousemove(function () { node.moved = true; }) + .click(function () { + // Ignore click from move event + if (node.moved) { return; } + self.select_node(n.node, node); + }); + + if (shape === 'rect') { node.attr({width: "60", height: "44"}); node.next.attr({"text-anchor": "middle", x: n.node.x + 20, y: n.node.y + 20}); + } else { + node.attr({rx: "40", ry: "20"}); } - return set; + + return nodes; }; _.each(res_nodes, function(res_node) { @@ -167,10 +177,7 @@ openerp.web.DiagramView = openerp.web.View.extend({ diagram.addEdge(connector['source'], connector['destination'], {directed : true, label: connector['signal']}); }); - - if ($('div#dia-canvas').children().length > 0) { - $('div#dia-canvas').children().remove(); - } + self.$element.find('.diagram').empty(); var layouter = new Graph.Layout.Ordered(diagram); var render_diagram = new Graph.Renderer.Raphael('dia-canvas', diagram, $('div#dia-canvas').width(), $('div#dia-canvas').height()); @@ -184,7 +191,8 @@ openerp.web.DiagramView = openerp.web.View.extend({ }); }, - add_edit_node: function(id, model) { + add_edit_node: function(id, model, defaults) { + defaults = defaults || {}; var self = this; if(!model) @@ -253,6 +261,15 @@ openerp.web.DiagramView = openerp.web.View.extend({ }); }); } + if (!_.isEmpty(defaults)) { + form_controller.on_record_loaded.add_last(function () { + _(form_fields).each(function (field) { + if (!defaults[field]) { return; } + form_controller.fields[field].set_value(defaults[field]); + form_controller.fields[field].dirty = true; + }); + }); + } }, on_pager_action: function(action) { diff --git a/addons/web_diagram/static/src/xml/base_diagram.xml b/addons/web_diagram/static/src/xml/base_diagram.xml index 7867befa957..20613c7b079 100644 --- a/addons/web_diagram/static/src/xml/base_diagram.xml +++ b/addons/web_diagram/static/src/xml/base_diagram.xml @@ -3,8 +3,6 @@ <div class="oe_diagram_header" t-att-id="element_id + '_header'"> <div class="oe_diagram_buttons"> <button type="button" id="new_node" class="oe_diagram_button_new">New Node</button> - <button type="button" id="new_edge" class="oe_diagram_button_new">New Edge</button> - <label>Show Grid:</label><input type="checkbox" id="toggle_grid" checked="checked"/> </div> <div class="oe_diagram_pager"> <button type="button" data-pager-action="first">First</button> @@ -16,6 +14,6 @@ <button type="button" data-pager-action="last">Last</button> </div> </div> - <div id="dia-canvas" class="diagram show_grid" style="overflow: auto;"></div> + <div id="dia-canvas" class="diagram" style="overflow: auto;"></div> </t> </template> diff --git a/addons/web_gantt/__openerp__.py b/addons/web_gantt/__openerp__.py index d2b24f96d08..cd24a8f7314 100644 --- a/addons/web_gantt/__openerp__.py +++ b/addons/web_gantt/__openerp__.py @@ -9,5 +9,8 @@ 'static/src/js/gantt.js' ], "css": ['static/lib/dhtmlxGantt/codebase/dhtmlxgantt.css'], + 'qweb' : [ + "static/src/xml/*.xml", + ], 'active': True } diff --git a/addons/web_gantt/static/src/js/gantt.js b/addons/web_gantt/static/src/js/gantt.js index 73e244edad7..d2eb3aed899 100644 --- a/addons/web_gantt/static/src/js/gantt.js +++ b/addons/web_gantt/static/src/js/gantt.js @@ -3,7 +3,6 @@ *---------------------------------------------------------*/ openerp.web_gantt = function (openerp) { var QWeb = openerp.web.qweb; -QWeb.add_template('/web_gantt/static/src/xml/web_gantt.xml'); openerp.web.views.add('gantt', 'openerp.web_gantt.GanttView'); openerp.web_gantt.GanttView = openerp.web.View.extend({ @@ -43,7 +42,7 @@ init: function(parent, dataset, view_id) { this.name = this.fields_view.arch.attrs.string; this.view_id = this.fields_view.view_id; - + this.date_start = this.fields_view.arch.attrs.date_start; this.date_delay = this.fields_view.arch.attrs.date_delay; this.date_stop = this.fields_view.arch.attrs.date_stop; @@ -71,7 +70,7 @@ init: function(parent, dataset, view_id) { ganttChartControl.setImagePath("/web_gantt/static/lib/dhtmlxGantt/codebase/imgs/"); ganttChartControl.setEditable(true); ganttChartControl.showTreePanel(true); - ganttChartControl.showContextMenu(true); + ganttChartControl.showContextMenu(false); ganttChartControl.showDescTask(true,'d,s-f'); ganttChartControl.showDescProject(true,'n,d'); @@ -228,7 +227,7 @@ init: function(parent, dataset, view_id) { var evt_date = ""; var evt_duration = ""; var evt_end_date = ""; - + var project_tree_field = []; for (var i in final_events){ evt_id = final_events[i]; evt_date = all_events[evt_id]['evt'][2]; @@ -254,7 +253,7 @@ init: function(parent, dataset, view_id) { self.render_events(all_events, 0); } - for (var i in final_events){ + for (var i in final_events) { evt_id = final_events[i]; res = all_events[evt_id]; task=new GanttTaskInfo(res['evt'][0], res['evt'][1], res['evt'][2], res['evt'][3], res['evt'][4], "",res['evt'][6]); @@ -278,8 +277,9 @@ init: function(parent, dataset, view_id) { ganttChartControl.attachEvent("onTaskStartDrag", function(task) {self.on_drag_start(task);}); ganttChartControl.attachEvent("onTaskEndResize", function(task) {self.on_resize_drag_end(task, "resize");}); ganttChartControl.attachEvent("onTaskEndDrag", function(task) {self.on_resize_drag_end(task, "drag");}); + ganttChartControl.attachEvent("onTaskDblClick", function(task) {self.open_popup(task);}); - + var taskdiv = jQuery("div.taskPanel").parent(); taskdiv.addClass('ganttTaskPanel'); taskdiv.prev().addClass('ganttDayPanel'); @@ -293,7 +293,7 @@ init: function(parent, dataset, view_id) { self.set_width(); }); - jQuery(window).bind('resize',function(){ + jQuery(window).bind('resize',function() { window.clearTimeout(ganttChartControl._resize_timer); ganttChartControl._resize_timer = window.setTimeout(function(){ self.reload_gantt(); @@ -385,53 +385,46 @@ init: function(parent, dataset, view_id) { }, open_popup : function(task) { + var self = this; var event_id = task.getId(); if(event_id.toString().search("_") != -1) return; if(event_id) event_id = parseInt(event_id, 10); - - var action = { - "res_model": this.dataset.model, - "res_id": event_id, - "views":[[false,"form"]], - "type":"ir.actions.act_window", - "view_type":"form", - "view_mode":"form" - }; - - action.flags = { - search_view: false, - sidebar : false, - views_switcher : false, - pager: false - }; - var element_id = _.uniqueId("act_window_dialog"); - var dialog = jQuery('<div>', { - 'id': element_id - }).dialog({ - modal: true, - width: 'auto', - height: 'auto', - buttons: { - Cancel: function() { - $(this).dialog("destroy"); - }, - Save: function() { - var view_manager = action_manager.viewmanager; - var _dialog = this; - view_manager.views[view_manager.active_view].controller.do_save(function(r) { - $(_dialog).dialog("destroy"); - self.reload_gantt(); - }) - } + + var action_manager = new openerp.web.ActionManager(this); + + var dialog = new openerp.web.Dialog(this, { + width: 800, + height: 600, + buttons : { + Cancel : function() { + $(this).dialog('destroy'); + }, + Save : function() { + var form_view = action_manager.inner_viewmanager.views.form.controller; + + form_view.do_save(function() { + self.get_events(); + }); + $(this).dialog('destroy'); } + } + }).start().open(); + action_manager.appendTo(dialog.$element); + action_manager.do_action({ + res_model : this.dataset.model, + res_id: event_id, + views : [[false, 'form']], + type : 'ir.actions.act_window', + auto_search : false, + flags : { + search_view: false, + sidebar : false, + views_switcher : false, + action_buttons : false, + pager: false + } }); - var action_manager = new openerp.web.ActionManager(this, element_id); - action_manager.start(); - action_manager.do_action(action); - - //Default_get - if(!event_id) action_manager.viewmanager.dataset.index = null; }, on_drag_start : function(task){ diff --git a/addons/web_graph/__openerp__.py b/addons/web_graph/__openerp__.py index 68775b7c0e3..d7c37acb180 100644 --- a/addons/web_graph/__openerp__.py +++ b/addons/web_graph/__openerp__.py @@ -7,5 +7,8 @@ "static/lib/dhtmlxGraph/codebase/dhtmlxchart_debug.js", "static/src/js/graph.js"], "css": ["static/lib/dhtmlxGraph/codebase/dhtmlxchart.css"], + 'qweb' : [ + "static/src/xml/*.xml", + ], "active": True } diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index bac147b1a91..04e9d77f5d0 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -13,7 +13,6 @@ var COLOR_PALETTE = [ '#cc0000', '#d400a8']; var QWeb = openerp.web.qweb; -QWeb.add_template('/web_graph/static/src/xml/web_graph.xml'); openerp.web.views.add('graph', 'openerp.web_graph.GraphView'); openerp.web_graph.GraphView = openerp.web.View.extend({ @@ -29,6 +28,14 @@ openerp.web_graph.GraphView = openerp.web.View.extend({ this.columns = []; this.group_field = null; this.is_loaded = $.Deferred(); + + this.renderer = null; + }, + stop: function () { + if (this.renderer) { + clearTimeout(this.renderer); + } + this._super(); }, do_show: function () { this.$element.show(); @@ -256,90 +263,113 @@ openerp.web_graph.GraphView = openerp.web.View.extend({ x_axis = abscissa_description; y_axis = ordinate_description; } - - var bar_chart = new dhtmlXChart({ - view: view_chart, - container: this.element_id+"-barchart", - value:"#"+group_list[0].group+"#", - gradient: "3d", - border: false, - width: 1024, - tooltip:{ - template: _.sprintf("#%s#, %s=#%s#", - this.abscissa, group_list[0].text, group_list[0].group) - }, - radius: 0, - color:group_list[0].color, - origin:0, - xAxis: x_axis, - yAxis: y_axis, - padding: { - left: 75 - }, - legend: { - values: group_list, - align:"left", - valign:"top", - layout: "x", - marker: { - type:"round", - width:12 - } + + var renderer = function () { + if (self.$element.is(':hidden')) { + self.renderer = setTimeout(renderer, 100); + return; } - }); - for (var m = 1; m<group_list.length;m++){ - var column = group_list[m]; - if (column.group === this.group_field) { continue; } - bar_chart.addSeries({ - value: "#"+column.group+"#", + self.renderer = null; + var bar_chart = new dhtmlXChart({ + view: view_chart, + container: self.element_id+"-barchart", + value:"#"+group_list[0].group+"#", + gradient: "3d", + border: false, + width: 1024, tooltip:{ template: _.sprintf("#%s#, %s=#%s#", - this.abscissa, column.text, column.group) + self.abscissa, group_list[0].text, group_list[0].group) + }, + radius: 0, + color:group_list[0].color, + origin:0, + xAxis: x_axis, + yAxis: y_axis, + padding: { + left: 75 }, - color: column.color + legend: { + values: group_list, + align:"left", + valign:"top", + layout: "x", + marker: { + type:"round", + width:12 + } + } + }); + for (var m = 1; m<group_list.length;m++){ + var column = group_list[m]; + if (column.group === self.group_field) { continue; } + bar_chart.addSeries({ + value: "#"+column.group+"#", + tooltip:{ + template: _.sprintf("#%s#, %s=#%s#", + self.abscissa, column.text, column.group) + }, + color: column.color + }); + } + bar_chart.parse(results, "json"); + self.$element.find("#"+self.element_id+"-barchart").height( + self.$element.find("#"+self.element_id+"-barchart").height()+50); + bar_chart.attachEvent("onItemClick", function(id) { + self.open_list_view(bar_chart.get(id)); }); + }; + if (this.renderer) { + clearTimeout(this.renderer); } - bar_chart.parse(results, "json"); - jQuery("#"+this.element_id+"-barchart").height(jQuery("#"+this.element_id+"-barchart").height()+50); - bar_chart.attachEvent("onItemClick", function(id) { - self.open_list_view(bar_chart.get(id)); - }); + this.renderer = setTimeout(renderer, 0); }, schedule_pie: function(result) { var self = this; - var chart = new dhtmlXChart({ - view:"pie3D", - container:self.element_id+"-piechart", - value:"#"+self.ordinate+"#", - pieInnerText:function(obj) { - var sum = chart.sum("#"+self.ordinate+"#"); - var val = obj[self.ordinate] / sum * 100 ; - return val.toFixed(1) + "%"; - }, - tooltip:{ - template:"#"+self.abscissa+"#"+"="+"#"+self.ordinate+"#" - }, - gradient:"3d", - height: 20, - radius: 200, - legend: { - width: 300, - align:"left", - valign:"top", - layout: "x", - marker:{ - type:"round", - width:12 + var renderer = function () { + if (self.$element.is(':hidden')) { + self.renderer = setTimeout(renderer, 100); + return; + } + self.renderer = null; + var chart = new dhtmlXChart({ + view:"pie3D", + container:self.element_id+"-piechart", + value:"#"+self.ordinate+"#", + pieInnerText:function(obj) { + var sum = chart.sum("#"+self.ordinate+"#"); + var val = obj[self.ordinate] / sum * 100 ; + return val.toFixed(1) + "%"; }, - template:function(obj){ - return obj[self.abscissa] || 'Undefined'; + tooltip:{ + template:"#"+self.abscissa+"#"+"="+"#"+self.ordinate+"#" + }, + gradient:"3d", + height: 20, + radius: 200, + legend: { + width: 300, + align:"left", + valign:"top", + layout: "x", + marker:{ + type:"round", + width:12 + }, + template:function(obj){ + return obj[self.abscissa] || 'Undefined'; + } } - } - }); - chart.parse(result,"json"); - chart.attachEvent("onItemClick", function(id) { - self.open_list_view(chart.get(id)); - }); + }); + chart.parse(result,"json"); + chart.attachEvent("onItemClick", function(id) { + self.open_list_view(chart.get(id)); + }); + }; + if (this.renderer) { + clearTimeout(this.renderer); + } + this.renderer = setTimeout(renderer, 0); }, open_list_view : function (id){ var self = this; diff --git a/addons/web_kanban/__openerp__.py b/addons/web_kanban/__openerp__.py index f39cd64999b..92d60b0f4ed 100644 --- a/addons/web_kanban/__openerp__.py +++ b/addons/web_kanban/__openerp__.py @@ -9,5 +9,8 @@ "css": [ "static/src/css/kanban.css" ], + 'qweb' : [ + "static/src/xml/*.xml", + ], 'active': True } diff --git a/addons/web_kanban/static/src/css/kanban.css b/addons/web_kanban/static/src/css/kanban.css index 82143e460d1..6c6ddd57dec 100644 --- a/addons/web_kanban/static/src/css/kanban.css +++ b/addons/web_kanban/static/src/css/kanban.css @@ -1,36 +1,71 @@ -.openerp .oe_kanban_view .oe_column { - width: 100%; -} - -.openerp .oe_vertical_text { - writing-mode:tb-rl; - -webkit-transform:rotate(90deg); - -moz-transform:rotate(90deg); - -o-transform: rotate(90deg); - -ms-transform: rotate(90deg); - transform: rotate(90deg); - display:block; - width:30px; - height:20px; - align:center; - font-size:24px; -} - .openerp .oe_kanban_view .ui-sortable-placeholder { border: 1px dotted black; visibility: visible !important; height: 60px !important; } +.openerp .oe_kanban_group_header { + position: relative; +} +.openerp .oe_kanban_group_folded { + padding: 0 5px 0 5px; +} +.openerp .oe_kanban_group_folded .oe_kanban_group_title, +.openerp .oe_kanban_group_folded .oe_kanban_aggregates { + display: none; +} +.openerp .oe_kanban_group_folded .oe_kanban_group_title_vertical { + display: block; +} -.openerp .oe_kanban_view .oe_column_heading { +.openerp .oe_kanban_group_title { color: #000000; - font-size: 1.5em; + font-size: 130%; font-weight: bold; } -.openerp .oe_kanban_view .fold-columns-icon { +.openerp .oe_kanban_group_title_undefined { + color: #666666; +} +.openerp .oe_kanban_group_title_vertical { + writing-mode: tb-rl; + -webkit-transform: rotate(90deg); + -moz-transform: rotate(90deg); + -o-transform: rotate(90deg); + -ms-transform: rotate(90deg); + transform: rotate(90deg); + width: 30px; + height: 20px; + align: center; + font-size: 24px; + white-space: nowrap; + display: none; + position: absolute; + top: 10px; +} + +.openerp .oe_kanban_fold_icon { + cursor: pointer; float: left; padding: 2px 2px 0 0; + width: 16px; + height: 16px; + background: url(/web_kanban/static/src/img/minus-icon.png) no-repeat; +} +.openerp .oe_kanban_group_folded .oe_kanban_fold_icon { + background: url(/web_kanban/static/src/img/plus-icon.png) no-repeat; +} + +.openerp ul.oe_kanban_aggregates { + padding: 0; + margin: 0 0 0 22px; } +.openerp ul.oe_kanban_aggregates li { + list-style: circle; + font-style: italic; +} +.openerp ul.oe_kanban_aggregates span { + text-decoration: underline; +} + .openerp .oe_kanban_action_button { height: 22px; margin: 0; @@ -50,17 +85,17 @@ border-bottom: 1px solid #CCC; } .openerp .oe_kanban_title1 { - font-size: 130%; + font-size: 120%; font-weight: bold; padding: 0 4px 0 4px; } .openerp .oe_kanban_title2 { - font-size: 120%; + font-size: 110%; font-weight: bold; padding: 0 4px 0 4px; } .openerp .oe_kanban_title3 { - font-size: 110%; + font-size: 100%; font-weight: normal; padding: 0 4px 0 4px; } @@ -87,6 +122,7 @@ white-space: nowrap; padding-top: 2px; position: relative; + clear: both; } .openerp .oe_kanban_buttons_set a { padding: 2px; @@ -132,91 +168,113 @@ } /* Custom colors are also present in kanban.js */ +/* Custom color#0 */ +.openerp .oe_kanban_color_0 .oe_kanban_color_bglight { + background: #FFFFFF; +} +.openerp .oe_kanban_color_0 .oe_kanban_color_bgdark { + background: #EEEEEE; +} +.openerp .oe_kanban_color_0 .oe_kanban_color_border { + border-color: #CCCCCC; +} + /* Custom color#1 */ .openerp .oe_kanban_color_1 .oe_kanban_color_bglight { - background: #FFC7C7; + background: #CCCCCC; } .openerp .oe_kanban_color_1 .oe_kanban_color_bgdark { - background: #FF8F8F; + background: #999999; } .openerp .oe_kanban_color_1 .oe_kanban_color_border { - border-color: #D97979; + border-color: #666666; } /* Custom color#2 */ .openerp .oe_kanban_color_2 .oe_kanban_color_bglight { - background: #FFF1C7; + background: #FFC7C7; } .openerp .oe_kanban_color_2 .oe_kanban_color_bgdark { - background: #FFE38F; + background: #FF8F8F; } .openerp .oe_kanban_color_2 .oe_kanban_color_border { - border-color: #D9C179; + border-color: #D97979; } /* Custom color#3 */ .openerp .oe_kanban_color_3 .oe_kanban_color_bglight { - background: #E3FFC7; + background: #FFF1C7; } .openerp .oe_kanban_color_3 .oe_kanban_color_bgdark { - background: #C7FF8F; + background: #FFE38F; } .openerp .oe_kanban_color_3 .oe_kanban_color_border { - border-color: #A9D979; + border-color: #D9C179; } /* Custom color#4 */ .openerp .oe_kanban_color_4 .oe_kanban_color_bglight { - background: #C7FFD5; + background: #E3FFC7; } .openerp .oe_kanban_color_4 .oe_kanban_color_bgdark { - background: #8FFFAB; + background: #C7FF8F; } .openerp .oe_kanban_color_4 .oe_kanban_color_border { - border-color: #79D991; + border-color: #A9D979; } /* Custom color#5 */ .openerp .oe_kanban_color_5 .oe_kanban_color_bglight { - background: #C7FFFF; + background: #C7FFD5; } .openerp .oe_kanban_color_5 .oe_kanban_color_bgdark { - background: #8FFFFF; + background: #8FFFAB; } .openerp .oe_kanban_color_5 .oe_kanban_color_border { - border-color: #79D9D9; + border-color: #79D991; } /* Custom color#6 */ .openerp .oe_kanban_color_6 .oe_kanban_color_bglight { - background: #C7D5FF; + background: #C7FFFF; } .openerp .oe_kanban_color_6 .oe_kanban_color_bgdark { - background: #8FABFF; + background: #8FFFFF; } .openerp .oe_kanban_color_6 .oe_kanban_color_border { - border-color: #8FABFF; + border-color: #79D9D9; } /* Custom color#7 */ .openerp .oe_kanban_color_7 .oe_kanban_color_bglight { - background: #E3C7FF; + background: #C7D5FF; } .openerp .oe_kanban_color_7 .oe_kanban_color_bgdark { - background: #C78FFF; + background: #8FABFF; } .openerp .oe_kanban_color_7 .oe_kanban_color_border { - border-color: #A979D9; + border-color: #8FABFF; } /* Custom color#8 */ .openerp .oe_kanban_color_8 .oe_kanban_color_bglight { - background: #FFC7F1; + background: #E3C7FF; } .openerp .oe_kanban_color_8 .oe_kanban_color_bgdark { - background: #FF8FE3; + background: #C78FFF; } .openerp .oe_kanban_color_8 .oe_kanban_color_border { + border-color: #A979D9; +} + +/* Custom color#9 */ +.openerp .oe_kanban_color_9 .oe_kanban_color_bglight { + background: #FFC7F1; +} +.openerp .oe_kanban_color_9 .oe_kanban_color_bgdark { + background: #FF8FE3; +} +.openerp .oe_kanban_color_9 .oe_kanban_color_border { border-color: #D979C1; } @@ -224,3 +282,8 @@ .openerp .oe_kanban_color_alert .oe_kanban_color_border { border-color: #c00 !important; } + +/* Green color */ +.openerp .oe_kanban_color_green .oe_kanban_color_border { + border-color: #0c0 !important; +} diff --git a/addons/web_kanban/static/src/js/kanban.js b/addons/web_kanban/static/src/js/kanban.js index 11d675a5705..c43ea503841 100644 --- a/addons/web_kanban/static/src/js/kanban.js +++ b/addons/web_kanban/static/src/js/kanban.js @@ -1,37 +1,58 @@ openerp.web_kanban = function (openerp) { +var _t = openerp.web._t; var QWeb = openerp.web.qweb; -QWeb.add_template('/web_kanban/static/src/xml/web_kanban.xml'); openerp.web.views.add('kanban', 'openerp.web_kanban.KanbanView'); + openerp.web_kanban.KanbanView = openerp.web.View.extend({ + template: "KanbanView", + default_nr_columns: 3, init: function (parent, dataset, view_id, options) { this._super(parent); this.set_default_options(options); this.dataset = dataset; - this.model = dataset.model; this.view_id = view_id; this.fields_view = {}; - this.group_by = []; - this.source_index = {}; - this.all_display_data = false; + this.fields_keys = []; + this.group_by = null; + this.state = { + groups : {}, + records : {} + }; this.groups = []; - this.qweb = new QWeb2.Engine(); - this.aggregates = {}; - this.NO_OF_COLUMNS = 3; this.form_dialog = new openerp.web.FormDialog(this, {}, this.options.action_views_ids.form, dataset).start(); - this.form_dialog.on_form_dialog_saved.add_last(this.on_record_saved); + this.form_dialog.on_form_dialog_saved.add_last(this.do_reload); + this.aggregates = {}; + this.qweb = new QWeb2.Engine(); + this.qweb.debug = openerp.connection.debug; + this.qweb.default_dict = { + '_' : _, + '_t' : _t + } + this.has_been_loaded = $.Deferred(); + this.search_domain = this.search_context = this.search_group_by = null; + this.currently_dragging = {}; }, start: function() { this._super(); - return this.rpc("/web/view/load", {"model": this.model, "view_id": this.view_id, "view_type": "kanban"}, this.on_loaded); + this.$element.find('button.oe_kanban_button_new').click(this.do_add_record); + this.$groups = this.$element.find('.oe_kanban_groups tr'); + var context = new openerp.web.CompoundContext(this.dataset.get_context()); + return this.rpc('/web/view/load', { + 'model': this.dataset.model, + 'view_id': this.view_id, + 'view_type': 'kanban', + context: context + }, this.on_loaded); }, on_loaded: function(data) { - var self = this; this.fields_view = data; + this.fields_keys = _.keys(this.fields_view.fields); this.add_qweb_template(); + this.has_been_loaded.resolve(); }, add_qweb_template: function() { - var group_operator = ["avg", "max", "min", "sum", "count"] + var group_operator = ['avg', 'max', 'min', 'sum', 'count'] for (var i=0, ii=this.fields_view.arch.children.length; i < ii; i++) { var child = this.fields_view.arch.children[i]; if (child.tag === "field") { @@ -49,28 +70,6 @@ openerp.web_kanban.KanbanView = openerp.web.View.extend({ } } }, - kanban_color: function(variable) { - var number_of_color_schemes = 8, - index = 0; - switch (typeof(variable)) { - case 'string': - for (var i=0, ii=variable.length; i<ii; i++) { - index += variable.charCodeAt(i); - } - break; - case 'number': - index = Math.round(variable); - break; - default: - return ''; - } - return 'oe_kanban_color_' + ((index % number_of_color_schemes) || number_of_color_schemes); - }, - kanban_gravatar: function(email, size) { - size = size || 22; - var email_md5 = '2eb60ad22dadcf4dc456b28390a80268'; - return 'http://www.gravatar.com/avatar/' + email_md5 + '.png?s=' + size; - }, transform_qweb_template: function(node) { var qweb_prefix = QWeb.prefix; switch (node.tag) { @@ -90,7 +89,7 @@ openerp.web_kanban.KanbanView = openerp.web.View.extend({ }); if (node.attrs['data-states']) { var states = _.map(node.attrs['data-states'].split(','), function(state) { - return "record.state.value == '" + _.trim(state) + "'"; + return "record.state.raw_value == '" + _.trim(state) + "'"; }); node.attrs['t-if'] = states.join(' or '); } @@ -122,359 +121,391 @@ openerp.web_kanban.KanbanView = openerp.web.View.extend({ } } }, - on_show_data: function() { - var self = this; - if (!this.group_by.length) { - this.do_record_group(); - } - this.$element.html(QWeb.render("KanbanView", {"data": self.all_display_data})); - this.on_reload_kanban(); - this.$element.find(".oe_vertical_text").hide(); - var drag_handel = false; - if (this.$element.find(".oe_kanban_draghandle").length > 0) { - drag_handel = ".oe_kanban_draghandle"; - } - if (!this.group_by.length) { - drag_handel = true; - } - this.$element.find(".oe_column").sortable({ - connectWith: ".oe_column", - handle : drag_handel, - start: function(event, ui) { - self.source_index['index'] = ui.item.index(); - self.source_index['column'] = ui.item.parent().attr('id'); - }, - stop: self.on_receive_record, - scroll: false - }); - this.$element.find(".oe_column").disableSelection() - this.$element.find('button.oe_kanban_button_new').click(this.do_add_record); - this.$element.find(".fold-columns-icon").click(function(event) { - self.do_fold_unfold_columns(event, this.id); - }); - }, - do_fold_unfold_columns: function(event, element_id) { - var column_id = "column_" + element_id; - var column_element = this.$element.find("#" + column_id + " .oe_fold_column"); - if (column_element.is(":hidden")) { - this.$element.find("#" + column_id).find("img.fold-columns-icon").attr('src', '/web_kanban/static/src/img/minus-icon.png'); - column_element.show(); - this.$element.find("#" + column_id + ".oe_table_column").css("width",Math.round(99 / this.all_display_data.length) + "%"); - this.$element.find("#" + column_id + ".oe_vertical_text").hide(); - } - else{ - this.$element.find("#" + column_id).find("img.fold-columns-icon").attr('src', '/web_kanban/static/src/img/plus-icon.png'); - column_element.hide(); - this.$element.find("#" + column_id + ".oe_table_column").css("width","0.5%"); - this.$element.find("#" + column_id + ".oe_vertical_text").show(); - } - - }, - do_record_group: function() { - if (this.NO_OF_COLUMNS && this.all_display_data.length > 0) { - var records = this.all_display_data[0].records; - var record_per_group = Math.round((records).length / this.NO_OF_COLUMNS); - this.all_display_data = []; - for (var i=0, ii=this.NO_OF_COLUMNS; i < ii; i++) { - this.all_display_data.push({'records': records.slice(0,record_per_group), 'value':i, 'header' : false, 'ids':[]}); - records.splice(0,record_per_group); - } - } - }, - on_button_click: function (button_attrs, record_id) { - this.on_execute_button_click(this.dataset, button_attrs, record_id); - }, do_add_record: function() { this.dataset.index = null; this.do_switch_view('form'); }, - do_edit_record: function(record_id) { + do_search: function(domain, context, group_by) { var self = this; - this.form_dialog.select_id(record_id).then(function() { - self.form_dialog.open(); + this.search_domain = domain; + this.search_context = context; + this.search_group_by = group_by; + $.when(this.has_been_loaded).then(function() { + self.group_by = group_by.length ? group_by[0] : self.fields_view.arch.attrs.default_group_by; + self.datagroup = new openerp.web.DataGroup(self, self.dataset.model, domain, context, self.group_by ? [self.group_by] : []); + self.datagroup.list(self.fields_keys, self.do_process_groups, self.do_process_dataset); }); }, - on_record_saved: function(r) { - var id = this.form_dialog.form.datarecord.id; - this.on_reload_record(id); - }, - do_change_color: function(record_id, $e) { + do_process_groups: function(groups) { + this.do_clear_groups(); + this.dataset.ids = []; var self = this, - id = record_id, - colors = '#FFC7C7,#FFF1C7,#E3FFC7,#C7FFD5,#C7FFFF,#C7D5FF,#E3C7FF,#FFC7F1'.split(','), - $cpicker = $(QWeb.render('KanbanColorPicker', { colors : colors, columns: 2 })); - $e.after($cpicker); - $cpicker.mouseenter(function() { - clearTimeout($cpicker.data('timeoutId')); - }).mouseleave(function(evt) { - var timeoutId = setTimeout(function() { $cpicker.remove() }, 500); - $cpicker.data('timeoutId', timeoutId); - }); - $cpicker.find('a').click(function(evt) { - var data = {}; - data[$e.data('name')] = $(this).data('color'); - self.dataset.write(id, data, {}, function() { - self.on_reload_record(id); + remaining = groups.length - 1, + groups_array = []; + _.each(groups, function (group, index) { + var group_name = group.value, + group_value = group.value, + group_aggregates = {}; + if (group.value instanceof Array) { + group_name = group.value[1]; + group_value = group.value[0]; + } + _.each(self.aggregates, function(value, key) { + group_aggregates[value] = group.aggregates[key]; + }); + var dataset = new openerp.web.DataSetSearch(self, self.dataset.model, group.context, group.domain); + dataset.read_slice(self.fields_keys, {'domain': group.domain, 'context': group.context}, function(records) { + self.dataset.ids.push.apply(self.dataset.ids, dataset.ids); + groups_array[index] = new openerp.web_kanban.KanbanGroup(self, records, group_value, group_name, group_aggregates); + if (!remaining--) { + self.dataset.index = self.dataset.ids.length ? 0 : null; + self.do_add_groups(groups_array); + } }); - $cpicker.remove(); - return false; }); }, - /** - Reload one record in view. - record_id : reload record id. - */ - on_reload_record: function (record_id){ + do_process_dataset: function(dataset) { var self = this; - this.dataset.read_ids([record_id], _.keys(self.fields_view.fields), function (records) { - if (records.length > 0) { - for (var i=0, ii=self.all_display_data.length; i < ii; i++) { - for(j=0, jj=self.all_display_data[i].records.length; j < jj; j++) { - if (self.all_display_data[i].records[j].id == record_id) { - _.extend(self.all_display_data[i].records[j], records[0]); - self.$element.find("#main_" + record_id).children().remove(); - self.$element.find("#main_" + record_id).append(self.qweb.render('kanban-box', { - record: self.do_transform_record(self.all_display_data[i].records[j]), - kanban_color: self.kanban_color, - kanban_gravatar: self.kanban_gravatar - })); - break; - } + this.do_clear_groups(); + this.dataset.read_slice(this.fields_keys, {}, function(records) { + var groups = []; + while (records.length) { + for (var i = 0; i < self.default_nr_columns; i++) { + if (!groups[i]) { + groups[i] = []; } + groups[i].push(records.shift()); } - self.$element.find("#main_" + record_id + " .oe_kanban_action").click(self.on_action_clicked); - self.$element.find("#main_" + record_id + " .oe_kanban_box_show_onclick_trigger").click(function() { - $(this).parent("#main_" + record_id + " .oe_kanban_box").find(".oe_kanban_box_show_onclick").toggle(); - }); } + for (var i = 0; i < groups.length; i++) { + groups[i] = new openerp.web_kanban.KanbanGroup(self, _.compact(groups[i])); + } + self.do_add_groups(groups); }); - }, - do_delete: function (id) { - var self = this; - return $.when(this.dataset.unlink([id])).then(function () { - self.drop_records(id); - }); + do_reload: function() { + this.do_search(this.search_domain, this.search_context, this.search_group_by); }, - drop_records: function (id) { - var self = this; - _.each(self.all_display_data, function(data, index) { - _.each(data.records, function(record, index_row) { - if (parseInt(record.id) == id) { - self.all_display_data[index]['records'].splice(index_row, 1); - self.all_display_data[index]['ids'].splice(index_row, 1); - return false; - } - }); + do_clear_groups: function() { + _.each(this.groups, function(group) { + group.stop(); }); - self.$element.find("#main_" + id).remove(); + this.groups = []; + this.$element.find('.oe_kanban_groups_headers, .oe_kanban_groups_records').empty(); }, - on_execute_button_click: function (dataset, button_attrs, record_id) { + do_add_groups: function(groups) { var self = this; - this.do_execute_action( - button_attrs, dataset, - record_id, function () { - self.on_reload_record(record_id); - } - ); + _.each(groups, function(group) { + self.groups[group.undefined_title ? 'unshift' : 'push'](group); + }); + _.each(this.groups, function(group) { + group.appendTo(self.$element.find('.oe_kanban_groups_headers')); + }); + this.on_groups_started(); }, - on_receive_record: function (event, ui) { + on_groups_started: function() { var self = this; - var from = ui.item.index(); - var search_action = false; - var to = ui.item.prev().index() || 0; - if (!ui.item.attr("id")) { - return false; + this.compute_groups_width(); + if (this.group_by) { + this.$element.find('.oe_kanban_column').sortable({ + connectWith: '.oe_kanban_column', + handle : '.oe_kanban_draghandle', + start: function(event, ui) { + self.currently_dragging.index = ui.item.index(); + self.currently_dragging.group = ui.item.parents('.oe_kanban_column:first').data('widget'); + }, + stop: function(event, ui) { + var record = ui.item.data('widget'), + old_index = self.currently_dragging.index, + new_index = ui.item.index(), + old_group = self.currently_dragging.group, + new_group = ui.item.parents('.oe_kanban_column:first').data('widget'); + if (!(old_group.title === new_group.title && old_group.value === new_group.value && old_index == new_index)) { + self.on_record_moved(record, old_group, old_index, new_group, new_index); + } + }, + scroll: false + }); + } else { + this.$element.find('.oe_kanban_draghandle').removeClass('oe_kanban_draghandle'); } - if (self.fields_view.fields.sequence != undefined && ((self.source_index.index >= 0 && self.source_index.index != from) || - (self.source_index.column && self.source_index.column != ui.item.parent().attr('id')))) { - var child_record = ui.item.parent().children(); - var data, sequence = 1, index = to; - child_record.splice(0, to); - var flag = false; - if (to >= 0 && child_record) { - var record_id = parseInt($(child_record).attr("id").split("_")[1]); - if (record_id) { - _.each(self.all_display_data, function(data, index) { - _.each(data.records, function(record, index_row) { - if(record_id == record.id && record.sequence) { - sequence = record.sequence; - flag = true; - return false; - } - }); - if(flag) {return false;} - }); - } - } - _.each(child_record, function (child) { - var child_id = parseInt($(child).attr("id").split("_")[1]); - if (child_id) { - flag = false; - _.each(self.all_display_data, function(data, index) { - _.each(data.records, function(record, index_row) { - if(parseInt(record.id) == child_id) { - self.all_display_data[index]['records'][index_row]['sequence'] = sequence; - flag = true; - return false; - } - }); - if (flag) {return false;} - }); - self.dataset.write(child_id, {sequence: sequence}); - sequence++; - search_action = true; - } + }, + on_record_moved : function(record, old_group, old_index, new_group, new_index) { + if (old_group === new_group) { + new_group.records.splice(old_index, 1); + new_group.records.splice(new_index, 0, record); + new_group.do_save_sequences(); + } else { + old_group.records.splice(old_index, 1); + new_group.records.splice(new_index, 0, record); + record.group = new_group; + var data = {}; + data[this.group_by] = new_group.value; + this.dataset.write(record.id, data, {}, function() { + record.do_reload(); + new_group.do_save_sequences(); }); } - if (self.group_by.length > 0 && self.source_index.column && self.source_index.column != ui.item.parent().attr('id')) { - var value = ui.item.closest("td").attr("id"); - if (value) { - var data_val = {}; - var wirte_id = parseInt(ui.item.attr("id").split("_")[1]); - value = value.split("_")[1]; - if (value == 'false') { - value = false; - } - var update_record = false; - _.each(self.all_display_data, function(data, index) { - _.each(data.records, function(record, index_row) { - if(parseInt(record.id) == wirte_id) { - self.all_display_data[index]['records'][index_row][self.group_by[0]] = value; - update_record = self.all_display_data[index]['records'].splice(index_row,1) - return false; - } - }); - if (update_record) {return false;} - }); - _.each(self.all_display_data, function(data, index) { - if (data.value == value || (data.value == 'false' && value == false)) { - self.all_display_data[index]['records'].push(update_record[0]); - } - }); - data_val[self.group_by[0]] = value; - self.dataset.write(wirte_id, data_val); - search_action = true; + }, + do_show: function () { + this.$element.show(); + }, + do_hide: function () { + this.$element.hide(); + }, + compute_groups_width: function() { + var unfolded = 0; + _.each(this.groups, function(group) { + unfolded += group.state.folded ? 0 : 1; + group.$element.css('width', ''); + }); + _.each(this.groups, function(group) { + if (!group.state.folded) { + group.$element.css('width', Math.round(100/unfolded) + '%'); } + }); + } +}); + +openerp.web_kanban.KanbanGroup = openerp.web.Widget.extend({ + template: 'KanbanView.group_header', + init: function (parent, records, value, title, aggregates) { + var self = this; + this._super(parent); + this.view = parent; + this.value = value; + this.title = title; + if (title === false) { + this.title = _t('Undefined'); + this.undefined_title = true; } - if (search_action) { - self.on_reload_kanban(); + this.aggregates = aggregates || {}; + var key = this.view.group_by + '-' + value; + if (!this.view.state.groups[key]) { + this.view.state.groups[key] = { + folded: false + } } - this.source_index = {}; + this.state = this.view.state.groups[key]; + this.$records = null; + this.records = _.map(records, function(record) { + return new openerp.web_kanban.KanbanRecord(self, record); + }); }, - on_reload_kanban: function (){ - var self = this; - _.each(self.all_display_data, function(data, index) { - if (data.records.length > 0){ - _.each(data.records, function(record) { - self.$element.find("#main_" + record.id).children().remove(); - self.$element.find("#main_" + record.id).append(self.qweb.render('kanban-box', { - record: self.do_transform_record(record), - kanban_color: self.kanban_color, - kanban_gravatar: self.kanban_gravatar - })); - }); - } + start: function() { + var self = this, + def = this._super(); + this.$records = $(QWeb.render('KanbanView.group_records_container', { widget : this})); + this.$records.appendTo(this.view.$element.find('.oe_kanban_groups_records')); + _.each(this.records, function(record) { + record.appendTo(self.$records); }); - this.$element.find('.oe_kanban_action').click(this.on_action_clicked); - this.$element.find('.oe_kanban_box_show_onclick_trigger').click(function() { - $(this).parent('.oe_kanban_box').find('.oe_kanban_box_show_onclick').toggle(); + this.$element.find(".oe_kanban_fold_icon").click(function() { + self.do_toggle_fold(); + self.view.compute_groups_width(); + return false; }); + if (this.state.folded) { + this.do_toggle_fold(); + } + this.$element.data('widget', this); + this.$records.data('widget', this); + return def; }, - on_action_clicked: function(evt) { - evt.preventDefault(); - var $action = $(evt.currentTarget), - record_id = parseInt($action.closest(".oe_kanban_record").attr("id").split('_')[1]), - type = $action.data('type'); - if (type == 'delete') { - this.do_delete(record_id); - } else if (type == 'edit') { - this.do_edit_record(record_id); - } else if (type == 'color') { - this.do_change_color(record_id, $action); - } else { - var button_attrs = $action.data(); - this.on_button_click(button_attrs, record_id); + stop: function() { + this._super(); + if (this.$records) { + this.$records.remove(); } }, - do_transform_record: function(record) { + remove_record: function(id, remove_from_dataset) { + for (var i = 0, ii = this.records.length; i < ii; i++) { + if (this.records[i]['id'] === id) { + this.records.splice(i, 1); + } + } + }, + do_toggle_fold: function(compute_width) { + this.$element.toggleClass('oe_kanban_group_folded'); + this.$records.find('.oe_kanban_record').toggle(); + this.state.folded = this.$element.is('.oe_kanban_group_folded'); + }, + do_save_sequences: function() { + var self = this; + if (_.indexOf(this.view.fields_keys, 'sequence') > -1) { + _.each(this.records, function(record, index) { + self.view.dataset.write(record.id, { sequence : index }); + }); + } + } +}); + +openerp.web_kanban.KanbanRecord = openerp.web.Widget.extend({ + template: 'KanbanView.record', + init: function (parent, record) { + this._super(parent); + this.group = parent; + this.view = parent.view; + this.id = null; + this.set_record(record); + if (!this.view.state.records[this.id]) { + this.view.state.records[this.id] = { + folded: false + }; + } + this.state = this.view.state.records[this.id]; + }, + set_record: function(record) { + this.id = record.id; + this.record = this.transform_record(record); + }, + start: function() { + this._super(); + this.$element.data('widget', this); + this.bind_events(); + }, + transform_record: function(record) { var self = this, new_record = {}; _.each(record, function(value, name) { - var r = _.clone(self.fields_view.fields[name]); + var r = _.clone(self.view.fields_view.fields[name]); r.raw_value = value; r.value = openerp.web.format_value(value, r); new_record[name] = r; }); return new_record; }, - do_search: function (domain, context, group_by) { - var self = this; - self.group_by = group_by; - var self = this, - group_by = self.group_by; - if (!group_by.length && this.fields_view.arch.attrs.default_group_by) { - group_by = [this.fields_view.arch.attrs.default_group_by]; - self.group_by = group_by; + render: function() { + var ctx = { + record: this.record, + widget: this } - self.datagroup = new openerp.web.DataGroup(self, self.model, domain, context, group_by); - self.datagroup.list( - _.keys(self.fields_view.fields), - function (groups) { - self.groups = groups; - if (groups.length) { - self.do_render_group(groups); - } else { - self.all_display_data = []; - self.on_show_data(); - } - }, - function (dataset) { - self.groups = []; - self.dataset.read_slice(_.keys(self.fields_view.fields), {}, function(records) { - if (records.length) { - self.all_display_data = [{'records': records, 'value':false, 'header' : false, 'ids': self.dataset.ids}]; - } else { - self.all_display_data = []; - } - self.$element.find(".oe_kanban_view").remove(); - self.on_show_data(); - }); + for (var p in this) { + if (_.startsWith(p, 'kanban_')) { + ctx[p] = _.bind(this[p], this); } - ); + } + return this._super({ + 'content': this.view.qweb.render('kanban-box', ctx) + }); }, - do_render_group : function (datagroups) { - this.all_display_data = []; - var self = this; - _.each(datagroups, function (group) { - var group_name = group.value; - var group_value = group.value; - if (!group.value) { - group_name = "Undefined"; - group_value = 'false'; - } else if (group.value instanceof Array) { - group_name = group.value[1]; - group_value = group.value[0]; + bind_events: function() { + var self = this, + $show_on_click = self.$element.find('.oe_kanban_box_show_onclick'); + $show_on_click.toggle(this.state.folded); + this.$element.find('.oe_kanban_box_show_onclick_trigger').click(function() { + $show_on_click.toggle(); + self.state.folded = !self.state.folded; + }); + this.$element.find('.oe_kanban_action').click(function() { + var $action = $(this), + type = $action.data('type') || 'button', + method = 'do_action_' + type; + if (typeof self[method] === 'function') { + self[method]($action); + } else { + self.do_warn("Kanban: no action for type : " + type); } - var group_aggregates = {}; - _.each(self.aggregates, function(value, key) { - group_aggregates[value] = group.aggregates[key]; + return false; + }); + }, + do_action_delete: function($action) { + var self = this; + if (confirm(_t("Are you sure you want to delete this record ?"))) { + return $.when(this.view.dataset.unlink([this.id])).then(function() { + self.group.remove_record(self.id) + self.stop(); }); - var dataset = new openerp.web.DataSetSearch(self, self.dataset.model, group.context, group.domain); - dataset.read_slice(_.keys(self.fields_view.fields), {'domain': group.domain, 'context': group.context}, function(records) { - self.all_display_data.push({"value" : group_value, "records": records, 'header':group_name, 'ids': dataset.ids, 'aggregates': group_aggregates}); - if (datagroups.length == self.all_display_data.length) { - self.$element.find(".oe_kanban_view").remove(); - self.on_show_data(); - } + } + }, + do_action_edit: function($action) { + var self = this; + if ($action.attr('target') === 'dialog') { + this.view.form_dialog.select_id(this.id).then(function() { + self.view.form_dialog.open(); + }); + } else { + if (self.view.dataset.select_id(this.id)) { + this.view.do_switch_view('form'); + } else { + this.do_warn("Kanban: could not find id#" + id); + } + } + }, + do_action_color: function($action) { + var self = this, + colors = '#FFFFFF,#CCCCCC,#FFC7C7,#FFF1C7,#E3FFC7,#C7FFD5,#C7FFFF,#C7D5FF,#E3C7FF,#FFC7F1'.split(','), + $cpicker = $(QWeb.render('KanbanColorPicker', { colors : colors, columns: 2 })); + $action.after($cpicker); + $cpicker.mouseenter(function() { + clearTimeout($cpicker.data('timeoutId')); + }).mouseleave(function(evt) { + var timeoutId = setTimeout(function() { $cpicker.remove() }, 500); + $cpicker.data('timeoutId', timeoutId); + }); + $cpicker.find('a').click(function() { + var data = {}; + data[$action.data('name')] = $(this).data('color'); + self.view.dataset.write(self.id, data, {}, function() { + self.record[$action.data('name')] = $(this).data('color'); + self.do_reload(); }); + $cpicker.remove(); + return false; }); }, - do_show: function () { - this.$element.show(); + do_action_object: function ($action) { + var button_attrs = $action.data(); + this.view.do_execute_action(button_attrs, this.view.dataset, this.id, this.do_reload); }, - do_hide: function () { - this.$element.hide(); + do_reload: function() { + var self = this; + this.view.dataset.read_ids([this.id], this.view.fields_keys, function(records) { + if (records.length) { + self.set_record(records[0]); + self.do_render(); + } else { + self.stop(); + } + }); + }, + do_render: function() { + this.$element.html(this.render()); + this.bind_events(); + }, + kanban_color: function(variable) { + var number_of_color_schemes = 10, + index = 0; + switch (typeof(variable)) { + case 'string': + for (var i=0, ii=variable.length; i<ii; i++) { + index += variable.charCodeAt(i); + } + break; + case 'number': + index = Math.round(variable); + break; + default: + return ''; + } + var color = (index % number_of_color_schemes); + return 'oe_kanban_color_' + color; + }, + kanban_gravatar: function(email, size) { + size = size || 22; + var email_md5 = $.md5(email); + return 'http://www.gravatar.com/avatar/' + email_md5 + '.png?s=' + size; + }, + kanban_image: function(model, field, id) { + id = id || ''; + return '/web/binary/image?session_id=' + this.session.session_id + '&model=' + model + '&field=' + field + '&id=' + id; + }, + kanban_text_ellipsis: function(s, size) { + size = size || 160; + if (!s) { + return ''; + } + return s.substr(0, size) + '...'; } }); }; diff --git a/addons/web_kanban/static/src/xml/web_kanban.xml b/addons/web_kanban/static/src/xml/web_kanban.xml index 8f3aaf457e9..c1346a0b90d 100644 --- a/addons/web_kanban/static/src/xml/web_kanban.xml +++ b/addons/web_kanban/static/src/xml/web_kanban.xml @@ -1,40 +1,50 @@ <template> <t t-name="KanbanView"> - <table style="width:100%;" class="oe_kanban_view"> - <tr> - <td> - <div class="oe_form_header"> - <button type="button" class="oe_kanban_button_new">New</button> - </div> - </td> - </tr> - <tr> - <td t-foreach="data" t-as="columns" class="oe_table_column" t-att-id="'column_' + columns.value"> - <img t-att-id="columns.value" class="fold-columns-icon" src="/web_kanban/static/src/img/minus-icon.png"/> - <div class="oe_fold_column" t-att-id="'column_' + columns.value"> - <div class="oe_column_heading" t-if="columns.value and columns.header"> - <t t-esc="columns.header"/> - </div> - <div t-foreach="columns.aggregates or {}" t-as="aggregate"> - <i><u><t t-esc="aggregate"/>:</u> <t t-esc="aggregate_value"/></i> + <div class="oe_kanban_header"> + <button type="button" class="oe_kanban_button_new">New</button> + </div> + <div class="oe_kanban_view"> + <table style="width:100%;" class="oe_kanban_groups"> + <tr class="oe_kanban_groups_headers"> + </tr> + <tr class="oe_kanban_groups_records"> + </tr> + </table> + </div> +</t> +<t t-name="KanbanView.group_header"> + <td class="oe_kanban_group_header"> + <t t-if="widget.view.group_by"> + <div class="oe_kanban_fold_icon"></div> + <div class="oe_fold_column"> + <div t-attf-class="oe_kanban_group_title #{widget.undefined_title ? 'oe_kanban_group_title_undefined' : ''}"> + <t t-esc="widget.title"/> </div> + <ul class="oe_kanban_aggregates"> + <li t-foreach="widget.aggregates" t-as="aggregate"> + <span><t t-esc="aggregate"/>:</span> <t t-esc="aggregate_value"/> + </li> + </ul> </div> - </td> - </tr> - <tr> - <td t-foreach="data" t-as="columns" class="oe_column oe_table_column" t-att-id="'column_' + columns.value" t-attf-style="width: #{Math.round(99 / data.length)}%"> - <p t-if="columns.header" class="oe_vertical_text" t-att-id="'column_' + columns.value"><t t-esc="columns.header"/></p> - <div t-foreach="columns.records" t-as="record" class="oe_fold_column oe_kanban_record" t-att-id="'main_' + record.id"/> - </td> - </tr> - </table> + <p t-if="widget.title" class="oe_kanban_group_title_vertical"><t t-esc="widget.title"/></p> + </t> + </td> +</t> +<t t-name="KanbanView.group_records_container"> + <td class="oe_kanban_column"> + </td> +</t> +<t t-name="KanbanView.record"> + <div class="oe_fold_column oe_kanban_record"> + <t t-raw="content"/> + </div> </t> <t t-name="KanbanColorPicker"> <table cellspacing="0" cellpadding="0" border="0" class="oe_kanban_color_picker"> <tr> <t t-foreach="colors" t-as="color"> <td t-att-bgcolor="color"> - <a href="#" t-att-data-color="color_index + 1"/> + <a href="#" t-att-data-color="color_index"/> </td> <t t-if="((color_index + 1) % Math.round(colors.length / columns)) == 0"></tr><tr></t> </t> diff --git a/addons/web_mobile/po/ar.po b/addons/web_mobile/po/ar.po new file mode 100644 index 00000000000..28e21aa44bf --- /dev/null +++ b/addons/web_mobile/po/ar.po @@ -0,0 +1,66 @@ +# Arabic translation for openerp-web +# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011 +# This file is distributed under the same license as the openerp-web package. +# FIRST AUTHOR <EMAIL@ADDRESS>, 2011. +# +msgid "" +msgstr "" +"Project-Id-Version: openerp-web\n" +"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n" +"POT-Creation-Date: 2011-10-07 10:39+0200\n" +"PO-Revision-Date: 2011-11-03 15:13+0000\n" +"Last-Translator: kifcaliph <kifcaliph@hotmail.com>\n" +"Language-Team: Arabic <ar@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: 2011-11-04 05:32+0000\n" +"X-Generator: Launchpad (build 14231)\n" + +#: addons/web_mobile/static/src/xml/web_mobile.xml:0 +msgid "OpenERP" +msgstr "OpenERP" + +#: addons/web_mobile/static/src/xml/web_mobile.xml:0 +msgid "Database:" +msgstr "قاعدة البيانات:" + +#: addons/web_mobile/static/src/xml/web_mobile.xml:0 +msgid "Login:" +msgstr "الدخول:" + +#: addons/web_mobile/static/src/xml/web_mobile.xml:0 +msgid "Password:" +msgstr "كلمة المرور:" + +#: addons/web_mobile/static/src/xml/web_mobile.xml:0 +msgid "Login" +msgstr "تسجيل الدخول" + +#: addons/web_mobile/static/src/xml/web_mobile.xml:0 +msgid "Bad username or password" +msgstr "اسم مستخدم او كلمة مرور خاطئة" + +#: addons/web_mobile/static/src/xml/web_mobile.xml:0 +msgid "Favourite" +msgstr "مفضّلة" + +#: addons/web_mobile/static/src/xml/web_mobile.xml:0 +msgid "Preference" +msgstr "التفضيلات" + +#: addons/web_mobile/static/src/xml/web_mobile.xml:0 +msgid "Applications" +msgstr "تطبيقات" + +#: addons/web_mobile/static/src/xml/web_mobile.xml:0 +msgid "Options" +msgstr "خيارات" + +#: addons/web_mobile/static/src/xml/web_mobile.xml:0 +msgid "Logout" +msgstr "تسجيل الخروج" + +#: addons/web_mobile/static/src/xml/web_mobile.xml:0 +msgid ":" +msgstr ":" diff --git a/addons/web_mobile/po/da.po b/addons/web_mobile/po/da.po index e0dbdc552d1..d61a3cba5b8 100644 --- a/addons/web_mobile/po/da.po +++ b/addons/web_mobile/po/da.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-10-12 04:44+0000\n" -"X-Generator: Launchpad (build 14124)\n" +"X-Launchpad-Export-Date: 2011-11-01 05:10+0000\n" +"X-Generator: Launchpad (build 14197)\n" #: addons/web_mobile/static/src/xml/web_mobile.xml:0 msgid "OpenERP" diff --git a/addons/web_mobile/po/de.po b/addons/web_mobile/po/de.po index 701026b9331..ab74249a7ba 100644 --- a/addons/web_mobile/po/de.po +++ b/addons/web_mobile/po/de.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-10-11 05:42+0000\n" -"X-Generator: Launchpad (build 14123)\n" +"X-Launchpad-Export-Date: 2011-11-01 05:10+0000\n" +"X-Generator: Launchpad (build 14197)\n" #: addons/web_mobile/static/src/xml/web_mobile.xml:0 msgid "OpenERP" diff --git a/addons/web_mobile/po/es.po b/addons/web_mobile/po/es.po index 9a9e02c4893..0995630c08e 100644 --- a/addons/web_mobile/po/es.po +++ b/addons/web_mobile/po/es.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-10-19 06:05+0000\n" -"X-Generator: Launchpad (build 14157)\n" +"X-Launchpad-Export-Date: 2011-11-01 05:10+0000\n" +"X-Generator: Launchpad (build 14197)\n" #: addons/web_mobile/static/src/xml/web_mobile.xml:0 msgid "OpenERP" diff --git a/addons/web_mobile/po/es_EC.po b/addons/web_mobile/po/es_EC.po index 5cff1023c4f..73dbcaea7e7 100644 --- a/addons/web_mobile/po/es_EC.po +++ b/addons/web_mobile/po/es_EC.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-10-08 05:30+0000\n" -"X-Generator: Launchpad (build 14110)\n" +"X-Launchpad-Export-Date: 2011-11-01 05:10+0000\n" +"X-Generator: Launchpad (build 14197)\n" #: addons/web_mobile/static/src/xml/web_mobile.xml:0 msgid "OpenERP" diff --git a/addons/web_mobile/po/et.po b/addons/web_mobile/po/et.po index 5b8d74c0c5b..c3e3994a9d9 100644 --- a/addons/web_mobile/po/et.po +++ b/addons/web_mobile/po/et.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-10-11 05:42+0000\n" -"X-Generator: Launchpad (build 14123)\n" +"X-Launchpad-Export-Date: 2011-11-01 05:10+0000\n" +"X-Generator: Launchpad (build 14197)\n" #: addons/web_mobile/static/src/xml/web_mobile.xml:0 msgid "OpenERP" diff --git a/addons/web_mobile/po/fr.po b/addons/web_mobile/po/fr.po index b64bcecfb1e..aead113ca02 100644 --- a/addons/web_mobile/po/fr.po +++ b/addons/web_mobile/po/fr.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-10-24 05:18+0000\n" -"X-Generator: Launchpad (build 14185)\n" +"X-Launchpad-Export-Date: 2011-11-01 05:10+0000\n" +"X-Generator: Launchpad (build 14197)\n" #: addons/web_mobile/static/src/xml/web_mobile.xml:0 msgid "OpenERP" diff --git a/addons/web_mobile/po/gl.po b/addons/web_mobile/po/gl.po index 4049dfb8d1f..482a3e05f58 100644 --- a/addons/web_mobile/po/gl.po +++ b/addons/web_mobile/po/gl.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-10-20 04:48+0000\n" -"X-Generator: Launchpad (build 14165)\n" +"X-Launchpad-Export-Date: 2011-11-01 05:10+0000\n" +"X-Generator: Launchpad (build 14197)\n" #: addons/web_mobile/static/src/xml/web_mobile.xml:0 msgid "OpenERP" diff --git a/addons/web_mobile/po/it.po b/addons/web_mobile/po/it.po index 8d155374c0a..fdfce4385f5 100644 --- a/addons/web_mobile/po/it.po +++ b/addons/web_mobile/po/it.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-10-09 05:22+0000\n" -"X-Generator: Launchpad (build 14110)\n" +"X-Launchpad-Export-Date: 2011-11-01 05:10+0000\n" +"X-Generator: Launchpad (build 14197)\n" #: addons/web_mobile/static/src/xml/web_mobile.xml:0 msgid "OpenERP" diff --git a/addons/web_mobile/po/nl_BE.po b/addons/web_mobile/po/nl_BE.po index f483032890b..0a1171f1fe9 100644 --- a/addons/web_mobile/po/nl_BE.po +++ b/addons/web_mobile/po/nl_BE.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-10-08 05:30+0000\n" -"X-Generator: Launchpad (build 14110)\n" +"X-Launchpad-Export-Date: 2011-11-01 05:10+0000\n" +"X-Generator: Launchpad (build 14197)\n" #: addons/web_mobile/static/src/xml/web_mobile.xml:0 msgid "OpenERP" diff --git a/addons/web_mobile/po/pl.po b/addons/web_mobile/po/pl.po new file mode 100644 index 00000000000..d5e04f22e00 --- /dev/null +++ b/addons/web_mobile/po/pl.po @@ -0,0 +1,66 @@ +# Polish translation for openerp-web +# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011 +# This file is distributed under the same license as the openerp-web package. +# FIRST AUTHOR <EMAIL@ADDRESS>, 2011. +# +msgid "" +msgstr "" +"Project-Id-Version: openerp-web\n" +"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n" +"POT-Creation-Date: 2011-10-07 10:39+0200\n" +"PO-Revision-Date: 2011-11-04 16:26+0000\n" +"Last-Translator: Grzegorz Grzelak (OpenGLOBE.pl) <grzegorz@openglobe.pl>\n" +"Language-Team: Polish <pl@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: 2011-11-05 06:04+0000\n" +"X-Generator: Launchpad (build 14231)\n" + +#: addons/web_mobile/static/src/xml/web_mobile.xml:0 +msgid "OpenERP" +msgstr "" + +#: addons/web_mobile/static/src/xml/web_mobile.xml:0 +msgid "Database:" +msgstr "Baza danych:" + +#: addons/web_mobile/static/src/xml/web_mobile.xml:0 +msgid "Login:" +msgstr "Login:" + +#: addons/web_mobile/static/src/xml/web_mobile.xml:0 +msgid "Password:" +msgstr "Hasło:" + +#: addons/web_mobile/static/src/xml/web_mobile.xml:0 +msgid "Login" +msgstr "Login" + +#: addons/web_mobile/static/src/xml/web_mobile.xml:0 +msgid "Bad username or password" +msgstr "Niepoprawna nazwa użytkownika lub hasło" + +#: addons/web_mobile/static/src/xml/web_mobile.xml:0 +msgid "Favourite" +msgstr "Ulubione" + +#: addons/web_mobile/static/src/xml/web_mobile.xml:0 +msgid "Preference" +msgstr "Preferencje" + +#: addons/web_mobile/static/src/xml/web_mobile.xml:0 +msgid "Applications" +msgstr "Aplikacje" + +#: addons/web_mobile/static/src/xml/web_mobile.xml:0 +msgid "Options" +msgstr "Opcje" + +#: addons/web_mobile/static/src/xml/web_mobile.xml:0 +msgid "Logout" +msgstr "Wyloguj" + +#: addons/web_mobile/static/src/xml/web_mobile.xml:0 +msgid ":" +msgstr "" diff --git a/addons/web_mobile/po/sk.po b/addons/web_mobile/po/sk.po index 5e10f135cf9..d550414317a 100644 --- a/addons/web_mobile/po/sk.po +++ b/addons/web_mobile/po/sk.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-10-24 05:18+0000\n" -"X-Generator: Launchpad (build 14185)\n" +"X-Launchpad-Export-Date: 2011-11-01 05:10+0000\n" +"X-Generator: Launchpad (build 14197)\n" #: addons/web_mobile/static/src/xml/web_mobile.xml:0 msgid "OpenERP" diff --git a/addons/web_mobile/po/sl.po b/addons/web_mobile/po/sl.po index 041141d4824..8141108f9a9 100644 --- a/addons/web_mobile/po/sl.po +++ b/addons/web_mobile/po/sl.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-10-20 04:48+0000\n" -"X-Generator: Launchpad (build 14165)\n" +"X-Launchpad-Export-Date: 2011-11-01 05:10+0000\n" +"X-Generator: Launchpad (build 14197)\n" #: addons/web_mobile/static/src/xml/web_mobile.xml:0 msgid "OpenERP" diff --git a/openerp-web.py b/openerp-web index fe33585a233..a3b3d2fa1d5 100755 --- a/openerp-web.py +++ b/openerp-web @@ -1,34 +1,29 @@ #!/usr/bin/env python +import json +import logging +import logging.config import optparse import os import sys -import json import tempfile -import logging -import logging.config import werkzeug.serving import werkzeug.contrib.fixers -path_root = os.path.dirname(os.path.abspath(__file__)) -path_addons = os.path.join(path_root, 'addons') -if path_addons not in sys.path: - sys.path.insert(0, path_addons) - optparser = optparse.OptionParser() optparser.add_option("-s", "--session-path", dest="session_storage", default=os.path.join(tempfile.gettempdir(), "oe-sessions"), - help="directory used for session storage", metavar="DIR") + help="Directory used for session storage", metavar="DIR") optparser.add_option("--server-host", dest="server_host", default='127.0.0.1', help="OpenERP server hostname", metavar="HOST") optparser.add_option("--server-port", dest="server_port", default=8069, help="OpenERP server port", type="int", metavar="NUMBER") optparser.add_option("--db-filter", dest="dbfilter", default='.*', - help="Filter listed database", metavar="REGEXP") -optparser.add_option('--addons-path', dest='addons_path', default=[path_addons], action='append', - help="Path do addons directory", metavar="PATH") + help="Filter listed databases", metavar="REGEXP") +optparser.add_option('--addons-path', dest='addons_path', default=[], action='append', + help="Path to addons directory", metavar="PATH") optparser.add_option('--load', dest='server_wide_modules', default=['web'], action='append', - help="Load a additional module before login (by default only 'web' is loaded)", metavar="MODULE") + help="Load an additional module before login (by default only 'web' is loaded)", metavar="MODULE") server_options = optparse.OptionGroup(optparser, "Server configuration") server_options.add_option("-p", "--port", dest="socket_port", default=8002, @@ -55,19 +50,39 @@ logging_opts.add_option("--log-config", dest="log_config", default=os.path.join( help="Logging configuration file", metavar="FILE") optparser.add_option_group(logging_opts) -import web.common.http if __name__ == "__main__": (options, args) = optparser.parse_args(sys.argv[1:]) - options.backend = 'xmlrpc' + if not options.addons_path: + path_root = os.path.dirname(os.path.abspath(__file__)) + path_addons = os.path.join(path_root, 'addons') + if os.path.exists(path_addons): + options.addons_path.append(path_addons) + + options.addons_path = [ + path[:-1] if path[-1] in r'\/' else path + for path in options.addons_path + if os.path.exists(path) + ] + + for path_addons in options.addons_path: + if path_addons not in sys.path: + sys.path.insert(0, path_addons) + + try: + import web.common.http + except ImportError: + optparser.error('Error Importing base web module. Check correctness of --addons-path.') + + options.backend = 'xmlrpc' os.environ["TZ"] = "UTC" - if sys.version_info >= (2, 7): + if sys.version_info >= (2, 7) and os.path.exists(options.log_config): with open(options.log_config) as file: dct = json.load(file) logging.config.dictConfig(dct) - logging.getLogger("").setLevel(getattr(logging, options.log_level.upper())) + logging.getLogger().setLevel(getattr(logging, options.log_level.upper())) else: logging.basicConfig(level=getattr(logging, options.log_level.upper())) diff --git a/setup.py b/setup.py index 374f7308ca8..3f108685f94 100755..100644 --- a/setup.py +++ b/setup.py @@ -1,113 +1,73 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>). -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. -# -############################################################################## -import glob, os, re, setuptools, sys -from os.path import join, isfile +import os +import re +import sys +from setuptools import setup, find_packages -# List all data files -def data(): - files = [] - for root, dirnames, filenames in os.walk('openerp'): - for filename in filenames: - if not re.match(r'.*(\.pyc|\.pyo|\~)$',filename): - files.append(os.path.join(root, filename)) - d = {} - for v in files: - k=os.path.dirname(v) - if k in d: - d[k].append(v) - else: - d[k]=[v] - r = d.items() - return r +execfile('addons/web/common/release.py') -def gen_manifest(): - file_list="\n".join(data()) - open('MANIFEST','w').write(file_list) +version_dash_incompatible = False +if 'bdist_rpm' in sys.argv: + version_dash_incompatible = True +try: + import py2exe + from py2exe_utils import opts + version_dash_incompatible = True +except ImportError: + opts = {} +if version_dash_incompatible: + version = version.split('-')[0] -def py2exe_options(): - if os.name == 'nt': - import py2exe - return { - "console" : [ { "script": "openerp-server", "icon_resources": [(1, join("pixmaps","openerp-icon.ico"))], }], - 'options' : { - "py2exe": { - "skip_archive": 1, - "optimize": 2, - "dist_dir": 'dist', - "packages": [ "DAV", "HTMLParser", "PIL", "asynchat", "asyncore", "commands", "dateutil", "decimal", "email", "encodings", "imaplib", "lxml", "lxml._elementpath", "lxml.builder", "lxml.etree", "lxml.objectify", "mako", "openerp", "poplib", "pychart", "pydot", "pyparsing", "reportlab", "select", "simplejson", "smtplib", "uuid", "vatnumber" "vobject", "xml", "xml", "xml.dom", "xml.xpath", "yaml", ], - "excludes" : ["Tkconstants","Tkinter","tcl"], - } - } - } - else: - return {} +FILE_PATTERNS = \ + r'.+\.(py|cfg|po|pot|mo|txt|rst|gif|png|jpg|ico|mako|html|js|css|htc|swf)$' +def find_data_files(source, patterns=FILE_PATTERNS): + file_matcher = re.compile(patterns, re.I) + out = [] + for base, _, files in os.walk(source): + cur_files = [] + for f in files: + if file_matcher.match(f): + cur_files.append(os.path.join(base, f)) + if cur_files: + out.append( + (base, cur_files)) -execfile(join(os.path.dirname(__file__), 'openerp', 'release.py')) + return out -setuptools.setup( - name = 'openerp', - version = version, - description = description, - long_description = long_desc, - url = url, - author = author, - author_email = author_email, - classifiers = filter(None, classifiers.split("\n")), - license = license, - scripts = ['openerp-server'], - data_files = data(), - packages = setuptools.find_packages(), - #include_package_data = True, - install_requires = [ - # TODO the pychart package we include in openerp corresponds to PyChart 1.37. - # It seems there is a single difference, which is a spurious print in generate_docs.py. - # It is probably safe to move to PyChart 1.39 (the latest one). - # (Let setup.py choose the latest one, and we should check we can remove pychart from - # our tree.) http://download.gna.org/pychart/ - # TODO 'pychart', - 'babel', - 'feedparser', - 'gdata', - 'lxml', - 'mako', - 'psycopg2', - 'pydot', - 'python-dateutil', - 'python-ldap', - 'python-openid', - 'pytz', - 'pywebdav', - 'pyyaml', - 'reportlab', - 'simplejson', - 'vatnumber', - 'vobject', - 'werkzeug', - 'zsi', - ], - extras_require = { - 'SSL' : ['pyopenssl'], - }, - **py2exe_options() +setup( + name=name, + version=version, + description=description, + long_description=long_description, + author=author, + author_email=author_email, + url=url, + download_url=download_url, + license=license, + install_requires=[ + "Babel >= 0.9.6", + "simplejson >= 2.0.9", + "python-dateutil >= 1.4.1", + "pytz", + "werkzeug == 0.7", + ], + tests_require=[ + 'unittest2', + 'mock', + ], + test_suite = 'unittest2.collector', + zip_safe=False, + packages=find_packages(), + classifiers=[ + 'Development Status :: 6 - Production/Stable', + 'Operating System :: OS Independent', + 'Programming Language :: Python', + 'Environment :: Web Environment', + 'Topic :: Office/Business :: Financial', + ], + scripts=['openerp-web'], + data_files=(find_data_files('addons') + + opts.pop('data_files', []) + ), + **opts ) - |
