diff --git a/app_base_chinese/__init__.py b/app_base_chinese/__init__.py
new file mode 100644
index 000000000..63a26a5ac
--- /dev/null
+++ b/app_base_chinese/__init__.py
@@ -0,0 +1,8 @@
+# -*- coding: utf-8 -*-
+
+from .hooks import pre_init_hook
+from .hooks import post_init_hook
+from . import controllers
+from . import models
+from . import ir
+from . import res
diff --git a/app_base_chinese/__manifest__.py b/app_base_chinese/__manifest__.py
new file mode 100644
index 000000000..5a9516bbd
--- /dev/null
+++ b/app_base_chinese/__manifest__.py
@@ -0,0 +1,130 @@
+# -*- coding: utf-8 -*-
+
+# Created on 2023-02-02
+# author: 欧度智能,https://www.odooai.cn
+# email: 300883@qq.com
+# resource of odooai
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+# Odoo在线中文用户手册(长期更新)
+# https://www.odooai.cn/documentation/user/10.0/zh_CN/index.html
+
+# Odoo10离线中文用户手册下载
+# https://www.odooai.cn/odoo10_user_manual_document_offline/
+# Odoo10离线开发手册下载-含python教程,jquery参考,Jinja2模板,PostgresSQL参考(odoo开发必备)
+# https://www.odooai.cn/odoo10_developer_document_offline/
+# description:
+
+
+{
+ 'name': 'odoo中文版套件之基础,中国会计基础,Chinese Enhance All in One,',
+ 'version': '17.0.24.12.27',
+ 'author': 'odooai.cn',
+ 'category': 'Base',
+ 'website': 'https://www.odooai.cn',
+ 'live_test_url': 'https://demo.odooapp.cn',
+ 'license': 'LGPL-3',
+ 'sequence': 2,
+ 'price': 0,
+ 'currency': 'EUR',
+ 'summary': '''
+ odoo简体中文版全面增强. Chinese enhance. Out of the box use odoo in china. Chinese address format, number format, money format.
+ Set all chinese default value. Default country, timezone, currency, partner.中国会计基础模块.
+ ''',
+ 'description': '''
+ odoo Chinese Enhance. odoo中国版增强-基础
+ 1. 中文地址格式,适用于所有中国中文客户、供应商、合作伙伴、用户、员工信息等
+ 2. 中文默认值,如国家、时区、货币等。处理模块 base, product.
+ 3. 客户加简称,地址显示中文化,客户编码显示优先
+ 4. 客户地址显示增加手机号与电话号码
+ 5. 货币处理,人民币增强,增加排序显示
+ 6. 修正品类的列表及m2o字段中不显示中文目录名的Bug
+ 7. 修正仓库位置的列表及m2o字段中不显示中文目录名的Bug
+ 8. 超级用户改时区为 中国
+ 9. 时间格式年月日为 中国格式,如 2023-08-08,时间为 12:34
+ 10. 国家增加排序,中国排第一
+ 11. 收款相关显示中国习惯
+ 12. 翻译导出默认中文,默认po
+ 13. [默认已移除,可自行加载.py]在 base 模型增加 name_en_US 字段,赋值后同时改翻译值
+ 14. 常用小数精度调整
+ 15. 销售团队改为中国
+ 16. 精简语言的显示,如 Chinese简体中文改为 中文
+ 21. 多语言支持,多公司支持
+ 22. Odoo 18,17,16,15,14,13,12, 企业版,社区版,在线SaaS.sh版,等全版本支持
+ 23. 代码完全开源
+ ======
+ 1. Chinese address format, applicable to all Chinese customers, suppliers, partners, users, employee information etc.
+ 2. Default values in Chinese such as country, time zone and currency. Processing module base, product.
+ 3. Add customer abbreviation and display addresses in Chinese; prioritize displaying customer codes.
+ 4. Display phone numbers along with mobile numbers for customer addresses.
+ 5. Currency processing with added sorting display.
+ 6. Fixed bug where the category list and m2o field did not display the name of the Chinese directory.
+ 7. Fixed bug where warehouse location list and m2o field did not display the name of the Chinese directory.
+ 8. Superuser changed time zone to China.
+ 9. Date format is year-month-day (e.g., 2023-08-08) and time is 12:34
+ 10.Country sorting added; China ranked first
+ 11.Display payment-related information according to typical practices in China.
+ 12.Default export translation is set to Mandarin (po).
+ 13.Added 'name_en_US' field in base model which updates translation value when assigned a value.
+ 14.Common decimal precision adjustments made.
+ 15.Sales team changed to [China].
+ 21. Multi-language Support. Multi-Company Support.
+ 22. Support Odoo 18,17,16,15,14,13,12, Enterprise and Community and odoo.sh Edition.
+ 23. Full Open Source.
+ ''',
+ 'pre_init_hook': 'pre_init_hook',
+ 'post_init_hook': 'post_init_hook',
+ 'depends': [
+ 'base_address_extended',
+ 'account',
+ 'sales_team',
+ 'sale',
+ 'stock',
+ 'app_odoo_customize',
+ ],
+ 'images': ['static/description/banner.jpg'],
+ 'data': [
+ 'views/res_partner_views.xml',
+ 'views/res_currency_views.xml',
+ 'views/sale_order_views.xml',
+ 'views/account_move_views.xml',
+ 'views/ir_default_views.xml',
+ # 'views/templates.xml',
+ 'wizard/sale_make_invoice_advance_views.xml',
+ 'data/res_lang_data.xml',
+ 'data/ir_default_data.xml',
+ 'data/base_data.xml',
+ 'data/decimal_precision_data.xml',
+ 'data/res_country_data.xml',
+ 'data/res_currency_data.xml',
+ 'data/res_company_data.xml',
+ 'data/res_partner_data.xml',
+ 'data/res_users_data.xml',
+ 'data/product_data.xml',
+ 'data/product_pricelist_data.xml',
+ 'data/stock_location_data.xml',
+ 'data/sales_team_data.xml',
+ 'views/ir_module_module_views.xml',
+ ],
+ 'assets': {
+ 'web.assets_backend': [
+ 'app_base_chinese/static/src/scss/app_style.scss',
+ ]
+ },
+ 'demo': [
+ 'demo/res_company_demo.xml',
+ 'demo/res_partner_demo.xml',
+ ],
+ 'test': [
+ ],
+ 'css': [
+ ],
+ 'qweb': [
+ 'static/src/xml/*.xml',
+ ],
+ 'js': [
+ ],
+ 'installable': True,
+ 'application': True,
+ 'auto_install': False,
+}
diff --git a/app_base_chinese/controllers/__init__.py b/app_base_chinese/controllers/__init__.py
new file mode 100644
index 000000000..4e65ea1a3
--- /dev/null
+++ b/app_base_chinese/controllers/__init__.py
@@ -0,0 +1,3 @@
+# -*- coding: utf-8 -*-
+
+from . import database
diff --git a/app_base_chinese/controllers/database.py b/app_base_chinese/controllers/database.py
new file mode 100644
index 000000000..2c63da28b
--- /dev/null
+++ b/app_base_chinese/controllers/database.py
@@ -0,0 +1,49 @@
+# -*- coding: utf-8 -*-
+
+import os
+import re
+from lxml import html
+import odoo
+import odoo.modules.registry
+from odoo import http
+from odoo.exceptions import AccessError
+from odoo.http import content_disposition, dispatch_rpc, request, Response
+from odoo.service import db
+from odoo.tools.misc import file_open, str2bool
+from odoo.addons.web.controllers.database import Database as Database
+from odoo.addons.base.models.ir_qweb import render as qweb_render
+
+DBNAME_PATTERN = '^[a-zA-Z0-9][a-zA-Z0-9_.-]+$'
+
+
+class Database(Database):
+
+ def _render_template(self, **d):
+ d.setdefault('manage', True)
+ d['insecure'] = odoo.tools.config.verify_admin_password('admin')
+ d['list_db'] = odoo.tools.config['list_db']
+ d['langs'] = odoo.service.db.exp_list_lang()
+ d['countries'] = odoo.service.db.exp_list_countries()
+ d['pattern'] = DBNAME_PATTERN
+ # databases list
+ try:
+ d['databases'] = http.db_list()
+ d['incompatible_databases'] = odoo.service.db.list_db_incompatible(d['databases'])
+ except odoo.exceptions.AccessDenied:
+ d['databases'] = [request.db] if request.db else []
+
+ templates = {}
+
+ with file_open("web/static/src/public/database_manager.qweb.html", "r") as fd:
+ templates['database_manager'] = fd.read()
+ with file_open("web/static/src/public/database_manager.master_input.qweb.html", "r") as fd:
+ templates['master_input'] = fd.read()
+ # with file_open("web/static/src/public/database_manager.create_form.qweb.html", "r") as fd:
+ with file_open("app_base_chinese/static/src/public/database_manager.create_form.qweb.html", "r") as fd:
+ templates['create_form'] = fd.read()
+
+ def load(template_name):
+ fromstring = html.document_fromstring if template_name == 'database_manager' else html.fragment_fromstring
+ return (fromstring(templates[template_name]), template_name)
+
+ return qweb_render('database_manager', d, load)
diff --git a/app_base_chinese/data/base_data.xml b/app_base_chinese/data/base_data.xml
new file mode 100644
index 000000000..20a794384
--- /dev/null
+++ b/app_base_chinese/data/base_data.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+ 欧度智能
+
+
+
+
+ 欧度智能
+
+
+
+ 超管
+
+
+
diff --git a/app_base_chinese/data/crm_team_data.xml b/app_base_chinese/data/crm_team_data.xml
new file mode 100644
index 000000000..19feb4351
--- /dev/null
+++ b/app_base_chinese/data/crm_team_data.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/app_base_chinese/data/decimal_precision_data.xml b/app_base_chinese/data/decimal_precision_data.xml
new file mode 100644
index 000000000..69354c372
--- /dev/null
+++ b/app_base_chinese/data/decimal_precision_data.xml
@@ -0,0 +1,14 @@
+
+
+
+
+ 0
+
+
+ 2
+
+
+ 3
+
+
+
\ No newline at end of file
diff --git a/app_base_chinese/data/ir_default_data.xml b/app_base_chinese/data/ir_default_data.xml
new file mode 100644
index 000000000..34ee2ce6d
--- /dev/null
+++ b/app_base_chinese/data/ir_default_data.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app_base_chinese/data/product_data.xml b/app_base_chinese/data/product_data.xml
new file mode 100644
index 000000000..23e214568
--- /dev/null
+++ b/app_base_chinese/data/product_data.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app_base_chinese/data/product_pricelist_data.xml b/app_base_chinese/data/product_pricelist_data.xml
new file mode 100644
index 000000000..6baeabd17
--- /dev/null
+++ b/app_base_chinese/data/product_pricelist_data.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
diff --git a/app_base_chinese/data/res_company_data.xml b/app_base_chinese/data/res_company_data.xml
new file mode 100644
index 000000000..239ab2591
--- /dev/null
+++ b/app_base_chinese/data/res_company_data.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/app_base_chinese/data/res_country_data.xml b/app_base_chinese/data/res_country_data.xml
new file mode 100644
index 000000000..6a046c5d3
--- /dev/null
+++ b/app_base_chinese/data/res_country_data.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app_base_chinese/data/res_currency_data.xml b/app_base_chinese/data/res_currency_data.xml
new file mode 100644
index 000000000..d6def48b2
--- /dev/null
+++ b/app_base_chinese/data/res_currency_data.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ 元
+ 分
+ before
+
+
+
diff --git a/app_base_chinese/data/res_lang_data.xml b/app_base_chinese/data/res_lang_data.xml
new file mode 100644
index 000000000..cb4b2e4d0
--- /dev/null
+++ b/app_base_chinese/data/res_lang_data.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+ 中文
+ %Y-%m-%d
+ %H:%M:%S
+ True
+
+
+ English
+
+
+
diff --git a/app_base_chinese/data/res_partner_data.xml b/app_base_chinese/data/res_partner_data.xml
new file mode 100644
index 000000000..df834a0ea
--- /dev/null
+++ b/app_base_chinese/data/res_partner_data.xml
@@ -0,0 +1,8 @@
+
+
+
+
+ 公共访客用户
+
+
+
diff --git a/app_base_chinese/data/res_users_data.xml b/app_base_chinese/data/res_users_data.xml
new file mode 100644
index 000000000..a6732e1bd
--- /dev/null
+++ b/app_base_chinese/data/res_users_data.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app_base_chinese/data/sales_team_data.xml b/app_base_chinese/data/sales_team_data.xml
new file mode 100644
index 000000000..007a20fe0
--- /dev/null
+++ b/app_base_chinese/data/sales_team_data.xml
@@ -0,0 +1,11 @@
+
+
+
+
+ 中国
+
+
+ China
+
+
+
diff --git a/app_base_chinese/data/stock.location.csv b/app_base_chinese/data/stock.location.csv
new file mode 100644
index 000000000..7c599d1de
--- /dev/null
+++ b/app_base_chinese/data/stock.location.csv
@@ -0,0 +1,7 @@
+id,name
+stock.stock_location_locations_partner,往来单位
+stock.stock_location_customers,客户区位
+stock.stock_location_suppliers,供应商区位
+stock.stock_location_locations,物理区位
+stock.stock_location_locations_virtual,虚拟区位
+stock.stock_location_inter_wh,内部中转区位
diff --git a/app_base_chinese/data/stock_location_data.xml b/app_base_chinese/data/stock_location_data.xml
new file mode 100644
index 000000000..ec2652431
--- /dev/null
+++ b/app_base_chinese/data/stock_location_data.xml
@@ -0,0 +1,51 @@
+
+
+
+
+ 先进先出(FIFO)
+
+
+ 后进先出(LIFO)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app_base_chinese/demo/base_demo.xml b/app_base_chinese/demo/base_demo.xml
new file mode 100644
index 000000000..89c6ac05d
--- /dev/null
+++ b/app_base_chinese/demo/base_demo.xml
@@ -0,0 +1,90 @@
+
+
+
+
+
+ Demo User
+
+
+ demo@yourcompany.example.com
+ YourCompany
+ Avenue des Dessus-de-Lives, 2
+ Namur (Loyers)
+ 5101
+
+
+
+
+ 60-16-13 31926819
+ bank
+
+
+
+
+ YourCompany
+ YourCompany
+ 1725 Slough Ave.
+ Scranton
+ 18540
+
+
+ +1 555 123 8069
+ info@yourcompany.example.com
+ www.example.com
+
+
+
+
+ YourCompany
+ standard
+
+
+
+
+ demo
+ demo
+ -- +Mr Demo
+
+
+
+
+
+
+ YourCompany
+ 215 Vine St
+ Scranton
+ 18503
+
+
+ +1 555-555-5555
+ admin@yourcompany.example.com
+ Europe/Brussels
+
+
+
+
+
+
+ Demo Portal User
+ demo.portal@yourcompany.example.com
+
+
+ Vivegnis
+ 4683
+
+ YourCompany
+ Rue Cesar de Paepe, 43
+
+
+
+ portal
+ portal
+ -- Mr Demo Portal]]>
+
+
+
+
+
+
+
+
diff --git a/app_base_chinese/demo/product_demo.xml b/app_base_chinese/demo/product_demo.xml
new file mode 100644
index 000000000..2a8e9305b
--- /dev/null
+++ b/app_base_chinese/demo/product_demo.xml
@@ -0,0 +1,738 @@
+
+
+
+
+
+
+ Internal
+
+
+
+ Services
+
+
+
+ Software
+
+
+
+ Physical
+
+
+
+ Prepaid Consulting
+
+ 40
+ 90
+ service
+
+
+ Example of product to invoice on order.
+ SERV_ORDER
+
+
+
+ Cost-plus Contract
+
+ 200.0
+ 180.0
+ service
+
+
+ SERV_DEL
+
+
+
+ External Audit
+
+ 160
+ 180
+ service
+
+
+ Example of products to invoice based on cost.
+ SERV_COST
+
+
+
+ Switch, 24 ports
+
+ 55.0
+ 70.0
+ consu
+
+
+ PROD_DEL
+
+
+
+ Datacard
+
+ 35.0
+ 40.0
+ consu
+
+
+ PROD_DEL02
+
+
+
+ Zed+ Antivirus
+
+ 235.0
+ 280.0
+ consu
+
+
+ PROD_ORDER
+
+
+
+ GAP Analysis Service
+
+ 20.5
+ 30.75
+ service
+
+
+ Example of products to invoice based on delivery.
+
+
+
+ Support Services
+
+ 25.5
+ 38.25
+ service
+
+
+ Example of product to invoice based on delivery.
+
+
+
+
+ Computer SC234
+
+ 450.0
+ 300.0
+ consu
+
+
+ 17" LCD Monitor
Processor AMD 8-Core
+ PCSC234
+
+
+
+
+
+ Memory
+
+
+ 16 GB
+
+
+
+ 32 GB
+
+
+
+
+ Color
+
+
+ White
+
+
+
+ Black
+
+
+
+
+ Wi-Fi
+
+
+ 2.4 GHz
+
+
+
+
+ iPad Retina Display
+
+ 500.0
+ 750.0
+ consu
+
+
+ 7.9‑inch (diagonal) LED-backlit, 128Gb
Dual-core A5 with quad-core graphics
FaceTime HD Camera, 1.2 MP Photos
+ E-COM01
+
+
+
+ E-COM02
+
+
+
+
+ E-COM03
+
+
+
+
+ E-COM04
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 50.40
+
+
+
+ Bose Mini Bluetooth Speaker
+
+ 140.0
+ 247.0
+ consu
+
+
+ Bose's smallest portable Bluetooth speaker
+ E-COM05
+
+
+
+
+ Custom Computer (kit)
+
+ 600.0
+ 147.0
+ consu
+
+
+ Custom computer shipped in kit.
+ E-COM06
+
+
+ Parts Replacement
+
+ 600.0
+ 147.0
+ service
+
+
+
+ iPad Mini
+
+ 800.0
+ 320.0
+ consu
+
+
+ E-COM07
+ 0.330
+
+
+
+ Repair
+
+ 800.0
+ 320.0
+ service
+
+
+ Apple In-Ear Headphones
+
+ 70.0
+ 79.0
+ consu
+
+
+ E-COM08
+
+
+
+ iMac
+
+ 1299.0
+ 1799.0
+ consu
+
+
+ E-COM09
+ 9.54
+
+
+
+ Apple Wireless Keyboard
+
+ 10.0
+ 47.0
+ consu
+
+
+ E-COM10
+
+
+
+ Mouse, Optical
+
+ 12.50
+ 14
+ consu
+
+
+ E-COM11
+
+
+
+ iPod
+
+ 14
+ 16.50
+ consu
+
+
+ E-COM12
+
+
+
+ E-COM13
+
+
+
+
+ Cleaning
+
+ 14
+ 16.50
+ service
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 6.40
+
+
+
+
+
+ Mouse, Wireless
+
+ 18
+ 12.50
+ consu
+
+
+ M-Wir
+
+
+
+ RAM SR5
+
+ 78.0
+ 85.0
+ consu
+
+
+ RAM-SR5
+
+
+
+ Computer Case
+
+ 20.0
+ 25.0
+ consu
+
+
+ C-Case
+
+
+
+ HDD SH-1
+
+ 860.0
+ 975.0
+ consu
+
+
+ HDD-SH1
+
+
+
+ Motherboard I9P57
+
+ 1700.0
+ 1950.0
+ consu
+
+
+ MBi9
+
+
+ Processor Core i5 2.70 Ghz
+
+ 2010.0
+ 2100.0
+ consu
+
+
+ CPUi5
+
+
+
+ Graphics Card
+
+ 876.0
+ 885.0
+ consu
+
+
+ CARD
+
+
+
+ Laptop E5023
+
+ 2870.0
+ 2950.0
+ consu
+
+
+ 17" Monitor, 4GB RAM
Standard-1294P Processor
+ LAP-E5
+
+
+
+ Laptop Customized
+
+ 3300.0
+ 3645.0
+ consu
+
+
+ Custom Laptop based on customer's requirement.
+ LAP-CUS
+
+
+
+ Basic Computer
+
+ 25000.0
+ 23500.0
+ consu
+
+
+ Dvorak keyboard
left-handed mouse
+ CONS_DEL03
+
+
+
+ Little server
+
+ 45000.0
+ 40000.0
+ consu
+
+
+ raid 1, 512ECC ram
+ CONS_DEL02
+
+
+
+ Server
+
+ 65000.0
+ 60000.0
+ consu
+
+
+ raid 10, 2048ECC ram
+ CONS_DEL01
+
+
+
+
+
+ Gold Membership
+ 180
+
+ service
+
+
+
+
+ Silver Membership
+
+ 80
+ service
+
+
+
+
+ Basic Membership
+
+ 40
+ service
+
+
+
+
+
+
+
+
+ 3
+ 1
+ 750
+
+
+
+
+
+ 3
+ 1
+ 790
+
+
+
+
+
+ 3
+ 3
+ 785
+
+
+
+
+
+ 3
+ 1
+ 65
+
+
+
+
+
+ 3
+ 1
+ 72
+
+
+
+
+
+ 2
+ 5
+ 1299
+
+
+
+
+
+ 4
+ 1
+ 1399
+
+
+
+
+
+ 2
+ 1
+ 12.50
+
+
+
+
+
+ 2
+ 1
+ 14
+
+
+
+
+
+ 5
+ 1
+ 78
+
+
+
+
+
+ 1
+ 1
+ 20
+
+
+
+
+
+ 3
+ 1
+ 860
+
+
+
+
+
+ 3
+ 1
+ 1700
+
+
+
+
+
+ 4
+ 5
+ 1720
+
+
+
+
+
+ 3
+ 1
+ 2010
+
+
+
+
+
+ 3
+ 1
+ 876
+
+
+
+
+
+ 8
+ 1
+ 2870
+
+
+
+
+
+ 4
+ 1
+ 390
+
+
+
+
+
+ 2
+ 12
+ 90
+
+
+
+
+
+ 4
+ 1
+ 66
+
+
+
+
+
+ 5
+ 1
+ 35
+
+
+
+
+
+ 7
+ 1
+ 55
+
+
+
+
+
+ 4
+ 0
+ 10
+
+
+
+
+
+ 10
+ 0
+ 3300
+
+
+
+
+
+ 3
+ 0
+ 12.50
+
+
+
+
+
+ 2
+ 0
+ 13.50
+
+
+
+ property_product_pricelist
+
+
+
+
+
+
+
+
diff --git a/app_base_chinese/demo/product_image_demo.xml b/app_base_chinese/demo/product_image_demo.xml
new file mode 100644
index 000000000..ab98b4a70
--- /dev/null
+++ b/app_base_chinese/demo/product_image_demo.xml
@@ -0,0 +1,110 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app_base_chinese/demo/res_bank_demo.xml b/app_base_chinese/demo/res_bank_demo.xml
new file mode 100644
index 000000000..bd563fc68
--- /dev/null
+++ b/app_base_chinese/demo/res_bank_demo.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+ ING
+ BBRUBEBB
+
+
+
+ Crelan
+ NICABEBB
+
+
+
+ CBC
+ CREGBEBB
+
+
+
+
diff --git a/app_base_chinese/demo/res_company_demo.xml b/app_base_chinese/demo/res_company_demo.xml
new file mode 100644
index 000000000..801999c6b
--- /dev/null
+++ b/app_base_chinese/demo/res_company_demo.xml
@@ -0,0 +1,8 @@
+
+
+
+
+ odooAi欧度智能
+
+
+
diff --git a/app_base_chinese/demo/res_partner_demo.xml b/app_base_chinese/demo/res_partner_demo.xml
new file mode 100644
index 000000000..247ba9d41
--- /dev/null
+++ b/app_base_chinese/demo/res_partner_demo.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+ info@odooai.cn
+ www.odooai.cn
+
+
+
+
diff --git a/app_base_chinese/demo/res_partner_image_demo.xml b/app_base_chinese/demo/res_partner_image_demo.xml
new file mode 100644
index 000000000..9186c569f
--- /dev/null
+++ b/app_base_chinese/demo/res_partner_image_demo.xml
@@ -0,0 +1,98 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app_base_chinese/hooks.py b/app_base_chinese/hooks.py
new file mode 100644
index 000000000..6a38a7e77
--- /dev/null
+++ b/app_base_chinese/hooks.py
@@ -0,0 +1,63 @@
+# -*- coding: utf-8 -*-
+
+# Created on 2017-11-22
+# author: 欧度智能,https://www.odooai.cn
+# email: 300883@qq.com
+# resource of odooai
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+# Odoo在线中文用户手册(长期更新)
+# https://www.odooai.cn/documentation/user/10.0/zh_CN/index.html
+
+# Odoo10离线中文用户手册下载
+# https://www.odooai.cn/odoo10_user_manual_document_offline/
+# Odoo10离线开发手册下载-含python教程,jquery参考,Jinja2模板,PostgresSQL参考(odoo开发必备)
+# https://www.odooai.cn/odoo10_developer_document_offline/
+# description:
+
+from odoo import api, SUPERUSER_ID, _
+
+
+def pre_init_hook(env):
+ """
+ 数据初始化,只在安装时执行,更新时不执行
+ """
+ # todo: 启用中文
+ pass
+
+
+def post_init_hook(env):
+ """
+ 数据初始化,只在安装后执行,更新时不执行
+ """
+ try:
+ ids = env['product.category'].sudo().with_context(lang='zh_CN', active_test=False).search([
+ ('parent_id', '!=', False)
+ ], order='parent_path')
+ for rec in ids:
+ rec._compute_complete_name()
+ ids = env['stock.location'].sudo().with_context(lang='zh_CN', active_test=False).search([
+ ('location_id', '!=', False),
+ ('usage', '!=', 'views'),
+ ], order='parent_path')
+ for rec in ids:
+ rec._compute_complete_name()
+ # 超级用户改时区为中国
+ ids = env['res.users'].sudo().with_context(lang='zh_CN', active_test=False).browse([1, 2])
+ ids.write({'tz': "Etc/GMT-8"})
+ # 公司价格改人民币
+ ids = env['res.company'].sudo().search([], limit=1)
+ if ids:
+ ids.write({'currency_id': env.ref('base.CNY').id})
+ # 价格表改人民币
+ ids = env['product.pricelist'].sudo().search([], limit=1)
+ if ids:
+ ids.write({'currency_id': env.ref('base.CNY').id})
+ except Exception as e:
+ raise Warning(e)
+
+def uninstall_hook(env):
+ """
+ 数据初始化,卸载时执行
+ """
+ pass
diff --git a/app_base_chinese/i18n/zh_CN.po b/app_base_chinese/i18n/zh_CN.po
new file mode 100644
index 000000000..54bad14d7
--- /dev/null
+++ b/app_base_chinese/i18n/zh_CN.po
@@ -0,0 +1,128 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * app_base_chinese
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 16.0+e-20221228\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2023-02-14 08:50+0000\n"
+"PO-Revision-Date: 2023-02-14 08:50+0000\n"
+"Last-Translator: \n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: \n"
+
+#. module: app_base_chinese
+#: model:ir.model.fields,field_description:app_base_chinese.field_account_tax_group__active
+msgid "Active"
+msgstr "激活"
+
+#. module: app_base_chinese
+#: model:ir.model,name:app_base_chinese.model_res_company
+msgid "Companies"
+msgstr "公司"
+
+#. module: app_base_chinese
+#: model:ir.model,name:app_base_chinese.model_res_partner
+msgid "Contact"
+msgstr "联系人"
+
+#. module: app_base_chinese
+#: model_terms:ir.ui.view,arch_db:app_base_chinese.app_res_partner_kanban_view
+msgid "Credit:"
+msgstr "信用额:"
+
+#. module: app_base_chinese
+#: model:ir.model,name:app_base_chinese.model_res_currency
+msgid "Currency"
+msgstr "币种"
+
+#. module: app_base_chinese
+#: model:ir.model.fields,help:app_base_chinese.field_res_currency__sequence
+msgid "Determine the display order. Sort ascending."
+msgstr "决定显示顺序,数字越小排序越前"
+
+#. module: app_base_chinese
+#: model_terms:ir.ui.view,arch_db:app_base_chinese.app_view_sale_advance_payment_inv
+msgid "FaPiao / Invoice Orders"
+msgstr "创建收据/发票"
+
+#. module: app_base_chinese
+#: model:ir.model.fields,field_description:app_base_chinese.field_res_partner__fax
+#: model:ir.model.fields,field_description:app_base_chinese.field_res_users__fax
+msgid "Fax"
+msgstr "传真"
+
+#. module: app_base_chinese
+#: model:ir.model.fields,field_description:app_base_chinese.field_stock_location__complete_name
+msgid "Full Location Name"
+msgstr "完整的位置名称"
+
+#. module: app_base_chinese
+#: model:ir.model,name:app_base_chinese.model_stock_location
+msgid "Inventory Locations"
+msgstr "库存位置"
+
+#. module: app_base_chinese
+#: model_terms:ir.ui.view,arch_db:app_base_chinese.app_view_order_form
+msgid "Invoices/FaPiao"
+msgstr "收据/发票"
+
+#. module: app_base_chinese
+#: model_terms:ir.ui.view,arch_db:app_base_chinese.app_view_order_form
+msgid "Make Collections"
+msgstr "收款"
+
+#. module: app_base_chinese
+#: model:ir.model.fields,field_description:app_base_chinese.field_res_partner__name
+#: model:ir.model.fields,field_description:app_base_chinese.field_res_users__name
+msgid "Name"
+msgstr "名称"
+
+#. module: app_base_chinese
+#: model_terms:ir.ui.view,arch_db:app_base_chinese.app_view_move_form
+msgid "Post Entry"
+msgstr "过帐"
+
+#. module: app_base_chinese
+#: model:ir.model,name:app_base_chinese.model_product_category
+msgid "Product Category"
+msgstr "品类"
+
+#. module: app_base_chinese
+#: model:ir.model.fields,field_description:app_base_chinese.field_res_currency__sequence
+msgid "Sequence"
+msgstr "排序"
+
+#. module: app_base_chinese
+#: model:ir.model.fields,help:app_base_chinese.field_account_tax_group__active
+msgid "Set active to false to hide the tax without removing it."
+msgstr "请不要删除指定税率,可以将其归档。"
+
+#. module: app_base_chinese
+#: model:ir.model.fields,field_description:app_base_chinese.field_res_partner__short_name
+#: model:ir.model.fields,field_description:app_base_chinese.field_res_users__short_name
+msgid "Short Name"
+msgstr "简称"
+
+#. module: app_base_chinese
+#: model:ir.model,name:app_base_chinese.model_account_tax_group
+msgid "Tax Group"
+msgstr "税组"
+
+#. module: app_base_chinese
+#. odoo-javascript
+#: code:addons/app_base_chinese/static/src/xml/views.xml:0
+#, python-format
+msgid "性能原因,只支持 200 条记录的显示"
+msgstr ""
+
+#. module: app_base_chinese
+#. odoo-javascript
+#: code:addons/app_base_chinese/static/src/xml/views.xml:0
+#, python-format
+msgid "记录没有树状结构"
+msgstr ""
diff --git a/app_base_chinese/ir/__init__.py b/app_base_chinese/ir/__init__.py
new file mode 100644
index 000000000..40a96afc6
--- /dev/null
+++ b/app_base_chinese/ir/__init__.py
@@ -0,0 +1 @@
+# -*- coding: utf-8 -*-
diff --git a/app_base_chinese/models/__init__.py b/app_base_chinese/models/__init__.py
new file mode 100644
index 000000000..b57e968ea
--- /dev/null
+++ b/app_base_chinese/models/__init__.py
@@ -0,0 +1,12 @@
+# -*- coding: utf-8 -*-
+
+from . import res_company
+from . import res_country
+from . import res_partner
+from . import res_currency
+from . import product_category
+from . import stock_location
+from . import account_tax_group
+from . import ir_module_module
+
+
diff --git a/app_base_chinese/models/account_tax_group.py b/app_base_chinese/models/account_tax_group.py
new file mode 100644
index 000000000..d14133591
--- /dev/null
+++ b/app_base_chinese/models/account_tax_group.py
@@ -0,0 +1,9 @@
+# -*- coding: utf-8 -*-
+
+from odoo import api, fields, models, _, tools
+
+class AccountTaxGroup(models.Model):
+ _inherit = 'account.tax.group'
+
+ active = fields.Boolean(default=True, help="Set active to false to hide the tax without removing it.")
+
diff --git a/app_base_chinese/models/ir_module_module.py b/app_base_chinese/models/ir_module_module.py
new file mode 100644
index 000000000..3bdb3c1d2
--- /dev/null
+++ b/app_base_chinese/models/ir_module_module.py
@@ -0,0 +1,33 @@
+# -*- coding: utf-8 -*-
+
+import logging
+import lxml.html
+from odoo import api, fields, models, modules, tools, _
+
+_logger = logging.getLogger(__name__)
+
+
+class Module(models.Model):
+ _inherit = "ir.module.module"
+
+ description_html_cn = fields.Html('Description HTML CN', compute='_get_desc_cn')
+
+ @api.depends('name', 'description')
+ def _get_desc_cn(self):
+ for module in self:
+ module_path = modules.get_module_path(module.name, display_warning=False) # avoid to log warning for fake community module
+ if module_path:
+ path = modules.check_resource_path(module_path, 'static/description/index_cn.html')
+ else:
+ module.description_html_cn = False
+ if module_path and path:
+ # 注意: b 不能在 mode中才能使用 utf-8
+ with tools.file_open(path, 'r') as desc_file:
+ doc = desc_file.read()
+ html = lxml.html.document_fromstring(doc)
+ for element, attribute, link, pos in html.iterlinks():
+ if element.get('src') and not '//' in element.get('src') and not 'static/' in element.get('src'):
+ element.set('src', "/%s/static/description/%s" % (module.name, element.get('src')))
+ module.description_html_cn = tools.html_sanitize(lxml.html.tostring(html))
+ else:
+ module.description_html_cn = False
diff --git a/app_base_chinese/models/product_category.py b/app_base_chinese/models/product_category.py
new file mode 100644
index 000000000..22ce37519
--- /dev/null
+++ b/app_base_chinese/models/product_category.py
@@ -0,0 +1,12 @@
+# -*- coding: utf-8 -*-
+
+import logging
+
+from odoo import api, fields, models, _
+
+_logger = logging.getLogger(__name__)
+
+
+class ProductCategory(models.Model):
+ _inherit = "product.category"
+
diff --git a/app_base_chinese/models/res_company.py b/app_base_chinese/models/res_company.py
new file mode 100644
index 000000000..a6c5e69d9
--- /dev/null
+++ b/app_base_chinese/models/res_company.py
@@ -0,0 +1,30 @@
+# -*- coding: utf-8 -*-
+
+from odoo import api, models, fields, _
+from odoo.exceptions import UserError, ValidationError
+
+
+class ResCompany(models.Model):
+ _inherit = 'res.company'
+
+ @api.model
+ def _adjust_wh_cn_name(self):
+ companys = self.env['res.company'].with_context(active_test=False, lang='zh_CN').search([])
+ for rec in companys:
+ # 修正区位名称
+ ids = self.env['stock.location'].with_context(active_test=False).search(
+ [('name', 'like', ': Transit Location'), ('company_id', '=', rec.id)])
+ ids.with_context(lang='zh_CN').write({'name': '%s:中转区位' % rec.name})
+ ids = self.env['stock.location'].with_context(active_test=False).search(
+ [('name', 'like', ': Scrap'), ('company_id', '=', rec.id)])
+ ids.with_context(lang='zh_CN').write({'name': '%s:报废区位' % rec.name})
+ ids = self.env['stock.location'].with_context(active_test=False).search(
+ [('name', 'like', ': Inventory adjustment'), ('company_id', '=', rec.id)])
+ ids.with_context(lang='zh_CN').write({'name': '%s:盘点区位' % rec.name})
+ # 注意,原生没有在生产中使用 _
+ ids = self.env['stock.location'].with_context(active_test=False).search([
+ ('name', 'like', ': Production'), ('company_id', '=', rec.id)])
+ ids.with_context(lang='zh_CN').write({'name': '%s:生产区位' % rec.name})
+ ids = self.env['stock.location'].with_context(active_test=False).search([
+ ('name', 'like', ': Subcontracting Location'), ('company_id', '=', rec.id)])
+ ids.with_context(lang='zh_CN').write({'name': '%s:委外区位' % rec.name})
diff --git a/app_base_chinese/models/res_country.py b/app_base_chinese/models/res_country.py
new file mode 100644
index 000000000..d0cf4869a
--- /dev/null
+++ b/app_base_chinese/models/res_country.py
@@ -0,0 +1,11 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+from odoo import fields, models
+
+
+class Country(models.Model):
+ _inherit = 'res.country'
+ _order = 'sequence,name'
+
+ sequence = fields.Integer('Sequence', help="Determine the display order", default=99)
diff --git a/app_base_chinese/models/res_currency.py b/app_base_chinese/models/res_currency.py
new file mode 100644
index 000000000..e78aec282
--- /dev/null
+++ b/app_base_chinese/models/res_currency.py
@@ -0,0 +1,53 @@
+# -*- coding: utf-8 -*-
+from odoo import api, fields, models
+
+
+class ResCurrency(models.Model):
+ _inherit = 'res.currency'
+ _order = 'active desc, sequence, name'
+
+ sequence = fields.Integer('Sequence', default=10, help="Determine the display order. Sort ascending.")
+
+ def rmb_upper(self, value):
+ """
+ 人民币大写
+ 传入浮点类型的值返回 unicode 字符串
+ :param 传入阿拉伯数字
+ :return 返回值是对应阿拉伯数字的绝对值的中文数字
+ """
+ if self.name != 'CNY':
+ return
+ rmbmap = [u"零", u"壹", u"贰", u"叁", u"肆", u"伍", u"陆", u"柒", u"捌", u"玖"]
+ unit = [u"分", u"角", u"元", u"拾", u"佰", u"仟", u"万", u"拾", u"佰", u"仟", u"亿",
+ u"拾", u"佰", u"仟", u"万", u"拾", u"佰", u"仟", u"兆"]
+ # 冲红负数处理
+ xflag = 0
+ if value < 0:
+ xflag = value
+ value = abs(value)
+ # 先把value 数字进行格式化保留两位小数,转成字符串然后去除小数点
+ nums = list(map(int, list(str('%0.2f' % value).replace('.', ''))))
+ words = []
+ zflag = 0 # 标记连续0次数,以删除万字,或适时插入零字
+ start = len(nums) - 3
+ for i in range(start, -3, -1): # 使i对应实际位数,负数为角分
+ # 大部分情况对应数字不等于零 或者是刚开始循环
+ if 0 != nums[start - i] or len(words) == 0:
+ if zflag:
+ words.append(rmbmap[0])
+ zflag = 0
+ words.append(rmbmap[nums[start - i]]) # 数字对应的中文字符
+ words.append(unit[i + 2]) # 列表此位置的单位
+ # 控制‘万/元’ 万和元比较特殊,如2拾万和2拾1万 无论有没有这个1 万字是必须的
+ elif 0 == i or (0 == i % 4 and zflag < 3):
+ # 上面那种情况定义了 2拾1万 的显示 这个是特殊对待的 2拾万(一类)的显示
+ words.append(unit[i + 2])
+ # 元(控制条件为 0 == i )和万(控制条为(0 == i % 4 and zflag < 3))的情况的处理是一样的
+ zflag = 0
+ else:
+ zflag += 1
+ if words[-1] != unit[0]: # 结尾非‘分’补整字 最小单位 如果最后一个字符不是最小单位(分)则要加一个整字
+ words.append(u"整")
+ if xflag < 0: # 如果为负数则要在数字前面加上‘负’字
+ words.insert(0, u"负")
+ return ''.join(words)
diff --git a/app_base_chinese/models/res_partner.py b/app_base_chinese/models/res_partner.py
new file mode 100644
index 000000000..47fa0a463
--- /dev/null
+++ b/app_base_chinese/models/res_partner.py
@@ -0,0 +1,33 @@
+# -*- coding: utf-8 -*-
+
+from odoo import api, models, fields, _
+from odoo.exceptions import UserError, ValidationError
+
+
+class ResPartner(models.Model):
+ _inherit = 'res.partner'
+
+ name = fields.Char(translate=False)
+ short_name = fields.Char('Short Name') # 简称
+ fax = fields.Char('Fax') # 简称
+
+ # 增加地址显示中的手机号与电话号码
+ # 选项 show_address 开启则增加显示手机与电话号
+ def _get_name(self):
+ name = super(ResPartner, self)._get_name()
+ partner = self
+ if self._context.get('show_address'):
+ if partner.mobile and partner.phone:
+ name = name + "\n" + partner.mobile + "," + partner.phone
+ elif partner.mobile:
+ name = name + "\n" + partner.mobile
+ elif partner.phone:
+ name = name + "\n" + partner.phone
+ return name.strip()
+
+ @api.model_create_multi
+ def create(self, vals_list):
+ for values in vals_list:
+ if 'lang' not in values:
+ values['lang'] = 'zh_CN'
+ return super(ResPartner, self).create(vals_list)
diff --git a/app_base_chinese/models/stock_location.py b/app_base_chinese/models/stock_location.py
new file mode 100644
index 000000000..48888cc94
--- /dev/null
+++ b/app_base_chinese/models/stock_location.py
@@ -0,0 +1,12 @@
+# -*- coding: utf-8 -*-
+
+import logging
+
+from odoo import api, fields, models, _
+
+_logger = logging.getLogger(__name__)
+
+class Location(models.Model):
+ _inherit = "stock.location"
+
+ complete_name = fields.Char(translate=True)
diff --git a/app_base_chinese/report/__init__.py b/app_base_chinese/report/__init__.py
new file mode 100644
index 000000000..633f86615
--- /dev/null
+++ b/app_base_chinese/report/__init__.py
@@ -0,0 +1,2 @@
+# -*- coding: utf-8 -*-
+
diff --git a/app_base_chinese/res/__init__.py b/app_base_chinese/res/__init__.py
new file mode 100644
index 000000000..40a96afc6
--- /dev/null
+++ b/app_base_chinese/res/__init__.py
@@ -0,0 +1 @@
+# -*- coding: utf-8 -*-
diff --git a/app_base_chinese/static/description/banner.jpg b/app_base_chinese/static/description/banner.jpg
new file mode 100644
index 000000000..b529b6f51
Binary files /dev/null and b/app_base_chinese/static/description/banner.jpg differ
diff --git a/app_base_chinese/static/description/banner.png b/app_base_chinese/static/description/banner.png
new file mode 100644
index 000000000..666667bb9
Binary files /dev/null and b/app_base_chinese/static/description/banner.png differ
diff --git a/app_base_chinese/static/description/cnreadme.png b/app_base_chinese/static/description/cnreadme.png
new file mode 100644
index 000000000..54018ff4f
Binary files /dev/null and b/app_base_chinese/static/description/cnreadme.png differ
diff --git a/app_base_chinese/static/description/demo1.jpg b/app_base_chinese/static/description/demo1.jpg
new file mode 100644
index 000000000..6c61c24c9
Binary files /dev/null and b/app_base_chinese/static/description/demo1.jpg differ
diff --git a/app_base_chinese/static/description/demo2.jpg b/app_base_chinese/static/description/demo2.jpg
new file mode 100644
index 000000000..0d66a4121
Binary files /dev/null and b/app_base_chinese/static/description/demo2.jpg differ
diff --git a/app_base_chinese/static/description/demo3.jpg b/app_base_chinese/static/description/demo3.jpg
new file mode 100644
index 000000000..d990d41cc
Binary files /dev/null and b/app_base_chinese/static/description/demo3.jpg differ
diff --git a/app_base_chinese/static/description/icon.png b/app_base_chinese/static/description/icon.png
new file mode 100644
index 000000000..22cbd2780
Binary files /dev/null and b/app_base_chinese/static/description/icon.png differ
diff --git a/app_base_chinese/static/description/index.html b/app_base_chinese/static/description/index.html
new file mode 100644
index 000000000..a080d9bb0
--- /dev/null
+++ b/app_base_chinese/static/description/index.html
@@ -0,0 +1,156 @@
+
+
+
+
Chinese Enhance All in One。 Local customize for china user
+
20+ chinese setting enhance.
+
+
Latest update: v17.24.10.08
+
+
+
Key features:
+
+
+
+ 1. Chinese address format, applicable to all Chinese customers, suppliers, partners, users, employee information etc.
+
+
+
+ 2. Default values in Chinese such as country, time zone and currency. Processing module base, product.
+
+
+
+ 3. Add customer abbreviation and display addresses in Chinese; prioritize displaying customer codes.
+
+
+
+ 4. Display phone numbers along with mobile numbers for customer addresses.
+
+
+
+ 5. Currency processing with added sorting display.
+
+
+
+ 6. Fixed bug where the category list and m2o field did not display the name of the Chinese directory.
+
+
+
+ 7. Fixed bug where warehouse location list and m2o field did not display the name of the Chinese directory.
+
+
+
+ 8. Superuser changed time zone to China.
+
+
+
+ 9. Date format is year-month-day (e.g., 2023-08-08) and time is 12:34
+
+
+
+ 10.Country sorting added; China ranked first
+
+
+
+ 11.Display payment-related information according to typical practices in China.
+
+
+
+ 12.Default export translation is set to Mandarin (po).
+
+
+
+ 13.Added 'name_en_US' field in base model which updates translation value when assigned a value.
+
+
+
+ 14.Common decimal precision adjustments made.
+
+
+
+ 15.Sales team changed to "China".
+
+
+
+ 21. Multi-language Support. Multi-Company Support.
+
+
+
+ 22. Support Odoo 18,17,16,15,14,13,12, Enterprise and Community and odoo.sh Edition.
+
+
+
+ 23. Full Open Source..
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Set the address format to chinese. Including all customer, supplier, users
+
+
+
+
+
+
+
+
+
+
Set Default country, state, timezone, currency.
+
+
+
+
+
+
+
+
+
Fix Category Display not in english bug.
+
+
+
+
+
+
+
+
+
+
Technical Help & Support
+
+
+
+
+ For any type of technical help & support requests, Feel free to contact us
+
+ odoo@china.com
+
+ Via QQ: 300883 (App user would not get QQ or any other IM support. Only for odoo project customize.)
+
+ 300883@qq.com
+
+
+
+ Visit our website for more support.
+https://www.odooai.cn
+
+
+
+
+
More Powerful addons, Make your odoo very easy to use, easy customize:
+ odooai.cn Odoo Addons
+
+
+
+
diff --git a/app_base_chinese/static/src/public/database_manager.create_form.qweb.html b/app_base_chinese/static/src/public/database_manager.create_form.qweb.html
new file mode 100644
index 000000000..341dba004
--- /dev/null
+++ b/app_base_chinese/static/src/public/database_manager.create_form.qweb.html
@@ -0,0 +1,67 @@
+
+
+
+
+
+
+
+
Language
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Country
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app_base_chinese/static/src/scss/app_style.scss b/app_base_chinese/static/src/scss/app_style.scss
new file mode 100644
index 000000000..649c0fb6e
--- /dev/null
+++ b/app_base_chinese/static/src/scss/app_style.scss
@@ -0,0 +1,39 @@
+//必须有 form ,故要特殊处理样式
+.o_form_view.o_form_nosheet.o_form_address_chinese, .o_form_view .o_form_nosheet.o_form_address_chinese {
+ padding: 0 0 0 0;
+}
+.o_form_view .o_address_format.o_address_chinese {
+ .o_address_country {
+ display: -webkit-inline-flex;
+ display: inline-flex;
+ width: 38%;
+ margin-right: 2%;
+ }
+}
+.o_form_view .o_address_format.o_address_chinese {
+ .o_address_country {
+ display: -webkit-inline-flex;
+ display: inline-flex;
+ width: 38%;
+ margin-right: 2%;
+ }
+}
+
+.o_form_view .o_form_editable .o_address_format.o_address_chinese {
+ .o_address_zip{
+ width: 38%;
+ margin-right: 2%;
+ }
+ .o_address_state {
+ width: 38%;
+ margin-right: 2%;
+ }
+ .o_address_city{
+ width: 38%;
+ margin-right: 2%;
+ }
+ .o_address_city_id{
+ width: 38%;
+ margin-right: 2%;
+ }
+}
diff --git a/app_base_chinese/static/src/xml/views.xml b/app_base_chinese/static/src/xml/views.xml
new file mode 100644
index 000000000..e05ae2a2b
--- /dev/null
+++ b/app_base_chinese/static/src/xml/views.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+ 性能原因,只支持 200 条记录的显示
+ 记录没有树状结构
+
+
+
+
\ No newline at end of file
diff --git a/app_base_chinese/views/account_move_views.xml b/app_base_chinese/views/account_move_views.xml
new file mode 100644
index 000000000..728d8a793
--- /dev/null
+++ b/app_base_chinese/views/account_move_views.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+ app.account.move.form
+ account.move
+
+
+
+
+ Post Entry
+
+
+
+
+
+
diff --git a/app_base_chinese/views/ir_default_views.xml b/app_base_chinese/views/ir_default_views.xml
new file mode 100644
index 000000000..d14570d7a
--- /dev/null
+++ b/app_base_chinese/views/ir_default_views.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+ app.res.currency.tree
+ res.currency
+
+
+
+
+
+
+
+
+
+ app.res.currency.form
+ res.currency
+
+
+
+
+
+
+
+
+
diff --git a/app_base_chinese/views/ir_module_module_views.xml b/app_base_chinese/views/ir_module_module_views.xml
new file mode 100644
index 000000000..7b84bda78
--- /dev/null
+++ b/app_base_chinese/views/ir_module_module_views.xml
@@ -0,0 +1,24 @@
+
+
+
+ app.base.chinese.module.module.form
+ ir.module.module
+
+
+
+
+
+
+
+
+
+ app.base.chinese.module.kanban
+ ir.module.module
+
+
+
+ https://www.odooapp.cn/pricing?utm_source=db&utm_medium=module#hosting=on_premise
+
+
+
+
\ No newline at end of file
diff --git a/app_base_chinese/views/res_company_views.xml b/app_base_chinese/views/res_company_views.xml
new file mode 100644
index 000000000..880be72b9
--- /dev/null
+++ b/app_base_chinese/views/res_company_views.xml
@@ -0,0 +1,26 @@
+
+
+
+
+ app.res.company.form
+ res.company
+
+
+
+
+
+
+
+
+
+ app.res.company.form
+ res.company
+
+
+
+
+
+
+
+
+
diff --git a/app_base_chinese/views/res_currency_views.xml b/app_base_chinese/views/res_currency_views.xml
new file mode 100644
index 000000000..51fe143ef
--- /dev/null
+++ b/app_base_chinese/views/res_currency_views.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+ app.ir.default tree view
+ ir.default
+
+
+
+
+
+
+
+
+
+ app.ir.default form view
+ ir.default
+
+
+
+
+
+
+
+
+
diff --git a/app_base_chinese/views/res_partner_views.xml b/app_base_chinese/views/res_partner_views.xml
new file mode 100644
index 000000000..cb4441f3e
--- /dev/null
+++ b/app_base_chinese/views/res_partner_views.xml
@@ -0,0 +1,105 @@
+
+
+
+
+
+ app.res.partner.form
+ res.partner
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+ 1
+
+
+
+
+
+
+
+ [ ]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ app.res.partner.form.chinese
+ res.partner
+
+
+
+
+
+
+
+ app.res.partner.tree
+ res.partner
+
+
+
+
+
+
+
+
+
+
+ app.res.partner.kanban
+ res.partner
+
+
+
+
+
+
+
+ Credit:
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app_base_chinese/views/sale_order_views.xml b/app_base_chinese/views/sale_order_views.xml
new file mode 100644
index 000000000..b67ab85ca
--- /dev/null
+++ b/app_base_chinese/views/sale_order_views.xml
@@ -0,0 +1,24 @@
+
+
+
+
+ app.sale.order.form
+ sale.order
+
+
+
+
+ Make Collections
+
+
+
+ Make Collections
+
+
+
+ Invoices/FaPiao
+
+
+
+
+
\ No newline at end of file
diff --git a/app_base_chinese/wizard/sale_make_invoice_advance_views.xml b/app_base_chinese/wizard/sale_make_invoice_advance_views.xml
new file mode 100644
index 000000000..1362a7aa5
--- /dev/null
+++ b/app_base_chinese/wizard/sale_make_invoice_advance_views.xml
@@ -0,0 +1,21 @@
+
+
+
+ FaPiao / Invoice Orders
+
+
+
+ app.account.move.form
+ sale.advance.payment.inv
+
+
+
+ FaPiao / Invoice Orders
+
+
+
+
+
+ Create FaPiao / Invoice
+
+
diff --git a/app_web_widget_ztree/__init__.py b/app_web_widget_ztree/__init__.py
new file mode 100644
index 000000000..cde864bae
--- /dev/null
+++ b/app_web_widget_ztree/__init__.py
@@ -0,0 +1,3 @@
+# -*- coding: utf-8 -*-
+
+from . import models
diff --git a/app_web_widget_ztree/__manifest__.py b/app_web_widget_ztree/__manifest__.py
new file mode 100644
index 000000000..1ef7be706
--- /dev/null
+++ b/app_web_widget_ztree/__manifest__.py
@@ -0,0 +1,91 @@
+# -*- coding: utf-8 -*-
+
+# Created on 2021-11-30
+# author: 欧度智能,https://www.odooai.cn
+# email: 300883@qq.com
+# resource of odooai
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+# Odoo12在线用户手册(长期更新)
+# https://www.odooai.cn/documentation/user/12.0/en/index.html
+
+# Odoo12在线开发者手册(长期更新)
+# https://www.odooai.cn/documentation/12.0/index.html
+
+# Odoo10在线中文用户手册(长期更新)
+# https://www.odooai.cn/documentation/user/10.0/zh_CN/index.html
+
+# Odoo10离线中文用户手册下载
+# https://www.odooai.cn/odoo10_user_manual_document_offline/
+# Odoo10离线开发手册下载-含python教程,jquery参考,Jinja2模板,PostgresSQL参考(odoo开发必备)
+# https://www.odooai.cn/odoo10_developer_document_offline/
+# change ztree to https://github.com/wenzhixin/font-awesome-zTree
+
+{
+ 'name': 'Many2One Hierarchy Parent Child M2o Selector, zTree 树状下拉选择器',
+ 'version': '17.0.24.12.18',
+ 'author': 'odooai.cn',
+ 'category': 'Base',
+ 'website': 'https://www.odooai.cn',
+ 'live_test_url': 'https://demo.odooapp.cn',
+ 'license': 'OPL-1',
+ 'sequence': 2,
+ 'summary': """
+ show parent tree, parent children node in m2o select field.
+ Use for parent children tree list select navigator.
+ ztree widget.
+ """,
+ 'description': """
+ zTree widget.
+ Advance search with real parent children tree, ListView or KanbanView ,
+ eg: Product category tree ,Department tree, stock location tree.
+M2O字段下拉树状选择器,Many2One动态父子多层级关系树展现widget小组件,可用于任何模块。
+用于父子树列表选择导航器。例如品类,部门等多层次展现。
+已内置10多个免费odoo应用的多层级选择,如产品,Hr部门,联系人,仓库货架等。
+ 1. M2o Select with Hierarchy parent/child dropdown.
+ 2. zTree widget for any app in odoo.
+ 3. Easy use in customize 3rd app. Easy to make custom parent children tree.
+ 4. Hierarchy selector out-of-box with all apps:
+ Product, Sales, Purchase, MRP, Stock, Etc...
+ 5. zTree树状下拉选择器,可完全自定义的Widget
+ """,
+ 'price': 108.00,
+ 'currency': 'EUR',
+ 'depends': [
+ 'web',
+ # 'product',
+ ],
+ 'images': ['static/description/banner.gif'],
+ 'data': [
+ # 'views/product_views.xml',
+ ],
+ 'assets': {
+ 'web.assets_qweb': [
+ ],
+ 'web.assets_backend': [
+ 'app_web_widget_ztree/static/src/lib/ztree_v3/css/awesomeStyle/fa.scss',
+ 'app_web_widget_ztree/static/src/lib/ztree_v3/css/awesomeStyle/awesome.scss',
+ 'app_web_widget_ztree/static/src/scss/variables.scss',
+ 'app_web_widget_ztree/static/src/scss/views.scss',
+ 'app_web_widget_ztree/static/src/lib/ztree_v3/js/jquery.ztree.core.js',
+ ('after', 'web/static/src/core/autocomplete/autocomplete.js', 'app_web_widget_ztree/static/src/js/ztree.js'),
+ ('after', 'web/static/src/views/fields/x2many/x2many_field.js', 'app_web_widget_ztree/static/src/js/ztree_chart.js'),
+ ('after', 'web/static/src/views/fields/relational_utils.js', 'app_web_widget_ztree/static/src/js/ztree_many2x.js'),
+ ('after', 'web/static/src/views/fields/many2one/many2one_field.js', 'app_web_widget_ztree/static/src/js/ztree_select.js'),
+ ('after', 'web/static/src/core/autocomplete/autocomplete.xml', 'app_web_widget_ztree/static/src/xml/ztree.xml'),
+ 'app_web_widget_ztree/static/src/xml/ztree_chart.xml',
+ ('after', 'web/static/src/views/fields/relational_utils.xml', 'app_web_widget_ztree/static/src/xml/ztree_many2x.xml'),
+ ('after', 'web/static/src/views/fields/many2one/many2one_field.xml', 'app_web_widget_ztree/static/src/xml/ztree_select.xml'),
+ ],
+ },
+ 'demo': [
+ ],
+ 'test': [
+ ],
+ 'post_load': None,
+ 'post_init_hook': None,
+ 'installable': True,
+ 'application': True,
+ 'auto_install': False,
+}
+
diff --git a/app_web_widget_ztree/images/form_view_edit.png b/app_web_widget_ztree/images/form_view_edit.png
new file mode 100644
index 000000000..716e936ee
Binary files /dev/null and b/app_web_widget_ztree/images/form_view_edit.png differ
diff --git a/app_web_widget_ztree/images/form_view_no_edit.png b/app_web_widget_ztree/images/form_view_no_edit.png
new file mode 100644
index 000000000..cb097a6cb
Binary files /dev/null and b/app_web_widget_ztree/images/form_view_no_edit.png differ
diff --git a/app_web_widget_ztree/models/__init__.py b/app_web_widget_ztree/models/__init__.py
new file mode 100644
index 000000000..0da73f997
--- /dev/null
+++ b/app_web_widget_ztree/models/__init__.py
@@ -0,0 +1,4 @@
+# -*- coding: utf-8 -*-
+
+from . import models
+from . import mixin_parent_chart
diff --git a/app_web_widget_ztree/models/mixin_parent_chart.py b/app_web_widget_ztree/models/mixin_parent_chart.py
new file mode 100644
index 000000000..a695052a3
--- /dev/null
+++ b/app_web_widget_ztree/models/mixin_parent_chart.py
@@ -0,0 +1,21 @@
+# -*- coding: utf-8 -*-
+import logging
+logger = logging.getLogger(__name__)
+
+from odoo import api, fields, models, _
+
+
+# 用于widget的树结构 mixin
+class MixinParentChart(models.AbstractModel):
+ _name = 'mixin.parent.chart'
+ _description = '树状结构基础mixin'
+
+ _parent_name = "parent_id"
+ _parent_store = True
+ _order = 'parent_path asc'
+ _parent_order = 'id'
+
+ # 上级生产单
+ parent_id = fields.Many2one(_name, string='上级对象', index=True, ondelete='cascade')
+ parent_path = fields.Char(index=True)
+ child_ids = fields.One2many(_name, 'parent_id', string='结构树')
diff --git a/app_web_widget_ztree/models/models.py b/app_web_widget_ztree/models/models.py
new file mode 100644
index 000000000..b60339cd1
--- /dev/null
+++ b/app_web_widget_ztree/models/models.py
@@ -0,0 +1,133 @@
+# -*- coding: utf-8 -*-
+from odoo import models, api
+
+
+class BaseModelExtend(models.AbstractModel):
+ _name = 'basemodel.extend'
+ _description = 'Base Extend for Ztree'
+
+
+ def _register_hook(self):
+ """
+ Register method in BaseModel
+ type: bar是在superbar中,field是在form中
+ """
+ # name_field 显示的字段
+ # type = chart 时,只取自己这棵树,使用 parent_path 处理
+ @api.model
+ def search_ztree(self, domain=None, context=None, parent_key=None, root_id=None, expend_level=None, name_field=None, limit=None, order=None, type=None,
+ selected_id=None):
+ if context:
+ self = self.with_context
+ try:
+ limit = int(limit)
+ except Exception:
+ limit = 1000
+ if not limit:
+ limit = 1000
+ if not order:
+ order = self._order
+ try:
+ expend_level = int(expend_level)
+ if expend_level == 0:
+ expend_level = 3
+ except Exception:
+ expend_level = 3
+
+ if name_field:
+ pass
+ elif self._fields.get("name"):
+ name_field = 'name'
+ elif self._fields.get("display_name"):
+ name_field = 'display_name'
+ else:
+ name_field = self._rec_name
+
+ if name_field == 'display_name':
+ fields = ['id', 'display_name']
+ else:
+ fields = ['id', name_field, 'display_name']
+
+ # 返回 id, name, value, pId, title, value
+ def ztree(x):
+ y = {}
+ p = parent_key
+ pid = False
+ if p and x.get(p):
+ pid = x[p]
+ if pid:
+ pid = pid[0]
+ y['id'] = x['id']
+ if x.get(name_field):
+ y['name'] = x[name_field]
+ else:
+ y['name'] = x['display_name']
+
+ y['value'] = x[name_field]
+ y['title'] = x['display_name']
+ y['pId'] = pid
+ return y
+
+ # 递归展开指定级别,即设定open
+ def getLevel(node, nodes, level=1):
+ if not node.get("pId"):
+ level = 1
+ else:
+ try:
+ level = level + getLevel(nodes[node.get("pId")], nodes)
+ except Exception:
+ level = 1
+ return level
+
+ # todo: 检查 root_id 的处理
+ if not parent_key:
+ parent_key = self._parent_name or False
+ if parent_key:
+ fields.append(parent_key)
+ if root_id:
+ r = self.search_read([('id', '=', root_id)], ['parent_path'], limit=1)
+ path = r[0]['parent_path']
+ domain += [('parent_path', '=like', path + '%')]
+ # type=chart时 遍历只取本棵树
+ elif type == 'chart' and not selected_id:
+ # 没有当前值,比如创建时,显示空
+ domain += [('id', '=', False)]
+ elif type == 'chart' and not self._fields.get("parent_path"):
+ # 没有parent_path,只显示当前
+ domain += [('id', '=', selected_id)]
+ elif type == 'chart' and selected_id:
+ r = self.search_read([('id', '=', selected_id)], ['parent_path'], limit=1)
+ if r:
+ path = r[0]['parent_path']
+ pos = path.find('/')
+ if pos > 0:
+ path = path[0:pos + 1]
+ domain += [('parent_path', '=like', path + '%')]
+ else:
+ domain += [('id', '=', selected_id)]
+ records = self.search_read(domain or [], fields, 0, limit=limit, order=order)
+
+ if not records:
+ return []
+
+ result = records
+ res = map(ztree, result)
+
+ if len(result) < 1:
+ return result
+
+ # reorder read, index: dict, res: list
+ index = {vals['id']: vals for vals in res}
+ for key in index:
+ index[key]["ztree_link"] = '/mail/view?model=%s&res_id=%s' % (self._name, index[key]["id"]),
+ index[key]["level"] = getLevel(index[key], index, 1)
+ if index[key]["level"] < expend_level:
+ index[key]["open"] = True
+ else:
+ index[key]["open"] = False
+
+ res = [index[record["id"]] for record in records if record["id"] in index]
+ return res
+
+ models.BaseModel.search_ztree = search_ztree
+ return super(BaseModelExtend, self)._register_hook()
diff --git a/app_web_widget_ztree/static/description/banner.gif b/app_web_widget_ztree/static/description/banner.gif
new file mode 100644
index 000000000..d67a2bdb2
Binary files /dev/null and b/app_web_widget_ztree/static/description/banner.gif differ
diff --git a/app_web_widget_ztree/static/description/banner.png b/app_web_widget_ztree/static/description/banner.png
new file mode 100644
index 000000000..bc8118fab
Binary files /dev/null and b/app_web_widget_ztree/static/description/banner.png differ
diff --git a/app_web_widget_ztree/static/description/banner1.png b/app_web_widget_ztree/static/description/banner1.png
new file mode 100644
index 000000000..9c2b888f4
Binary files /dev/null and b/app_web_widget_ztree/static/description/banner1.png differ
diff --git a/app_web_widget_ztree/static/description/demo1-1.jpg b/app_web_widget_ztree/static/description/demo1-1.jpg
new file mode 100644
index 000000000..477ebc05d
Binary files /dev/null and b/app_web_widget_ztree/static/description/demo1-1.jpg differ
diff --git a/app_web_widget_ztree/static/description/demo1.jpg b/app_web_widget_ztree/static/description/demo1.jpg
new file mode 100644
index 000000000..2b5d329e3
Binary files /dev/null and b/app_web_widget_ztree/static/description/demo1.jpg differ
diff --git a/app_web_widget_ztree/static/description/demo11.jpg b/app_web_widget_ztree/static/description/demo11.jpg
new file mode 100644
index 000000000..72ad356bc
Binary files /dev/null and b/app_web_widget_ztree/static/description/demo11.jpg differ
diff --git a/app_web_widget_ztree/static/description/demo12.jpg b/app_web_widget_ztree/static/description/demo12.jpg
new file mode 100644
index 000000000..ecc581860
Binary files /dev/null and b/app_web_widget_ztree/static/description/demo12.jpg differ
diff --git a/app_web_widget_ztree/static/description/demo2.jpg b/app_web_widget_ztree/static/description/demo2.jpg
new file mode 100644
index 000000000..121df60cd
Binary files /dev/null and b/app_web_widget_ztree/static/description/demo2.jpg differ
diff --git a/app_web_widget_ztree/static/description/demo3-1.jpg b/app_web_widget_ztree/static/description/demo3-1.jpg
new file mode 100644
index 000000000..d86177b70
Binary files /dev/null and b/app_web_widget_ztree/static/description/demo3-1.jpg differ
diff --git a/app_web_widget_ztree/static/description/demo3-2.jpg b/app_web_widget_ztree/static/description/demo3-2.jpg
new file mode 100644
index 000000000..64db2359f
Binary files /dev/null and b/app_web_widget_ztree/static/description/demo3-2.jpg differ
diff --git a/app_web_widget_ztree/static/description/demo3.jpg b/app_web_widget_ztree/static/description/demo3.jpg
new file mode 100644
index 000000000..2c96d077f
Binary files /dev/null and b/app_web_widget_ztree/static/description/demo3.jpg differ
diff --git a/app_web_widget_ztree/static/description/demo31.jpg b/app_web_widget_ztree/static/description/demo31.jpg
new file mode 100644
index 000000000..9d9209c99
Binary files /dev/null and b/app_web_widget_ztree/static/description/demo31.jpg differ
diff --git a/app_web_widget_ztree/static/description/demo32.jpg b/app_web_widget_ztree/static/description/demo32.jpg
new file mode 100644
index 000000000..f34ea97ec
Binary files /dev/null and b/app_web_widget_ztree/static/description/demo32.jpg differ
diff --git a/app_web_widget_ztree/static/description/demo33.jpg b/app_web_widget_ztree/static/description/demo33.jpg
new file mode 100644
index 000000000..dd075614d
Binary files /dev/null and b/app_web_widget_ztree/static/description/demo33.jpg differ
diff --git a/app_web_widget_ztree/static/description/demo34.jpg b/app_web_widget_ztree/static/description/demo34.jpg
new file mode 100644
index 000000000..825ca2b1a
Binary files /dev/null and b/app_web_widget_ztree/static/description/demo34.jpg differ
diff --git a/app_web_widget_ztree/static/description/demo35.jpg b/app_web_widget_ztree/static/description/demo35.jpg
new file mode 100644
index 000000000..9d06ce733
Binary files /dev/null and b/app_web_widget_ztree/static/description/demo35.jpg differ
diff --git a/app_web_widget_ztree/static/description/demo36.jpg b/app_web_widget_ztree/static/description/demo36.jpg
new file mode 100644
index 000000000..eb955b2b9
Binary files /dev/null and b/app_web_widget_ztree/static/description/demo36.jpg differ
diff --git a/app_web_widget_ztree/static/description/demo37.jpg b/app_web_widget_ztree/static/description/demo37.jpg
new file mode 100644
index 000000000..a443ce8ca
Binary files /dev/null and b/app_web_widget_ztree/static/description/demo37.jpg differ
diff --git a/app_web_widget_ztree/static/description/demo4.jpg b/app_web_widget_ztree/static/description/demo4.jpg
new file mode 100644
index 000000000..42033aec9
Binary files /dev/null and b/app_web_widget_ztree/static/description/demo4.jpg differ
diff --git a/app_web_widget_ztree/static/description/demo41.jpg b/app_web_widget_ztree/static/description/demo41.jpg
new file mode 100644
index 000000000..bf7364ec6
Binary files /dev/null and b/app_web_widget_ztree/static/description/demo41.jpg differ
diff --git a/app_web_widget_ztree/static/description/demo5.jpg b/app_web_widget_ztree/static/description/demo5.jpg
new file mode 100644
index 000000000..c4fde2989
Binary files /dev/null and b/app_web_widget_ztree/static/description/demo5.jpg differ
diff --git a/app_web_widget_ztree/static/description/demo6.jpg b/app_web_widget_ztree/static/description/demo6.jpg
new file mode 100644
index 000000000..4203cc728
Binary files /dev/null and b/app_web_widget_ztree/static/description/demo6.jpg differ
diff --git a/app_web_widget_ztree/static/description/demo_bom.jpg b/app_web_widget_ztree/static/description/demo_bom.jpg
new file mode 100644
index 000000000..7907893e6
Binary files /dev/null and b/app_web_widget_ztree/static/description/demo_bom.jpg differ
diff --git a/app_web_widget_ztree/static/description/icon.png b/app_web_widget_ztree/static/description/icon.png
new file mode 100644
index 000000000..c95d817e3
Binary files /dev/null and b/app_web_widget_ztree/static/description/icon.png differ
diff --git a/app_web_widget_ztree/static/description/index.html b/app_web_widget_ztree/static/description/index.html
new file mode 100644
index 000000000..7eaaae76d
--- /dev/null
+++ b/app_web_widget_ztree/static/description/index.html
@@ -0,0 +1,348 @@
+
+
+
+
+
+ App ztree widget,Hierarchy Parent tree in m2o select. Hierarchy Chart selector
+ 树状视图m2o及结构图widget套件,用于Odoo所有应用以展现树状层级结构
+
+
+
+
+
+
Very useful for parent child relationship, like product category, stock location, hr department
+
+
+
+
+
+
+
+
Update: v18.0.24.12.18
+
Support better for odoo 18 and OWL rule
+
Update: v16.24.12.18
+
Optimize style
+
Key features:
+
+
+
+ 1. M2o Select with Hierarchy parent/child dropdown
+
+
+
+ 2. zTree widget for any app in odoo. MRP, Account, User, Product Category, Stock location, etc...
+
+
+
+ 3. Easy use in customize 3rd app. Easy to make custom parent children tree.
+
+
+
+ 4. Hierarchy selector out-of-box with all apps:
+
+
+
+ 5. Hierarchy Chart widget zChart. easy with all apps. MRP, Account, User, Product Category, Stock location, etc...
+
+
+
+ 6. We provide 10+ more free Demo for you can use it in anywhere in odoo.
+
+
+
+
+
Get relate Demo(All Free. Only 2 paid for Multi-level BoM)
+
+
+
+
+
+
+
+
+
Buy this apps, get Extra bonus apps, App zTree widget, Hierarchy Parent tree in m2o select
+
Ready for product category Hierarchy Parent tree in m2o select
+
+
+
+
Ready for Stock Location Hierarchy Parent tree in m2o select
+
+
+
+
Ready for Hr Department Hierarchy Parent tree in m2o select
+
+
+
+
+
+
+
+
+
The Feature Including in this module.
+
Use in product.
+
+
+
+
+
+
+
+
+
Free to Use in product category.
+
+
+
+
Also Show product category in Hierarchy Char
+
+
+
+
+
+
+
+
+
Free to Use in Account multi level COA
+
+
+
+
+
+
+
+
+
Free to Use in stock location.
+
+
+
+
Support Chart view
+
+
+
+
+
+
+
+
+
Free to Use in MRP Workcenter.
+
+
+
+
+
+
+
+
+
Use in hr department.
+
+
+
+
+
+
+
+
+
Use in hr employee.
+
+
+
+
+
+
+
+
+
+
Product category Chart Hierarchy
+
+
+
+
+
+
+
+
+
Pay(Not Free) Multi-Level Bom Chart zChart hierarchy
+
快速在统一界面中管理多层级BoM
+
+
+
+
+
+
+
+
+
+
+
+
+
Stock Location Chart Hierarchy
+
+
+
+
+
+
+
+
+
+
HR Department Chart Hierarchy
+
+
+
+
HR Employee Chart Hierarchy (this is include in odoo)
+
+
+
+
+
+
+
+
Pay(Not Free) Multi-Level Account zChart Hierarchy
+
快速在统一界面中管理多层级会计科目
+
+
+
+
+
+
+
+
+
+
User Alliance Distribution Multi level
+
+
+
+
+
+
+
+
+
+
MRP Production Chart Hierarchy
+
+
+
+
+
+
+
+
+
Easy to setup just use widget='ztree_select'. and widget='ztree_chart' like this
+
+
+
+
Use follow param to setup widget:
+
ztree_parent_key: --the key field of parent children relation.
+
ztree_expend_level: --how many level to expend the tree for initialize. Default is 2
+
limit: --how many record to show ztree. Default is 16
+
order: --the field to order by
+
+
+
+
+
+
+
+
Advance Search Sidebar with Hierarchy Parent Children Tree
+
+
+
+
+
+
+
+
+
+
Technical Help & Support
+
+
+
+
+ For any type of technical help & support requests, Feel free to contact us
+
+ odoo@china.com
+
+ Via QQ: 300883 (App user would not get QQ or any other IM support. Only for odoo project customize.)
+
+ 300883@qq.com
+
+
+
+ Visit our website for more support.
+https://www.odooai.cn
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app_web_widget_ztree/static/description/index_cn.html b/app_web_widget_ztree/static/description/index_cn.html
new file mode 100644
index 000000000..469a54b27
--- /dev/null
+++ b/app_web_widget_ztree/static/description/index_cn.html
@@ -0,0 +1,206 @@
+
+
+
+
+
+
+
+
+
App ztree小插件,层次父树在m2o选择
+
非常有用的树状结构关系,如产品类别,库存位置,人力资源部门
+
+
+
+
+
+
+
+
更新: v12.19.05.02
+
优化的风格
+
关键特性:
+
+
+
+ 易于自定义的树状结构.
+
+
+
+ 在产品类别中免费使用.
+
+
+
+ 在仓库和库位中免费使用.
+
+
+
+ 在HR、员工管理中免费使用.
+
+
+
+ 它是一个小插件,你可以在odoo的任何地方使用它
+
+
+
+
+
+
+
+
+
+
+
+
+
+
高级搜索侧边栏与层次父子树
+
+
+
+
+
+
+
+
+
购买这个应用程序,得到额外的奖励应用程序,应用程序zTree小部件,层次父树在m2o选择
+
在m2o为产品类别选择树状结构
+
+
+
+
在m2o为仓库选择树状结构
+
+
+
+
在m2o为HR部门选择树状结构
+
+
+
+
+
+
+
+
+
包含在这个模块中的特性.
+
在产品中使用.
+
+
+
+
+
+
+
+
+
免费在产品目录中使用.
+
+
+
+
+
+
+
+
+
免费在仓库中使用.
+
+
+
+
+
+
+
+
+
在部门中使用.
+
+
+
+
+
+
+
+
+
在员工管理中使用.
+
+
+
+
+
+
+
+
+
很容易设置,只需使用widget='widget_select'。像这样
+
+
+
+
使用跟随参数设置小插件:
+
ztree_parent_key: --父子关系的关键字段.
+
ztree_expend_level: --初始化树需要扩展多少个级别。默认是2
+
limit: --显示ztree的记录数。默认是16
+
order: --订单的字段
+
+
+
+
+
+
diff --git a/app_web_widget_ztree/static/description/setup1.jpg b/app_web_widget_ztree/static/description/setup1.jpg
new file mode 100644
index 000000000..d5ade2b1a
Binary files /dev/null and b/app_web_widget_ztree/static/description/setup1.jpg differ
diff --git a/app_web_widget_ztree/static/description/superbar.gif b/app_web_widget_ztree/static/description/superbar.gif
new file mode 100644
index 000000000..78c2090c5
Binary files /dev/null and b/app_web_widget_ztree/static/description/superbar.gif differ
diff --git a/app_web_widget_ztree/static/description/z_hr1.gif b/app_web_widget_ztree/static/description/z_hr1.gif
new file mode 100644
index 000000000..796162fe4
Binary files /dev/null and b/app_web_widget_ztree/static/description/z_hr1.gif differ
diff --git a/app_web_widget_ztree/static/description/z_product1.gif b/app_web_widget_ztree/static/description/z_product1.gif
new file mode 100644
index 000000000..e471a66c3
Binary files /dev/null and b/app_web_widget_ztree/static/description/z_product1.gif differ
diff --git a/app_web_widget_ztree/static/description/z_stock1.gif b/app_web_widget_ztree/static/description/z_stock1.gif
new file mode 100644
index 000000000..2e947ba39
Binary files /dev/null and b/app_web_widget_ztree/static/description/z_stock1.gif differ
diff --git a/app_web_widget_ztree/static/src/img/line.svg b/app_web_widget_ztree/static/src/img/line.svg
new file mode 100644
index 000000000..49b41fb12
--- /dev/null
+++ b/app_web_widget_ztree/static/src/img/line.svg
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app_web_widget_ztree/static/src/js/ztree.js b/app_web_widget_ztree/static/src/js/ztree.js
new file mode 100644
index 000000000..b5dead2e0
--- /dev/null
+++ b/app_web_widget_ztree/static/src/js/ztree.js
@@ -0,0 +1,188 @@
+/** @odoo-module */
+
+import { AutoComplete } from "@web/core/autocomplete/autocomplete";
+import { loadJS } from "@web/core/assets";
+const { Component, useRef } = owl;
+import {session} from "@web/session";
+import { useService } from "@web/core/utils/hooks";
+//todo: ztree 继承 import { AutoComplete } from "@web/core/autocomplete/autocomplete";
+//field ztree 继承 fieldm2o,优化 xml 并入 Many2XAutocomplete
+export class Ztree extends AutoComplete {
+ setup() {
+ super.setup();
+ let self = this;
+ let setting = self.props.setting;
+ let data = self.props.data;
+ this.rpc = useService("rpc");
+ this.orm = useService("orm");
+ this.ztree_root = useRef("ztree_root");
+ this.$Ztree = false;
+ this.zNodes = false;
+ let ztree_Max = 1000;
+ this.setting = {
+ view: {
+ selectedMulti: true,
+ fontCss: function getFont(treeId, node) {
+ return node.font ? node.font : {};
+ },
+ nameIsHTML: true,
+ showIcon: false,
+ txtSelectedEnable: true,
+ },
+ data: {
+ key: {
+ title: "title"
+ },
+ simpleData: {
+ enable: true,
+ }
+ }
+ };
+
+ if (setting)
+ $.extend(this.setting, setting);
+
+ //如果有定义zNodes,则直接按 zNodes数据展现,否则 rpc 取
+
+ if (data && data.zNodes && data.zNodes.length)
+ this.zNodes = data.zNodes;
+ this.ztree_field = data.ztree_field;
+ this.ztree_model = data.ztree_model;
+ this.ztree_parent_key = data.ztree_parent_key;
+ //todo: root_id,这个是节点的根id,用 parent_left < x < parent_right 实现,在 domain 增加值
+ this.ztree_root_id = data.ztree_root_id;
+ this.ztree_domain = data.ztree_domain;
+ this.ztree_context = data.ztree_context ? data.ztree_context : session.user_context;
+ this.order = data.order;
+ this.ztree_selected_id = Number(data.ztree_selected_id);
+ this.ztree_selected_vals = [];
+ this.ztree_with_sub_node = data.ztree_with_sub_node;
+ this.ztree_index = data.ztree_index;
+ this.ztree_add_show_all = data.ztree_add_show_all;
+ //默认2级
+ this.ztree_expend_level = data.ztree_expend_level ? data.ztree_expend_level : 2;
+ this.ztree_name_field = data.ztree_name_field;
+ this.limit = data.limit > 0 ? data.limit : ztree_Max;
+ this.ztree_id = 'ztree-' + this.guid();
+ this.ztree_type = data.ztree_type ? data.ztree_type : 'select';
+
+ //点击外部关闭ztree
+ $(document).delegate('body', 'click', function (ev) {
+ var $parent = $(ev.target).parents('.dropdown')
+ if (!$parent.length && self.zNodes) {
+ self.close()}
+ });
+ }
+
+ loadSources(useInput) {
+ let self = this;
+ this.sources = [];
+ this.state.activeSourceOption = null;
+ const proms = [];
+ let request = useInput ? this.inputRef.el.value.trim() : ""
+ for (const pSource of this.props.sources) {
+ const source = this.makeSource(pSource);
+ this.sources.push(source);
+ const options = this.loadOptions(
+ pSource.options,
+ useInput ? this.inputRef.el.value.trim() : ""
+ );
+ if (options instanceof Promise) {
+ source.isLoading = true;
+ const prom = options.then((options) => {
+ source.options = options.map((option) => this.makeOption(option));
+ source.isLoading = false;
+ this.state.optionsRev++;
+ this.zNodes = options;
+ this.state.open = true;
+ });
+ proms.push(prom);
+ }
+ }
+
+ Promise.all(proms).then(() => {
+ self.navigate(0);
+ var $el = $('#' + self.ztree_id);
+ if ($el) {
+ self.$Ztree = $.fn.zTree.init($el, self.setting, self.zNodes);
+ let ztree_selected_id = this.inputRef.el.getAttribute('data-ztree_selected_id');
+ if (!request && ztree_selected_id != undefined && ztree_selected_id > 0) {
+ var node = self.$Ztree.getNodeByParam('id', ztree_selected_id, null);
+ if (node)
+ self.$Ztree.selectNode(node);
+ }
+ }
+ });
+ }
+
+ makeOption(option) {
+ let res = {};
+ if (!option.action)
+ option = {label: option.name, value: option.id};
+ else
+ option = {
+ label: option.label,
+ value: option.id,
+ action: option.action
+ }
+ res = Object.assign(Object.create(option), {
+ id: ++this.nextOptionId,
+ });
+ return res;
+ }
+
+ close() {
+ super.close();
+ if (this.zNodes) {
+ $.fn.zTree.destroy(this.ztree_id);
+ this.$Ztree = undefined;
+ this.zNodes = false;
+ }
+ }
+
+ onInputBlur() {
+ const value = this.inputRef.el.value;
+ if (
+ this.props.autoSelect &&
+ value.length > 0
+ ) {
+ ;
+ } else {
+ this.props.onBlur({
+ inputValue: value,
+ });
+ this.close();
+ }
+ }
+
+ guid() {
+ return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
+ var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
+ return v.toString(16);
+ });
+ }
+
+ getChildNodes(treeNode) {
+ var childNodes = this.$Ztree.transformToArray(treeNode);
+ var nodes = new Array();
+ var i;
+ for (i = 0; i < childNodes.length; i++) {
+ nodes[i] = childNodes[i].id;
+ }
+
+ return nodes.join(",");
+ }
+}
+
+Ztree.template = "App.Ztree";
+
+Ztree.props = {
+ ...AutoComplete.props,
+ setting: {type: Object, optional: true},
+ data: {type: Object, optional: true},
+};
+
+Ztree.defaultProps = {
+ ...AutoComplete.defaultProps,
+};
+
diff --git a/app_web_widget_ztree/static/src/js/ztree_chart.js b/app_web_widget_ztree/static/src/js/ztree_chart.js
new file mode 100644
index 000000000..f0ea9c1a4
--- /dev/null
+++ b/app_web_widget_ztree/static/src/js/ztree_chart.js
@@ -0,0 +1,208 @@
+/** @odoo-module */
+
+import {X2ManyField, x2ManyField} from '@web/views/fields/x2many/x2many_field';
+
+import { onMounted, useRef } from "@odoo/owl";
+import {session} from "@web/session";
+import {Ztree} from './ztree';
+import {ZtreeMany2X} from './ztree_many2x';
+import {registry} from "@web/core/registry";
+import {useService} from "@web/core/utils/hooks";
+import {_lt} from "@web/core/l10n/translation";
+import {FieldZTree} from "./ztree_select";
+
+export class FieldZTreeChart extends X2ManyField {
+ async setup() {
+ super.setup();
+ let self = this;
+ let setting = self.props.setting;
+ let data = self.props;
+ this.rpc = useService("rpc");
+ this.orm = useService("orm");
+ this.action = useService("action");
+ this.ztree_root = useRef("ztree_root");
+ this.$Ztree = false;
+ this.zNodes = false;
+ let ztree_Max = 1000;
+ this.setting = {
+ view: {
+ selectedMulti: true,
+ fontCss: function getFont(treeId, node) {
+ return node.font ? node.font : {};
+ },
+ nameIsHTML: true,
+ showIcon: false,
+ txtSelectedEnable: true,
+ },
+ callback: {
+ onClick: function (event, treeId, treeNode, clickFlag) {
+ self.onSelect(event, {
+ treeId: treeId,
+ treeNode: treeNode,
+ });
+ }
+ },
+ data: {
+ key: {
+ title: "title"
+ },
+ simpleData: {
+ enable: true,
+ }
+ }
+ };
+
+ if (setting)
+ $.extend(this.setting, setting);
+
+ //如果有定义zNodes,则直接按 zNodes数据展现,否则 rpc 取
+
+ if (self.props && self.props.zNodes && self.props.zNodes.length)
+ this.zNodes = self.props.zNodes;
+ this.ztree_field = self.props.name;
+ this.ztree_model = self.props.record.resModel;
+ this.ztree_parent_key = self.field.relation_field;
+ //todo: root_id,这个是节点的根id,用 parent_left < x < parent_right 实现,在 domain 增加值
+ this.ztree_root_id = data.ztree_root_id;
+ this.ztree_domain = data.ztree_domain;
+ this.ztree_context = data.ztree_context ? data.ztree_context : session.user_context;
+ this.order = data.order;
+ this.ztree_selected_id = Number(data.record.data.id);
+ this.ztree_selected_vals = [];
+ this.ztree_with_sub_node = data.ztree_with_sub_node;
+ this.ztree_index = data.ztree_index;
+ this.ztree_add_show_all = false;
+ //默认2级
+ this.ztree_expend_level = data.ztree_expend_level ? data.ztree_expend_level : 2;
+ this.ztree_name_field = data.ztree_name_field;
+ this.limit = data.limit > 0 ? data.limit : ztree_Max;
+ self.ztree_id = 'ztree-' + self.guid();
+ this.ztree_type = data.ztree_type ? data.ztree_type : 'chart';
+ onMounted(this.handleComponentUpdate.bind(this));
+ }
+
+ async handleComponentUpdate() {
+ let self = this;
+ self.zNodes = await self.loadZchartSource().then(function (){
+ var $el = $('#' + self.ztree_id);
+ if ($el && self.zNodes) {
+ self.$Ztree = $.fn.zTree.init($el, self.setting, self.zNodes);
+ let ztree_selected_id = self.props.record.data.id;
+ if (ztree_selected_id != undefined && ztree_selected_id > 0 && self.props.record.data.id) {
+ var node = self.$Ztree.getNodeByParam('id', ztree_selected_id, null);
+ if (node)
+ self.$Ztree.selectNode(node);
+ };
+ };
+ });
+ }
+
+ async loadZchartSource() {
+ //数据初始化
+ let self = this;
+ if (self.lastProm) {
+ self.lastProm.abort(false);
+ }
+ let ztree_Max = 1000;
+ var domain = self.ztree_domain || [];
+ let root_id = self.ztree_root_id;
+ if (!root_id) {
+ root_id = self.props.record.data.parent_id ? self.props.record.data.parent_id[0] : 0;
+ }
+ if (!root_id) {
+ root_id = self.props.record.data.id;
+ }
+ self.ztree_selected_id = self.props.record.data.id;
+ let para = {
+ context: self.ztree_context || {},
+ domain: domain,
+ parent_key: self.ztree_parent_key,
+ root_id: root_id,
+ expend_level: self.ztree_expend_level,
+ name_field: self.ztree_name_field,
+ order: self.order,
+ limit: parseInt(self.props.limit ? self.props.limit : ztree_Max),
+ type: 'chart',
+ //如果 type='chart',要按 selected_id 得到 root_id 遍历
+ selected_id: self.ztree_selected_id,
+ };
+ this.lastProm = this.orm.call(this.props.record.resModel, 'search_ztree', [], para);
+
+ const records = await this.lastProm;
+ self.zNodes = records || [];
+ return records;
+ }
+
+ async onSelect(option, params = {}) {
+ var self = this;
+ var record = {
+ id: 0,
+ name: '',
+ };
+ if (params.treeNode) {
+ record = {
+ id: params.treeNode.id,
+ name: params.treeNode.name,
+ };
+ //todo: 面包屑处理不生效,后续优化
+ // let action = await self.orm.call(self.props.record.resModel, 'get_formview_action', [record.id]);
+ var action = self.env.model.action.currentController.action;
+ action = {...action,
+ res_id: record.id,
+ views: [[false, "form"]],
+ };
+ var bs = self.env.config.breadcrumbs;
+ if (bs.length > 1) {
+ self.action.doAction(action, {
+ clearBreadcrumbs: true,
+ });
+ } else {
+ self.action.doAction(action);
+ }
+ }
+ }
+
+ guid() {
+ return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
+ var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
+ return v.toString(16);
+ });
+ }
+
+}
+
+FieldZTreeChart.components = {Ztree};
+
+FieldZTree.components = {
+ ...X2ManyField.components,
+ Ztree,
+ ZtreeMany2X,
+};
+
+FieldZTreeChart.props = {
+ ...X2ManyField.props,
+ ztree_parent_key: {type: String, optional: true},
+ ztree_root_id: {type: Number, optional: true},
+ ztree_name_field: {type: String, optional: true},
+ order: {type: String, optional: true},
+ ztree_expend_level: {type: String, optional: true},
+};
+FieldZTreeChart.supportedTypes = ["one2many"];
+FieldZTreeChart.displayName = _lt("Hierarchy Chart");
+FieldZTreeChart.template = 'App.FieldZtreeChart';
+
+export const fieldZTreeChart = {
+ ...x2ManyField,
+ component: FieldZTreeChart,
+ extractProps({ options }) {
+ const props = x2ManyField.extractProps(...arguments);
+ props.ztree_parent_key = options.ztree_parent_key;
+ props.ztree_root_id = options.ztree_root_id;
+ props.ztree_name_field = options.ztree_name_field;
+ props.order = options.order;
+ props.ztree_expend_level = options.ztree_expend_level;
+ return props;
+ },
+};
+
+registry.category("fields").add("ztree_chart", fieldZTreeChart);
diff --git a/app_web_widget_ztree/static/src/js/ztree_many2x.js b/app_web_widget_ztree/static/src/js/ztree_many2x.js
new file mode 100644
index 000000000..3cccafd40
--- /dev/null
+++ b/app_web_widget_ztree/static/src/js/ztree_many2x.js
@@ -0,0 +1,147 @@
+/** @odoo-module */
+
+import { _t } from "@web/core/l10n/translation";
+import { Many2XAutocomplete } from "@web/views/fields/relational_utils";
+import { Ztree } from "@app_web_widget_ztree/js/ztree";
+import { sprintf } from "@web/core/utils/strings";
+
+export class ZtreeMany2X extends Many2XAutocomplete {
+ setup() {
+ super.setup();
+ let self = this;
+ self.props = Object.assign(self.props, {
+ setting: {
+ callback: {
+ onClick: function (event, treeId, treeNode, clickFlag) {
+ self.onSelect(event, {
+ treeId: treeId,
+ treeNode: treeNode,
+ });
+ }
+ }
+ },
+ data: Object.assign(self.props.data,{
+ ztree_model: self.props.resModel,
+ }),
+ })
+ };
+
+ async loadOptionsSource(request) {
+ //数据初始化
+ if (this.lastProm) {
+ this.lastProm.abort(false);
+ }
+ let ztree_Max = 1000;
+ let data = this.props.data;
+ var domain = data.ztree_domain;
+ if (data.ztree_name_field && request && request.trim().length >= 1) {
+ domain = domain.concat([[data.ztree_name_field, 'ilike', request]]);
+ }
+
+ let para = {
+ context: data.ztree_context,
+ domain: domain,
+ parent_key: data.ztree_parent_key,
+ root_id: data.ztree_root_id,
+ expend_level: data.ztree_expend_level,
+ name_field: data.ztree_name_field,
+ order: data.order,
+ limit: parseInt(data.limit ? data.limit : ztree_Max),
+ type: data.ztree_type,
+ //如果 type='chart',要按 selected_id 得到 root_id 遍历
+ selected_id: data.ztree_selected_id,
+ }
+ this.lastProm = this.orm.call(this.props.resModel, 'search_ztree', [], para)
+
+ const records = await this.lastProm;
+ const options = records;
+ const max_id = Math.max.apply(Math,records.map(item => { return item.id }))
+
+ if (this.props.quickCreate && request.length) {
+ options.push({
+ id: max_id + ztree_Max + 1,
+ name: sprintf(_t(`Create "%s"`), request),
+ label: sprintf(_t(`Create "%s"`), request),
+ classList: "o_m2o_dropdown_option o_m2o_dropdown_option_create",
+ font: {'text-align': 'right', 'padding-right': '10px'},
+ action: async (params) => {
+ try {
+ await this.props.quickCreate(request, params);
+ } catch (e) {
+ if (e && e.name === "RPC_ERROR") {
+ const context = this.getCreationContext(request);
+ return this.openMany2X({ context });
+ }
+ // Compatibility with legacy code
+ if (e && e.message && e.message.name === "RPC_ERROR") {
+ // The event.preventDefault() is necessary because we still use the legacy
+ e.event.preventDefault();
+ const context = this.getCreationContext(request);
+ return this.openMany2X({ context });
+ }
+ throw e;
+ }
+ },
+ });
+ }
+
+ const canCreateEdit =
+ "createEdit" in this.activeActions
+ ? this.activeActions.createEdit
+ : this.activeActions.create;
+
+ if (request.length && canCreateEdit) {
+ const context = this.getCreationContext(request);
+ options.push({
+ id: max_id + ztree_Max + 2,
+ name: _t("Create and edit..."),
+ label: _t("Create and edit..."),
+ classList: "o_m2o_dropdown_option o_m2o_dropdown_option_create_edit",
+ font: {'text-align': 'right', 'padding-right': '10px'},
+ action: () => this.openMany2X({ context }),
+ });
+ }
+
+ if (!this.props.noSearchMore && this.props.searchLimit < records.length) {
+ options.push({
+ id: max_id + ztree_Max + 3,
+ name: _t("Search More..."),
+ label: _t("Search More..."),
+ classList: "o_m2o_dropdown_option o_m2o_dropdown_option_search_more",
+ font: {'text-align': 'right', 'padding-right': '10px'},
+ action: this.onSearchMore.bind(this, request),
+ });
+ }
+ return options;
+ }
+
+ onSelect(option, params = {}) {
+ let self = this;
+ let record = {
+ id: 0,
+ name: '',
+ };
+ if (params.treeNode) {
+ if (params.treeNode.action) {
+ const autoCompleteInput = this.autoCompleteContainer.el.querySelector("input");
+ return params.treeNode.action(autoCompleteInput);
+ }
+ else
+ record = {
+ id: params.treeNode.id,
+ name: params.treeNode.name,
+ };
+ }
+ self.props.data.ztree_selected_id = record.id;
+ self.props.update([record], params);
+ const autoCompleteInput = this.autoCompleteContainer.el.querySelector("input");
+ autoCompleteInput.setAttribute('data-ztree_selected_id', record.id);
+ }
+}
+
+ZtreeMany2X.template = "App.ZtreeMany2X";
+ZtreeMany2X.components = { Ztree };
+ZtreeMany2X.props = {
+ ...Many2XAutocomplete.props,
+ data: {type: Object, optional: true},
+}
\ No newline at end of file
diff --git a/app_web_widget_ztree/static/src/js/ztree_select.js b/app_web_widget_ztree/static/src/js/ztree_select.js
new file mode 100644
index 000000000..f70b8da1f
--- /dev/null
+++ b/app_web_widget_ztree/static/src/js/ztree_select.js
@@ -0,0 +1,101 @@
+/** @odoo-module */
+
+// const { Component, useEffect, onWillStart, onWillUnmount } = owl;
+import {session} from "@web/session";
+import { useService } from "@web/core/utils/hooks";
+import { registry } from "@web/core/registry";
+import { ZtreeMany2X } from "@app_web_widget_ztree/js/ztree_many2x";
+import { Many2OneField, many2OneField } from '@web/views/fields/many2one/many2one_field';
+
+//todo: ztree 继承 import { AutoComplete } from "@web/core/autocomplete/autocomplete";
+//field ztree 继承 fieldm2o,优化 xml 并入 Many2XAutocomplete
+
+export class FieldZTree extends Many2OneField {
+ setup() {
+ super.setup();
+ let self = this;
+ this.limit = this.SEARCH_MORE_LIMIT ? this.SEARCH_MORE_LIMIT : 1000;
+ this.ztree_domain = self.getDomain();
+ this.ztree_field = self.props.name;
+ this.ztree_model = self.relation;
+ this.ztree_parent_key = self.props.ztree_parent_key;
+ this.ztree_root_id = self.props.ztree_root_id;
+ this.ztree_name_field = self.props.ztree_name_field;
+ this.ztree_selected_id = self.props.value ? self.props.value[0] : false;
+ this.order = self.props.order;
+ this.ztree_expend_level = self.props.ztree_expend_level;
+ // onWillStart(async () => {
+ // //数据初始化
+ // await this.willStart();
+ // });
+ // useEffect(() => this.start());
+ }
+
+ get ZtreeMany2xProps() {
+ let self = this;
+ let res = {
+ ...self.Many2XAutocompleteProps,
+ data: {
+ ztree_domain: self.ztree_domain,
+ ztree_field: self.ztree_field,
+ ztree_model: self.relation,
+ ztree_parent_key: self.ztree_parent_key,
+ ztree_root_id: self.ztree_root_id,
+ ztree_expend_level: self.ztree_expend_level,
+ ztree_name_field: self.props.ztree_name_field,
+ ztree_selected_id: self.props.value ? self.props.value[0] : false,
+ order: self.order,
+ },
+ }
+ return res;
+ }
+
+}
+
+
+FieldZTree.template = "App.FieldZtree";
+FieldZTree.supportedTypes = ["many2one"];
+FieldZTree.components = {
+ ...Many2OneField.components,
+ ZtreeMany2X,
+};
+
+//todo: 自行渲染 Many2XAutocomplete , loadOptionsSource, web.Many2XAutocomplete
+
+FieldZTree.props = {
+ ...Many2OneField.props,
+ ztree_parent_key: { type: String, optional: true },
+ ztree_root_id: { type: Number, optional: true },
+ ztree_name_field: { type: String, optional: true },
+ order: { type: String, optional: true },
+ ztree_expend_level: { type: String, optional: true },
+};
+
+FieldZTree.extractProps = ({ field, attrs }) => {
+ return {
+ ...Many2OneField.extractProps({ field, attrs }),
+ ztree_parent_key: attrs.options.ztree_parent_key,
+ ztree_root_id: attrs.options.ztree_root_id,
+ ztree_name_field: attrs.options.ztree_name_field,
+ order: attrs.options.order,
+ ztree_expend_level: attrs.options.ztree_expend_level,
+ };
+};
+
+export const fieldZTree = {
+ ...many2OneField,
+ component: FieldZTree,
+ extractProps({ options }) {
+ const props = many2OneField.extractProps(...arguments);
+ props.ztree_parent_key = options.ztree_parent_key;
+ props.ztree_root_id = options.ztree_root_id;
+ props.ztree_name_field = options.ztree_name_field;
+ props.order = options.order;
+ props.ztree_expend_level = options.ztree_expend_level;
+ return props;
+ },
+};
+
+registry.category("fields").add("ztree_select", fieldZTree);
+// registry.category("fields").add("list.ztree_select", FieldZTree);
+// registry.category("fields").add("kanban.ztree_select", FieldZTree);
diff --git a/app_web_widget_ztree/static/src/lib/ztree_v3/css/awesomeStyle/awesome.scss b/app_web_widget_ztree/static/src/lib/ztree_v3/css/awesomeStyle/awesome.scss
new file mode 100644
index 000000000..0f32bc74a
--- /dev/null
+++ b/app_web_widget_ztree/static/src/lib/ztree_v3/css/awesomeStyle/awesome.scss
@@ -0,0 +1,448 @@
+/*-------------------------------------
+zTree Style using fontawesome instead of images
+
+version: 1.1
+author: Mike King
+email: mikkelking $ hotmail . com
+website: http://code.google.com/p/jquerytree/
+
+-------------------------------------*/
+
+// Colors
+/* Definitions ----------------------*/
+$font-size: $o-font-size-base;
+// Regular icon and text color is white, which suits any medium -> dark background
+$color-normal: $o-main-text-color;
+// Background color
+$color-bg: $o-list-footer-bg-color;
+// Highlight color
+$color-highlight: white;
+$color-highlight-bg: $o-brand-primary;
+// Partially selected (checkboxes, radio buttons)
+$color-partial: $o-main-text-color;
+;
+// Partially selected and focused (checkboxes, radio buttons)
+$color-partfocus: $o-main-text-color;
+;
+// Disabled altogether
+$color-disabled: $o-main-color-muted;
+// Editing color
+$color-edit: yellow;
+$w: 22px;
+$h: 24px;
+$pad-left: 2px;
+$pad-top: 10px;
+/* End of Definitions ---------------*/
+.ztree * {
+ padding: 0;
+ margin: 0;
+ font-size: $font-size;
+}
+
+.ztree {
+ margin: 0;
+ padding: 5px;
+ color: $color-normal;
+
+ li {
+ padding: 0 5px;
+ margin: 0;
+ list-style: none;
+ line-height: 17px;
+ text-align: left;
+ white-space: nowrap;
+ outline: 0;
+ ul {
+ margin: 0px;
+ padding: 0 0 0 18px;
+ }
+ ul.line {
+ }
+ a {
+ padding-right: 3px;
+ margin: 0;
+ cursor: pointer;
+ height: $h;
+ color: $color-normal;
+ background-color: transparent;
+ text-decoration: none;
+ vertical-align: top;
+ display: inline-block;
+ width: calc(100% - 10px);
+ .showAll {
+
+ }
+ input.rename {
+ height: 14px;
+ width: 80px;
+ padding: 0;
+ margin: 0;
+ color: $color-bg;
+ background-color: $color-normal;
+ font-size: $font-size;
+ border: 1px #585956 solid;
+ *border: 0px
+ }
+ }
+ a:hover {
+ background-color: $color-highlight-bg;
+ color: $color-highlight;
+ opacity: 0.8;
+ }
+ a.curSelectedNode {
+ padding-top: 0px;
+ background-color: $color-highlight-bg;
+ color: $color-highlight;
+ height: $h;
+ }
+ a.curSelectedNode_Edit {
+ padding-top: 0px;
+ background-color: transparent;
+ color: $color-highlight;
+ height: $h;
+ border: 1px $o-brand-primary solid;
+ opacity: 0.8;
+ }
+ a.tmpTargetNode_inner {
+ padding-top: 0px;
+ background-color: $o-brand-primary;
+ color: $color-highlight;
+ height: $h;
+ border: 1px $o-brand-primary solid;
+ opacity: 0.8;
+ filter: alpha(opacity=80)
+ }
+ a.tmpTargetNode_prev {
+ }
+ a.tmpTargetNode_next {
+ }
+ span {
+ line-height: $h;
+ margin-right: 2px;
+ background-color: transparent;
+ }
+ span.button {
+ line-height: 0;
+ margin: 0;
+ padding: 0 2px;
+ width: $w;
+ height: $h;
+ display: inline-block;
+ vertical-align: top;
+ border: 0px solid;
+ cursor: pointer;
+ outline: none;
+ background-color: transparent;
+ background-repeat: no-repeat;
+ background-attachment: scroll;
+
+ &::before {
+ font-family: FontAwesome;
+ padding-top: $pad-top;
+ }
+ &.chk {
+ margin: 0px;
+ cursor: auto;
+ width: 12px;
+ display: inline-block;
+ padding-top: $pad-top;
+ padding-left: $pad-left;
+
+ &.checkbox_false_full::before {
+ content: $fa-square-o;
+ }
+ &.checkbox_false_full_focus::before {
+ content: $fa-square-o;
+ color: $color-highlight;
+ }
+ &.checkbox_false_part::before {
+ content: $fa-square-o;
+ color: $color-partial;
+ }
+ &.checkbox_false_part_focus::before {
+ content: $fa-square-o;
+ color: $color-partfocus;
+ }
+ &.checkbox_false_disable::before {
+ content: $fa-square-o;
+ color: $color-disabled;
+ }
+ &.checkbox_true_full::before {
+ content: $fa-check-square-o;
+ }
+ &.checkbox_true_full_focus::before {
+ content: $fa-check-square-o;
+ }
+ &.checkbox_true_part::before {
+ content: $fa-check-square;
+ }
+ &.checkbox_true_part_focus::before {
+ content: $fa-check-square;
+ color: $color-highlight
+ }
+ &.checkbox_true_full_focus::before {
+ content: $fa-check-square-o;
+ color: $color-highlight
+ }
+ &.checkbox_true_part::before {
+ content: $fa-check-square-o;
+ color: $color-partial
+ }
+ &.checkbox_true_part_focus::before {
+ content: $fa-check-square-o;
+ color: $color-partfocus;
+ }
+ &.checkbox_true_disable::before {
+ content: $fa-check-square-o;
+ color: $color-disabled
+ }
+
+ &.radio_false_full::before {
+ content: $fa-circle-o;
+ }
+ &.radio_false_full_focus::before {
+ content: $fa-circle-o;
+ color: $color-highlight
+ }
+ &.radio_false_part::before {
+ content: $fa-circle-o;
+ color: $color-partial
+ }
+ &.radio_false_part_focus::before {
+ content: $fa-circle-o;
+ color: $color-highlight
+ }
+ &.radio_false_disable::before {
+ content: $fa-circle-thin;
+ color: $color-disabled
+ }
+ &.radio_true_full::before {
+ content: $fa-dot-circle-o;
+ }
+ &.radio_true_full_focus::before {
+ content: $fa-dot-circle-o;
+ color: $color-highlight
+ }
+ &.radio_true_part::before {
+ content: $fa-dot-circle-o;
+ color: $color-partial
+ }
+ &.radio_true_part_focus::before {
+ content: $fa-dot-circle-o;
+ color: $color-partial;
+ }
+ &.radio_true_disable::before {
+ content: $fa-circle-thin;
+ color: $color-disabled
+ }
+
+ }
+ &.switch {
+ width: $w;
+ height: $h
+ }
+ &.root_open::before {
+ content: $fa-chevron-down;
+ padding-top: $pad-top;
+ padding-left: $pad-left;
+ display: inline-block;
+ }
+ &.root_close::before {
+ content: $fa-chevron-right;
+ padding-top: $pad-top;
+ padding-left: $pad-left;
+ display: inline-block;
+ }
+ &.roots_open::before {
+ content: $fa-chevron-down;
+ padding-top: $pad-top;
+ padding-left: $pad-left;
+ display: inline-block;
+ }
+ &.roots_close::before {
+ content: $fa-chevron-right;
+ padding-top: $pad-top;
+ padding-left: $pad-left;
+ display: inline-block;
+ }
+ &.center_open::before {
+ content: $fa-chevron-down;
+ padding-top: $pad-top;
+ padding-left: $pad-left;
+ display: inline-block;
+ }
+ &.center_close::before {
+ content: $fa-chevron-right;
+ padding-top: $pad-top;
+ padding-left: $pad-left;
+ display: inline-block;
+ }
+ &.bottom_open::before {
+ content: $fa-chevron-down;
+ padding-top: $pad-top;
+ padding-left: $pad-left;
+ display: inline-block;
+ }
+ &.bottom_close::before {
+ content: $fa-chevron-right;
+ padding-top: $pad-top;
+ padding-left: $pad-left;
+ display: inline-block;
+ }
+ &.noline_open {
+ }
+ &.noline_close {
+ }
+ &.root_docu {
+ background: none;
+ }
+ &.roots_docu::before {
+ content: $fa-list-alt;
+ padding-left: $pad-left;
+ display: inline-block;
+
+ }
+ &.center_docu::before {
+ padding-top: $pad-top;
+ padding-left: $pad-left;
+ display: inline-block;
+
+ }
+ &.bottom_docu::before {
+ padding-top: $pad-top;
+ padding-left: $pad-left;
+ display: inline-block;
+
+ }
+ &.noline_docu {
+ background: none;
+ }
+
+ &.ico_open::before {
+ content: $fa-folder-open-o;
+ font-family: FontAwesome;
+ padding-top: $pad-top;
+ padding-left: $pad-left;
+ display: inline-block;
+
+ }
+ &.ico_close::before {
+ content: $fa-folder-o;
+ font-family: FontAwesome;
+ padding-top: $pad-top;
+ padding-left: $pad-left;
+ display: inline-block;
+
+ }
+ &.ico_docu::before {
+ content: $fa-list-alt;
+ font-family: FontAwesome;
+ padding-top: $pad-top;
+ padding-left: $pad-left;
+ display: inline-block;
+
+ }
+ &.showAll_ico_docu::before {
+ content: $fa-list;
+ font-family: FontAwesome;
+ padding-top: $pad-top;
+ padding-left: $pad-left;
+ display: inline-block;
+
+ }
+
+ &.edit {
+ margin-left: 4px;
+ margin-right: -1px;
+ vertical-align: top;
+ *vertical-align: middle;
+ padding-top: $pad-top;
+ }
+ &.edit::before {
+ content: $fa-pencil-square-o;
+ font-family: FontAwesome;
+ }
+
+ &.remove {
+ margin-left: 4px;
+ margin-right: -1px;
+ vertical-align: top;
+ *vertical-align: middle;
+ padding-top: $pad-top;
+ }
+ &.remove::before {
+ content: $fa-trash;
+ font-family: FontAwesome;
+ }
+
+ &.add {
+ margin-left: 4px;
+ margin-right: -1px;
+ vertical-align: top;
+ *vertical-align: middle;
+ padding-top: $pad-top;
+ }
+ &.add::before {
+ content: $fa-plus;
+ font-family: FontAwesome;
+ }
+
+ &.ico_loading {
+ margin-right: 2px;
+ background: url(./img/loading.gif) no-repeat scroll 0 0 transparent;
+ vertical-align: top;
+ *vertical-align: middle
+ }
+ }
+
+ }
+}
+
+ul.tmpTargetzTree {
+ background-color: #FFE6B0;
+ opacity: 0.8;
+ filter: alpha(opacity=80)
+}
+
+// this is the arrow that moves
+span.tmpzTreeMove_arrow {
+ width: 16px;
+ height: $h;
+ display: inline-block;
+ padding: 0;
+ margin: 2px 0 0 1px;
+ border: 0 none;
+ position: absolute;
+ background-color: transparent;
+ background-attachment: scroll;
+}
+
+span.tmpzTreeMove_arrow::before {
+ content: $fa-play;
+ font-family: FontAwesome;
+ color: $color-highlight;
+}
+
+// outline
+
+ul.ztree.zTreeDragUL {
+ margin: 0;
+ padding: 0;
+ position: absolute;
+ width: auto;
+ height: auto;
+ overflow: hidden;
+ background-color: #cfcfcf;
+ border: 1px $color-highlight dotted;
+ opacity: 0.8;
+ filter: alpha(opacity=80)
+}
+
+.ztreeMask {
+ z-index: 10000;
+ background-color: #cfcfcf;
+ opacity: 0.0;
+ filter: alpha(opacity=0);
+ position: absolute
+}
+
diff --git a/app_web_widget_ztree/static/src/lib/ztree_v3/css/awesomeStyle/fa.scss b/app_web_widget_ztree/static/src/lib/ztree_v3/css/awesomeStyle/fa.scss
new file mode 100644
index 000000000..e0586e099
--- /dev/null
+++ b/app_web_widget_ztree/static/src/lib/ztree_v3/css/awesomeStyle/fa.scss
@@ -0,0 +1,480 @@
+$fa-glass: "\f000";
+$fa-music: "\f001";
+$fa-search: "\f002";
+$fa-envelope-o: "\f003";
+$fa-heart: "\f004";
+$fa-star: "\f005";
+$fa-star-o: "\f006";
+$fa-user: "\f007";
+$fa-film: "\f008";
+$fa-th-large: "\f009";
+$fa-th: "\f00a";
+$fa-th-list: "\f00b";
+$fa-check: "\f00c";
+$fa-times: "\f00d";
+$fa-search-plus: "\f00e";
+$fa-search-minus: "\f010";
+$fa-power-off: "\f011";
+$fa-signal: "\f012";
+$fa-cog: "\f013";
+$fa-trash-o: "\f014";
+$fa-home: "\f015";
+$fa-file-o: "\f016";
+$fa-clock-o: "\f017";
+$fa-road: "\f018";
+$fa-download: "\f019";
+$fa-arrow-circle-o-down: "\f01a";
+$fa-arrow-circle-o-up: "\f01b";
+$fa-inbox: "\f01c";
+$fa-play-circle-o: "\f01d";
+$fa-repeat: "\f01e";
+$fa-refresh: "\f021";
+$fa-list-alt: "\f022";
+$fa-lock: "\f023";
+$fa-flag: "\f024";
+$fa-headphones: "\f025";
+$fa-volume-off: "\f026";
+$fa-volume-down: "\f027";
+$fa-volume-up: "\f028";
+$fa-qrcode: "\f029";
+$fa-barcode: "\f02a";
+$fa-tag: "\f02b";
+$fa-tags: "\f02c";
+$fa-book: "\f02d";
+$fa-bookmark: "\f02e";
+$fa-print: "\f02f";
+$fa-camera: "\f030";
+$fa-font: "\f031";
+$fa-bold: "\f032";
+$fa-italic: "\f033";
+$fa-text-height: "\f034";
+$fa-text-width: "\f035";
+$fa-align-left: "\f036";
+$fa-align-center: "\f037";
+$fa-align-right: "\f038";
+$fa-align-justify: "\f039";
+$fa-list: "\f03a";
+$fa-outdent: "\f03b";
+$fa-indent: "\f03c";
+$fa-video-camera: "\f03d";
+$fa-picture-o: "\f03e";
+$fa-pencil: "\f040";
+$fa-map-marker: "\f041";
+$fa-adjust: "\f042";
+$fa-tint: "\f043";
+$fa-pencil-square-o: "\f044";
+$fa-share-square-o: "\f045";
+$fa-check-square-o: "\f046";
+$fa-arrows: "\f047";
+$fa-step-backward: "\f048";
+$fa-fast-backward: "\f049";
+$fa-backward: "\f04a";
+$fa-play: "\f04b";
+$fa-pause: "\f04c";
+$fa-stop: "\f04d";
+$fa-forward: "\f04e";
+$fa-fast-forward: "\f050";
+$fa-step-forward: "\f051";
+$fa-eject: "\f052";
+$fa-chevron-left: "\f053";
+$fa-chevron-right: "\f054";
+$fa-plus-circle: "\f055";
+$fa-minus-circle: "\f056";
+$fa-times-circle: "\f057";
+$fa-check-circle: "\f058";
+$fa-question-circle: "\f059";
+$fa-info-circle: "\f05a";
+$fa-crosshairs: "\f05b";
+$fa-times-circle-o: "\f05c";
+$fa-check-circle-o: "\f05d";
+$fa-ban: "\f05e";
+$fa-arrow-left: "\f060";
+$fa-arrow-right: "\f061";
+$fa-arrow-up: "\f062";
+$fa-arrow-down: "\f063";
+$fa-share: "\f064";
+$fa-expand: "\f065";
+$fa-compress: "\f066";
+$fa-plus: "\f067";
+$fa-minus: "\f068";
+$fa-asterisk: "\f069";
+$fa-exclamation-circle: "\f06a";
+$fa-gift: "\f06b";
+$fa-leaf: "\f06c";
+$fa-fire: "\f06d";
+$fa-eye: "\f06e";
+$fa-eye-slash: "\f070";
+$fa-exclamation-triangle: "\f071";
+$fa-plane: "\f072";
+$fa-calendar: "\f073";
+$fa-random: "\f074";
+$fa-comment: "\f075";
+$fa-magnet: "\f076";
+$fa-chevron-up: "\f077";
+$fa-chevron-down: "\f078";
+$fa-retweet: "\f079";
+$fa-shopping-cart: "\f07a";
+$fa-folder: "\f07b";
+$fa-folder-open: "\f07c";
+$fa-arrows-v: "\f07d";
+$fa-arrows-h: "\f07e";
+$fa-bar-chart: "\f080";
+$fa-twitter-square: "\f081";
+$fa-facebook-square: "\f082";
+$fa-camera-retro: "\f083";
+$fa-key: "\f084";
+$fa-cogs: "\f085";
+$fa-comments: "\f086";
+$fa-thumbs-o-up: "\f087";
+$fa-thumbs-o-down: "\f088";
+$fa-star-half: "\f089";
+$fa-heart-o: "\f08a";
+$fa-sign-out: "\f08b";
+$fa-linkedin-square: "\f08c";
+$fa-thumb-tack: "\f08d";
+$fa-external-link: "\f08e";
+$fa-sign-in: "\f090";
+$fa-trophy: "\f091";
+$fa-github-square: "\f092";
+$fa-upload: "\f093";
+$fa-lemon-o: "\f094";
+$fa-phone: "\f095";
+$fa-square-o: "\f096";
+$fa-bookmark-o: "\f097";
+$fa-phone-square: "\f098";
+$fa-twitter: "\f099";
+$fa-facebook: "\f09a";
+$fa-github: "\f09b";
+$fa-unlock: "\f09c";
+$fa-credit-card: "\f09d";
+$fa-rss: "\f09e";
+$fa-hdd-o: "\f0a0";
+$fa-bullhorn: "\f0a1";
+$fa-bell: "\f0f3";
+$fa-certificate: "\f0a3";
+$fa-hand-o-right: "\f0a4";
+$fa-hand-o-left: "\f0a5";
+$fa-hand-o-up: "\f0a6";
+$fa-hand-o-down: "\f0a7";
+$fa-arrow-circle-left: "\f0a8";
+$fa-arrow-circle-right: "\f0a9";
+$fa-arrow-circle-up: "\f0aa";
+$fa-arrow-circle-down: "\f0ab";
+$fa-globe: "\f0ac";
+$fa-wrench: "\f0ad";
+$fa-tasks: "\f0ae";
+$fa-filter: "\f0b0";
+$fa-briefcase: "\f0b1";
+$fa-arrows-alt: "\f0b2";
+$fa-users: "\f0c0";
+$fa-link: "\f0c1";
+$fa-cloud: "\f0c2";
+$fa-flask: "\f0c3";
+$fa-scissors: "\f0c4";
+$fa-files-o: "\f0c5";
+$fa-paperclip: "\f0c6";
+$fa-floppy-o: "\f0c7";
+$fa-square: "\f0c8";
+$fa-bars: "\f0c9";
+$fa-list-ul: "\f0ca";
+$fa-list-ol: "\f0cb";
+$fa-strikethrough: "\f0cc";
+$fa-underline: "\f0cd";
+$fa-table: "\f0ce";
+$fa-magic: "\f0d0";
+$fa-truck: "\f0d1";
+$fa-pinterest: "\f0d2";
+$fa-pinterest-square: "\f0d3";
+$fa-google-plus-square: "\f0d4";
+$fa-google-plus: "\f0d5";
+$fa-money: "\f0d6";
+$fa-caret-down: "\f0d7";
+$fa-caret-up: "\f0d8";
+$fa-caret-left: "\f0d9";
+$fa-caret-right: "\f0da";
+$fa-columns: "\f0db";
+$fa-sort: "\f0dc";
+$fa-sort-desc: "\f0dd";
+$fa-sort-asc: "\f0de";
+$fa-envelope: "\f0e0";
+$fa-linkedin: "\f0e1";
+$fa-undo: "\f0e2";
+$fa-gavel: "\f0e3";
+$fa-tachometer: "\f0e4";
+$fa-comment-o: "\f0e5";
+$fa-comments-o: "\f0e6";
+$fa-bolt: "\f0e7";
+$fa-sitemap: "\f0e8";
+$fa-umbrella: "\f0e9";
+$fa-clipboard: "\f0ea";
+$fa-lightbulb-o: "\f0eb";
+$fa-exchange: "\f0ec";
+$fa-cloud-download: "\f0ed";
+$fa-cloud-upload: "\f0ee";
+$fa-user-md: "\f0f0";
+$fa-stethoscope: "\f0f1";
+$fa-suitcase: "\f0f2";
+$fa-bell-o: "\f0a2";
+$fa-coffee: "\f0f4";
+$fa-cutlery: "\f0f5";
+$fa-file-text-o: "\f0f6";
+$fa-building-o: "\f0f7";
+$fa-hospital-o: "\f0f8";
+$fa-ambulance: "\f0f9";
+$fa-medkit: "\f0fa";
+$fa-fighter-jet: "\f0fb";
+$fa-beer: "\f0fc";
+$fa-h-square: "\f0fd";
+$fa-plus-square: "\f0fe";
+$fa-angle-double-left: "\f100";
+$fa-angle-double-right: "\f101";
+$fa-angle-double-up: "\f102";
+$fa-angle-double-down: "\f103";
+$fa-angle-left: "\f104";
+$fa-angle-right: "\f105";
+$fa-angle-up: "\f106";
+$fa-angle-down: "\f107";
+$fa-desktop: "\f108";
+$fa-laptop: "\f109";
+$fa-tablet: "\f10a";
+$fa-mobile: "\f10b";
+$fa-circle-o: "\f10c";
+$fa-quote-left: "\f10d";
+$fa-quote-right: "\f10e";
+$fa-spinner: "\f110";
+$fa-circle: "\f111";
+$fa-reply: "\f112";
+$fa-github-alt: "\f113";
+$fa-folder-o: "\f114";
+$fa-folder-open-o: "\f115";
+$fa-smile-o: "\f118";
+$fa-frown-o: "\f119";
+$fa-meh-o: "\f11a";
+$fa-gamepad: "\f11b";
+$fa-keyboard-o: "\f11c";
+$fa-flag-o: "\f11d";
+$fa-flag-checkered: "\f11e";
+$fa-terminal: "\f120";
+$fa-code: "\f121";
+$fa-reply-all: "\f122";
+$fa-star-half-o: "\f123";
+$fa-location-arrow: "\f124";
+$fa-crop: "\f125";
+$fa-code-fork: "\f126";
+$fa-chain-broken: "\f127";
+$fa-question: "\f128";
+$fa-info: "\f129";
+$fa-exclamation: "\f12a";
+$fa-superscript: "\f12b";
+$fa-subscript: "\f12c";
+$fa-eraser: "\f12d";
+$fa-puzzle-piece: "\f12e";
+$fa-microphone: "\f130";
+$fa-microphone-slash: "\f131";
+$fa-shield: "\f132";
+$fa-calendar-o: "\f133";
+$fa-fire-extinguisher: "\f134";
+$fa-rocket: "\f135";
+$fa-maxcdn: "\f136";
+$fa-chevron-circle-left: "\f137";
+$fa-chevron-circle-right: "\f138";
+$fa-chevron-circle-up: "\f139";
+$fa-chevron-circle-down: "\f13a";
+$fa-html5: "\f13b";
+$fa-css3: "\f13c";
+$fa-anchor: "\f13d";
+$fa-unlock-alt: "\f13e";
+$fa-bullseye: "\f140";
+$fa-ellipsis-h: "\f141";
+$fa-ellipsis-v: "\f142";
+$fa-rss-square: "\f143";
+$fa-play-circle: "\f144";
+$fa-ticket: "\f145";
+$fa-minus-square: "\f146";
+$fa-minus-square-o: "\f147";
+$fa-level-up: "\f148";
+$fa-level-down: "\f149";
+$fa-check-square: "\f14a";
+$fa-pencil-square: "\f14b";
+$fa-external-link-square: "\f14c";
+$fa-share-square: "\f14d";
+$fa-compass: "\f14e";
+$fa-caret-square-o-down: "\f150";
+$fa-caret-square-o-up: "\f151";
+$fa-caret-square-o-right: "\f152";
+$fa-eur: "\f153";
+$fa-gbp: "\f154";
+$fa-usd: "\f155";
+$fa-inr: "\f156";
+$fa-jpy: "\f157";
+$fa-rub: "\f158";
+$fa-krw: "\f159";
+$fa-btc: "\f15a";
+$fa-file: "\f15b";
+$fa-file-text: "\f15c";
+$fa-sort-alpha-asc: "\f15d";
+$fa-sort-alpha-desc: "\f15e";
+$fa-sort-amount-asc: "\f160";
+$fa-sort-amount-desc: "\f161";
+$fa-sort-numeric-asc: "\f162";
+$fa-sort-numeric-desc: "\f163";
+$fa-thumbs-up: "\f164";
+$fa-thumbs-down: "\f165";
+$fa-youtube-square: "\f166";
+$fa-youtube: "\f167";
+$fa-xing: "\f168";
+$fa-xing-square: "\f169";
+$fa-youtube-play: "\f16a";
+$fa-dropbox: "\f16b";
+$fa-stack-overflow: "\f16c";
+$fa-instagram: "\f16d";
+$fa-flickr: "\f16e";
+$fa-adn: "\f170";
+$fa-bitbucket: "\f171";
+$fa-bitbucket-square: "\f172";
+$fa-tumblr: "\f173";
+$fa-tumblr-square: "\f174";
+$fa-long-arrow-down: "\f175";
+$fa-long-arrow-up: "\f176";
+$fa-long-arrow-left: "\f177";
+$fa-long-arrow-right: "\f178";
+$fa-apple: "\f179";
+$fa-windows: "\f17a";
+$fa-android: "\f17b";
+$fa-linux: "\f17c";
+$fa-dribbble: "\f17d";
+$fa-skype: "\f17e";
+$fa-foursquare: "\f180";
+$fa-trello: "\f181";
+$fa-female: "\f182";
+$fa-male: "\f183";
+$fa-gittip: "\f184";
+$fa-sun-o: "\f185";
+$fa-moon-o: "\f186";
+$fa-archive: "\f187";
+$fa-bug: "\f188";
+$fa-vk: "\f189";
+$fa-weibo: "\f18a";
+$fa-renren: "\f18b";
+$fa-pagelines: "\f18c";
+$fa-stack-exchange: "\f18d";
+$fa-arrow-circle-o-right: "\f18e";
+$fa-arrow-circle-o-left: "\f190";
+$fa-caret-square-o-left: "\f191";
+$fa-dot-circle-o: "\f192";
+$fa-wheelchair: "\f193";
+$fa-vimeo-square: "\f194";
+$fa-try: "\f195";
+$fa-plus-square-o: "\f196";
+$fa-space-shuttle: "\f197";
+$fa-slack: "\f198";
+$fa-envelope-square: "\f199";
+$fa-wordpress: "\f19a";
+$fa-openid: "\f19b";
+$fa-university: "\f19c";
+$fa-graduation-cap: "\f19d";
+$fa-yahoo: "\f19e";
+$fa-google: "\f1a0";
+$fa-reddit: "\f1a1";
+$fa-reddit-square: "\f1a2";
+$fa-stumbleupon-circle: "\f1a3";
+$fa-stumbleupon: "\f1a4";
+$fa-delicious: "\f1a5";
+$fa-digg: "\f1a6";
+$fa-pied-piper: "\f1a7";
+$fa-pied-piper-alt: "\f1a8";
+$fa-drupal: "\f1a9";
+$fa-joomla: "\f1aa";
+$fa-language: "\f1ab";
+$fa-fax: "\f1ac";
+$fa-building: "\f1ad";
+$fa-child: "\f1ae";
+$fa-paw: "\f1b0";
+$fa-spoon: "\f1b1";
+$fa-cube: "\f1b2";
+$fa-cubes: "\f1b3";
+$fa-behance: "\f1b4";
+$fa-behance-square: "\f1b5";
+$fa-steam: "\f1b6";
+$fa-steam-square: "\f1b7";
+$fa-recycle: "\f1b8";
+$fa-car: "\f1b9";
+$fa-taxi: "\f1ba";
+$fa-tree: "\f1bb";
+$fa-spotify: "\f1bc";
+$fa-deviantart: "\f1bd";
+$fa-soundcloud: "\f1be";
+$fa-database: "\f1c0";
+$fa-file-pdf-o: "\f1c1";
+$fa-file-word-o: "\f1c2";
+$fa-file-excel-o: "\f1c3";
+$fa-file-powerpoint-o: "\f1c4";
+$fa-file-image-o: "\f1c5";
+$fa-file-archive-o: "\f1c6";
+$fa-file-audio-o: "\f1c7";
+$fa-file-video-o: "\f1c8";
+$fa-file-code-o: "\f1c9";
+$fa-vine: "\f1ca";
+$fa-codepen: "\f1cb";
+$fa-jsfiddle: "\f1cc";
+$fa-life-ring: "\f1cd";
+$fa-circle-o-notch: "\f1ce";
+$fa-rebel: "\f1d0";
+$fa-empire: "\f1d1";
+$fa-git-square: "\f1d2";
+$fa-git: "\f1d3";
+$fa-hacker-news: "\f1d4";
+$fa-tencent-weibo: "\f1d5";
+$fa-qq: "\f1d6";
+$fa-weixin: "\f1d7";
+$fa-paper-plane: "\f1d8";
+$fa-paper-plane-o: "\f1d9";
+$fa-history: "\f1da";
+$fa-circle-thin: "\f1db";
+$fa-header: "\f1dc";
+$fa-paragraph: "\f1dd";
+$fa-sliders: "\f1de";
+$fa-share-alt: "\f1e0";
+$fa-share-alt-square: "\f1e1";
+$fa-bomb: "\f1e2";
+$fa-futbol-o: "\f1e3";
+$fa-tty: "\f1e4";
+$fa-binoculars: "\f1e5";
+$fa-plug: "\f1e6";
+$fa-slideshare: "\f1e7";
+$fa-twitch: "\f1e8";
+$fa-yelp: "\f1e9";
+$fa-newspaper-o: "\f1ea";
+$fa-wifi: "\f1eb";
+$fa-calculator: "\f1ec";
+$fa-paypal: "\f1ed";
+$fa-google-wallet: "\f1ee";
+$fa-cc-visa: "\f1f0";
+$fa-cc-mastercard: "\f1f1";
+$fa-cc-discover: "\f1f2";
+$fa-cc-amex: "\f1f3";
+$fa-cc-paypal: "\f1f4";
+$fa-cc-stripe: "\f1f5";
+$fa-bell-slash: "\f1f6";
+$fa-bell-slash-o: "\f1f7";
+$fa-trash: "\f1f8";
+$fa-copyright: "\f1f9";
+$fa-at: "\f1fa";
+$fa-eyedropper: "\f1fb";
+$fa-paint-brush: "\f1fc";
+$fa-birthday-cake: "\f1fd";
+$fa-area-chart: "\f1fe";
+$fa-pie-chart: "\f200";
+$fa-line-chart: "\f201";
+$fa-lastfm: "\f202";
+$fa-lastfm-square: "\f203";
+$fa-toggle-off: "\f204";
+$fa-toggle-on: "\f205";
+$fa-bicycle: "\f206";
+$fa-bus: "\f207";
+$fa-ioxhost: "\f208";
+$fa-angellist: "\f209";
+$fa-cc: "\f20a";
+$fa-ils: "\f20b";
+$fa-meanpath: "\f20c";
+
diff --git a/app_web_widget_ztree/static/src/lib/ztree_v3/css/awesomeStyle/img/1home.png b/app_web_widget_ztree/static/src/lib/ztree_v3/css/awesomeStyle/img/1home.png
new file mode 100644
index 000000000..cd65a2d4c
Binary files /dev/null and b/app_web_widget_ztree/static/src/lib/ztree_v3/css/awesomeStyle/img/1home.png differ
diff --git a/app_web_widget_ztree/static/src/lib/ztree_v3/css/awesomeStyle/img/home.png b/app_web_widget_ztree/static/src/lib/ztree_v3/css/awesomeStyle/img/home.png
new file mode 100644
index 000000000..68ccb3c3b
Binary files /dev/null and b/app_web_widget_ztree/static/src/lib/ztree_v3/css/awesomeStyle/img/home.png differ
diff --git a/app_web_widget_ztree/static/src/lib/ztree_v3/css/awesomeStyle/img/loading.gif b/app_web_widget_ztree/static/src/lib/ztree_v3/css/awesomeStyle/img/loading.gif
new file mode 100644
index 000000000..e8c289293
Binary files /dev/null and b/app_web_widget_ztree/static/src/lib/ztree_v3/css/awesomeStyle/img/loading.gif differ
diff --git a/app_web_widget_ztree/static/src/lib/ztree_v3/js/jquery-1.4.4.min.js b/app_web_widget_ztree/static/src/lib/ztree_v3/js/jquery-1.4.4.min.js
new file mode 100644
index 000000000..8f3ca2e2d
--- /dev/null
+++ b/app_web_widget_ztree/static/src/lib/ztree_v3/js/jquery-1.4.4.min.js
@@ -0,0 +1,167 @@
+/*!
+ * jQuery JavaScript Library v1.4.4
+ * http://jquery.com/
+ *
+ * Copyright 2010, John Resig
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * Includes Sizzle.js
+ * http://sizzlejs.com/
+ * Copyright 2010, The Dojo Foundation
+ * Released under the MIT, BSD, and GPL Licenses.
+ *
+ * Date: Thu Nov 11 19:04:53 2010 -0500
+ */
+(function(E,B){function ka(a,b,d){if(d===B&&a.nodeType===1){d=a.getAttribute("data-"+b);if(typeof d==="string"){try{d=d==="true"?true:d==="false"?false:d==="null"?null:!c.isNaN(d)?parseFloat(d):Ja.test(d)?c.parseJSON(d):d}catch(e){}c.data(a,b,d)}else d=B}return d}function U(){return false}function ca(){return true}function la(a,b,d){d[0].type=a;return c.event.handle.apply(b,d)}function Ka(a){var b,d,e,f,h,l,k,o,x,r,A,C=[];f=[];h=c.data(this,this.nodeType?"events":"__events__");if(typeof h==="function")h=
+h.events;if(!(a.liveFired===this||!h||!h.live||a.button&&a.type==="click")){if(a.namespace)A=RegExp("(^|\\.)"+a.namespace.split(".").join("\\.(?:.*\\.)?")+"(\\.|$)");a.liveFired=this;var J=h.live.slice(0);for(k=0;kd)break;a.currentTarget=f.elem;a.data=f.handleObj.data;a.handleObj=f.handleObj;A=f.handleObj.origHandler.apply(f.elem,arguments);if(A===false||a.isPropagationStopped()){d=f.level;if(A===false)b=false;if(a.isImmediatePropagationStopped())break}}return b}}function Y(a,b){return(a&&a!=="*"?a+".":"")+b.replace(La,
+"`").replace(Ma,"&")}function ma(a,b,d){if(c.isFunction(b))return c.grep(a,function(f,h){return!!b.call(f,h,f)===d});else if(b.nodeType)return c.grep(a,function(f){return f===b===d});else if(typeof b==="string"){var e=c.grep(a,function(f){return f.nodeType===1});if(Na.test(b))return c.filter(b,e,!d);else b=c.filter(b,e)}return c.grep(a,function(f){return c.inArray(f,b)>=0===d})}function na(a,b){var d=0;b.each(function(){if(this.nodeName===(a[d]&&a[d].nodeName)){var e=c.data(a[d++]),f=c.data(this,
+e);if(e=e&&e.events){delete f.handle;f.events={};for(var h in e)for(var l in e[h])c.event.add(this,h,e[h][l],e[h][l].data)}}})}function Oa(a,b){b.src?c.ajax({url:b.src,async:false,dataType:"script"}):c.globalEval(b.text||b.textContent||b.innerHTML||"");b.parentNode&&b.parentNode.removeChild(b)}function oa(a,b,d){var e=b==="width"?a.offsetWidth:a.offsetHeight;if(d==="border")return e;c.each(b==="width"?Pa:Qa,function(){d||(e-=parseFloat(c.css(a,"padding"+this))||0);if(d==="margin")e+=parseFloat(c.css(a,
+"margin"+this))||0;else e-=parseFloat(c.css(a,"border"+this+"Width"))||0});return e}function da(a,b,d,e){if(c.isArray(b)&&b.length)c.each(b,function(f,h){d||Ra.test(a)?e(a,h):da(a+"["+(typeof h==="object"||c.isArray(h)?f:"")+"]",h,d,e)});else if(!d&&b!=null&&typeof b==="object")c.isEmptyObject(b)?e(a,""):c.each(b,function(f,h){da(a+"["+f+"]",h,d,e)});else e(a,b)}function S(a,b){var d={};c.each(pa.concat.apply([],pa.slice(0,b)),function(){d[this]=a});return d}function qa(a){if(!ea[a]){var b=c("<"+
+a+">").appendTo("body"),d=b.css("display");b.remove();if(d==="none"||d==="")d="block";ea[a]=d}return ea[a]}function fa(a){return c.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:false}var t=E.document,c=function(){function a(){if(!b.isReady){try{t.documentElement.doScroll("left")}catch(j){setTimeout(a,1);return}b.ready()}}var b=function(j,s){return new b.fn.init(j,s)},d=E.jQuery,e=E.$,f,h=/^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]+)$)/,l=/\S/,k=/^\s+/,o=/\s+$/,x=/\W/,r=/\d/,A=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,
+C=/^[\],:{}\s]*$/,J=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,w=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,I=/(?:^|:|,)(?:\s*\[)+/g,L=/(webkit)[ \/]([\w.]+)/,g=/(opera)(?:.*version)?[ \/]([\w.]+)/,i=/(msie) ([\w.]+)/,n=/(mozilla)(?:.*? rv:([\w.]+))?/,m=navigator.userAgent,p=false,q=[],u,y=Object.prototype.toString,F=Object.prototype.hasOwnProperty,M=Array.prototype.push,N=Array.prototype.slice,O=String.prototype.trim,D=Array.prototype.indexOf,R={};b.fn=b.prototype={init:function(j,
+s){var v,z,H;if(!j)return this;if(j.nodeType){this.context=this[0]=j;this.length=1;return this}if(j==="body"&&!s&&t.body){this.context=t;this[0]=t.body;this.selector="body";this.length=1;return this}if(typeof j==="string")if((v=h.exec(j))&&(v[1]||!s))if(v[1]){H=s?s.ownerDocument||s:t;if(z=A.exec(j))if(b.isPlainObject(s)){j=[t.createElement(z[1])];b.fn.attr.call(j,s,true)}else j=[H.createElement(z[1])];else{z=b.buildFragment([v[1]],[H]);j=(z.cacheable?z.fragment.cloneNode(true):z.fragment).childNodes}return b.merge(this,
+j)}else{if((z=t.getElementById(v[2]))&&z.parentNode){if(z.id!==v[2])return f.find(j);this.length=1;this[0]=z}this.context=t;this.selector=j;return this}else if(!s&&!x.test(j)){this.selector=j;this.context=t;j=t.getElementsByTagName(j);return b.merge(this,j)}else return!s||s.jquery?(s||f).find(j):b(s).find(j);else if(b.isFunction(j))return f.ready(j);if(j.selector!==B){this.selector=j.selector;this.context=j.context}return b.makeArray(j,this)},selector:"",jquery:"1.4.4",length:0,size:function(){return this.length},
+toArray:function(){return N.call(this,0)},get:function(j){return j==null?this.toArray():j<0?this.slice(j)[0]:this[j]},pushStack:function(j,s,v){var z=b();b.isArray(j)?M.apply(z,j):b.merge(z,j);z.prevObject=this;z.context=this.context;if(s==="find")z.selector=this.selector+(this.selector?" ":"")+v;else if(s)z.selector=this.selector+"."+s+"("+v+")";return z},each:function(j,s){return b.each(this,j,s)},ready:function(j){b.bindReady();if(b.isReady)j.call(t,b);else q&&q.push(j);return this},eq:function(j){return j===
+-1?this.slice(j):this.slice(j,+j+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(N.apply(this,arguments),"slice",N.call(arguments).join(","))},map:function(j){return this.pushStack(b.map(this,function(s,v){return j.call(s,v,s)}))},end:function(){return this.prevObject||b(null)},push:M,sort:[].sort,splice:[].splice};b.fn.init.prototype=b.fn;b.extend=b.fn.extend=function(){var j,s,v,z,H,G=arguments[0]||{},K=1,Q=arguments.length,ga=false;
+if(typeof G==="boolean"){ga=G;G=arguments[1]||{};K=2}if(typeof G!=="object"&&!b.isFunction(G))G={};if(Q===K){G=this;--K}for(;K0))if(q){var s=0,v=q;for(q=null;j=v[s++];)j.call(t,b);b.fn.trigger&&b(t).trigger("ready").unbind("ready")}}},bindReady:function(){if(!p){p=true;if(t.readyState==="complete")return setTimeout(b.ready,1);if(t.addEventListener){t.addEventListener("DOMContentLoaded",u,false);E.addEventListener("load",b.ready,false)}else if(t.attachEvent){t.attachEvent("onreadystatechange",u);E.attachEvent("onload",
+b.ready);var j=false;try{j=E.frameElement==null}catch(s){}t.documentElement.doScroll&&j&&a()}}},isFunction:function(j){return b.type(j)==="function"},isArray:Array.isArray||function(j){return b.type(j)==="array"},isWindow:function(j){return j&&typeof j==="object"&&"setInterval"in j},isNaN:function(j){return j==null||!r.test(j)||isNaN(j)},type:function(j){return j==null?String(j):R[y.call(j)]||"object"},isPlainObject:function(j){if(!j||b.type(j)!=="object"||j.nodeType||b.isWindow(j))return false;if(j.constructor&&
+!F.call(j,"constructor")&&!F.call(j.constructor.prototype,"isPrototypeOf"))return false;for(var s in j);return s===B||F.call(j,s)},isEmptyObject:function(j){for(var s in j)return false;return true},error:function(j){throw j;},parseJSON:function(j){if(typeof j!=="string"||!j)return null;j=b.trim(j);if(C.test(j.replace(J,"@").replace(w,"]").replace(I,"")))return E.JSON&&E.JSON.parse?E.JSON.parse(j):(new Function("return "+j))();else b.error("Invalid JSON: "+j)},noop:function(){},globalEval:function(j){if(j&&
+l.test(j)){var s=t.getElementsByTagName("head")[0]||t.documentElement,v=t.createElement("script");v.type="text/javascript";if(b.support.scriptEval)v.appendChild(t.createTextNode(j));else v.text=j;s.insertBefore(v,s.firstChild);s.removeChild(v)}},nodeName:function(j,s){return j.nodeName&&j.nodeName.toUpperCase()===s.toUpperCase()},each:function(j,s,v){var z,H=0,G=j.length,K=G===B||b.isFunction(j);if(v)if(K)for(z in j){if(s.apply(j[z],v)===false)break}else for(;Ha ";var f=d.getElementsByTagName("*"),h=d.getElementsByTagName("a")[0],l=t.createElement("select"),
+k=l.appendChild(t.createElement("option"));if(!(!f||!f.length||!h)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(h.getAttribute("style")),hrefNormalized:h.getAttribute("href")==="/a",opacity:/^0.55$/.test(h.style.opacity),cssFloat:!!h.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:k.selected,deleteExpando:true,optDisabled:false,checkClone:false,
+scriptEval:false,noCloneEvent:true,boxModel:null,inlineBlockNeedsLayout:false,shrinkWrapBlocks:false,reliableHiddenOffsets:true};l.disabled=true;c.support.optDisabled=!k.disabled;b.type="text/javascript";try{b.appendChild(t.createTextNode("window."+e+"=1;"))}catch(o){}a.insertBefore(b,a.firstChild);if(E[e]){c.support.scriptEval=true;delete E[e]}try{delete b.test}catch(x){c.support.deleteExpando=false}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function r(){c.support.noCloneEvent=
+false;d.detachEvent("onclick",r)});d.cloneNode(true).fireEvent("onclick")}d=t.createElement("div");d.innerHTML=" ";a=t.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var r=t.createElement("div");r.style.width=r.style.paddingLeft="1px";t.body.appendChild(r);c.boxModel=c.support.boxModel=r.offsetWidth===2;if("zoom"in r.style){r.style.display="inline";r.style.zoom=
+1;c.support.inlineBlockNeedsLayout=r.offsetWidth===2;r.style.display="";r.innerHTML="
";c.support.shrinkWrapBlocks=r.offsetWidth!==2}r.innerHTML="";var A=r.getElementsByTagName("td");c.support.reliableHiddenOffsets=A[0].offsetHeight===0;A[0].style.display="";A[1].style.display="none";c.support.reliableHiddenOffsets=c.support.reliableHiddenOffsets&&A[0].offsetHeight===0;r.innerHTML="";t.body.removeChild(r).style.display=
+"none"});a=function(r){var A=t.createElement("div");r="on"+r;var C=r in A;if(!C){A.setAttribute(r,"return;");C=typeof A[r]==="function"}return C};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=f=h=null}})();var ra={},Ja=/^(?:\{.*\}|\[.*\])$/;c.extend({cache:{},uuid:0,expando:"jQuery"+c.now(),noData:{embed:true,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:true},data:function(a,b,d){if(c.acceptData(a)){a=a==E?ra:a;var e=a.nodeType,f=e?a[c.expando]:null,h=
+c.cache;if(!(e&&!f&&typeof b==="string"&&d===B)){if(e)f||(a[c.expando]=f=++c.uuid);else h=a;if(typeof b==="object")if(e)h[f]=c.extend(h[f],b);else c.extend(h,b);else if(e&&!h[f])h[f]={};a=e?h[f]:h;if(d!==B)a[b]=d;return typeof b==="string"?a[b]:a}}},removeData:function(a,b){if(c.acceptData(a)){a=a==E?ra:a;var d=a.nodeType,e=d?a[c.expando]:a,f=c.cache,h=d?f[e]:e;if(b){if(h){delete h[b];d&&c.isEmptyObject(h)&&c.removeData(a)}}else if(d&&c.support.deleteExpando)delete a[c.expando];else if(a.removeAttribute)a.removeAttribute(c.expando);
+else if(d)delete f[e];else for(var l in a)delete a[l]}},acceptData:function(a){if(a.nodeName){var b=c.noData[a.nodeName.toLowerCase()];if(b)return!(b===true||a.getAttribute("classid")!==b)}return true}});c.fn.extend({data:function(a,b){var d=null;if(typeof a==="undefined"){if(this.length){var e=this[0].attributes,f;d=c.data(this[0]);for(var h=0,l=e.length;h-1)return true;return false},val:function(a){if(!arguments.length){var b=this[0];if(b){if(c.nodeName(b,"option")){var d=b.attributes.value;return!d||d.specified?b.value:b.text}if(c.nodeName(b,"select")){var e=b.selectedIndex;d=[];var f=b.options;b=b.type==="select-one";
+if(e<0)return null;var h=b?e:0;for(e=b?e+1:f.length;h=0;else if(c.nodeName(this,"select")){var A=c.makeArray(r);c("option",this).each(function(){this.selected=c.inArray(c(this).val(),A)>=0});if(!A.length)this.selectedIndex=-1}else this.value=r}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},
+attr:function(a,b,d,e){if(!a||a.nodeType===3||a.nodeType===8)return B;if(e&&b in c.attrFn)return c(a)[b](d);e=a.nodeType!==1||!c.isXMLDoc(a);var f=d!==B;b=e&&c.props[b]||b;var h=Ta.test(b);if((b in a||a[b]!==B)&&e&&!h){if(f){b==="type"&&Ua.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed");if(d===null)a.nodeType===1&&a.removeAttribute(b);else a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&
+b.specified?b.value:Va.test(a.nodeName)||Wa.test(a.nodeName)&&a.href?0:B;return a[b]}if(!c.support.style&&e&&b==="style"){if(f)a.style.cssText=""+d;return a.style.cssText}f&&a.setAttribute(b,""+d);if(!a.attributes[b]&&a.hasAttribute&&!a.hasAttribute(b))return B;a=!c.support.hrefNormalized&&e&&h?a.getAttribute(b,2):a.getAttribute(b);return a===null?B:a}});var X=/\.(.*)$/,ia=/^(?:textarea|input|select)$/i,La=/\./g,Ma=/ /g,Xa=/[^\w\s.|`]/g,Ya=function(a){return a.replace(Xa,"\\$&")},ua={focusin:0,focusout:0};
+c.event={add:function(a,b,d,e){if(!(a.nodeType===3||a.nodeType===8)){if(c.isWindow(a)&&a!==E&&!a.frameElement)a=E;if(d===false)d=U;else if(!d)return;var f,h;if(d.handler){f=d;d=f.handler}if(!d.guid)d.guid=c.guid++;if(h=c.data(a)){var l=a.nodeType?"events":"__events__",k=h[l],o=h.handle;if(typeof k==="function"){o=k.handle;k=k.events}else if(!k){a.nodeType||(h[l]=h=function(){});h.events=k={}}if(!o)h.handle=o=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(o.elem,
+arguments):B};o.elem=a;b=b.split(" ");for(var x=0,r;l=b[x++];){h=f?c.extend({},f):{handler:d,data:e};if(l.indexOf(".")>-1){r=l.split(".");l=r.shift();h.namespace=r.slice(0).sort().join(".")}else{r=[];h.namespace=""}h.type=l;if(!h.guid)h.guid=d.guid;var A=k[l],C=c.event.special[l]||{};if(!A){A=k[l]=[];if(!C.setup||C.setup.call(a,e,r,o)===false)if(a.addEventListener)a.addEventListener(l,o,false);else a.attachEvent&&a.attachEvent("on"+l,o)}if(C.add){C.add.call(a,h);if(!h.handler.guid)h.handler.guid=
+d.guid}A.push(h);c.event.global[l]=true}a=null}}},global:{},remove:function(a,b,d,e){if(!(a.nodeType===3||a.nodeType===8)){if(d===false)d=U;var f,h,l=0,k,o,x,r,A,C,J=a.nodeType?"events":"__events__",w=c.data(a),I=w&&w[J];if(w&&I){if(typeof I==="function"){w=I;I=I.events}if(b&&b.type){d=b.handler;b=b.type}if(!b||typeof b==="string"&&b.charAt(0)==="."){b=b||"";for(f in I)c.event.remove(a,f+b)}else{for(b=b.split(" ");f=b[l++];){r=f;k=f.indexOf(".")<0;o=[];if(!k){o=f.split(".");f=o.shift();x=RegExp("(^|\\.)"+
+c.map(o.slice(0).sort(),Ya).join("\\.(?:.*\\.)?")+"(\\.|$)")}if(A=I[f])if(d){r=c.event.special[f]||{};for(h=e||0;h=0){a.type=f=f.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[f]&&c.each(c.cache,function(){this.events&&this.events[f]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===
+8)return B;a.result=B;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(e=d.nodeType?c.data(d,"handle"):(c.data(d,"__events__")||{}).handle)&&e.apply(d,b);e=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+f]&&d["on"+f].apply(d,b)===false){a.result=false;a.preventDefault()}}catch(h){}if(!a.isPropagationStopped()&&e)c.event.trigger(a,b,e,true);else if(!a.isDefaultPrevented()){var l;e=a.target;var k=f.replace(X,""),o=c.nodeName(e,"a")&&k===
+"click",x=c.event.special[k]||{};if((!x._default||x._default.call(d,a)===false)&&!o&&!(e&&e.nodeName&&c.noData[e.nodeName.toLowerCase()])){try{if(e[k]){if(l=e["on"+k])e["on"+k]=null;c.event.triggered=true;e[k]()}}catch(r){}if(l)e["on"+k]=l;c.event.triggered=false}}},handle:function(a){var b,d,e,f;d=[];var h=c.makeArray(arguments);a=h[0]=c.event.fix(a||E.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive;if(!b){e=a.type.split(".");a.type=e.shift();d=e.slice(0).sort();e=RegExp("(^|\\.)"+
+d.join("\\.(?:.*\\.)?")+"(\\.|$)")}a.namespace=a.namespace||d.join(".");f=c.data(this,this.nodeType?"events":"__events__");if(typeof f==="function")f=f.events;d=(f||{})[a.type];if(f&&d){d=d.slice(0);f=0;for(var l=d.length;f-1?c.map(a.options,function(e){return e.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d},Z=function(a,b){var d=a.target,e,f;if(!(!ia.test(d.nodeName)||d.readOnly)){e=c.data(d,"_change_data");f=xa(d);if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data",f);if(!(e===B||f===e))if(e!=null||f){a.type="change";a.liveFired=
+B;return c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:Z,beforedeactivate:Z,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return Z.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return Z.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a,"_change_data",xa(a))}},setup:function(){if(this.type===
+"file")return false;for(var a in V)c.event.add(this,a+".specialChange",V[a]);return ia.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return ia.test(this.nodeName)}};V=c.event.special.change.filters;V.focus=V.beforeactivate}t.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(e){e=c.event.fix(e);e.type=b;return c.event.trigger(e,null,e.target)}c.event.special[b]={setup:function(){ua[b]++===0&&t.addEventListener(a,d,true)},teardown:function(){--ua[b]===
+0&&t.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,e,f){if(typeof d==="object"){for(var h in d)this[b](h,e,d[h],f);return this}if(c.isFunction(e)||e===false){f=e;e=B}var l=b==="one"?c.proxy(f,function(o){c(this).unbind(o,l);return f.apply(this,arguments)}):f;if(d==="unload"&&b!=="one")this.one(d,e,f);else{h=0;for(var k=this.length;h0?this.bind(b,d,e):this.trigger(b)};if(c.attrFn)c.attrFn[b]=true});E.attachEvent&&!E.addEventListener&&c(E).bind("unload",function(){for(var a in c.cache)if(c.cache[a].handle)try{c.event.remove(c.cache[a].handle.elem)}catch(b){}});
+(function(){function a(g,i,n,m,p,q){p=0;for(var u=m.length;p0){F=y;break}}y=y[g]}m[p]=F}}}var d=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,e=0,f=Object.prototype.toString,h=false,l=true;[0,0].sort(function(){l=false;return 0});var k=function(g,i,n,m){n=n||[];var p=i=i||t;if(i.nodeType!==1&&i.nodeType!==9)return[];if(!g||typeof g!=="string")return n;var q,u,y,F,M,N=true,O=k.isXML(i),D=[],R=g;do{d.exec("");if(q=d.exec(R)){R=q[3];D.push(q[1]);if(q[2]){F=q[3];
+break}}}while(q);if(D.length>1&&x.exec(g))if(D.length===2&&o.relative[D[0]])u=L(D[0]+D[1],i);else for(u=o.relative[D[0]]?[i]:k(D.shift(),i);D.length;){g=D.shift();if(o.relative[g])g+=D.shift();u=L(g,u)}else{if(!m&&D.length>1&&i.nodeType===9&&!O&&o.match.ID.test(D[0])&&!o.match.ID.test(D[D.length-1])){q=k.find(D.shift(),i,O);i=q.expr?k.filter(q.expr,q.set)[0]:q.set[0]}if(i){q=m?{expr:D.pop(),set:C(m)}:k.find(D.pop(),D.length===1&&(D[0]==="~"||D[0]==="+")&&i.parentNode?i.parentNode:i,O);u=q.expr?k.filter(q.expr,
+q.set):q.set;if(D.length>0)y=C(u);else N=false;for(;D.length;){q=M=D.pop();if(o.relative[M])q=D.pop();else M="";if(q==null)q=i;o.relative[M](y,q,O)}}else y=[]}y||(y=u);y||k.error(M||g);if(f.call(y)==="[object Array]")if(N)if(i&&i.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&k.contains(i,y[g])))n.push(u[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&n.push(u[g]);else n.push.apply(n,y);else C(y,n);if(F){k(F,p,n,m);k.uniqueSort(n)}return n};k.uniqueSort=function(g){if(w){h=
+l;g.sort(w);if(h)for(var i=1;i0};k.find=function(g,i,n){var m;if(!g)return[];for(var p=0,q=o.order.length;p":function(g,i){var n,m=typeof i==="string",p=0,q=g.length;if(m&&!/\W/.test(i))for(i=i.toLowerCase();p=0))n||m.push(u);else if(n)i[q]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()},CHILD:function(g){if(g[1]==="nth"){var i=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=i[1]+(i[2]||1)-0;g[3]=i[3]-0}g[0]=e++;return g},ATTR:function(g,i,n,
+m,p,q){i=g[1].replace(/\\/g,"");if(!q&&o.attrMap[i])g[1]=o.attrMap[i];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,i,n,m,p){if(g[1]==="not")if((d.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=k(g[3],null,null,i);else{g=k.filter(g[3],i,n,true^p);n||m.push.apply(m,g);return false}else if(o.match.POS.test(g[0])||o.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===
+true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,i,n){return!!k(n[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)},text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===
+g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}},setFilters:{first:function(g,i){return i===0},last:function(g,i,n,m){return i===m.length-1},even:function(g,i){return i%2===0},odd:function(g,i){return i%2===1},lt:function(g,i,n){return in[3]-0},nth:function(g,i,n){return n[3]-
+0===i},eq:function(g,i,n){return n[3]-0===i}},filter:{PSEUDO:function(g,i,n,m){var p=i[1],q=o.filters[p];if(q)return q(g,n,i,m);else if(p==="contains")return(g.textContent||g.innerText||k.getText([g])||"").indexOf(i[3])>=0;else if(p==="not"){i=i[3];n=0;for(m=i.length;n=0}},ID:function(g,i){return g.nodeType===1&&g.getAttribute("id")===i},TAG:function(g,i){return i==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===
+i},CLASS:function(g,i){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(i)>-1},ATTR:function(g,i){var n=i[1];n=o.attrHandle[n]?o.attrHandle[n](g):g[n]!=null?g[n]:g.getAttribute(n);var m=n+"",p=i[2],q=i[4];return n==null?p==="!=":p==="="?m===q:p==="*="?m.indexOf(q)>=0:p==="~="?(" "+m+" ").indexOf(q)>=0:!q?m&&n!==false:p==="!="?m!==q:p==="^="?m.indexOf(q)===0:p==="$="?m.substr(m.length-q.length)===q:p==="|="?m===q||m.substr(0,q.length+1)===q+"-":false},POS:function(g,i,n,m){var p=o.setFilters[i[2]];
+if(p)return p(g,n,i,m)}}},x=o.match.POS,r=function(g,i){return"\\"+(i-0+1)},A;for(A in o.match){o.match[A]=RegExp(o.match[A].source+/(?![^\[]*\])(?![^\(]*\))/.source);o.leftMatch[A]=RegExp(/(^(?:.|\r|\n)*?)/.source+o.match[A].source.replace(/\\(\d+)/g,r))}var C=function(g,i){g=Array.prototype.slice.call(g,0);if(i){i.push.apply(i,g);return i}return g};try{Array.prototype.slice.call(t.documentElement.childNodes,0)}catch(J){C=function(g,i){var n=0,m=i||[];if(f.call(g)==="[object Array]")Array.prototype.push.apply(m,
+g);else if(typeof g.length==="number")for(var p=g.length;n
";n.insertBefore(g,n.firstChild);if(t.getElementById(i)){o.find.ID=function(m,p,q){if(typeof p.getElementById!=="undefined"&&!q)return(p=p.getElementById(m[1]))?p.id===m[1]||typeof p.getAttributeNode!=="undefined"&&p.getAttributeNode("id").nodeValue===m[1]?[p]:B:[]};o.filter.ID=function(m,p){var q=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&q&&q.nodeValue===p}}n.removeChild(g);
+n=g=null})();(function(){var g=t.createElement("div");g.appendChild(t.createComment(""));if(g.getElementsByTagName("*").length>0)o.find.TAG=function(i,n){var m=n.getElementsByTagName(i[1]);if(i[1]==="*"){for(var p=[],q=0;m[q];q++)m[q].nodeType===1&&p.push(m[q]);m=p}return m};g.innerHTML=" ";if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")o.attrHandle.href=function(i){return i.getAttribute("href",2)};g=null})();t.querySelectorAll&&
+function(){var g=k,i=t.createElement("div");i.innerHTML="
";if(!(i.querySelectorAll&&i.querySelectorAll(".TEST").length===0)){k=function(m,p,q,u){p=p||t;m=m.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!u&&!k.isXML(p))if(p.nodeType===9)try{return C(p.querySelectorAll(m),q)}catch(y){}else if(p.nodeType===1&&p.nodeName.toLowerCase()!=="object"){var F=p.getAttribute("id"),M=F||"__sizzle__";F||p.setAttribute("id",M);try{return C(p.querySelectorAll("#"+M+" "+m),q)}catch(N){}finally{F||
+p.removeAttribute("id")}}return g(m,p,q,u)};for(var n in g)k[n]=g[n];i=null}}();(function(){var g=t.documentElement,i=g.matchesSelector||g.mozMatchesSelector||g.webkitMatchesSelector||g.msMatchesSelector,n=false;try{i.call(t.documentElement,"[test!='']:sizzle")}catch(m){n=true}if(i)k.matchesSelector=function(p,q){q=q.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!k.isXML(p))try{if(n||!o.match.PSEUDO.test(q)&&!/!=/.test(q))return i.call(p,q)}catch(u){}return k(q,null,null,[p]).length>0}})();(function(){var g=
+t.createElement("div");g.innerHTML="
";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){o.order.splice(1,0,"CLASS");o.find.CLASS=function(i,n,m){if(typeof n.getElementsByClassName!=="undefined"&&!m)return n.getElementsByClassName(i[1])};g=null}}})();k.contains=t.documentElement.contains?function(g,i){return g!==i&&(g.contains?g.contains(i):true)}:t.documentElement.compareDocumentPosition?
+function(g,i){return!!(g.compareDocumentPosition(i)&16)}:function(){return false};k.isXML=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false};var L=function(g,i){for(var n,m=[],p="",q=i.nodeType?[i]:i;n=o.match.PSEUDO.exec(g);){p+=n[0];g=g.replace(o.match.PSEUDO,"")}g=o.relative[g]?g+"*":g;n=0;for(var u=q.length;n0)for(var h=d;h0},closest:function(a,b){var d=[],e,f,h=this[0];if(c.isArray(a)){var l,k={},o=1;if(h&&a.length){e=0;for(f=a.length;e-1:c(h).is(e))d.push({selector:l,elem:h,level:o})}h=
+h.parentNode;o++}}return d}l=cb.test(a)?c(a,b||this.context):null;e=0;for(f=this.length;e-1:c.find.matchesSelector(h,a)){d.push(h);break}else{h=h.parentNode;if(!h||!h.ownerDocument||h===b)break}d=d.length>1?c.unique(d):d;return this.pushStack(d,"closest",a)},index:function(a){if(!a||typeof a==="string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var d=typeof a==="string"?c(a,b||this.context):
+c.makeArray(a),e=c.merge(this.get(),d);return this.pushStack(!d[0]||!d[0].parentNode||d[0].parentNode.nodeType===11||!e[0]||!e[0].parentNode||e[0].parentNode.nodeType===11?e:c.unique(e))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode",d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,
+2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,
+b){c.fn[a]=function(d,e){var f=c.map(this,b,d);Za.test(a)||(e=d);if(e&&typeof e==="string")f=c.filter(e,f);f=this.length>1?c.unique(f):f;if((this.length>1||ab.test(e))&&$a.test(a))f=f.reverse();return this.pushStack(f,a,bb.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return b.length===1?c.find.matchesSelector(b[0],a)?[b[0]]:[]:c.find.matches(a,b)},dir:function(a,b,d){var e=[];for(a=a[b];a&&a.nodeType!==9&&(d===B||a.nodeType!==1||!c(a).is(d));){a.nodeType===1&&
+e.push(a);a=a[b]}return e},nth:function(a,b,d){b=b||1;for(var e=0;a;a=a[d])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var za=/ jQuery\d+="(?:\d+|null)"/g,$=/^\s+/,Aa=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,Ba=/<([\w:]+)/,db=/\s]+\/)>/g,P={option:[1,
+""," "],legend:[1,""," "],thead:[1,""],tr:[2,""],td:[3,""],col:[2,""],area:[1,""," "],_default:[0,"",""]};P.optgroup=P.option;P.tbody=P.tfoot=P.colgroup=P.caption=P.thead;P.th=P.td;if(!c.support.htmlSerialize)P._default=[1,"div","
"];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d=
+c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==B)return this.empty().append((this[0]&&this[0].ownerDocument||t).createTextNode(a));return c.text(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this},
+wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})},
+prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,
+this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},remove:function(a,b){for(var d=0,e;(e=this[d])!=null;d++)if(!a||c.filter(a,[e]).length){if(!b&&e.nodeType===1){c.cleanData(e.getElementsByTagName("*"));c.cleanData([e])}e.parentNode&&e.parentNode.removeChild(e)}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild);
+return this},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,e=this.ownerDocument;if(!d){d=e.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(za,"").replace(fb,'="$1">').replace($,"")],e)[0]}else return this.cloneNode(true)});if(a===true){na(this,b);na(this.find("*"),b.find("*"))}return b},html:function(a){if(a===B)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(za,""):null;
+else if(typeof a==="string"&&!Ca.test(a)&&(c.support.leadingWhitespace||!$.test(a))&&!P[(Ba.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Aa,"<$1>$2>");try{for(var b=0,d=this.length;b0||e.cacheable||this.length>1?h.cloneNode(true):h)}k.length&&c.each(k,Oa)}return this}});c.buildFragment=function(a,b,d){var e,f,h;b=b&&b[0]?b[0].ownerDocument||b[0]:t;if(a.length===1&&typeof a[0]==="string"&&a[0].length<512&&b===t&&!Ca.test(a[0])&&(c.support.checkClone||!Da.test(a[0]))){f=true;if(h=c.fragments[a[0]])if(h!==1)e=h}if(!e){e=b.createDocumentFragment();c.clean(a,b,e,d)}if(f)c.fragments[a[0]]=h?e:1;return{fragment:e,cacheable:f}};c.fragments={};c.each({appendTo:"append",
+prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var e=[];d=c(d);var f=this.length===1&&this[0].parentNode;if(f&&f.nodeType===11&&f.childNodes.length===1&&d.length===1){d[b](this[0]);return this}else{f=0;for(var h=d.length;f0?this.clone(true):this).get();c(d[f])[b](l);e=e.concat(l)}return this.pushStack(e,a,d.selector)}}});c.extend({clean:function(a,b,d,e){b=b||t;if(typeof b.createElement==="undefined")b=b.ownerDocument||
+b[0]&&b[0].ownerDocument||t;for(var f=[],h=0,l;(l=a[h])!=null;h++){if(typeof l==="number")l+="";if(l){if(typeof l==="string"&&!eb.test(l))l=b.createTextNode(l);else if(typeof l==="string"){l=l.replace(Aa,"<$1>$2>");var k=(Ba.exec(l)||["",""])[1].toLowerCase(),o=P[k]||P._default,x=o[0],r=b.createElement("div");for(r.innerHTML=o[1]+l+o[2];x--;)r=r.lastChild;if(!c.support.tbody){x=db.test(l);k=k==="table"&&!x?r.firstChild&&r.firstChild.childNodes:o[1]===""&&!x?r.childNodes:[];for(o=k.length-
+1;o>=0;--o)c.nodeName(k[o],"tbody")&&!k[o].childNodes.length&&k[o].parentNode.removeChild(k[o])}!c.support.leadingWhitespace&&$.test(l)&&r.insertBefore(b.createTextNode($.exec(l)[0]),r.firstChild);l=r.childNodes}if(l.nodeType)f.push(l);else f=c.merge(f,l)}}if(d)for(h=0;f[h];h++)if(e&&c.nodeName(f[h],"script")&&(!f[h].type||f[h].type.toLowerCase()==="text/javascript"))e.push(f[h].parentNode?f[h].parentNode.removeChild(f[h]):f[h]);else{f[h].nodeType===1&&f.splice.apply(f,[h+1,0].concat(c.makeArray(f[h].getElementsByTagName("script"))));
+d.appendChild(f[h])}return f},cleanData:function(a){for(var b,d,e=c.cache,f=c.event.special,h=c.support.deleteExpando,l=0,k;(k=a[l])!=null;l++)if(!(k.nodeName&&c.noData[k.nodeName.toLowerCase()]))if(d=k[c.expando]){if((b=e[d])&&b.events)for(var o in b.events)f[o]?c.event.remove(k,o):c.removeEvent(k,o,b.handle);if(h)delete k[c.expando];else k.removeAttribute&&k.removeAttribute(c.expando);delete e[d]}}});var Ea=/alpha\([^)]*\)/i,gb=/opacity=([^)]*)/,hb=/-([a-z])/ig,ib=/([A-Z])/g,Fa=/^-?\d+(?:px)?$/i,
+jb=/^-?\d/,kb={position:"absolute",visibility:"hidden",display:"block"},Pa=["Left","Right"],Qa=["Top","Bottom"],W,Ga,aa,lb=function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){if(arguments.length===2&&b===B)return this;return c.access(this,a,b,true,function(d,e,f){return f!==B?c.style(d,e,f):c.css(d,e)})};c.extend({cssHooks:{opacity:{get:function(a,b){if(b){var d=W(a,"opacity","opacity");return d===""?"1":d}else return a.style.opacity}}},cssNumber:{zIndex:true,fontWeight:true,opacity:true,
+zoom:true,lineHeight:true},cssProps:{"float":c.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,b,d,e){if(!(!a||a.nodeType===3||a.nodeType===8||!a.style)){var f,h=c.camelCase(b),l=a.style,k=c.cssHooks[h];b=c.cssProps[h]||h;if(d!==B){if(!(typeof d==="number"&&isNaN(d)||d==null)){if(typeof d==="number"&&!c.cssNumber[h])d+="px";if(!k||!("set"in k)||(d=k.set(a,d))!==B)try{l[b]=d}catch(o){}}}else{if(k&&"get"in k&&(f=k.get(a,false,e))!==B)return f;return l[b]}}},css:function(a,b,d){var e,f=c.camelCase(b),
+h=c.cssHooks[f];b=c.cssProps[f]||f;if(h&&"get"in h&&(e=h.get(a,true,d))!==B)return e;else if(W)return W(a,b,f)},swap:function(a,b,d){var e={},f;for(f in b){e[f]=a.style[f];a.style[f]=b[f]}d.call(a);for(f in b)a.style[f]=e[f]},camelCase:function(a){return a.replace(hb,lb)}});c.curCSS=c.css;c.each(["height","width"],function(a,b){c.cssHooks[b]={get:function(d,e,f){var h;if(e){if(d.offsetWidth!==0)h=oa(d,b,f);else c.swap(d,kb,function(){h=oa(d,b,f)});if(h<=0){h=W(d,b,b);if(h==="0px"&&aa)h=aa(d,b,b);
+if(h!=null)return h===""||h==="auto"?"0px":h}if(h<0||h==null){h=d.style[b];return h===""||h==="auto"?"0px":h}return typeof h==="string"?h:h+"px"}},set:function(d,e){if(Fa.test(e)){e=parseFloat(e);if(e>=0)return e+"px"}else return e}}});if(!c.support.opacity)c.cssHooks.opacity={get:function(a,b){return gb.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var d=a.style;d.zoom=1;var e=c.isNaN(b)?"":"alpha(opacity="+b*100+")",f=
+d.filter||"";d.filter=Ea.test(f)?f.replace(Ea,e):d.filter+" "+e}};if(t.defaultView&&t.defaultView.getComputedStyle)Ga=function(a,b,d){var e;d=d.replace(ib,"-$1").toLowerCase();if(!(b=a.ownerDocument.defaultView))return B;if(b=b.getComputedStyle(a,null)){e=b.getPropertyValue(d);if(e===""&&!c.contains(a.ownerDocument.documentElement,a))e=c.style(a,d)}return e};if(t.documentElement.currentStyle)aa=function(a,b){var d,e,f=a.currentStyle&&a.currentStyle[b],h=a.style;if(!Fa.test(f)&&jb.test(f)){d=h.left;
+e=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;h.left=b==="fontSize"?"1em":f||0;f=h.pixelLeft+"px";h.left=d;a.runtimeStyle.left=e}return f===""?"auto":f};W=Ga||aa;if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b=a.offsetHeight;return a.offsetWidth===0&&b===0||!c.support.reliableHiddenOffsets&&(a.style.display||c.css(a,"display"))==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var mb=c.now(),nb=/