diff --git a/anita_theme_setting/__init__.py b/anita_theme_setting/__init__.py
deleted file mode 100644
index 511a0ca3a..000000000
--- a/anita_theme_setting/__init__.py
+++ /dev/null
@@ -1,4 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from . import controllers
-from . import models
\ No newline at end of file
diff --git a/anita_theme_setting/__manifest__.py b/anita_theme_setting/__manifest__.py
deleted file mode 100644
index 413476691..000000000
--- a/anita_theme_setting/__manifest__.py
+++ /dev/null
@@ -1,96 +0,0 @@
-# -*- coding: utf-8 -*-
-{
- 'name': "anita_theme_setting",
-
- 'summary': """
- anita theme
- advance theme
- sunsine theme
- mnk theme for odoo
- free backend theme
- odoo theme
- owl theme
- multi mode theme
- free theme
- multi style theme
- button style theme
- crazy theme
- nice theme
- mutli tab theme
- multi layout theme
- mult tab style theme
- """,
-
- 'description': """
- anita theme setting for odoo, it is a powerfull theme
- """,
-
- 'author': "OpenERPnext",
- 'website': "https://www.openerpnext.com",
- 'live_test_url': 'https://www.openerpnext.com',
- 'images': [
- 'static/description/screen_shot.png',
- 'static/description/banner.png',
- ],
- 'license': 'OPL-1',
-
- 'category': 'Themes/Backend',
- 'version': '17.0.0.3',
- 'price': 999,
-
- 'depends': ['web', 'web_enterprise'],
-
- 'data': [
- 'security/ir.model.access.csv',
-
- # settings, setting page add by modules
- 'views/anita_theme_mode.xml',
- 'views/anita_theme_style.xml',
- 'views/anita_theme_style_group.xml',
- 'views/anita_theme_style_item.xml',
- 'views/anita_theme_style_item_sub_group.xml',
- 'views/anita_theme_var.xml',
- 'views/anita_import_theme_style.xml',
- 'views/anita_web.xml',
- 'views/anita_bk_image_wizard.xml',
- 'views/anita_res_setting.xml',
- ],
-
- 'assets': {
-
- 'web.assets_backend': [
-
- # aniate.css
- 'anita_theme_setting/static/libs/animate.css',
-
- # theme customizer
- 'anita_theme_setting/static/src/components/customizer/*',
- 'anita_theme_setting/static/src/components/settings/*.js',
- 'anita_theme_setting/static/src/components/settings/*.xml',
-
- 'anita_theme_setting/static/src/anita_theme_setting.js',
-
- # according
- 'anita_theme_setting/static/src/components/accordion/*',
-
- # dialog
- 'anita_theme_setting/static/src/components/dialog/*',
-
- # color picker
- 'anita_theme_setting/static/src/components/color_picker/color_picker.js',
- 'anita_theme_setting/static/src/components/color_picker/color_picker.xml',
- 'anita_theme_setting/static/src/components/color_picker/color_picker.scss',
-
- 'anita_theme_setting/static/libs/spectrum.js',
- 'anita_theme_setting/static/libs/spectrum.css',
- 'anita_theme_setting/static/src/anita_icon.js',
-
- # client
- 'anita_theme_setting/static/src/components/webclient/webclient.js',
- ],
-
- 'web.assets_web': [
- ('replace', 'web_enterprise/static/src/main.js', 'anita_theme_setting/static/src/anita_main.js'),
- ]
- }
-}
diff --git a/anita_theme_setting/controllers/__init__.py b/anita_theme_setting/controllers/__init__.py
deleted file mode 100644
index 1ba382538..000000000
--- a/anita_theme_setting/controllers/__init__.py
+++ /dev/null
@@ -1,3 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from . import anita_home
\ No newline at end of file
diff --git a/anita_theme_setting/controllers/anita_home.py b/anita_theme_setting/controllers/anita_home.py
deleted file mode 100644
index 9b1759a45..000000000
--- a/anita_theme_setting/controllers/anita_home.py
+++ /dev/null
@@ -1,87 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import odoo
-import odoo.modules.registry
-from odoo.tools.translate import _
-from odoo.exceptions import AccessError
-from odoo.addons.web.controllers.home import Home, SIGN_UP_REQUEST_PARAMS
-from odoo.addons.web.controllers.utils import ensure_db, is_user_internal
-from odoo import http
-from odoo.http import request
-from odoo.tools.mimetypes import guess_mimetype
-from odoo.tools.misc import file_path
-
-try:
- from werkzeug.utils import send_file
-except ImportError:
- from odoo.tools._vendor.send_file import send_file
-
-import json
-import base64
-import functools
-import io
-import os
-import logging
-
-_logger = logging.getLogger(__name__)
-
-BASE_PATH = os.path.dirname(os.path.dirname(__file__))
-
-
-class anitaHome(Home):
- '''
- inherit home to extend web.login style
- '''
- @http.route([
- '/web/binary/company_logo',
- '/logo',
- '/logo.png',
- ], type='http', auth="none", cors="*")
- def company_logo(self, dbname=None, **kw):
- imgname = 'logo'
- imgext = '.png'
- dbname = request.db
- uid = (request.session.uid if dbname else None) or odoo.SUPERUSER_ID
-
- if not dbname:
- response = http.Stream.from_path(file_path('web/static/img/logo.png')).get_response()
- else:
- try:
- # create an empty registry
- registry = odoo.modules.registry.Registry(dbname)
- with registry.cursor() as cr:
- company = int(kw['company']) if kw and kw.get('company') else False
- if company:
- cr.execute("""SELECT logo_web, write_date
- FROM res_company
- WHERE id = %s
- """, (company,))
- else:
- cr.execute("""SELECT c.logo_web, c.write_date
- FROM res_users u
- LEFT JOIN res_company c
- ON c.id = u.company_id
- WHERE u.id = %s
- """, (uid,))
- row = cr.fetchone()
- if row and row[0]:
- image_base64 = base64.b64decode(row[0])
- image_data = io.BytesIO(image_base64)
- mimetype = guess_mimetype(image_base64, default='image/png')
- imgext = '.' + mimetype.split('/')[1]
- if imgext == '.svg+xml':
- imgext = '.svg'
- response = send_file(
- image_data,
- request.httprequest.environ,
- download_name=imgname + imgext,
- mimetype=mimetype,
- last_modified=row[1],
- response_class=Response,
- )
- else:
- response = http.Stream.from_path(file_path('web/static/img/nologo.png')).get_response()
- except Exception:
- response = http.Stream.from_path(file_path(f'web/static/img/{imgname}{imgext}')).get_response()
-
- return response
\ No newline at end of file
diff --git a/anita_theme_setting/data/default_templates.xml b/anita_theme_setting/data/default_templates.xml
deleted file mode 100644
index 7bf915715..000000000
--- a/anita_theme_setting/data/default_templates.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/anita_theme_setting/models/__init__.py b/anita_theme_setting/models/__init__.py
deleted file mode 100644
index c4465a819..000000000
--- a/anita_theme_setting/models/__init__.py
+++ /dev/null
@@ -1,21 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from . import anita_setting_base
-from . import anita_template_var_vals
-from . import anita_theme_mode
-from . import anita_theme_style
-from . import anita_theme_style_item_group
-from . import anita_theme_style_item
-from . import anita_company
-from . import anita_theme_users
-from . import anita_theme_vars
-from . import anita_setting_manager
-from . import anita_res_setting
-from . import anita_default_mode_data
-from . import anita_mode_template
-from . import anita_theme_style_item_sub_group
-from . import anita_import_theme_style
-from . import anita_default_menu_icon
-from . import anita_menu_extend
-from . import anita_favorite_menu
-from . import anita_bk_image_wizard
\ No newline at end of file
diff --git a/anita_theme_setting/models/anita_bk_image_wizard.py b/anita_theme_setting/models/anita_bk_image_wizard.py
deleted file mode 100644
index a8591f314..000000000
--- a/anita_theme_setting/models/anita_bk_image_wizard.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from odoo import models, fields, api
-
-
-class AnitaBkImageWizard(models.TransientModel):
- '''
- background image wizard
- '''
- _name = 'anita_theme_setting.background_image_wizard'
- _description = 'background image wizard'
-
- data = fields.Binary(string='data', required=True)
- opacity = fields.Float(string='theme opacity', default=0.8)
diff --git a/anita_theme_setting/models/anita_company.py b/anita_theme_setting/models/anita_company.py
deleted file mode 100644
index 9564f3e9d..000000000
--- a/anita_theme_setting/models/anita_company.py
+++ /dev/null
@@ -1,130 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from odoo import fields, models, exceptions
-import base64
-from datetime import date, datetime
-from odoo.tools.misc import file_path
-
-
-class AnitaCompany(models.Model):
- '''
- extend to support current mode and current style
- '''
- _inherit = "res.company"
- _name = 'res.company'
-
- setting_id = fields.Many2one(
- comodel_name="anita_theme_setting.setting_base",
- ondelete="cascade",
- string="setting id")
-
- def _get_default_favicon_icon(self):
- """
- get default favicon icon form static path
- """
- tmp_path = file_path('anita_theme_setting/static/src/img/favicon.png')
- return base64.b64encode(open(tmp_path, 'rb').read())
-
- favicon_icon = fields.Binary(
- string='Web Favicon Icon', default='_get_default_favicon_icon')
-
- def _get_default_small_logo(self):
- '''
- get the default small logo
- :return:
- '''
- tmp_path = file_path('anita_theme_setting/static/src/img/res_small_logo.png')
- return base64.b64encode(open(tmp_path, 'rb').read())
-
- logo_small = fields.Binary(
- default=_get_default_small_logo, string="Company Small Logo")
-
- def get_mode_data(self):
- '''
- get mode data
- :return:
- '''
- owner = 'res.company, {company_id}'.format(
- company_id=self.env.user.company_id)
- self.env["anita_theme_setting.theme_mode"].check_default_mode_data(owner)
- return self.env["anita_theme_setting.theme_mode"].get_mode_data()
-
- def get_mode_domain(self):
- """
- get mode domain dynamic
- :return:
- """
- owner = 'res.company, {company_id}'.format(
- company_id=self.env.user.company_id.id)
- return [('owner', '=', owner)]
-
- def get_company_mode_data(self):
- '''
- get company mode data
- :return:
- '''
- return self.get_mode_data()
-
- def ensure_setting_id(self):
- '''
- check setting id
- :return:
- '''
- self.ensure_one()
- if self.setting_id:
- return
-
- # copy use the global default data
- values = self.env['res.config.settings'].get_theme_settings()
-
- # get fields of anita_theme_setting.setting_base
- field_names = [name for name, field in self.setting_id._fields.items() if name not in [
- 'id', 'create_uid', 'create_date', 'write_uid', 'write_date']]
-
- # remove name not in fields
- values = {k: v for k, v in values.items() if k in field_names}
-
- del values["current_theme_mode"]
- del values["current_theme_style"]
-
- if not self.setting_id:
- tmp_record = self.env["anita_theme_setting.setting_base"].create(values)
- self.setting_id = tmp_record.id
-
- return self.setting_id
-
- def get_theme_setting(self):
- '''
- get company setting
- :return:
- '''
- record = self.env.user.company_id
- record.ensure_setting_id()
- result = record.setting_id.read()[0]
- result["current_theme_mode"] = record.setting_id.current_theme_mode.id
- result["current_theme_style"] = record.setting_id.current_theme_style.id
- for key, item in result.items():
- if isinstance(item, datetime):
- result[key] = fields.Datetime.to_string(item)
- if isinstance(item, date):
- result[key] = fields.Date.to_string(item)
-
- return result
-
- def check_default_data(self):
- """
- check default data
- :return:
- """
- # check mode data
- owner = 'res.company, {company_id}'.format(company_id=self.id)
- self.env["anita_theme_setting.theme_mode"].check_default_mode_data(owner)
-
- def save_theme_setting(self, settings):
- '''
- save theme setting
- :param settings:
- :return:
- '''
- self.ensure_setting_id()
- self.setting_id.write(settings)
diff --git a/anita_theme_setting/models/anita_default_menu_icon.py b/anita_theme_setting/models/anita_default_menu_icon.py
deleted file mode 100644
index 276368e14..000000000
--- a/anita_theme_setting/models/anita_default_menu_icon.py
+++ /dev/null
@@ -1,133 +0,0 @@
-
-
-svg_icons = {
-
- '追踪': '',
-
- '联系人': '',
-
- 'Dashboards': '',
-
- 'Sales': '',
-
- 'Inventory': '',
-
- 'Calendar': '',
-
- 'Note': '',
-
- 'Website': '',
-
- 'Manufacturing': '',
-
- 'Repairs': '',
-
- 'Email Marketing': '',
-
- 'SMS Marketing':'',
- 'Project': '',
-
- 'Surveys': '',
-
- 'Employees': '',
-
- 'Recruitment': '',
-
- 'Attendances': '',
-
- 'Time Off': '',
-
- 'Expenses': '',
-
- 'Maintenance': '',
-
- 'Live Chat': '',
-
- 'Lunch': '',
-
- 'Fleet': '',
-
- 'Timesheets': '',
-
- 'Events': '',
-
- 'eLearning': '',
-
- 'Members': '',
-
- 'Apps': '',
-
- '设置': '',
-
- '讨论': '',
-
- 'CRM': '',
-
- '会计': '',
-
- '系统设置': '',
-
- '零工结算': '',
-
- '市场推广': '',
-
- '系统设置': '',
-
- '文档': '',
- '采购': '',
- '制造': '',
- '条码': '',
- '员工': '',
- '审批': '',
- '应用': '',
- '工作流': '',
- '日历': '',
- '驾驶舱': '',
- '库存': '',
- '销售': '',
- '仪表板':'',
- '跟踪链': '',
- '质量': '',
- 'PLM': '',
- '销售点': '',
- '更新管理': '',
- '网站': '',
- '在线学习': '',
- '调查': ''
-}
-
-font_icons = {
- 'Link Tracker':'fa fa-link',
- 'Dashboards':'fa fa-tachometer',
- 'Sales':'fa fa-shopping-cart',
- 'Invoicing':'fa fa-file-text-o',
- 'Inventory':'fa fa-cubes',
- 'Purchase':'fa fa-shopping-basket',
- 'Calendar':'fa fa-calendar',
- 'CRM':'fa fa-users',
- 'Note':'fa fa-sticky-note-o',
- 'Website':'fa fa-globe',
- 'Point of Sale':'fa fa-shopping-cart',
- 'Manufacturing':'fa fa-industry',
- 'Repairs':'fa fa-wrench',
- 'Email Marketing':'fa fa-envelope',
- 'SMS Marketing':'fa fa-commenting-o',
- 'Project':'fa fa-briefcase',
- 'Surveys':'fa fa-bar-chart',
- 'Employees':'fa fa-users',
- 'Recruitment':'fa fa-users',
- 'Attendances':'fa fa-users',
- 'Time Off':'fa fa-users',
- 'Expenses':'fa fa-money',
- 'Maintenance':'fa fa-wrench',
- 'Live Chat':'fa fa-comments-o',
- 'Lunch':'fa fa-cutlery',
- 'Fleet':'fa fa-car',
- 'Timesheets':'fa fa-clock-o',
- 'Events':'fa fa-calendar',
- 'eLearning':'fa fa-graduation-cap',
- 'Members':'fa fa-users',
- 'Apps':'fa fa-apple',
- 'Settings':'fa fa-cogs',
- 'Discuss':'fa fa-comments-o',
-}
diff --git a/anita_theme_setting/models/anita_default_mode_data.py b/anita_theme_setting/models/anita_default_mode_data.py
deleted file mode 100644
index b2d447ff5..000000000
--- a/anita_theme_setting/models/anita_default_mode_data.py
+++ /dev/null
@@ -1,147 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from odoo import models, fields, api, exceptions
-from odoo.tools import ormcache
-import json
-from odoo.tools.misc import file_path
-
-import logging
-_logger = logging.getLogger(__name__)
-
-
-class AnitaDefaultMode(models.Model):
- '''
- default mode
- '''
- _name = 'anita_theme_setting.default_mode_data'
- _description = 'anita Theme Setting Mode Template'
-
- name = fields.Char(string="Name", required=True)
- data = fields.Text(string="Content", required=True)
- template_var_vals = fields.Text(string="Template Var Vals")
- version = fields.Char(string="Version", required=True)
- config_path = fields.Char(string="Config Path", help="This is the file path of the template")
-
- _sql_constraints = [('name_unique', 'UNIQUE(name)', "Name Must Be Unique!")]
-
- @ormcache('self.id')
- def get_mode_data(self):
- """
- get mode
- :return:
- """
- self.ensure_one()
- mode_data = json.loads(self.data)
- mode_data.update({
- "name": self.name,
- "version": self.version
- })
- return mode_data
-
- @ormcache('self.id')
- def get_var_val_cache(self):
- """
- get var value cache
- """
- self.ensure_one()
-
- try:
- var_vals = self.template_var_vals
- var_vals = var_vals.replace('\'', '\"')
- data = json.loads(var_vals)
- except Exception as e:
- _logger.error(e)
- data = {}
-
- var_val_cache = {}
- for group_name in data:
- group = data[group_name]
- for var_item in group:
- var_val_cache[var_item['name']] = var_item['value']
- return var_val_cache
-
- @ormcache()
- def get_default_modes(self):
- """
- get default modes
- :return:
- """
- records = self.search([])
- default_models = []
- for record in records:
- default_models.append(record.get_mode_data())
- return default_models
-
- @api.model
- def refresh_default_mode(self):
- """
- udpate data
- """
- records = self.search([])
- for record in records:
- if not record.config_path:
- return
-
- tmp_path = file_path(record.config_path.lstrip('/'))
- if not tmp_path:
- continue
- with open(tmp_path, 'r') as fd:
- mode_text = fd.read()
-
- # check the data is valid json
- try:
- mode_data = json.loads(mode_text)
- record.write({
- "data": json.dumps(mode_data),
- "template_var_vals": json.dumps(mode_data.get('template_var_vals', {}))
- })
- except Exception as e:
- self.data = False
- _logger.error(e)
-
- @api.model
- def install_mode(self, config_path, template):
- """
- install mode
- :return:
- """
- # trim start '/'
- tmp_path = file_path(config_path.lstrip('/'))
-
- if not tmp_path:
- raise exceptions.ValidationError('File not found! {}'.format(config_path))
-
- with open(tmp_path, 'r') as fd:
-
- mode_text = fd.read()
-
- # check the data is valid json
- try:
- mode_data = json.loads(mode_text)
- except Exception as e:
- raise exceptions.ValidationError(
- 'Template {template} must be a valid json file!'.format(template=config_path))
-
- name = mode_data.get('name')
- if not name:
- raise exceptions.ValidationError(
- 'Template {template} must has a name!'.format(template=config_path))
-
- model_record = self.search([('name', '=', name)])
- if not model_record:
- self.create([{
- "name": name,
- "data": json.dumps(mode_data),
- "version": mode_data.get('version', '1.0'),
- "config_path": config_path,
- "template_var_vals": mode_data.get("template_var_vals", "")
- }])
- else:
- model_record.write({
- "name": name,
- "data": json.dumps(mode_data),
- "version": mode_data.get('version', '1.0'),
- "config_path": config_path,
- "template_var_vals": mode_data.get("template_var_vals", "")
- })
- return model_record
diff --git a/anita_theme_setting/models/anita_favorite_menu.py b/anita_theme_setting/models/anita_favorite_menu.py
deleted file mode 100644
index 78cfbdb21..000000000
--- a/anita_theme_setting/models/anita_favorite_menu.py
+++ /dev/null
@@ -1,53 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from odoo import api, fields, models
-
-
-class AnitaFavoriteMenu(models.Model):
- '''
- user favorite menu
- '''
- _name = 'anita_theme_setting.favorite_menu'
- _order = "sequence"
- _description = "user favorite menu"
-
- def _default_sequence(self):
- return self.env['ir.sequence'].next_by_code('anita_theme_setting.favorite.menu')
-
- sequence = fields.Integer(
- string="sequence",
- default=_default_sequence)
-
- menu_id = fields.Many2one(
- comodel_name='ir.ui.menu',
- string='Favorite Menu',
- required=True,
- ondelete='cascade')
-
- user_id = fields.Many2one(
- comodel_name='res.users',
- string='User Name',
- default=lambda self: self.env.user.id)
-
- @api.model
- def unlink_menu_id(self, user_id, menu_id):
- '''
- unlink
- :param user_id:
- :param menu_id:
- :return:
- '''
- value = self.search(
- [('menu_id', '=', menu_id), ('user_id', '=', user_id)])
- return value.unlink()
-
- @api.model
- def update_favorite_menu(self, favorites):
- '''
- update favoirte
- :return:
- '''
- records = self.search([('user_id', '=', self.env.uid)])
- records.unlink()
- self.create(favorites)
- return self.search_read([('user_id', '=', self.env.uid)])
diff --git a/anita_theme_setting/models/anita_import_theme_style.py b/anita_theme_setting/models/anita_import_theme_style.py
deleted file mode 100644
index 55d7cd344..000000000
--- a/anita_theme_setting/models/anita_import_theme_style.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from odoo import models, fields
-
-
-class AnitaImportThemeStyle(models.TransientModel):
- '''
- user theme style setting
- '''
- _name = 'anita_theme_setting.import_theme_style'
- _description = 'user setting'
-
- file = fields.Binary(string="Theme File", required=True)
diff --git a/anita_theme_setting/models/anita_menu_extend.py b/anita_theme_setting/models/anita_menu_extend.py
deleted file mode 100644
index 2b590af50..000000000
--- a/anita_theme_setting/models/anita_menu_extend.py
+++ /dev/null
@@ -1,244 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from odoo.tools.convert import xml_import, nodeattr2bool
-import odoo
-from odoo import api, fields, models, tools
-from odoo.osv import expression
-from .anita_default_menu_icon import svg_icons, font_icons
-
-
-class AnitaMenuExtend(models.Model):
- '''
- extend to support font icon and svg icon
- '''
- _inherit = 'ir.ui.menu'
-
- font_icon = fields.Char(string='font icon')
- svg_icon = fields.Text(string='svg icon')
-
- def load_web_menus(self, debug):
- """ Loads all menu items (all applications and their sub-menus) and
- processes them to be used by the webclient. Mainly, it associates with
- each application (top level menu) the action of its first child menu
- that is associated with an action (recursively), i.e. with the action
- to execute when the opening the app.
-
- :return: the menus (including the images in Base64)
- """
- theme_setting = self.env["anita_theme_setting.setting_manager"].sudo().get_theme_setting()
- icon_policy = theme_setting.get("icon_policy", "svg_icon")
-
- menus = self.load_menus(debug)
- favorite_cache = {}
- if theme_setting.get("favorite_mode", False):
- favorite_apps = self.env['anita_theme_setting.favorite_menu'].sudo().search(
- [('user_id', '=', self.env.uid)])
- favorite_cache = {fav.menu_id.id: fav for fav in favorite_apps}
-
- web_menus = {}
- for menu in menus.values():
- if not menu['id']:
- # special root menu case
- web_menus['root'] = {
- "id": 'root',
- "name": menu['name'],
- "children": menu['children'],
- "appID": False,
- "xmlid": "",
- "actionID": False,
- "actionModel": False,
- "webIcon": None,
- "webIconData": None,
- "backgroundImage": menu.get('backgroundImage'),
- "icon_policy": icon_policy,
- }
- else:
- action = menu['action']
-
- if menu['id'] == menu['app_id']:
- # if it's an app take action of first (sub)child having one defined
- child = menu
- while child and not action:
- action = child['action']
- child = menus[child['children'][0]] if child['children'] else False
-
- action_model, action_id = action.split(',') if action else (False, False)
- action_id = int(action_id) if action_id else False
-
- web_menus[menu['id']] = {
- "id": menu['id'],
- "name": menu['name'],
- "children": menu['children'],
- "appID": menu['app_id'],
- "xmlid": menu['xmlid'],
- "actionID": action_id,
- "actionModel": action_model,
- "svg_icon": menu.get('svg_icon'),
- "font_icon": menu.get('font_icon'),
- "webIcon": menu['web_icon'],
- "webIconData": menu['web_icon_data'],
- "is_favorite": True if favorite_cache.get(menu['id']) else False,
- "sequence": favorite_cache.get(menu['id'], {}).sequence if favorite_cache.get(menu['id']) else 0
- }
-
- return web_menus
-
- @api.model
- # @tools.ormcache_context('self._uid', 'debug', keys=('lang',))
- def load_menus(self, debug):
- """ Loads all menu items (all applications and their sub-menus).
- :return: the menu root
- :rtype: dict('children': menu_nodes)
- """
- theme_setting = self.env["anita_theme_setting.setting_manager"].sudo().get_theme_setting()
- icon_policy = theme_setting.get("icon_policy", "svg_icon")
-
- fields = ['name', 'sequence', 'parent_id', 'action', 'web_icon']
- if icon_policy == "font_icon":
- fields.append('font_icon')
- elif icon_policy == "svg_icon":
- fields.append('svg_icon')
- else:
- fields.append('web_icon')
- fields.append('web_icon_data')
-
- menu_roots = self.get_user_roots()
- menu_roots_data = menu_roots.read(fields) if menu_roots else []
-
- menu_root = {
- 'id': False,
- 'name': 'root',
- 'parent_id': [-1, ''],
- 'children': [menu['id'] for menu in menu_roots_data],
- }
-
- all_menus = {'root': menu_root}
-
- if not menu_roots_data:
- return all_menus
-
- # menus are loaded fully unlike a regular tree view, cause there are a
- # limited number of items (752 when all 6.1 addons are installed)
- menus_domain = [('id', 'child_of', menu_roots.ids)]
- blacklisted_menu_ids = self._load_menus_blacklist()
- if blacklisted_menu_ids:
- menus_domain = expression.AND([menus_domain, [('id', 'not in', blacklisted_menu_ids)]])
- menus = self.search(menus_domain)
- menu_items = menus.read(fields)
- xmlids = (menu_roots + menus)._get_menuitems_xmlids()
-
- # add roots at the end of the sequence, so that they will overwrite
- # equivalent menu items from full menu read when put into id:item
- # mapping, resulting in children being correctly set on the roots.
- menu_items.extend(menu_roots_data)
-
- # set children ids and xmlids
- menu_items_map = {menu_item["id"]: menu_item for menu_item in menu_items}
- for menu_item in menu_items:
- menu_item.setdefault('children', [])
-
- # set the default icons
- if icon_policy == "svg_icon":
- if not menu_item.get('svg_icon'):
- menu_item["svg_icon"] = svg_icons.get(menu_item["name"], False) or False
- elif icon_policy == "font_icon":
- if not menu_item.get('font_icon'):
- menu_item["font_icon"] = font_icons.get(menu_item["name"], False) or "fa fa-circle-o"
-
- parent = menu_item['parent_id'] and menu_item['parent_id'][0]
- menu_item['xmlid'] = xmlids.get(menu_item['id'], "")
- if parent in menu_items_map:
- menu_items_map[parent].setdefault(
- 'children', []).append(menu_item['id'])
-
- all_menus.update(menu_items_map)
-
- # sort by sequence
- for menu_id in all_menus:
- all_menus[menu_id]['children'].sort(key=lambda id: all_menus[id]['sequence'])
-
- # recursively set app ids to related children
- def _set_app_id(app_id, menu):
- menu['app_id'] = app_id
- for child_id in menu['children']:
- _set_app_id(app_id, all_menus[child_id])
-
- for app in menu_roots_data:
- app_id = app['id']
- _set_app_id(app_id, all_menus[app_id])
-
- # filter out menus not related to an app (+ keep root menu)
- all_menus = {menu['id']: menu for menu in all_menus.values() if menu.get('app_id')}
- all_menus['root'] = menu_root
-
- return all_menus
-
-def _tag_menuitem_extend(self, rec, parent=None):
- """
- extend tag menu item
- """
- rec_id = rec.attrib["id"]
- self._test_xml_id(rec_id)
-
- # The parent attribute was specified, if non-empty determine its ID, otherwise
- # explicitly make a top-level menu
- values = {
- 'parent_id': False,
- 'active': nodeattr2bool(rec, 'active', default=True),
- }
-
- if rec.get('sequence'):
- values['sequence'] = int(rec.get('sequence'))
-
- if parent is not None:
- values['parent_id'] = parent
- elif rec.get('parent'):
- values['parent_id'] = self.id_get(rec.attrib['parent'])
- elif rec.get('web_icon'):
- values['web_icon'] = rec.attrib['web_icon']
-
- if rec.get('name'):
- values['name'] = rec.attrib['name']
-
- if rec.get('action'):
- a_action = rec.attrib['action']
-
- if '.' not in a_action:
- a_action = '%s.%s' % (self.module, a_action)
- act = self.env.ref(a_action).sudo()
- values['action'] = "%s,%d" % (act.type, act.id)
-
- if not values.get('name') and act.type.endswith(('act_window', 'wizard', 'url', 'client', 'server')) and act.name:
- values['name'] = act.name
-
- if not values.get('name'):
- values['name'] = rec_id or '?'
-
- groups = []
- for group in rec.get('groups', '').split(','):
- if group.startswith('-'):
- group_id = self.id_get(group[1:])
- groups.append(odoo.Command.unlink(group_id))
- elif group:
- group_id = self.id_get(group)
- groups.append(odoo.Command.link(group_id))
- if groups:
- values['groups_id'] = groups
-
- # read font icon
- if rec.get('font_icon'):
- values['font_icon'] = rec.get('font_icon')
-
- if rec.get('svg_icon'):
- values['svg_icon'] = rec.get('svg_icon')
-
- data = {
- 'xml_id': self.make_xml_id(rec_id),
- 'values': values,
- 'noupdate': self.noupdate,
- }
- menu = self.env['ir.ui.menu']._load_records([data], self.mode == 'update')
- for child in rec.iterchildren('menuitem'):
- self._tag_menuitem(child, parent=menu.id)
-
-xml_import._tag_menuitem = _tag_menuitem_extend
diff --git a/anita_theme_setting/models/anita_mode_template.py b/anita_theme_setting/models/anita_mode_template.py
deleted file mode 100644
index 11975d20c..000000000
--- a/anita_theme_setting/models/anita_mode_template.py
+++ /dev/null
@@ -1,107 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from odoo import models, fields, api, exceptions
-import json
-from odoo.tools import ormcache
-from odoo.tools.misc import file_path
-from odoo.tools.config import config
-
-
-class AnitaModeTemplate(models.Model):
- '''
- user theme style setting
- '''
- _name = 'anita_theme_setting.mode_template'
- _description = 'anita Mode Template'
-
- name = fields.Char(string="Name", required=True)
- template = fields.Text(string="Template")
- color_vars = fields.Text(
- string="Color Vars", help="This is the default var values for this template")
- template_path = fields.Char(
- string="Template Path", help="This is the template path of the template")
-
- _sql_constraints = [('name_unique', 'UNIQUE(name)', "Name Must Be Unique!")]
-
- @ormcache()
- def get_templates(self):
- """
- get templates
- :return:
- """
- records = self.search([])
- return {record.name: record for record in records}
-
- @ormcache('self.id')
- def get_template(self):
- """
- get template
- :return:
- """
- return json.loads(self.template)
-
- @ormcache('self.id')
- def get_color_vars(self):
- """
- get vars
- :return:
- """
- return json.loads(self.color_vars)
-
- def refresh_templates(self):
- """
- update template content
- """
- records = self.search([])
- for record in records:
- if record.template_path:
- tmp_path = file_path(record.template_path.lstrip('/'))
- with open(tmp_path, 'r') as fd:
- template = fd.read()
- record.template = template
-
- def _register_hook(self):
- """
- stuff to do right after the registry is built
- """
- if config.get('debug', False):
- records = self.search([])
- records.refresh_templates()
-
- @api.model
- def install_template(self, name, template_path, theme_mode_paths):
- """
- install mode
- :return:
- """
- tmp_path = file_path(template_path.lstrip('/'))
- if not tmp_path:
- raise exceptions.ValidationError("Template Path is not valid!")
-
- with open(tmp_path, 'r') as fd:
- template = fd.read()
- if not name:
- raise exceptions.ValidationError(
- 'Template {template} must has a name!'.format(template=template_path))
-
- template_record = self.search([('name', '=', name)])
- if not template_record:
- self.create([{
- "name": name,
- "template": template,
- "template_path": template_path
- }])
- else:
- template_record.write({
- "name": name,
- "template": template,
- "template_path": template_path
- })
-
- for index, mode_path in enumerate(theme_mode_paths):
- record = self.env['anita_theme_setting.default_mode_data'].install_mode(
- mode_path, template_record)
- if index == 0:
- template_record.write({
- "color_vars": record.template_var_vals
- })
diff --git a/anita_theme_setting/models/anita_res_setting.py b/anita_theme_setting/models/anita_res_setting.py
deleted file mode 100644
index 88e510755..000000000
--- a/anita_theme_setting/models/anita_res_setting.py
+++ /dev/null
@@ -1,109 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from odoo import api, fields, models
-import base64
-from odoo.tools.mimetypes import guess_mimetype
-from datetime import date, datetime
-
-
-class AnitaUserSetting(models.TransientModel):
- '''
- anita user setting
- '''
- _inherit = 'res.config.settings'
-
- theme_setting_mode = fields.Selection(
- string="theme style mode",
- config_parameter="anita_theme_setting.theme_setting_mode",
- selection=[('system', 'system'),
- ('company', 'company'),
- ('user', 'user')],
- default='system')
-
- allow_debug = fields.Boolean(
- string="allow debug",
- config_parameter="anita_theme_setting.allow_debug",
- default=False)
-
- window_default_title = fields.Char(
- string="login title",
- config_parameter="anita_theme_setting.window_default_title",
- default="Odoo")
-
- powered_by = fields.Char(
- string="powered by",
- config_parameter="anita_theme_setting.powered_by",
- default="Odoo")
-
- @api.model
- def get_theme_setting_mode(self):
- '''
- get theme setting mode
- :return:
- '''
- config = self.env['ir.config_parameter'].sudo()
- theme_setting_mode = config.get_param(
- key='anita_theme_setting.theme_setting_mode', default='system')
- return theme_setting_mode
-
- def set_values_company_favicon(self):
- '''
- set the favicon of company
- :return:
- '''
- company = self.sudo().env['res.company']
- records = company.search([])
-
- if len(records) > 0:
- for record in records:
- record.write({'favicon': self._set_web_favicon(original=True)})
-
- return {
- 'type': 'ir.actions.client',
- 'tag': 'reload',
- }
-
- @api.model
- def get_login_style(self):
- '''
- get login style
- :return:
- '''
- ir_config = self.env['ir.config_parameter'].sudo()
- login_style = ir_config.get_param(
- key='anita_theme_setting.login_style', default='login_style1')
- return login_style
-
- def get_setting_record(self):
- '''
- get setting record
- :return:
- '''
- record = self.env['anita_theme_setting.setting_base'].search([('owner', '=', False)], limit=1)
- if not record:
- record = self.env['anita_theme_setting.setting_base'].create({'owner': False})
- return record
-
- @api.model
- def save_theme_setting(self, settings):
- """
- save settings
- """
- record = self.get_setting_record()
- record.write(settings)
-
- @api.model
- def get_theme_setting(self):
- """
- get theme settings
- """
- record = self.get_setting_record()
- result = record.read()[0]
- result["current_theme_mode"] = record.current_theme_mode.id
- result["current_theme_style"] = record.current_theme_style.id
- for key, item in result.items():
- if isinstance(item, datetime):
- result[key] = fields.Datetime.to_string(item)
- if isinstance(item, date):
- result[key] = fields.Date.to_string(item)
- return result
diff --git a/anita_theme_setting/models/anita_setting_base.py b/anita_theme_setting/models/anita_setting_base.py
deleted file mode 100644
index 2f0a50a0a..000000000
--- a/anita_theme_setting/models/anita_setting_base.py
+++ /dev/null
@@ -1,133 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from odoo import models, fields, api
-
-
-class AnitaThemeSettingBase(models.Model):
- '''
- anita Setting Base
- '''
- _name = 'anita_theme_setting.setting_base'
- _description = 'Anita Setting Base'
-
- owner = fields.Reference(
- string="Owner",
- selection=[('res.company', 'res.company'),
- ('res.users', 'res.users')],
- default=False,
- help="owner which this theme is create by, if it is false, it mean it is owned to the system!")
-
- layout_mode = fields.Char(
- string="Layout Mode",
- default='Layout1')
-
- control_panel_mode = fields.Char(
- string="Control Panel Mode",
- default='mode1')
-
- login_style = fields.Char(
- string="login style",
- default='login_style1')
-
- icon_policy = fields.Selection(
- string="Menu Icon Policy",
- selection=[
- ('web_icon', 'web_icon'),
- ('font_icon', 'font_icon'),
- ('svg_icon', 'svg_icon')],
- default='svg_icon')
-
- current_theme_mode = fields.Many2one(
- comodel_name='anita_theme_setting.theme_mode',
- string="Current Theme Mode")
-
- current_theme_style = fields.Many2one(
- string="Current Theme Style",
- comodel_name="anita_theme_setting.theme_style",
- domain="[('theme_mode', '=', current_theme_mode)]",
- help="Just use when theme style mode is system")
-
- dialog_animation_in_style = fields.Char(
- string="Dialog Animation In Style",
- default="animate__bounceIn")
- dialog_animation_out_style = fields.Char(
- string="Dialog Animation Out Style",
- compute="_compute_dialog_animation_out_style")
-
- button_style = fields.Char(
- string="Button Style",
- default="style1")
-
- input_style = fields.Char(
- string="Input Style",
- default="style1")
-
- tab_style = fields.Char(
- string="Tab Style",
- default="style1")
-
- font_name = fields.Char(
- string="Font Name",
- default="Roboto", help="Roboto, Helvetica, Verdana, Tahoma, OpenSans, Poppins, NotoSansArabic")
-
- loading_style = fields.Char(
- string="Loading Style",
- default="style1")
-
- loading_svg = fields.Char(string="Loading SVG", compute="_compute_loading_svg")
-
- checkbox_style = fields.Char(
- string="Checkbox Style",
- default="style1")
-
- radio_style = fields.Char(
- string="Radio Style",
- default="style1")
-
- separator_style = fields.Char(
- string="Separator Style",
- default="style1")
-
- rtl_mode = fields.Boolean(
- string="RTL MODE",
- default=False)
-
- allow_debug = fields.Boolean(
- string="Allow Debug",
- default=True)
-
- @api.onchange('current_theme_mode')
- def on_current_theme_mode_change(self):
- """
- change the style
- :return:
- """
- if self.current_theme_mode.theme_styles:
- self.current_theme_style = \
- self.current_theme_mode.theme_styles[0].id
- else:
- self.current_theme_style = False
-
- @api.depends('loading_style')
- def _compute_loading_svg(self):
- """
- compute loading svg
- :return:
- """
- for rec in self:
- if rec.loading_style:
- rec.loading_svg = "/anita_theme_setting/static/loadings/loading_%s.svg" % rec.loading_style
- else:
- rec.loading_svg = False
-
- @api.depends('dialog_animation_in_style')
- def _compute_dialog_animation_out_style(self):
- '''
- compute the dialog animation out style
- :return:
- '''
- for record in self:
- if record.dialog_animation_in_style:
- record.dialog_animation_out_style = record.dialog_animation_in_style.replace('In', 'Out')
- else:
- record.dialog_animation_out_style = 'animate__bounceOut'
\ No newline at end of file
diff --git a/anita_theme_setting/models/anita_setting_manager.py b/anita_theme_setting/models/anita_setting_manager.py
deleted file mode 100644
index 6101740ea..000000000
--- a/anita_theme_setting/models/anita_setting_manager.py
+++ /dev/null
@@ -1,314 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from inspect import trace
-from math import fabs
-from odoo import models, api, tools, fields, _
-from odoo.tools.config import config
-import traceback
-import datetime
-from datetime import date, datetime
-
-import logging
-_logger = logging.getLogger(__name__)
-
-
-class AnitaThemeSettingManager(models.AbstractModel):
- '''
- user theme style setting
- '''
- _name = 'anita_theme_setting.setting_manager'
- _description = 'theme setting manager'
-
- def _register_hook(self):
- """
- stuff to do right after the registry is built
- """
- # check theme mode data
- try:
- # check mode data
- owner = self.get_current_owner()
- force = False
- if config.get('debug', False):
- self.env['anita_theme_setting.default_mode_data'].sudo().refresh_default_mode()
- force = True
- self.env["anita_theme_setting.theme_mode"].check_default_mode_data(owner, force)
- except Exception as e:
- traceback.print_stack(e)
- _logger.error(e)
-
- @api.model
- def get_user_setting(self, get_style=True):
- '''
- get user setting
- :return:
- '''
- rst = dict()
-
- # just get the setting data
- theme_setting_mode = \
- self.env["res.config.settings"].sudo().get_theme_setting_mode()
-
- # check mode data
- owner = self.get_current_owner()
-
- # get the setting data
- if theme_setting_mode == 'system':
- theme_settings = self.env["res.config.settings"].get_theme_setting()
- elif theme_setting_mode == 'company':
- theme_settings = self.env["res.company"].get_theme_setting()
- else:
- theme_settings = self.env["res.users"].get_theme_setting()
-
- # deal the datetime data
- for key, item in theme_settings.items():
- if isinstance(item, datetime):
- theme_settings[key] = fields.Datetime.to_string(item)
- if isinstance(item, date):
- theme_settings[key] = fields.Date.to_string(item)
-
- all_modes = self.env["anita_theme_setting.theme_mode"].search(
- [('owner', '=', owner)])
-
- cur_style_id = theme_settings["current_theme_style"]
- cur_mode_id = theme_settings["current_theme_mode"]
-
- theme_mode = self.env["anita_theme_setting.theme_mode"].search(
- [('id', '=', cur_mode_id)])
- theme_style = self.env["anita_theme_setting.theme_style"].search(
- [('id', '=', cur_style_id)])
- cur_mode_name = theme_mode.name
-
- if not cur_mode_id \
- or cur_mode_id not in all_modes.ids:
- if all_modes:
- cur_mode_id = all_modes[0].id
- cur_style_id = all_modes[0].theme_styles[0].id if all_modes[0].theme_styles else False
- cur_mode_name = all_modes[0].name
- theme_mode = all_modes[0]
- theme_style = all_modes[0].theme_styles[0] if all_modes[0].theme_styles else False
- else:
- cur_mode_id = False
- cur_style_id = False
- cur_mode_name = False
- theme_mode = self.env["anita_theme_setting.theme_mode"]
-
- if not cur_style_id:
- theme_styles = theme_mode.theme_styles
- theme_style = theme_styles[0] if theme_styles else self.env["anita_theme_setting.theme_style"]
- cur_style_id = theme_style.id if theme_style else False
-
- rst['settings'] = theme_settings
- rst['cur_mode_id'] = cur_mode_id
- rst['cur_style_id'] = cur_style_id
-
- # used to set the body class
- rst['cur_mode_name'] = cur_mode_name
- rst['theme_setting_mode'] = theme_setting_mode
-
- rst["window_default_title"] = self.env['ir.config_parameter'].sudo().get_param(
- "anita_theme_setting.window_default_title", "Odoo")
- rst["powered_by"] = self.env['ir.config_parameter'].sudo().get_param(
- "anita_theme_setting.powered_by", "Odoo")
-
- # check the user is anita
- rst['is_anita'] = self.env.user._is_admin()
-
- # add font info
- font_name = theme_settings.get("font_name", False)
- if font_name:
- font_type_css = "*:not(.fa):not(.oi) {font-family: " + font_name + ", sans-serif !important;}"
- else:
- font_type_css = ""
-
- rst['theme_modes'] = self.get_all_mode_data(owner)
-
- # get the style
- if get_style:
- if theme_style:
- style_datas = [font_type_css]
- if theme_style:
- style_datas += theme_style.get_styles_txt()
-
- style_txt = '\n'.join(style_datas)
- rst['style_txt'] = style_txt
-
- if not theme_style.background_image:
- # get from theme mode
- rst['mode_style_css'] = theme_mode.get_mode_style_css()
- else:
- # get from style
- rst['mode_style_css'] = theme_style.get_mode_style_css()
-
- else:
- rst['style_txt'] = ""
- rst['mode_style_css'] = ""
-
- return rst
-
- @api.model
- def get_font_link(self):
- """
- get font link
- :return:
- """
- theme_settings = self.get_theme_setting()
- result = ""
- if theme_settings.get('font_name', False):
- result = '/anita_theme_setting/static/fonts/{font_name}/fonts.css'.format(font_name=theme_settings.get('font_name'))
- return result
-
- @api.model
- def get_theme_setting(self):
- """
- get theme setting
- :return:
- """
- # just get the setting data
- theme_setting_mode = \
- self.env["res.config.settings"].sudo().get_theme_setting_mode()
-
- if theme_setting_mode == 'system':
- theme_settings = self.env["res.config.settings"].get_theme_setting()
- elif theme_setting_mode == 'company':
- theme_settings = self.env["res.company"].get_theme_setting()
- else:
- theme_settings = self.env["res.users"].get_theme_setting()
-
- return theme_settings
-
- @api.model
- def get_font_name(self):
- """
- get font name
- """
- theme_settings = self.get_theme_setting()
- return theme_settings.get('font_name')
-
- @api.model
- def update_cur_style(self, mode_id, style_id):
- '''
- update user cur mode
- :return:
- '''
- ir_config = self.env['ir.config_parameter'].sudo()
- setting_mode = self.env["res.config.settings"].get_theme_setting_mode()
- if setting_mode == "system":
- ir_config.set_param("anita_theme_setting.current_theme_mode", mode_id)
- ir_config.set_param("anita_theme_setting.current_theme_style", style_id)
- elif setting_mode == "company":
- company = self.env.user.company_id
- company.setting_id.current_theme_mode = mode_id
- company.setting_id.current_theme_style = style_id
- elif setting_mode == "user":
- user_id = self.env.user.id
- user = self.env["res.users"].browse(user_id)
- user.setting_id.current_theme_mode = mode_id
- user.setting_id.current_theme_style = style_id
- else:
- assert False
-
- @api.model
- def save_style_data(self, style_id, style_data, owner):
- '''
- save style datas
- :param style_id:
- :param style_data:
- :param owner:
- :return:
- '''
- theme_style = self.env["anita_theme_setting.theme_style"].browse(style_id)
- theme_style.ensure_one()
-
- theme_mode = theme_style.theme_mode
- # save current style just when type is same
- mode_id = theme_mode.id
- if owner:
- if owner.startswith('res.users'):
- parts = owner.split(',')
- user = self.env["res.users"].browse(int(parts[1].strip()))
- if user:
- user.ensure_setting_id()
- user.setting_id.current_theme_mode = mode_id
- user.setting_id.current_theme_style = style_id
- elif owner.startswith('res.company'):
- parts = owner.split(',')
- company = self.env["res.company"].browse(int(parts[1].strip()))
- if company:
- company.ensure_setting_id()
- company.setting_id.current_theme_mode = mode_id
- company.setting_id.current_theme_style = style_id
- else:
- system_setting = self.env["res.config.settings"].get_setting_record()
- system_setting.current_theme_mode = mode_id
- system_setting.current_theme_style = style_id
-
- # as the image is direct change from database so not need to update it
- var_infos = theme_style.mapped('groups.sub_groups.style_items.vars')
- var_cache = {var_info.id: var_info for var_info in var_infos}
- for data in style_data:
- var_id = data["id"]
- tmp_var = var_cache[var_id]
- tmp_var.write({
- "color": data.get('color', False)
- })
-
- if theme_style.background_image:
- mode_style_cs = theme_style.get_mode_style_css()
- else:
- mode_style_cs = theme_mode.get_mode_style_css()
-
- # return the style data
- return {
- 'theme_style': theme_style.get_style(),
- 'mode_style_css': mode_style_cs
- }
-
- def get_current_owner(self):
- """
- get current owner
- :return:
- """
- theme_setting_mode = \
- self.env["res.config.settings"].sudo().get_theme_setting_mode()
-
- # check mode data
- owner = False
- if theme_setting_mode == 'system':
- owner = False
- elif theme_setting_mode == 'company':
- owner = 'res.company, {company_id}'.format(
- company_id=self.env.user.company_id.id)
- elif theme_setting_mode == 'user':
- owner = 'res.users, {user_id}'.format(user_id=self.env.user.id)
-
- return owner
-
- @tools.ormcache('owner')
- @api.model
- def get_all_mode_data(self, owner):
- """
- get all mode data
- """
- all_modes = self.env["anita_theme_setting.theme_mode"].search([('owner', '=', owner)])
- result = []
- for mode in all_modes:
- result.append(mode.get_mode_data()[0])
- return result
-
- @api.model
- def save_settings(self, settings):
- """
- save the settings
- """
- # get the setting mode
- setting_mode = self.env["res.config.settings"].get_theme_setting_mode()
- if setting_mode == "system":
- self.env["res.config.settings"].save_theme_setting(settings)
- elif setting_mode == "company":
- self.env["res.company"].save_theme_setting(settings)
- elif setting_mode == "user":
- self.env["res.users"].save_theme_setting(settings)
- else:
- assert False
-
- return self.get_theme_setting()
diff --git a/anita_theme_setting/models/anita_template_var_vals.py b/anita_theme_setting/models/anita_template_var_vals.py
deleted file mode 100644
index 2127efc98..000000000
--- a/anita_theme_setting/models/anita_template_var_vals.py
+++ /dev/null
@@ -1,21 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from odoo import models, fields, api, exceptions
-import json
-from odoo.tools import ormcache
-
-
-class AnitaTemplateVarVal(models.Model):
- '''
- user theme style setting
- '''
- _name = 'anita_theme_setting.template_var_val'
- _description = 'anita Mode Template'
-
- theme_mode = fields.Many2one(string="Theme Mode", comodel_name="anita_theme_setting.theme_mode")
- name = fields.Char(string="Name", required=True)
- group = fields.Char(string="Group", required=True)
- value = fields.Char(string="Value", required=True)
- disable_opacity = fields.Boolean(string="Disable Opacity", default=False)
- description = fields.Char(string="Description")
-
diff --git a/anita_theme_setting/models/anita_theme_mode.py b/anita_theme_setting/models/anita_theme_mode.py
deleted file mode 100644
index 51be64b27..000000000
--- a/anita_theme_setting/models/anita_theme_mode.py
+++ /dev/null
@@ -1,588 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from odoo import models, fields, api, exceptions, tools
-import json
-import re
-from odoo.tools.misc import file_path
-from odoo.tools.config import config
-from .anita_utility import apply_alpha
-
-try:
- import sass as libsass
-except ImportError:
- libsass = None
-
-import logging
-_logger = logging.getLogger(__name__)
-
-
-class AnitaThemeMode(models.Model):
- '''
- user theme style setting
- '''
- _name = 'anita_theme_setting.theme_mode'
- _description = 'anita theme mode'
-
- name = fields.Char(string="Name", required=True)
- sequence = fields.Integer(string="Mode Sequence", default=0)
-
- theme_styles = fields.One2many(
- string="Theme Styles",
- comodel_name="anita_theme_setting.theme_style",
- inverse_name="theme_mode")
-
- mode_template = fields.Many2one(
- comodel_name="anita_theme_setting.mode_template",
- string="Mode Template")
-
- template_var_vals = fields.One2many(
- comodel_name="anita_theme_setting.template_var_val",
- inverse_name="theme_mode",
- string="Template Vars")
-
- # if owner is False, so the style own to global
- owner = fields.Reference(
- string="Owner",
- selection=[('res.company', 'res.company'),
- ('res.users', 'res.users')],
- default=False,
- help="owner which this theme is create by, if it is false, it mean it is owned to the system!")
- mode_style_css = fields.Text(string="Mode Style Css")
- compiled_mode_style_css = fields.Text(string="Compiled mode style css")
-
- is_default = fields.Boolean(string="Is Default", default=False)
- version = fields.Char(
- string="Version", help="use version to check update or not")
-
- _sql_constraints = [('theme_mode_name_unique', 'UNIQUE(name, owner)',
- "Theme mode name and owner must unique")]
-
- def get_mode_preview_data(self, style_id=False):
- """
- get mode preview data
- :return:
- """
- if self.mode_template:
- if style_id:
- theme_style = self.env['anita_theme_setting.theme_style'].browse(
- style_id)
- if theme_style.is_semi_transparent():
- result = theme_style.get_mode_style_css()
- else:
- result = self.get_mode_style_css()
- else:
- result = self.get_mode_style_css()
- else:
- result = ""
-
- mode_name = 'body.{name}'.format(name=self.name)
- # replace mode_name with body.preview
- result = result.replace(mode_name, 'body.preview')
- return result
-
- @api.onchange('mode_template')
- def on_mode_template_changed(self):
- """
- compute mode style
- :return:
- """
- # check id is instance of NewId
- if self.mode_template:
- scss_vars = self.mode_template.get_color_vars()
- template_var_vals = [(5, 0, 0)]
- for group_name in scss_vars:
- var_items = scss_vars[group_name]
- for var_item in var_items:
- template_var_vals.append((0, 0, {
- "name": var_item["name"],
- "group": group_name,
- "value": var_item["value"],
- "disable_opacity": var_item.get("disable_opacity", False),
- "description": var_item["description"]
- }))
- self.template_var_vals = template_var_vals
- else:
- self.template_var_vals = [(5, 0, 0)]
-
- def check_template_vars(self):
- """
- check style css
- :return:
- """
- return
-
- @tools.ormcache('self.id')
- def get_scss_vars_cache(self):
- """
- get scss vars
- :return:
- """
- records = self.template_var_vals.read(['name', 'value'])
- return {record['name']: record['value'] for record in records}
-
- @tools.ormcache('self.id')
- def get_scss_var_record_cache(self):
- """
- get scss vars
- :return:
- """
- records = self.template_var_vals
- return {record.name: {
- "name": record.name,
- "value": record.value,
- "disable_opacity": record.disable_opacity,
- } for record in records}
-
- def _compile_scss(self, alpha=False):
- """
- This code will compile valid scss into css.
- Simply copied and adapted slightly
- """
- self.ensure_one()
- scss_source = self.mode_template.template
-
- scss_vars = []
- var_val_cache = self.get_scss_var_record_cache()
- for var_name in var_val_cache:
- var_record = var_val_cache[var_name]
- name = var_record.get("name")
- if alpha and alpha < 1:
- color = apply_alpha(var_record.get('name'), var_record.get('value'), alpha)
- else:
- color = var_record.get('value')
- # new color
- scss_vars.append('{name}: {value};'.format(
- name=name, value=color))
- # origin color, some element disable alpha
- scss_vars.append('{name}: {value};'.format(
- name=name.replace('$', '$_'), value=var_record.get('value')))
-
- precision = 8
- output_style = 'expanded'
-
- bootstrap_scss_path = file_path('web/static/lib/bootstrap/scss')
-
- mode_selectors = "$mode_selectors: 'body.{name}';".format(name=self.name)
- extra_vars = [
- mode_selectors,
- "$compile_normal: 1;",
- "$semi_transparent: {semi_trans};".format(semi_trans=True if alpha < 1.0 else False),
- ]
-
- total_vars = extra_vars + scss_vars
- normal_source = '\n'.join(total_vars) + '\n' + scss_source if scss_source else ''
-
- # compile normal
- results = []
- try:
- result = libsass.compile(
- string=normal_source,
- include_paths=[bootstrap_scss_path],
- output_style=output_style,
- precision=precision)
- # remove the import bootstrap
- index = result.find("body.{name}".format(name=self.name))
- result = result[index:]
- results.append(result)
- except libsass.CompileError as e:
- _logger.error(e.args[0])
-
- # compile for background
- if alpha < 1.0:
- scss_vars = []
- for var_name in var_val_cache:
- var_record = var_val_cache[var_name]
- name = var_record.get("name")
- # new color
- scss_vars.append('{name}: {value};'.format(name=name, value=var_record.get('value')))
- # origin color
- scss_vars.append('{name}: {value};'.format(name=name.replace('$', '$_'), value=var_record.get('value')))
-
- mode_selectors = "$mode_selectors: 'body.{name} .o_dialog_container';".format(name=self.name)
- extra_vars = [
- mode_selectors,
- "$compile_normal: 0;",
- "$semi_transparent: {semi_trans};".format(semi_trans=1 if alpha < 1.0 else 0),
- ]
- total_vars = extra_vars + scss_vars
- normal_source = '\n'.join(total_vars) + '\n' + str(scss_source)
- try:
- result = libsass.compile(
- string=normal_source,
- include_paths=[bootstrap_scss_path],
- output_style=output_style,
- precision=precision)
- # remove the import bottstrap
- index = result.find('body.{name} .o_dialog_container'.format(name=self.name))
- result = result[index:]
- results.append(result)
- except libsass.CompileError as e:
- _logger.error(e.args[0])
-
- return '\n'.join(results)
-
- @api.model
- def compute_mode_style_url(self):
- """
- compute mode style url
- :return:
- """
- for record in self:
- record.mode_style_url = \
- '/web/image/anita_theme_setting.anita_theme_setting/{var_id}/icon128x128'.format(
- var_id=record.id)
-
- def get_default_mode_style_text(self, theme_mode_info):
- """
- get default mode data
- :return:
- """
- if self.name == 'normal':
- return
-
- color_vars = theme_mode_info["template_vars"]
- mode_template = theme_mode_info["mode_template"]
- if not mode_template:
- raise exceptions.ValidationError('Can not find the theme template!')
-
- template = mode_template.template
- # css template data
- template = template.replace('$mode_name', self.name)
-
- # replace the var
- for var_nam in color_vars:
- template = str(template).replace(var_nam, color_vars[var_nam])
-
- return template
-
- @api.model
- def check_default_mode_data(self, owner=False, force = False):
- '''
- check default mode data
- :return:
- '''
- modes = self.search([('owner', '=', owner)])
- olde_mode_cache = {mode.name: mode for mode in modes}
-
- default_modes = \
- self.env["anita_theme_setting.default_mode_data"].search([])
-
- # create new mode if the mode do not exits
- for default_mode in default_modes:
-
- if not default_mode.data:
- continue
-
- # need to reload the mode data
- mode_data = default_mode.get_mode_data()
- if default_mode.name not in olde_mode_cache:
- mode_data["name"] = default_mode["name"]
-
- # create new mode use the mode data
- record = self.create_mode(mode_data, owner)
- if not record.mode_template:
- continue
-
- # check the templates
- templates = self.env["anita_theme_setting.mode_template"].get_templates(
- )
- template = mode_data.get('mode_template', False)
- if template and template not in templates:
- raise exceptions.ValidationError(
- '{template} do not exits!'.format(template=mode_data["template"]))
-
- template = templates[mode_data["mode_template"]]
- record.mode_template = template.id
-
- # check vars are defined in the template vars
- record.check_template_vars()
- else:
- # check version, if the version is different
- mode = olde_mode_cache[default_mode.name]
- if force or mode.version != mode_data["version"]:
- # update template vars
- temlate_var_vals = mode_data["template_var_vals"]
- mode.update_template_var_values(temlate_var_vals)
- # update template
- mode_templates = self.env["anita_theme_setting.mode_template"].get_templates(
- )
- if mode_data.get("mode_template", False):
- template_name = mode_data["mode_template"]
- mode.mode_template = \
- mode_templates.get(template_name, False)
- mode.version = mode_data["version"]
- mode.check_mode_data()
- # recompile the template
- mode.compiled_mode_style_css = False
-
- # unlink the invalid mode
- for default_mode in default_modes:
- if not default_mode.data:
- default_mode.unlink()
-
- def create_mode(self, mode_config, owner=False, is_default=True):
- '''
- create mode
- :param mode style txt:
- :param mode_data:
- :param owner:
- :param is_default:
- :return:
- '''
- mode_templates = \
- self.env["anita_theme_setting.mode_template"].get_templates()
- mode_template = mode_config.get('mode_template', False)
- if mode_template and mode_template not in mode_templates:
- raise exceptions.ValidationError('Can not find mode template {mode_template}'.format(
- mode_template=mode_template))
-
- # convert to cache data
- template_var_vals = mode_config.get('template_var_vals', {})
- var_val_cache = {}
- for group in template_var_vals:
- var_items = template_var_vals[group]
- for var_item in var_items:
- var_val_cache[var_item["name"]] = var_item["value"]
-
- theme_styles = mode_config['theme_styles']
- theme_style_array = []
- for theme_style in theme_styles:
- groups = theme_style["groups"]
- group_datas = []
- for group_index, var_items in enumerate(groups):
- sub_groups = var_items["sub_groups"]
- sub_group_array = []
- for sub_group_index, sub_group in enumerate(sub_groups):
- # create sub group
- item_array = []
- style_items = sub_group["style_items"]
- for item_index, style_item in enumerate(style_items):
- var_val_array = []
- var_infos = style_item["vars"]
- for var_index, var_info in enumerate(var_infos):
- color = var_info.get("color", False)
- ref_var = var_info.get("ref_var", False)
- if ref_var:
- if ref_var not in var_val_cache:
- color = False
- _logger.info(
- "Can not find ref var {ref_var}".format(ref_var=ref_var))
- else:
- color = var_val_cache[ref_var]
-
- var_val_array.append((0, 0, {
- "name": var_info["name"],
- "type": var_info["type"],
- "sequence": var_index,
- "is_default": is_default,
- "color": color,
- "image": var_info.get('image', False),
- "image_url": var_info.get('image_url', False),
- "svg": var_info.get('svg', False),
- "identity": var_info.get('identity', False)
- }))
-
- item_array.append((0, 0, {
- "name": style_item["name"],
- "is_default": is_default,
- "sequence": item_index,
- "val_template": style_item["val_template"],
- "sub_group": sub_group["name"],
- "vars": var_val_array,
- "selectors": json.dumps(style_item["selectors"])
- }))
-
- sub_group_array.append((0, 0, {
- "name": sub_group["name"],
- "sequence": sub_group_index,
- "style_items": item_array,
- "is_default": is_default
- }))
-
- group_datas.append((0, 0, {
- "name": var_items["name"],
- "sequence": group_index,
- "is_default": is_default,
- "sub_groups": sub_group_array
- }))
-
- theme_style_array.append((0, 0, {
- "name": theme_style["name"],
- "is_default": is_default,
- "groups": group_datas
- }))
-
- vals = []
- template_var_vals = mode_config.get('template_var_vals', {})
- for group_name in template_var_vals:
- var_items = template_var_vals[group_name]
- for var_item in var_items:
- vals.append((0, 0, {
- "name": var_item["name"],
- "group": group_name,
- "value": var_item["value"],
- "disable_opacity": var_item.get("disable_opacity", False),
- "description": var_item["description"]
- }))
-
- mode_template = mode_config.get("mode_template", False)
- return self.env["anita_theme_setting.theme_mode"].create([{
- "name": mode_config["name"],
- "theme_styles": theme_style_array,
- "is_default": is_default,
- "version": mode_config["version"],
- "mode_template": mode_templates[mode_template].id if mode_template else False,
- "owner": owner,
- "template_var_vals": vals
- }])
-
- def get_mode_data(self):
- '''
- get the mode data
- :return:
- '''
- self.ensure_theme_style()
- rst = []
- for record in self:
- tmp_data = record.read(
- ['name', 'is_default', 'sequence', 'version'])[0]
- tmp_data['theme_styles'] = record.theme_styles.get_styles()
- rst.append(tmp_data)
- return rst
-
- def delete_mode(self):
- """
- delete the mode
- :return:
- """
- self.unlink()
-
- def check_style_css(self):
- """
- check style css
- :return:
- """
- if self.mode_template and not self.compiled_mode_style_css:
- self.compiled_mode_style_css = self._compile_scss()
-
- def update_template_var_values(self, template_var_vals):
- """
- update template var values
- :param temlate_var_vals:
- :return:
- """
- self.ensure_one()
- vals = [(5, 0, 0)]
- for group_name in template_var_vals:
- var_items = template_var_vals[group_name]
- for var_item in var_items:
- vals.append((0, 0, {
- "name": var_item["name"],
- "group": group_name,
- "value": var_item["value"],
- "description": var_item.get("description")
- }))
- self.template_var_vals = vals
-
- def get_mode_style_css(self):
- """
- get mode style css
- """
- if config.get('debug', False) or not self.compiled_mode_style_css:
- self.compiled_mode_style_css = self._compile_scss()
-
- return self.compiled_mode_style_css
-
- def check_mode_data(self):
- '''
- check the mode data
- :return:
- '''
- self.ensure_one()
-
- default_modes = self.env[
- "anita_theme_setting.default_mode_data"].search([])
- default_mode_cache = {
- default_mode.name: default_mode for default_mode in default_modes}
-
- mode_name = self.name
- if mode_name not in default_mode_cache:
- return
-
- theme_styles = self.theme_styles
- theme_style_cache = {
- theme_style.name: theme_style for theme_style in theme_styles if theme_style.is_default}
-
- default_mode = default_mode_cache[mode_name]
- default_mode_data = default_mode.get_mode_data()
-
- theme_styles = default_mode_data['theme_styles']
- for theme_style in theme_styles:
- # create new style
- style_name = theme_style['name']
- if style_name not in theme_style_cache:
- self.env["anita_theme_setting.theme_style"].create_style(
- self.id, theme_style)
- else:
- # check the style data, may be one more style with the same name
- tmp_style = theme_style_cache[style_name]
- tmp_style.check_groups(default_mode, theme_style["groups"])
-
- def get_mode_edit_action(self, style_id):
- """
- get theme mode edit action
- """
- self.ensure_one()
- form_id = self.env.ref("anita_theme_setting.edit_theme_mode_form").id
-
- var_vals = []
- for var_val in self.template_var_vals:
- var_vals.append((0, 0, {
- "name": var_val.name,
- "group": var_val.group,
- "value": var_val.value,
- "disable_opacity": var_val.disable_opacity,
- "description": var_val.description
- }))
-
- return {
- "type": "ir.actions.act_window",
- "res_model": "anita_theme_setting.theme_mode",
- "views": [[form_id, "form"]],
- "res_id": self.id,
- "view_mode": "form",
- "target": "new",
- "context": {
- "default_name": self.name,
- "default_mode_template": self.mode_template.id,
- "sequnce": self.sequence,
- "template_var_vals": var_vals,
- "default_style_id": style_id
- }
- }
-
- @api.model
- def get_new_mode_action(self):
- """
- get create new mode action
- """
- form_id = self.env.ref("anita_theme_setting.new_theme_mode_form").id
- return {
- "type": "ir.actions.act_window",
- "res_model": "anita_theme_setting.theme_mode",
- "views": [[form_id, "form"]],
- "view_mode": "form",
- "target": "new"
- }
-
- def ensure_theme_style(self):
- """
- create a empty theme style
- """
- if not self.theme_styles:
- self.env["anita_theme_setting.theme_style"].create_style(
- self.id, {
- "name": "style1",
- "is_default": False,
- "groups": []
- })
\ No newline at end of file
diff --git a/anita_theme_setting/models/anita_theme_style.py b/anita_theme_setting/models/anita_theme_style.py
deleted file mode 100644
index ebfa11385..000000000
--- a/anita_theme_setting/models/anita_theme_style.py
+++ /dev/null
@@ -1,506 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from odoo import models, fields, api, _, exceptions, tools
-import json
-import base64
-from odoo.tools.config import config
-from .anita_utility import apply_alpha
-import traceback
-
-import logging
-_logger = logging.getLogger(__name__)
-
-
-class AnitaThemeStyle(models.Model):
- '''
- Theme style
- '''
- _name = 'anita_theme_setting.theme_style'
- _description = 'awesome theme style'
- _order = 'sequence asc, id asc'
-
- name = fields.Char(string="style name", required=True)
- theme_mode = fields.Many2one(
- comodel_name="anita_theme_setting.theme_mode",
- string="theme mode",
- ondelete="cascade")
- mode_css = fields.Text(string="mode style scss")
- style_css = fields.Text(string="style css")
-
- is_default = fields.Boolean(string="is default", default=False)
-
- background_image = fields.Binary(string="background image")
- opacity = fields.Float(string="opacity", default=1.0)
-
- owner = fields.Reference(
- string="owner",
- selection=[
- ('res.company', 'res.company'),
- ('res.users', 'res.users')],
- default=False,
- help="Owner which this theme is create by")
-
- sequence = fields.Integer(string="style sequence", default=0)
-
- groups = fields.One2many(
- string="Groups",
- comodel_name="anita_theme_setting.style_item_group",
- inverse_name="theme_style")
-
- side_bar_style = fields.Selection(
- string="side bar style",
- selection=[
- ('style1', 'style1'),
- ('style2', 'style2'),
- ('style3', 'style3')])
-
- sidebar_width = fields.Integer(string="sidebar width", default=80)
- sidebar_menu_width = fields.Integer(
- string="sidebar menu width", default=220)
-
- @tools.ormcache('self.id')
- def get_style(self):
- '''
- get simple style data
- :return:
- '''
- self.ensure_one()
- result = self.read(['id', 'name', 'is_default'])[0]
- result["groups"] = self.groups.get_group_data()
- result["theme_mode"] = self.theme_mode.name
- # get background image ulr
- if self.background_image:
- result["background_image"] = self.get_background_image_url()
- else:
- result["background_image"] = False
- result["opacity"] = self.opacity
- identities = dict()
- groups = result["groups"]
- # collect identity
- for group in groups:
- sub_groups = group["sub_groups"]
- for sub_group in sub_groups:
- style_items = sub_group["style_items"]
- for item in style_items:
- if not item["vars"]:
- continue
- # collect the identity
- var_infos = item["vars"]
- for var in var_infos:
- if var.get('identity', False):
- if self.is_semi_transparent():
- identities[var['identity']] = apply_alpha(var['name'], var['color'], self.opacity, var.get('color_type'))
- else:
- identities[var['identity']] = var['color']
-
- result["identities"] = identities
- return result
-
- def get_styles(self):
- '''
- get mode datas
- :return:
- '''
- results = []
- for record in self:
- results.append(record.get_style())
- return results
-
- def _get_style_data(self):
- '''
- get mode datas
- :return:
- '''
- self.ensure_one()
- results = []
- result = self.read(['name', 'is_default', 'sequence'])[0]
- if self.background_image:
- result["background_image"] = self.get_background_image_url()
- result["groups"] = self.groups.get_group_data()
- results.append(result)
- return results
-
- def get_styles_txt(self):
- '''
- get style txt
- :return:
- '''
- self.ensure_one()
-
- mode_prefix = 'body.' + self.theme_mode.name + ' '
- result = []
- groups = self.groups
- for group in groups:
- for sub_group in group.sub_groups:
- style_items = sub_group.style_items
- for style_item in style_items:
- val = style_item.val
-
- # if the val is same as the ref var, then ignore it
- if not val or val == "" or not style_item.selectors:
- continue
-
- try:
- selector = mode_prefix + \
- ','.join(json.loads(style_item["selectors"]))
- tmp_txt = selector + " {" + val + "}"
- result.append(tmp_txt)
- except Exception as error:
- traceback.print_stack(e)
- _logger.info(error)
-
- # append the background image
- if self.background_image:
- background_image_url = self.get_background_image_url()
- if background_image_url:
- result.append(
- mode_prefix + " {background-image: url('" +
- background_image_url + "') !important;")
-
- return result
-
- def is_semi_transparent(self):
- '''
- is semi transparent
- :return:
- '''
- self.ensure_one()
- return self.opacity < 1.0
-
- def get_mode_style_css(self):
- '''
- get mode styles
- :return:
- '''
- self.ensure_one()
-
- if not self.is_semi_transparent():
- return self.theme_mode.get_mode_style_css()
- else:
- if config.get('debug', False) or not self.mode_css:
- self.mode_css = self.theme_mode._compile_scss(self.opacity or 1)
- return self.mode_css
-
- def _compute_var_val(self, style_item_info):
- '''
- compute the val, use by the
- :return:
- '''
- self.ensure_one()
-
- background_image = self.background_image
- scss_var_cache = self.theme_mode.get_scss_vars_cache()
- opacity = self.opacity
- vars_cache = dict()
- all_color = True
- all_ref = True
- all_same = True
- for var in style_item_info.get('vars', []):
- name = var.get('name', False)
- type = var.get('type', False)
- if type == 'color':
- # check if has opacity
- color = var.get('color')
- ref_var = var.get('ref_var', False)
- if ref_var:
- ref_color = scss_var_cache[ref_var]
- if ref_color != color:
- all_same = False
- else:
- all_ref = False
-
- try:
- if background_image:
- if not var.get('disable_opacity', False):
- color = apply_alpha(name, color, opacity, var.get('color_type'))
- except Exception as e:
- traceback.print_stack(e)
- _logger.error("apply alpha error {e}".format(e=e))
- vars_cache[name] = color
- elif var.type == 'image':
- vars_cache[name] = var.get('image_file_url')
- all_color = False
- elif var.type == 'image_url':
- vars_cache[name] = var.get('image_url')
- all_color = False
- else:
- vars_cache[name] = var.get('svg')
- all_color = False
-
- # if all the color are the original color, them ignore it
- if all_color and all_ref and all_same:
- style_item_info['val'] = False
- else:
- try:
- val_template = style_item_info.get('val_template', False)
- style_item_info['val'] = val_template.format(**vars_cache)
- except Exception as error:
- style_item_info['val'] = False
- traceback.print_stack(e)
- _logger.info('parse var value error, item name {item_name}->{error}'.format(
- item_name=style_item_info['name'], error=error))
-
- def post_deal_preview_data(self, style_item_infos, font_info, preview = False):
- '''
- get mode datas
- :return:
- '''
- self.ensure_one()
-
- if preview:
- mode_prefix = 'body.preview '
- else:
- mode_prefix = 'body.' + self.theme_mode.name + ' '
-
- result = [font_info]
- groups = self.groups
- for group in groups:
- for sub_group in group.sub_groups:
- style_items = sub_group.style_items
- for style_item in style_items:
- if str(style_item.id) not in style_item_infos:
- val = style_item.val
- if val == "":
- continue
- if not style_item.selectors:
- continue
- try:
- selector = mode_prefix + \
- ','.join(json.loads(style_item["selectors"]))
- tmp_txt = selector + " {" + val + "}"
- result.append(tmp_txt)
- except Exception as error:
- traceback.print_stack(e)
- _logger.info(error)
- else:
- style_item = style_item_infos[str(style_item.id)]
-
- # compute the val
- self._compute_var_val(style_item)
- val = style_item.get('val', False)
-
- # if the val is same as the ref var, then ignore it
- selectors = style_item.get('selectors', False)
- if not val or val == "" or not selectors:
- continue
-
- try:
- # check selector is a array
- if not isinstance(selectors, list):
- selectors = [selectors]
- selector = mode_prefix + ','.join(selectors)
- tmp_txt = selector + " {" + val + "}"
- result.append(tmp_txt)
- except Exception as error:
- traceback.print_stack(error)
- _logger.info(error)
-
- # append the background image
- if self.background_image:
- background_image_url = self.get_background_image_url()
- if background_image_url:
- result.append(
- mode_prefix + " {background-image: url('" +
- background_image_url + "') !important;")
-
- return "\n".join(result)
-
- @api.model
- def delete_style(self, style_id):
- '''
- delete styel of user
- :return:
- '''
- record = self.search([('id', '=', style_id)])
- record.unlink()
-
- def check_groups(self, default_mode, groups):
- '''
- check the style group
- :param groups:
- :return:
- '''
- self.ensure_one()
-
- new_group_cache = {group["name"]: group for group in groups}
- old_group_cache = {group.name: group for group in self.groups}
-
- for group_index, name in enumerate(new_group_cache):
- default_group = new_group_cache[name]
- if name not in old_group_cache:
- self.env['anita_theme_setting.style_item_group']\
- .create_group_from_default_data(self, default_group, group_index)
- else:
- # update the style item
- tmp_group = old_group_cache[name]
- tmp_group.write({
- "name": name,
- "is_default": True,
- "sequence": group_index,
- })
- # check group item data
- sub_group_items = default_group["sub_groups"]
- tmp_group.check_sub_group(default_mode, sub_group_items)
-
- # delete the style item
- for tmp_group_name in old_group_cache:
- if tmp_group_name not in new_group_cache \
- and old_group_cache[tmp_group_name].is_default:
- old_group_cache[tmp_group_name].unlink()
-
- def create_style(
- self, model_id, style_data, owner=False, is_default=True):
- '''
- create theme style from default info
- :return:
- '''
- default_groups = style_data['groups']
- mode = self.env['anita_theme_setting.theme_mode'].browse(model_id)
- scss_vars_cache = mode.get_scss_vars_cache()
-
- group_datas = []
- for group_index, group in enumerate(default_groups):
- sub_groups = group["sub_groups"]
- sub_group_array = []
- for sub_group_index, sub_group in enumerate(sub_groups):
-
- style_items = sub_group["style_items"]
- style_item_datas = []
- for style_item_index, style_item in enumerate(style_items):
- selectors = json.dumps(style_item['selectors'])
- var_vals = []
- var_infos = style_item['vars']
- for var_info in var_infos:
- ref_var = var_info.get('ref', False)
- if ref_var:
- if ref_var in scss_vars_cache:
- raise exceptions.ValidationError(
- _("The variable %s has been used") % ref_var)
- else:
- color = scss_vars_cache[ref_var]
- else:
- color = var_info.get('color', False)
-
- var_vals.append((0, 0, {
- "name": var_info["name"],
- "is_default": is_default,
- "type": var_info["type"],
- "color": color,
- "image": var_info.get('image', False),
- "image_url": var_info.get('image_url', False),
- "svg": var_info.get('svg', False),
- "identity": var_info.get('identity', False)
- }))
-
- tmp_style_item = dict()
- tmp_style_item['selectors'] = selectors
- tmp_style_item['sequence'] = style_item_index
- tmp_style_item['name'] = style_item["name"]
- tmp_style_item["is_default"] = is_default
- tmp_style_item["val_template"] = style_item["val_template"]
- tmp_style_item["vars"] = var_vals
-
- style_item_datas.append((0, 0, tmp_style_item))
-
- sub_group_array.append((0, 0, {
- "name": sub_group["name"],
- "sequence": sub_group_index,
- "style_items": style_item_datas,
- "is_default": True
- }))
-
- group_datas.append((0, 0, {
- "name": group["name"],
- "sequence": group_index,
- "sub_groups": sub_group_array,
- "is_default": True
- }))
-
- return self.env['anita_theme_setting.theme_style'].create({
- "name": style_data["name"],
- "theme_mode": model_id,
- "is_default": is_default,
- "groups": group_datas,
- "owner": owner
- })
-
- @api.model
- def add_new_style(
- self, mode_id, style_data, owner=False, is_default=False):
- '''
- add new style, get the first style as the default, call from the front web
- :return:
- '''
- # if not owner, use the current owner
- if not owner:
- owner = self.env["anita_theme_setting.setting_manager"].get_current_owner()
-
- theme_style = self.create_style(
- mode_id, style_data, owner, is_default)
-
- # return the new style data
- style_data = theme_style.get_styles()[0]
-
- return style_data
-
- def clone_style(self, owner=False):
- '''
- clone style
- :return:
- '''
- self.ensure_one()
- if not owner:
- owner = self.env["anita_theme_setting.setting_manager"].get_current_owner()
-
- style_data = self.get_styles()[0]
- return self.add_new_style(self.theme_mode.id, style_data, owner)
-
- @api.model
- def import_new_style(self, mode_id, wizard_id):
- """
- import new style
- :param mode_id:
- :param wizard_id:
- :return:
- """
- wizard = self.env["anita_theme_setting.import_theme_style"].browse(
- wizard_id)
- style_data = json.loads(
- base64.decodebytes(wizard.file).decode('utf-8'))
- return self.add_new_style(mode_id, style_data)
-
- def set_bk_image(self, wizard_id):
- """
- set background image
- """
- self.ensure_one()
- wizard = self.env["anita_theme_setting.background_image_wizard"].browse(
- wizard_id)
-
- self.background_image = wizard.data
- self.opacity = wizard.opacity
-
- # reutrn the image url
- url = self.get_background_image_url()
-
- # clear cache
- self.clear_caches()
-
- return url
-
- def get_background_image_url(self):
- """
- get image url
- """
- self.ensure_one()
- if self.background_image:
- return 'web/image/anita_theme_setting.theme_style/' + str(self.id) + '/background_image'
- else:
- return False
-
- def clear_style_css(self):
- """
- clear style css when style change
- """
- self.ensure_one()
- self.style_css = False
diff --git a/anita_theme_setting/models/anita_theme_style_item.py b/anita_theme_setting/models/anita_theme_style_item.py
deleted file mode 100644
index cd65f1c33..000000000
--- a/anita_theme_setting/models/anita_theme_style_item.py
+++ /dev/null
@@ -1,332 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from odoo import models, fields, api, exceptions
-import logging
-import json
-from .anita_utility import apply_alpha
-
-_logger = logging.getLogger(__name__)
-
-
-class AnitaThemeStyleItem(models.Model):
- '''
- user theme style setting
- '''
- _name = 'anita_theme_setting.style_item'
- _order = 'sequence asc'
- _description = "style item"
-
- sub_group = fields.Many2one(
- comodel_name="anita_theme_setting.style_item_sub_group", string="sub group")
- theme_mode = fields.Many2one(
- comodel_name="anita_theme_setting.theme_mode",
- related="sub_group.group.theme_style.theme_mode",
- store=True,
- string="theme mode")
- theme_style = fields.Many2one(
- comodel_name="anita_theme_setting.theme_style",
- related = "sub_group.group.theme_style",
- string="theme style")
-
- name = fields.Char(string="name", required=True, default="var1")
- val = fields.Char(string="val", compute="_compute_val")
- sequence = fields.Integer(string="sequence", default=0)
- mode = fields.Selection(
- selection=[('override', 'override'), ('primary', 'primary')],
- string="mode",
- default="override",
- help="override or primary, override is override the default style and primary is create a new style")
- val_template = fields.Char(
- string="val template",
- required=True,
- default="background: {var1}", help="Save the last val")
- vars = fields.One2many(
- string="vars",
- comodel_name="anita_theme_setting.theme_var",
- inverse_name="style_item")
- selectors = fields.Char(string="selectors", required=True)
- is_default = fields.Boolean(string="Is Default", default=True)
- type = fields.Selection(
- string="type",
- selection=[('normal', 'normal'),
- ('login', 'login')],
- default='normal')
- login_style = fields.Char(string="login style", default="login_style1")
-
-
- def check_vars(self, default_mode, sub_group_id, default_vars):
- '''
- check vars
- :return:
- '''
- # check vars
- self.ensure_one()
- var_val_cache = default_mode.get_var_val_cache()
-
- # get current var cache
- old_var_cache = {var.name: var for var in self.vars}
- default_var_cache = \
- {default_var["name"]: default_var for default_var in default_vars}
-
- tmp_vals = []
- for default_var in default_vars:
-
- color = default_var.get("color", False)
- ref_var = default_var.get("ref_var",False)
- if ref_var:
- if ref_var not in var_val_cache:
- color = False
- _logger.info("ref var {ref_var} not in var cache".format(ref_var=ref_var))
- else:
- color = var_val_cache[ref_var]
-
- # item exits must keep
- if default_var["name"] not in old_var_cache:
- tmp_vals.append({
- "sub_group": sub_group_id,
- "name": default_var["name"],
- "style_item": self.id,
- "type": default_var["type"],
- "color": color,
- "image": default_var.get('image', False),
- "image_url": default_var.get('image_url', False),
- "svg": default_var.get('svg', False),
- "is_default": default_var.get('is_default', True),
- "identity": default_var.get('identity', False),
- "ref_var": ref_var,
- "disable_opacity": default_var.get('disable_opacity', False),
- })
- else:
- # keep the val, maybe user will
- tmp_var = old_var_cache[default_var["name"]]
- tmp_var.write({
- "type": default_var["type"],
- "is_default": default_var.get('is_default', True),
- "identity": default_var.get('identity', False),
- "color": color,
- "image": default_var.get('image', False),
- "image_url": default_var.get('image_url', False),
- "svg": default_var.get('svg', False),
- "ref_var": ref_var,
- "disable_opacity": default_var.get('disable_opacity', False),
- })
-
- # create the missing vars
- self.env["anita_theme_setting.theme_var"].create(tmp_vals)
-
- # unlink the old var
- for name in old_var_cache:
- if name not in default_var_cache:
- tmp_var = old_var_cache[name]
- tmp_var.unlink()
-
- @api.depends('selectors', 'val_template', "vars")
- def _compute_val(self):
- '''
- compute the val
- :return:
- '''
- # check if mode has background image
- for record in self:
- # if every var is color and the color val is same as the ref var
- background_image = record.theme_style.background_image
- scss_var_cache = record.theme_mode.get_scss_var_record_cache()
- opacity = record.theme_style.opacity
- vars_cache = dict()
- all_color = True
- all_ref = True
- all_same = True
- for var in record.vars:
- if var.type == 'color':
- # check if has opacity
- color = var.color
- if var.ref_var and var.ref_var in scss_var_cache:
- ref_color = scss_var_cache[var.ref_var]
- if ref_color != color:
- all_same = False
- else:
- all_ref = False
-
- try:
- if background_image:
- if not var.disable_opacity:
- color = apply_alpha(var.name, color, opacity, var.color_type)
- except Exception as e:
- _logger.error("apply alpha error {e}".format(e=e))
-
- vars_cache[var.name] = color
- elif var.type == 'image':
- vars_cache[var.name] = var.image_file_url
- all_color = False
- elif var.type == 'image_url':
- vars_cache[var.name] = var.image_url
- all_color = False
- else:
- vars_cache[var.name] = var.svg
- all_color = False
-
- # if all the color are the original color, them ignore it
- if all_color and all_ref and all_same:
- record.val = False
- else:
- if not record.vars:
- record.val = False
- else:
- try:
- record.val = str(record.val_template).format(**vars_cache)
- except Exception as error:
- record.val = False
- _logger.info('parse var value error, item name {item_name}->{error}'.format(
- item_name=record['name'], error=error))
-
- def get_style_item_data(self):
- '''
- get the style item data
- :return:
- '''
- export_style = self.env.context.get('export_style', False)
- style_items = []
- for record in self:
- style_item = record.read(
- fields=["id", "name", "is_default", "val_template", "val", "selectors"])[0]
-
- try:
- style_item['selectors'] = json.loads(style_item['selectors'])
- except Exception as error:
- _logger.info('try to decode selectors error!', error)
-
- if not export_style:
- # maybe the image is very large, so do not read the image
- style_item["vars"] = \
- record.vars.read(
- ["name", "identity", "type", "image_file_url", "image_url", "color", "svg", "color_type"])
- else:
- style_item["vars"] = \
- record.vars.read(
- ["name", "identity", "type", "image", "image_url", "color", "svg", "color_type"])
- for tmp_var in style_item["vars"]:
- if tmp_var["image"]:
- tmp_var["image"] = str(tmp_var["image"])
-
- style_items.append(style_item)
- return style_items
-
- def write(self, vals):
- """
- rewrite to check if the selectors are right
- :param vals:
- :return:
- """
- super(AnitaThemeStyleItem, self).write(vals)
-
- vars_cache = dict()
- for var in self.vars:
- if var.type == 'color':
- vars_cache[var.name] = var.color
- elif var.type == 'image':
- vars_cache[var.name] = var.image_file_url
- elif var.type == 'image_url':
- vars_cache[var.name] = var.image_url
- else:
- vars_cache[var.name] = var.svg
-
- # check the var
- try:
- str(self.val_template).format(**vars_cache)
- except Exception as error:
- _logger.info('parse var value error, item name {item_name}->{error}'.format(
- item_name=self['name'], error=error))
-
- def get_login_style_data(
- self, theme_style_id, login_style):
- """
- get login style data
- :return:
- """
- result = []
- theme_style = self.env["anita_theme_setting.theme_style"].browse(theme_style_id)
- sub_group_ids = theme_style.mapped('groups.sub_groups.id')
- style_items = self.search(
- [('type', '=', 'login'),
- ('login_style', '=', login_style),
- ('sub_group', 'in', sub_group_ids)])
- for style_item in style_items:
- val = style_item.val
- if val == "":
- continue
- if not style_item.selectors:
- continue
- try:
- selector = ','.join(json.loads(style_item["selectors"]))
- tmp_txt = selector + " {" + val + "}"
- result.append(tmp_txt)
- except Exception as error:
- _logger.info(error)
- return ";".join(result)
-
- def delete_style_item(self):
- '''
- delete style item
- :return:
- '''
- self.ensure_one()
- self.unlink()
-
- def create_style_item(
- self, default_mode, sub_group, style_item, style_item_index):
- '''
- create group from default data
- :return:
- '''
- selectors = json.dumps(style_item["selectors"])
- var_infos = style_item["vars"]
- var_val_cache = default_mode.get_var_val_cache()
-
- var_vals = []
- for var_index, var_info in enumerate(var_infos):
-
- color = var_info.get("color", False)
- ref_var = var_info.get("ref_var", False)
- if ref_var:
- if ref_var not in var_val_cache:
- color = False
- _logger.info("ref var not in var cache", ref_var)
- else:
- color = var_val_cache[ref_var]
-
- var_vals.append((0, 0, {
- "name": var_info["name"],
- "type": var_info["type"],
- "sequence": var_index,
- "color": color,
- "image": var_info.get('image', False),
- "image_url": var_info.get('image_url', False),
- "svg": var_info.get('svg', False),
- "identity": var_info.get('identity', False),
- "ref_var": ref_var
- }))
-
- style_item_val = {
- "name": style_item["name"],
- "sequence": style_item_index,
- "val_template": style_item["val_template"],
- "selectors": selectors,
- "vars": var_vals,
- "sub_group": sub_group
- }
-
- return self.create([style_item_val])
-
- def resert_var(self):
- """
- reset var, resut to the derfault value
- :return:
- """
- if not self.ref_var and self.type != 'color':
- return False
- # get mode first
- var_cache = self.sub_group.group.theme_style.theme_mode.get_scss_vars_cache()
- for var in self.vars.filtered(lambda x: x.type == 'color'):
- if var.ref_var:
- var.color = var_cache.get(var.ref_var, False)
- return True
\ No newline at end of file
diff --git a/anita_theme_setting/models/anita_theme_style_item_group.py b/anita_theme_setting/models/anita_theme_style_item_group.py
deleted file mode 100644
index eaba64563..000000000
--- a/anita_theme_setting/models/anita_theme_style_item_group.py
+++ /dev/null
@@ -1,199 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from odoo import models, fields, api, exceptions, _, exceptions
-import json
-
-
-class AnitaStyleGroup(models.Model):
- '''
- user theme style group
- '''
- _name = 'anita_theme_setting.style_item_group'
- _order = 'sequence asc'
- _description = "style item group"
-
- name = fields.Char(string="name", required=True)
- is_default = fields.Boolean(string="is default", default=False)
- theme_style = fields.Many2one(
- string="theme style",
- comodel_name="anita_theme_setting.theme_style",
- ondelete="cascade")
- sub_groups = fields.One2many(
- string="sub groups",
- comodel_name="anita_theme_setting.style_item_sub_group",
- inverse_name="group")
- sequence = fields.Integer(string="sequence", default=0)
-
- def check_sub_group(self, default_mode, sub_groups):
- '''
- check group items, if not exsits create it else update it
- need fixed
- :return:0
- '''
- self.ensure_one()
-
- old_sub_group_cache = {
- sub_group.name: sub_group for sub_group in self.sub_groups}
- default_sub_group_cache = {
- default_group["name"]: default_group for default_group in sub_groups}
-
- for sub_group_index, sub_group in enumerate(sub_groups):
- if sub_group["name"] not in old_sub_group_cache:
- self.env['anita_theme_setting.style_item_sub_group']\
- .create_sub_group(default_mode, self.id, sub_group, sub_group_index)
- else:
- # update the style item
- tmp_group = old_sub_group_cache[sub_group["name"]]
- tmp_group.write({
- "name": sub_group["name"],
- "is_default": True,
- "sequence": sub_group_index,
- })
- # check group item data
- style_items = sub_group["style_items"]
- tmp_group.check_style_items(default_mode, style_items)
-
- # delete the style item (just not default, user may add item)
- for sub_group_name in old_sub_group_cache:
- if sub_group_name not in default_sub_group_cache \
- and not old_sub_group_cache[sub_group_name].is_default:
- old_sub_group_cache[sub_group_name].unlink()
-
- def create_group_from_default_data(self, theme_style, group, group_index):
- '''
- create group from default data
- :return:
- '''
- val = {
- "name": group["name"],
- "theme_style": theme_style.id,
- "sequence": group_index,
- }
-
- mode = theme_style.theme_mode # get theme mode
- scss_vars_cache = mode.get_scss_vars_cache()
-
- sub_group_array = []
- sub_groups = group["sub_groups"]
- for sub_group_index, sub_group in enumerate(sub_groups):
-
- style_item_vals = []
- items = sub_group["style_items"]
- for item_index, item in enumerate(items):
- selectors = json.dumps(item["selectors"])
- var_infos = item["vars"]
-
- var_vals = []
- for var_index, var_info in enumerate(var_infos):
-
- ref_var = var_info.get('ref', False)
- if ref_var:
- if ref_var in scss_vars_cache:
- raise exceptions.ValidationError(
- _("The variable %s has been used") % ref_var)
- else:
- color = scss_vars_cache[ref_var]
- else:
- color = var_info.get('color', False)
-
- var_vals.append((0, 0, {
- "name": var_info["name"],
- "type": var_info["type"],
- "sequence": var_index,
- "color": color,
- "image": var_info.get('image', False),
- "image_url": var_info.get('image_url', False),
- "svg": var_info.get('svg', False),
- "identity": var_info.get('identity', False)
- }))
-
- style_item_vals.append((0, 0, {
- "name": item["name"],
- "sequence": item_index,
- "sub_group": sub_group["name"],
- "selectors": selectors,
- "vars": var_vals
- }))
-
- sub_group_array.append((0, 0, {
- "name": sub_group["name"],
- "sequence": sub_group_index,
- "style_items": style_item_vals,
- "is_default": True
- }))
-
- val["sub_groups"] = sub_group_array
- return self.create([val])
-
- @api.model
- def get_add_new_group_action(self, style_id):
- """
- get add new group action
- :param style_id:
- :return:
- """
- theme_style = self.env["anita_theme_setting.theme_style"].browse(style_id)
- old_groups = theme_style.groups
- return {
- "type": "ir.actions.act_window",
- "res_model": "anita_theme_setting.style_item_group",
- "view_mode": "form",
- "target": "new",
- "context": {
- "default_theme_style": style_id,
- "default_sequence": len(old_groups) + 1
- },
- "views": [[self.env.ref('anita_theme_setting.style_item_group_form').id, "form"]]
- }
-
- def get_group_data(self):
- """
- get sub group data
- :return:
- """
- group_datas = []
- for record in self:
- group_datas.append({
- "id": record.id,
- "name": record.name,
- "is_default": record.is_default,
- "sequence": record.sequence,
- "sub_groups": record.sub_groups.get_sub_group_data()
- })
- return group_datas
-
- def get_add_sub_group_action(self):
- """
- get add sub group action
- :return:
- """
- return {
- "type": "ir.actions.act_window",
- "res_model": "anita_theme_setting.style_item_sub_group",
- "view_mode": 'form',
- "target": "new",
- "context": {
- "default_group": self.id,
- },
- "views": [[self.env.ref('anita_theme_setting.style_item_sub_group_form').id, "form"]]
- }
-
- def delete_item_group(self):
- """
- delete item group
- :return:
- """
- if len(self.sub_groups) > 0:
- raise exceptions.ValidationError(
- 'there has some sub group left, please delete them first!')
- self.unlink()
-
- def get_sub_group_data(self):
- """
- get sub group data
- :return:
- """
- sub_group_datas = []
- for record in self:
- sub_group_datas.append(record.get_sub_group_data())
- return sub_group_datas
diff --git a/anita_theme_setting/models/anita_theme_style_item_sub_group.py b/anita_theme_setting/models/anita_theme_style_item_sub_group.py
deleted file mode 100644
index 6f0e49f38..000000000
--- a/anita_theme_setting/models/anita_theme_style_item_sub_group.py
+++ /dev/null
@@ -1,147 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from odoo import models, fields, exceptions
-import logging, json
-
-_logger = logging.getLogger(__name__)
-
-
-class AnitaStyleSubGroup(models.Model):
- '''
- user theme style group
- '''
- _name = 'anita_theme_setting.style_item_sub_group'
- _order = 'sequence asc'
- _description = "style item group"
-
- name = fields.Char(string="name", required=True)
- is_default = fields.Boolean(string="is default", default=False)
- group = fields.Many2one(string="group",
- comodel_name="anita_theme_setting.style_item_group",
- ondelete="cascade")
- sequence = fields.Integer(string="sequence", default=0)
- style_items = fields.One2many(
- string="style items",
- comodel_name="anita_theme_setting.style_item",
- inverse_name="sub_group")
-
- def check_style_items(self, default_mode, style_items):
- '''
- check group items, if not exsits create it else update it
- need fixed
- :return:0
- '''
- self.ensure_one()
-
- old_style_item_cache = {
- style_item.name: style_item for style_item in self.style_items if style_item.is_default}
- new_style_item_cache = {
- style_item["name"]: style_item for style_item in style_items}
-
- for item_index, style_item in enumerate(style_items):
- if style_item["name"] not in old_style_item_cache:
- self.env["anita_theme_setting.style_item"].create_style_item(
- default_mode, self.id, style_item, item_index)
- else:
- old_style_item = old_style_item_cache[style_item["name"]]
- old_style_item.write({
- "selectors": json.dumps(style_item["selectors"]),
- "name": style_item["name"],
- "val_template": style_item["val_template"],
- "sequence": item_index,
- })
- item_vars = style_item["vars"]
- old_style_item.check_vars(default_mode, self.id, item_vars)
-
- # delete the style item (just not default, user may add item)
- for tmp_style_item in self.style_items:
- if tmp_style_item.name not in new_style_item_cache:
- old_style_item_cache[tmp_style_item.name].unlink()
-
- def create_sub_group(self, default_mode, group, sub_group, sub_group_index):
- '''
- create sub group from default data
- :return:
- '''
- val = {
- "name": sub_group["name"],
- "group": group,
- "sequence": sub_group_index,
- "is_default": True
- }
-
- var_val_cache = default_mode.get_var_val_cache()
-
- style_item_vals = []
- style_items = sub_group["style_items"]
- for item_index, item in enumerate(style_items):
- try:
- selectors = json.dumps(item["selectors"])
- except Exception as error:
- _logger.info('parse selectors error:', error)
- continue
-
- var_infos = item["vars"]
- var_vals = []
- for var_index, var_info in enumerate(var_infos):
-
- color = var_info.get("color", False)
- ref_var = var_info.get("ref_var", False)
- if ref_var:
- if ref_var not in var_val_cache:
- color = False
- _logger.info('ref_var not in var_val_cache:', ref_var)
- else:
- color = var_val_cache[ref_var]
-
- var_vals.append((0, 0, {
- "name": var_info["name"],
- "type": var_info["type"],
- "sequence": var_index,
- "color": color,
- "image": var_info.get('image', False),
- "image_url": var_info.get('image_url', False),
- "svg": var_info.get('svg', False),
- "identity": var_info.get('identity', False),
- "ref_var": ref_var
- }))
-
- style_item_vals.append((0, 0, {
- "name": item["name"],
- "sequence": item_index,
- "sub_group": sub_group["name"],
- "selectors": selectors,
- "vars": var_vals
- }))
-
- val["style_items"] = style_item_vals
-
- return self.create([val])
-
- def get_sub_group_data(self):
- '''
- get group data
- :return:
- '''
- sub_groups = []
- for record in self:
- sub_groups.append({
- "id": record.id,
- "name": record.name,
- "style_items": record.style_items.get_style_item_data(),
- "sequence": record.sequence,
- "is_default": record.is_default,
- "expanded": False
- })
- return sub_groups
-
- def delete_sub_group(self):
- """
- delete sub group
- :return:
- """
- self.ensure_one()
- if len(self.style_items) > 0:
- raise exceptions.ValidationError(
- 'there has some style item left, please delete the style item first!')
- self.unlink()
diff --git a/anita_theme_setting/models/anita_theme_users.py b/anita_theme_setting/models/anita_theme_users.py
deleted file mode 100644
index 80d8ae9f3..000000000
--- a/anita_theme_setting/models/anita_theme_users.py
+++ /dev/null
@@ -1,124 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from odoo import models, fields, api, exceptions
-import datetime
-from datetime import date, datetime
-
-
-class AnitaThemeUsers(models.Model):
- '''
- user theme style setting
- '''
- _inherit = "res.users"
- _description = 'user setting'
-
- setting_id = fields.Many2one(
- comodel_name="anita_theme_setting.setting_base",
- ondelete="cascade",
- string="settings")
-
- @api.model
- def save_theme_setting(self, settings):
- '''
- save settings, create if there is no user info
- just use full when the mode is user wide mode
- :param settings:
- :return:
- '''
- self.ensure_setting_id()
- self.setting_id.write(settings)
-
- def ensure_setting_id(self):
- '''
- check setting id
- :return:
- '''
- self.ensure_one()
- if self.setting_id:
- return
-
- # copy use the global default data
- values = self.env['res.config.settings'].get_theme_values()
-
- # get fields of anita_theme_setting.setting_base
- field_names = [name for name, field in self.setting_id._fields.items() if name not in [
- 'id', 'create_uid', 'create_date', 'write_uid', 'write_date']]
-
- # remove name not in fields
- values = {k: v for k, v in values.items() if k in field_names}
-
- del values["current_theme_mode"]
- del values["current_theme_style"]
-
- if not self.setting_id:
- tmp_record = self.env["anita_theme_setting.setting_base"].create(values)
- self.setting_id = tmp_record.id
-
- def get_theme_setting(self):
- '''
- get settings
- :return:
- '''
- record = self.env.user
- record.ensure_setting_id()
- field_names = [name for name, field in record.setting_id._fields.items() if name not in [
- "icon128x128", "icon144x144", "icon152x152", "icon192x192", "icon256x256", "icon512x512"]]
- result = record.setting_id.read(fields=field_names)[0]
- result["current_theme_mode"] = record.setting_id.current_theme_mode.id
- result["current_theme_style"] = record.setting_id.current_theme_style.id
- for key, item in result.items():
- if isinstance(item, datetime):
- result[key] = fields.Datetime.to_string(item)
- if isinstance(item, date):
- result[key] = fields.Date.to_string(item)
-
- return result
-
- def check_default_data(self):
- """
- check default data
- :return:
- """
- # check mode data
- owner = 'res.users, {user_id}'.format(user_id=self.id)
- self.env["anita_theme_setting.theme_mode"].check_default_mode_data(owner)
-
- @api.model
- def get_user_xml_groups(self):
- '''
- :return:
- '''
- group_ids = self.env.user.groups_id.ids
- records = self.env['ir.model.data']\
- .sudo() \
- .search_read([('model', '=', 'res.groups'),
- ('res_id', 'in', group_ids)], fields=["complete_name"])
- return {record["complete_name"]: True for record in records}
-
- def get_mode_domain(self):
- """
- get mode domain dynamic
- :return:
- """
- owner = 'res.users, {user_id}'.format(user_id=self.id)
- return [('owner', '=', owner)]
-
- @api.model
- def get_group_infos(self):
- '''
- :return:
- '''
- group_ids = self.env.user.groups_id.ids
- records = self.env['ir.model.data']\
- .sudo() \
- .search_read(
- [('model', '=', 'res.groups'),
- ('res_id', 'in', group_ids)],
- fields=["complete_name"])
- groups = {record["complete_name"]: True for record in records}
-
- return {
- "groups": groups,
- "group_ids": group_ids,
- "user_id": self.env.user.id
- }
diff --git a/anita_theme_setting/models/anita_theme_vars.py b/anita_theme_setting/models/anita_theme_vars.py
deleted file mode 100644
index 28ec40a1f..000000000
--- a/anita_theme_setting/models/anita_theme_vars.py
+++ /dev/null
@@ -1,96 +0,0 @@
-# -*- coding: utf-8 -*-
-from odoo import models, fields, api
-
-
-class AnitaThemeVar(models.Model):
- '''
- user theme style setting
- '''
- _name = 'anita_theme_setting.theme_var'
- _order = 'sequence asc'
- _description = "Theme Var"
-
- sequence = fields.Integer(string="sequence", default=0)
- style_item = fields.Many2one(
- comodel_name="anita_theme_setting.style_item",
- string="style_item",
- required=True,
- ondelete="cascade")
- type = fields.Selection(
- selection=[('color', 'color'),
- ('image', 'image'),
- ('image_url', 'image_url'),
- ('svg', 'svg')],
- string="type",
- default="color")
-
- name = fields.Char(string="Name", default="var1")
- color = fields.Char(string="Val")
- color_type = fields.Selection(
- selection=[
- ('background', 'background'),
- ('text', 'text'),
- ('border', 'border'),
- ('shadow', 'shadow')],
- default='background', string="color type", help="Type use to apply aphla!")
- disable_opacity = fields.Boolean(string="Disable Opacity", default=False)
- image = fields.Binary(string="image", attachment=True)
- image_file_url = fields.Char(string="Image File Url", compute="_compute_image_file_url")
- image_url = fields.Char(string="Image Url")
- svg = fields.Text(string="Svg")
- ref_var = fields.Char(string="Ref Var Name")
- opacity = fields.Float(string="Opacity", default=1.0)
-
- identity = fields.Char(string="identify")
- is_default = fields.Boolean(string="Is Default", default=False)
-
- @api.depends('image')
- def _compute_image_file_url(self):
- """
- compute image file url
- :return:
- """
- for record in self:
- if record.type == 'image' and record.image:
- record.image_file_url = \
- '/web/image/anita_theme_setting.theme_var/{var_id}/image'.format(
- var_id=record.id)
- else:
- record.image_file_url = False
-
- def get_edit_var_action(self):
- """
- get edit action
- :return:
- """
- return {
- "type": "ir.actions.act_window",
- "res_model": "anita_theme_setting.theme_var",
- "res_id": self.id,
- "view_mode": "form",
- "target": "new",
- "views": [[self.env.ref(
- 'anita_theme_setting.edit_theme_var_form').id, "form"]]
- }
-
- def get_var_data(self):
- """
- get var data
- :return:
- """
- return self.read(
- fields=["name", "identity", "type",
- "image_file_url", "image_url", "color", "svg"])
-
- def reset_var(self):
- """
- reset var
- :return:
- """
- if not self.ref_var and self.type != 'color':
- return False
- # get mode first
- var_cache = self.style_item.sub_group.group.theme_style.theme_mode.get_scss_vars_cache()
- if self.ref_var in var_cache:
- self.color = var_cache.get(self.ref_var, False)
- return True
diff --git a/anita_theme_setting/models/anita_utility.py b/anita_theme_setting/models/anita_utility.py
deleted file mode 100644
index 04782a763..000000000
--- a/anita_theme_setting/models/anita_utility.py
+++ /dev/null
@@ -1,132 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from math import fabs
-from odoo import exceptions
-
-def apply_alpha(var_name, color, alpha, color_type = False):
- """
- safe alpha
- :param color:
- :param alpha:
- :return:
- """
- if not color:
- return ''
-
- color.strip()
-
- # check var_name endwith text_color
- if var_name.endswith("text_color") or color_type == "text_color":
- return color
-
- # replace white to fff and black to 000 etc
- if color == "white":
- color = "fff"
- elif color == "black":
- color = "000"
- elif color == "red":
- color = "f00"
- elif color == "green":
- color = "0f0"
- elif color == "blue":
- color = "00f"
- elif color == "yellow":
- color = "ff0"
-
- # check if start with rgba
- if color.startswith("rgba"):
- # get the content between ( and )
- color = color[color.find("(") + 1:color.find(")")]
- # get the alpha
- rgba_color = color.split(",")
- if len(rgba_color) == 4:
- # convert to float
- tmp = float(rgba_color[3])
- # check var_name has shadow in it
- tmp = alpha * tmp
- # make rgba string
- tmp = "rgba({rgba_color[0]},{rgba_color[1]},{rgba_color[2]},{tmp})".format(
- rgba_color=rgba_color,
- tmp=tmp)
- return tmp
- else:
- return color
- # check if start with # and length is 9
- elif color.startswith("#"):
- if len(color) == 9 or len(color) == 7:
- # get red color
- red = color[1:3]
- # get green color
- green = color[3:5]
- # get blue color
- blue = color[5:7]
- # get the old alpha
- if len(color) == 9:
- old_alpha = color[7:9]
- # convert to int
- old_alpha = int(old_alpha, 16) / 255.0
- new_alpha = int(old_alpha * alpha)
- else:
- new_alpha = alpha
-
- # make rgba string
- return "rgba({red},{green},{blue},{new_alpha})".format(
- red=int(red, 16),
- green=int(green, 16),
- blue=int(blue, 16),
- new_alpha=new_alpha)
-
- # color like #ffff
- elif len(color) == 5:
- # get red color
- red = color[1:2]
- # get green color
- green = color[2:3]
- # get blue color
- blue = color[3:4]
- # alpha
- old_alpha = color[4:5]
- # convert to int
- old_alpha = int(old_alpha + old_alpha, 16) / 255.0
- new_alpha = old_alpha * alpha
-
- # make rgba string
- return "rgba({red},{green},{blue},{alpha})".format(
- red=int(red + red, 16),
- green=int(green + green, 16),
- blue=int(blue + blue, 16),
- alpha=new_alpha)
-
- # color like #fff
- elif len(color) == 4:
- # get red color
- red = color[1:2]
- # get green color
- green = color[2:3]
- # get blue color
- blue = color[3:4]
- # make rgba string
- return "rgba({red},{green},{blue},{alpha})".format(
- red=int(red + red, 16),
- green=int(green +green, 16),
- blue=int(blue + blue, 16),
- alpha=alpha)
- else:
- return color
- else:
- # check if start with rgb
- if color.startswith("rgb"):
- # get the content between ( and )
- color = color[color.find("(") + 1:color.find(")")]
- # get the alpha
- rgb_color = color.split(",")
- if len(rgb_color) == 3:
- # make rgba string
- tmp = "rgba({rgb_color[0]},{rgb_color[1]},{rgb_color[2]},{alpha})".format(
- rgb_color=rgb_color,
- alpha=alpha)
- return tmp
- else:
- return color
- else:
- return 'rgba({color},{alpha})'.format(color=color, alpha=alpha)
diff --git a/anita_theme_setting/security/ir.model.access.csv b/anita_theme_setting/security/ir.model.access.csv
deleted file mode 100644
index 155425b82..000000000
--- a/anita_theme_setting/security/ir.model.access.csv
+++ /dev/null
@@ -1,16 +0,0 @@
-id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
-anita_theme_setting_style_item,anita_theme_setting.style_item,model_anita_theme_setting_style_item,,1,1,1,1
-anita_theme_setting_theme_style,anita_theme_setting.theme_style,model_anita_theme_setting_theme_style,,1,1,1,1
-anita_theme_setting_theme_mode,anita_theme_setting.theme_mode,model_anita_theme_setting_theme_mode,,1,1,1,1
-anita_theme_setting_style_item_group,anita_theme_setting.style_item_group,model_anita_theme_setting_style_item_group,,1,1,1,1
-anita_theme_setting_style_item_sub_group,anita_theme_setting.style_item_sub_group,model_anita_theme_setting_style_item_sub_group,,1,1,1,1
-anita_theme_setting_setting_base,anita_theme_setting.setting_base,model_anita_theme_setting_setting_base,,1,1,1,1
-anita_theme_setting_theme_var,anita_theme_setting.theme_var,model_anita_theme_setting_theme_var,,1,1,1,1
-anita_theme_setting_setting_manager,anita_theme_setting.setting_manager,model_anita_theme_setting_setting_manager,,1,1,1,1
-anita_theme_setting_default_mode_data,anita_theme_setting.default_mode_data,model_anita_theme_setting_default_mode_data,,1,1,1,1
-anita_theme_setting_mode_template,anita_theme_setting.mode_template,model_anita_theme_setting_mode_template,,1,1,1,1
-anita_theme_setting_import_theme_style,anita_theme_setting_import_theme_style,model_anita_theme_setting_import_theme_style,,1,1,1,1
-anita_theme_setting_template_var_val,anita_theme_setting.template_var_val,model_anita_theme_setting_template_var_val,,1,1,1,1
-access_anita_theme_setting_template_var_val,anita_theme_setting.template_var_val,model_anita_theme_setting_template_var_val,,1,1,1,1
-access_anita_theme_setting_background_image_wizard,anita_theme_setting.background_image_wizard,model_anita_theme_setting_background_image_wizard,,1,1,1,1
-access_anita_theme_setting_favorite_menu',anita_theme_setting.favorite_menu,model_anita_theme_setting_favorite_menu,,1,1,1,1
diff --git a/anita_theme_setting/static/description/anita_description.png b/anita_theme_setting/static/description/anita_description.png
deleted file mode 100644
index 1a9031c40..000000000
Binary files a/anita_theme_setting/static/description/anita_description.png and /dev/null differ
diff --git a/anita_theme_setting/static/description/anita_list.gif b/anita_theme_setting/static/description/anita_list.gif
deleted file mode 100644
index f63e756a3..000000000
Binary files a/anita_theme_setting/static/description/anita_list.gif and /dev/null differ
diff --git a/anita_theme_setting/static/description/anita_modeler.png b/anita_theme_setting/static/description/anita_modeler.png
deleted file mode 100644
index a56f812f4..000000000
Binary files a/anita_theme_setting/static/description/anita_modeler.png and /dev/null differ
diff --git a/anita_theme_setting/static/description/anita_screenshot.png b/anita_theme_setting/static/description/anita_screenshot.png
deleted file mode 100644
index 9157fc68c..000000000
Binary files a/anita_theme_setting/static/description/anita_screenshot.png and /dev/null differ
diff --git a/anita_theme_setting/static/description/anita_switcher.png b/anita_theme_setting/static/description/anita_switcher.png
deleted file mode 100644
index f7309adcc..000000000
Binary files a/anita_theme_setting/static/description/anita_switcher.png and /dev/null differ
diff --git a/anita_theme_setting/static/description/awesome_theme.gif b/anita_theme_setting/static/description/awesome_theme.gif
deleted file mode 100644
index c45dd1fdd..000000000
Binary files a/anita_theme_setting/static/description/awesome_theme.gif and /dev/null differ
diff --git a/anita_theme_setting/static/description/banner.gif b/anita_theme_setting/static/description/banner.gif
deleted file mode 100644
index 920c745ca..000000000
Binary files a/anita_theme_setting/static/description/banner.gif and /dev/null differ
diff --git a/anita_theme_setting/static/description/banner.png b/anita_theme_setting/static/description/banner.png
deleted file mode 100644
index 3390bef13..000000000
Binary files a/anita_theme_setting/static/description/banner.png and /dev/null differ
diff --git a/anita_theme_setting/static/description/banner2.png b/anita_theme_setting/static/description/banner2.png
deleted file mode 100644
index e8a45c50e..000000000
Binary files a/anita_theme_setting/static/description/banner2.png and /dev/null differ
diff --git a/anita_theme_setting/static/description/description.png b/anita_theme_setting/static/description/description.png
deleted file mode 100644
index 200bd1375..000000000
Binary files a/anita_theme_setting/static/description/description.png and /dev/null differ
diff --git a/anita_theme_setting/static/description/icon.png b/anita_theme_setting/static/description/icon.png
deleted file mode 100644
index e43c36cf3..000000000
Binary files a/anita_theme_setting/static/description/icon.png and /dev/null differ
diff --git a/anita_theme_setting/static/description/images/akl_multi_tab_plugin.gif b/anita_theme_setting/static/description/images/akl_multi_tab_plugin.gif
deleted file mode 100644
index f964000e0..000000000
Binary files a/anita_theme_setting/static/description/images/akl_multi_tab_plugin.gif and /dev/null differ
diff --git a/anita_theme_setting/static/description/images/anita_list.gif b/anita_theme_setting/static/description/images/anita_list.gif
deleted file mode 100644
index f63e756a3..000000000
Binary files a/anita_theme_setting/static/description/images/anita_list.gif and /dev/null differ
diff --git a/anita_theme_setting/static/description/images/anita_modeler.gif b/anita_theme_setting/static/description/images/anita_modeler.gif
deleted file mode 100644
index 693bf2386..000000000
Binary files a/anita_theme_setting/static/description/images/anita_modeler.gif and /dev/null differ
diff --git a/anita_theme_setting/static/description/images/anita_theme_pro.gif b/anita_theme_setting/static/description/images/anita_theme_pro.gif
deleted file mode 100644
index c45dd1fdd..000000000
Binary files a/anita_theme_setting/static/description/images/anita_theme_pro.gif and /dev/null differ
diff --git a/anita_theme_setting/static/description/index.html b/anita_theme_setting/static/description/index.html
deleted file mode 100644
index 9b1aca48b..000000000
--- a/anita_theme_setting/static/description/index.html
+++ /dev/null
@@ -1,128 +0,0 @@
-
-
-
-
-
-
-
- Anita theme setting is theme configer for our themes, it support to change theme color, font, background, header, footer, menu, etc. and also support to change theme layout, it is very easy to use and very useful for our themes.
-
-
-
-
-
-
-
(Current Release V16.0.0.1 -- 2022.11.22)
-
-
-
-
- Theme Settings
-
-
-
- there has a theme setting configer, it can set the button style\ input style \ radio style \ checkbox style etc
-
-
-
-
-
-
-
-
- Theme Style
-
-
-
- there has a theme configer, it can set the theme color\ font\ background\ header\ footer\ menu etc
-
-
-
-
-
-
-
-
- Semi Trans Support
-
-
-
- user can set a bk image and set the alpha for elements, it will be very beautiful
-
-
-
-
-
-
-
-
- Back Image Support
-
-
-
- user can set a bk image and set the alpha for elements, it will be very beautiful
-
"
- ].join(''),
- markup = (function () {
-
- // IE does not support gradients with multiple stops, so we need to simulate
- // that for the rainbow slider with 8 divs that each have a single gradient
- var gradientFix = "";
- if (IE) {
- for (var i = 1; i <= 6; i++) {
- gradientFix += "";
- }
- }
-
- return [
- "
",
- "
",
- "",
- "
",
- "",
- "
",
- "
",
- "
",
- "
",
- "",
- "
",
- "
",
- "
",
- "
",
- "",
- "
",
- "
",
- "
",
- "
",
- "
",
- "
",
- "",
- gradientFix,
- "
",
- "
",
- "
",
- "
",
- "
",
- "",
- "
",
- "",
- "
",
- "",
- "",
- "
",
- "
",
- "
"
- ].join("");
- })();
-
- function paletteTemplate (p, color, className, opts) {
- var html = [];
- for (var i = 0; i < p.length; i++) {
- var current = p[i];
- if(current) {
- var tiny = tinycolor(current);
- var c = tiny.toHsl().l < 0.5 ? "sp-thumb-el sp-thumb-dark" : "sp-thumb-el sp-thumb-light";
- c += (tinycolor.equals(color, current)) ? " sp-thumb-active" : "";
- var formattedString = tiny.toString(opts.preferredFormat || "rgb");
- var swatchStyle = rgbaSupport ? ("background-color:" + tiny.toRgbString()) : "filter:" + tiny.toFilter();
- html.push('');
- } else {
- var cls = 'sp-clear-display';
- html.push($('')
- .append($('')
- .attr('title', opts.noColorSelectedText)
- )
- .html()
- );
- }
- }
- return "
" + html.join('') + "
";
- }
-
- function hideAll() {
- for (var i = 0; i < spectrums.length; i++) {
- if (spectrums[i]) {
- spectrums[i].hide();
- }
- }
- }
-
- function instanceOptions(o, callbackContext) {
- var opts = $.extend({}, defaultOpts, o);
- opts.callbacks = {
- 'move': bind(opts.move, callbackContext),
- 'change': bind(opts.change, callbackContext),
- 'show': bind(opts.show, callbackContext),
- 'hide': bind(opts.hide, callbackContext),
- 'beforeShow': bind(opts.beforeShow, callbackContext)
- };
-
- return opts;
- }
-
- function spectrum(element, o) {
-
- var opts = instanceOptions(o, element),
- flat = opts.flat,
- showSelectionPalette = opts.showSelectionPalette,
- localStorageKey = opts.localStorageKey,
- theme = opts.theme,
- callbacks = opts.callbacks,
- resize = throttle(reflow, 10),
- visible = false,
- isDragging = false,
- dragWidth = 0,
- dragHeight = 0,
- dragHelperHeight = 0,
- slideHeight = 0,
- slideWidth = 0,
- alphaWidth = 0,
- alphaSlideHelperWidth = 0,
- slideHelperHeight = 0,
- currentHue = 0,
- currentSaturation = 0,
- currentValue = 0,
- currentAlpha = 1,
- palette = [],
- paletteArray = [],
- paletteLookup = {},
- selectionPalette = opts.selectionPalette.slice(0),
- maxSelectionSize = opts.maxSelectionSize,
- draggingClass = "sp-dragging",
- shiftMovementDirection = null;
-
- var doc = element.ownerDocument,
- body = doc.body,
- boundElement = $(element),
- disabled = false,
- container = $(markup, doc).addClass(theme),
- pickerContainer = container.find(".sp-picker-container"),
- dragger = container.find(".sp-color"),
- dragHelper = container.find(".sp-dragger"),
- slider = container.find(".sp-hue"),
- slideHelper = container.find(".sp-slider"),
- alphaSliderInner = container.find(".sp-alpha-inner"),
- alphaSlider = container.find(".sp-alpha"),
- alphaSlideHelper = container.find(".sp-alpha-handle"),
- textInput = container.find(".sp-input"),
- paletteContainer = container.find(".sp-palette"),
- initialColorContainer = container.find(".sp-initial"),
- cancelButton = container.find(".sp-cancel"),
- clearButton = container.find(".sp-clear"),
- chooseButton = container.find(".sp-choose"),
- toggleButton = container.find(".sp-palette-toggle"),
- isInput = boundElement.is("input"),
- isInputTypeColor = isInput && boundElement.attr("type") === "color" && inputTypeColorSupport(),
- shouldReplace = isInput && !flat,
- replacer = (shouldReplace) ? $(replaceInput).addClass(theme).addClass(opts.className).addClass(opts.replacerClassName) : $([]),
- offsetElement = (shouldReplace) ? replacer : boundElement,
- previewElement = replacer.find(".sp-preview-inner"),
- initialColor = opts.color || (isInput && boundElement.val()),
- colorOnShow = false,
- currentPreferredFormat = opts.preferredFormat,
- clickoutFiresChange = !opts.showButtons || opts.clickoutFiresChange,
- isEmpty = !initialColor,
- allowEmpty = opts.allowEmpty && !isInputTypeColor;
-
- function applyOptions() {
-
- if (opts.showPaletteOnly) {
- opts.showPalette = true;
- }
-
- toggleButton.text(opts.showPaletteOnly ? opts.togglePaletteMoreText : opts.togglePaletteLessText);
-
- if (opts.palette) {
- palette = opts.palette.slice(0);
- paletteArray = Array.isArray(palette[0]) ? palette : [palette];
- paletteLookup = {};
- for (var i = 0; i < paletteArray.length; i++) {
- for (var j = 0; j < paletteArray[i].length; j++) {
- var rgb = tinycolor(paletteArray[i][j]).toRgbString();
- paletteLookup[rgb] = true;
- }
- }
- }
-
- container.toggleClass("sp-flat", flat);
- container.toggleClass("sp-input-disabled", !opts.showInput);
- container.toggleClass("sp-alpha-enabled", opts.showAlpha);
- container.toggleClass("sp-clear-enabled", allowEmpty);
- container.toggleClass("sp-buttons-disabled", !opts.showButtons);
- container.toggleClass("sp-palette-buttons-disabled", !opts.togglePaletteOnly);
- container.toggleClass("sp-palette-disabled", !opts.showPalette);
- container.toggleClass("sp-palette-only", opts.showPaletteOnly);
- container.toggleClass("sp-initial-disabled", !opts.showInitial);
- container.addClass(opts.className).addClass(opts.containerClassName);
-
- reflow();
- }
-
- function initialize() {
-
- if (IE) {
- container.find("*:not(input)").attr("unselectable", "on");
- }
-
- applyOptions();
-
- if (shouldReplace) {
- boundElement.after(replacer).hide();
- }
-
- if (!allowEmpty) {
- clearButton.hide();
- }
-
- if (flat) {
- boundElement.after(container).hide();
- }
- else {
-
- var appendTo = opts.appendTo === "parent" ? boundElement.parent() : $(opts.appendTo);
- if (appendTo.length !== 1) {
- appendTo = $("body");
- }
-
- appendTo.append(container);
- }
-
- updateSelectionPaletteFromStorage();
-
- offsetElement.on("click.spectrum touchstart.spectrum", function (e) {
- if (!disabled) {
- toggle();
- }
-
- e.stopPropagation();
-
- if (!$(e.target).is("input")) {
- e.preventDefault();
- }
- });
-
- if(boundElement.is(":disabled") || (opts.disabled === true)) {
- disable();
- }
-
- // Prevent clicks from bubbling up to document. This would cause it to be hidden.
- container.on("click", stopPropagation);
-
- // Handle user typed input
- textInput.on("change", setFromTextInput);
- textInput.on("paste", function () {
- setTimeout(setFromTextInput, 1);
- });
- textInput.on("keydown", function (e) { if (e.keyCode == 13) { setFromTextInput(); } });
-
- cancelButton.text(opts.cancelText);
- cancelButton.on("click.spectrum", function (e) {
- e.stopPropagation();
- e.preventDefault();
- revert();
- hide();
- });
-
- clearButton.attr("title", opts.clearText);
- clearButton.on("click.spectrum", function (e) {
- e.stopPropagation();
- e.preventDefault();
- isEmpty = true;
- move();
-
- if(flat) {
- //for the flat style, this is a change event
- updateOriginalInput(true);
- }
- });
-
- chooseButton.text(opts.chooseText);
- chooseButton.on("click.spectrum", function (e) {
- e.stopPropagation();
- e.preventDefault();
-
- if (IE && textInput.is(":focus")) {
- textInput.trigger('change');
- }
-
- if (isValid()) {
- updateOriginalInput(true);
- hide();
- }
- });
-
- toggleButton.text(opts.showPaletteOnly ? opts.togglePaletteMoreText : opts.togglePaletteLessText);
- toggleButton.on("click.spectrum", function (e) {
- e.stopPropagation();
- e.preventDefault();
-
- opts.showPaletteOnly = !opts.showPaletteOnly;
-
- // To make sure the Picker area is drawn on the right, next to the
- // Palette area (and not below the palette), first move the Palette
- // to the left to make space for the picker, plus 5px extra.
- // The 'applyOptions' function puts the whole container back into place
- // and takes care of the button-text and the sp-palette-only CSS class.
- if (!opts.showPaletteOnly && !flat) {
- container.css('left', '-=' + (pickerContainer.outerWidth(true) + 5));
- }
- applyOptions();
- });
-
- draggable(alphaSlider, function (dragX, dragY, e) {
- currentAlpha = (dragX / alphaWidth);
- isEmpty = false;
- if (e.shiftKey) {
- currentAlpha = Math.round(currentAlpha * 10) / 10;
- }
-
- move();
- }, dragStart, dragStop);
-
- draggable(slider, function (dragX, dragY) {
- currentHue = parseFloat(dragY / slideHeight);
- isEmpty = false;
- if (!opts.showAlpha) {
- currentAlpha = 1;
- }
- move();
- }, dragStart, dragStop);
-
- draggable(dragger, function (dragX, dragY, e) {
-
- // shift+drag should snap the movement to either the x or y axis.
- if (!e.shiftKey) {
- shiftMovementDirection = null;
- }
- else if (!shiftMovementDirection) {
- var oldDragX = currentSaturation * dragWidth;
- var oldDragY = dragHeight - (currentValue * dragHeight);
- var furtherFromX = Math.abs(dragX - oldDragX) > Math.abs(dragY - oldDragY);
-
- shiftMovementDirection = furtherFromX ? "x" : "y";
- }
-
- var setSaturation = !shiftMovementDirection || shiftMovementDirection === "x";
- var setValue = !shiftMovementDirection || shiftMovementDirection === "y";
-
- if (setSaturation) {
- currentSaturation = parseFloat(dragX / dragWidth);
- }
- if (setValue) {
- currentValue = parseFloat((dragHeight - dragY) / dragHeight);
- }
-
- isEmpty = false;
- if (!opts.showAlpha) {
- currentAlpha = 1;
- }
-
- move();
-
- }, dragStart, dragStop);
-
- if (!!initialColor) {
- set(initialColor);
-
- // In case color was black - update the preview UI and set the format
- // since the set function will not run (default color is black).
- updateUI();
- currentPreferredFormat = opts.preferredFormat || tinycolor(initialColor).format;
-
- addColorToSelectionPalette(initialColor);
- }
- else {
- updateUI();
- }
-
- if (flat) {
- show();
- }
-
- function paletteElementClick(e) {
- if (e.data && e.data.ignore) {
- set($(e.target).closest(".sp-thumb-el").data("color"));
- move();
- }
- else {
- set($(e.target).closest(".sp-thumb-el").data("color"));
- move();
-
- // If the picker is going to close immediately, a palette selection
- // is a change. Otherwise, it's a move only.
- if (opts.hideAfterPaletteSelect) {
- updateOriginalInput(true);
- hide();
- } else {
- updateOriginalInput();
- }
- }
-
- return false;
- }
-
- var paletteEvent = IE ? "mousedown.spectrum" : "click.spectrum touchstart.spectrum";
- paletteContainer.on(paletteEvent, ".sp-thumb-el", paletteElementClick);
- initialColorContainer.on(paletteEvent, ".sp-thumb-el:nth-child(1)", { ignore: true }, paletteElementClick);
- }
-
- function updateSelectionPaletteFromStorage() {
-
- if (localStorageKey && window.localStorage) {
-
- // Migrate old palettes over to new format. May want to remove this eventually.
- try {
- var oldPalette = window.localStorage[localStorageKey].split(",#");
- if (oldPalette.length > 1) {
- delete window.localStorage[localStorageKey];
- $.each(oldPalette, function(i, c) {
- addColorToSelectionPalette(c);
- });
- }
- }
- catch(e) { }
-
- try {
- selectionPalette = window.localStorage[localStorageKey].split(";");
- }
- catch (e) { }
- }
- }
-
- function addColorToSelectionPalette(color) {
- if (showSelectionPalette) {
- var rgb = tinycolor(color).toRgbString();
- if (!paletteLookup[rgb] && $.inArray(rgb, selectionPalette) === -1) {
- selectionPalette.push(rgb);
- while(selectionPalette.length > maxSelectionSize) {
- selectionPalette.shift();
- }
- }
-
- if (localStorageKey && window.localStorage) {
- try {
- window.localStorage[localStorageKey] = selectionPalette.join(";");
- }
- catch(e) { }
- }
- }
- }
-
- function getUniqueSelectionPalette() {
- var unique = [];
- if (opts.showPalette) {
- for (var i = 0; i < selectionPalette.length; i++) {
- var rgb = tinycolor(selectionPalette[i]).toRgbString();
-
- if (!paletteLookup[rgb]) {
- unique.push(selectionPalette[i]);
- }
- }
- }
-
- return unique.reverse().slice(0, opts.maxSelectionSize);
- }
-
- function drawPalette() {
-
- var currentColor = get();
-
- var html = $.map(paletteArray, function (palette, i) {
- return paletteTemplate(palette, currentColor, "sp-palette-row sp-palette-row-" + i, opts);
- });
-
- updateSelectionPaletteFromStorage();
-
- if (selectionPalette) {
- html.push(paletteTemplate(getUniqueSelectionPalette(), currentColor, "sp-palette-row sp-palette-row-selection", opts));
- }
-
- paletteContainer.html(html.join(""));
- }
-
- function drawInitial() {
- if (opts.showInitial) {
- var initial = colorOnShow;
- var current = get();
- initialColorContainer.html(paletteTemplate([initial, current], current, "sp-palette-row-initial", opts));
- }
- }
-
- function dragStart() {
- if (dragHeight <= 0 || dragWidth <= 0 || slideHeight <= 0) {
- reflow();
- }
- isDragging = true;
- container.addClass(draggingClass);
- shiftMovementDirection = null;
- boundElement.trigger('dragstart.spectrum', [ get() ]);
- }
-
- function dragStop() {
- isDragging = false;
- container.removeClass(draggingClass);
- boundElement.trigger('dragstop.spectrum', [ get() ]);
- }
-
- function setFromTextInput() {
-
- var value = textInput.val();
-
- if ((value === null || value === "") && allowEmpty) {
- set(null);
- move();
- updateOriginalInput();
- }
- else {
- var tiny = tinycolor(value);
- if (tiny.isValid()) {
- set(tiny);
- move();
- updateOriginalInput();
- }
- else {
- textInput.addClass("sp-validation-error");
- }
- }
- }
-
- function toggle() {
- if (visible) {
- hide();
- }
- else {
- show();
- }
- }
-
- function show() {
- var event = $.Event('beforeShow.spectrum');
-
- if (visible) {
- reflow();
- return;
- }
-
- boundElement.trigger(event, [ get() ]);
-
- if (callbacks.beforeShow(get()) === false || event.isDefaultPrevented()) {
- return;
- }
-
- hideAll();
- visible = true;
-
- $(doc).on("keydown.spectrum", onkeydown);
- $(doc).on("click.spectrum", clickout);
- $(window).on("resize.spectrum", resize);
- replacer.addClass("sp-active");
- container.removeClass("sp-hidden");
-
- reflow();
- updateUI();
-
- colorOnShow = get();
-
- drawInitial();
- callbacks.show(colorOnShow);
- boundElement.trigger('show.spectrum', [ colorOnShow ]);
- }
-
- function onkeydown(e) {
- // Close on ESC
- if (e.keyCode === 27) {
- hide();
- }
- }
-
- function clickout(e) {
- // Return on right click.
- if (e.button == 2) { return; }
-
- // If a drag event was happening during the mouseup, don't hide
- // on click.
- if (isDragging) { return; }
-
- if (clickoutFiresChange) {
- updateOriginalInput(true);
- }
- else {
- revert();
- }
- hide();
- }
-
- function hide() {
- // Return if hiding is unnecessary
- if (!visible || flat) { return; }
- visible = false;
-
- $(doc).off("keydown.spectrum", onkeydown);
- $(doc).off("click.spectrum", clickout);
- $(window).off("resize.spectrum", resize);
-
- replacer.removeClass("sp-active");
- container.addClass("sp-hidden");
-
- callbacks.hide(get());
- boundElement.trigger('hide.spectrum', [ get() ]);
- }
-
- function revert() {
- set(colorOnShow, true);
- updateOriginalInput(true);
- }
-
- function set(color, ignoreFormatChange) {
- if (tinycolor.equals(color, get())) {
- // Update UI just in case a validation error needs
- // to be cleared.
- updateUI();
- return;
- }
-
- var newColor, newHsv;
- if (!color && allowEmpty) {
- isEmpty = true;
- } else {
- isEmpty = false;
- newColor = tinycolor(color);
- newHsv = newColor.toHsv();
-
- currentHue = (newHsv.h % 360) / 360;
- currentSaturation = newHsv.s;
- currentValue = newHsv.v;
- currentAlpha = newHsv.a;
- }
- updateUI();
-
- if (newColor && newColor.isValid() && !ignoreFormatChange) {
- currentPreferredFormat = opts.preferredFormat || newColor.getFormat();
- }
- }
-
- function get(opts) {
- opts = opts || { };
-
- if (allowEmpty && isEmpty) {
- return null;
- }
-
- return tinycolor.fromRatio({
- h: currentHue,
- s: currentSaturation,
- v: currentValue,
- a: Math.round(currentAlpha * 1000) / 1000
- }, { format: opts.format || currentPreferredFormat });
- }
-
- function isValid() {
- return !textInput.hasClass("sp-validation-error");
- }
-
- function move() {
- updateUI();
-
- callbacks.move(get());
- boundElement.trigger('move.spectrum', [ get() ]);
- }
-
- function updateUI() {
-
- textInput.removeClass("sp-validation-error");
-
- updateHelperLocations();
-
- // Update dragger background color (gradients take care of saturation and value).
- var flatColor = tinycolor.fromRatio({ h: currentHue, s: 1, v: 1 });
- dragger.css("background-color", flatColor.toHexString());
-
- // Get a format that alpha will be included in (hex and names ignore alpha)
- var format = currentPreferredFormat;
- if (currentAlpha < 1 && !(currentAlpha === 0 && format === "name")) {
- if (format === "hex" || format === "hex3" || format === "hex6" || format === "name") {
- format = "rgb";
- }
- }
-
- var realColor = get({ format: format }),
- displayColor = '';
-
- //reset background info for preview element
- previewElement.removeClass("sp-clear-display");
- previewElement.css('background-color', 'transparent');
-
- if (!realColor && allowEmpty) {
- // Update the replaced elements background with icon indicating no color selection
- previewElement.addClass("sp-clear-display");
- }
- else {
- var realHex = realColor.toHexString(),
- realRgb = realColor.toRgbString();
-
- // Update the replaced elements background color (with actual selected color)
- if (rgbaSupport || realColor.alpha === 1) {
- previewElement.css("background-color", realRgb);
- }
- else {
- previewElement.css("background-color", "transparent");
- previewElement.css("filter", realColor.toFilter());
- }
-
- if (opts.showAlpha) {
- var rgb = realColor.toRgb();
- rgb.a = 0;
- var realAlpha = tinycolor(rgb).toRgbString();
- var gradient = "linear-gradient(left, " + realAlpha + ", " + realHex + ")";
-
- if (IE) {
- alphaSliderInner.css("filter", tinycolor(realAlpha).toFilter({ gradientType: 1 }, realHex));
- }
- else {
- alphaSliderInner.css("background", "-webkit-" + gradient);
- alphaSliderInner.css("background", "-moz-" + gradient);
- alphaSliderInner.css("background", "-ms-" + gradient);
- // Use current syntax gradient on unprefixed property.
- alphaSliderInner.css("background",
- "linear-gradient(to right, " + realAlpha + ", " + realHex + ")");
- }
- }
-
- displayColor = realColor.toString(format);
- }
-
- // Update the text entry input as it changes happen
- if (opts.showInput) {
- textInput.val(displayColor);
- }
-
- if (opts.showPalette) {
- drawPalette();
- }
-
- drawInitial();
- }
-
- function updateHelperLocations() {
- var s = currentSaturation;
- var v = currentValue;
-
- if(allowEmpty && isEmpty) {
- //if selected color is empty, hide the helpers
- alphaSlideHelper.hide();
- slideHelper.hide();
- dragHelper.hide();
- }
- else {
- //make sure helpers are visible
- alphaSlideHelper.show();
- slideHelper.show();
- dragHelper.show();
-
- // Where to show the little circle in that displays your current selected color
- var dragX = s * dragWidth;
- var dragY = dragHeight - (v * dragHeight);
- dragX = Math.max(
- -dragHelperHeight,
- Math.min(dragWidth - dragHelperHeight, dragX - dragHelperHeight)
- );
- dragY = Math.max(
- -dragHelperHeight,
- Math.min(dragHeight - dragHelperHeight, dragY - dragHelperHeight)
- );
- dragHelper.css({
- "top": dragY + "px",
- "left": dragX + "px"
- });
-
- var alphaX = currentAlpha * alphaWidth;
- alphaSlideHelper.css({
- "left": (alphaX - (alphaSlideHelperWidth / 2)) + "px"
- });
-
- // Where to show the bar that displays your current selected hue
- var slideY = (currentHue) * slideHeight;
- slideHelper.css({
- "top": (slideY - slideHelperHeight) + "px"
- });
- }
- }
-
- function updateOriginalInput(fireCallback) {
- var color = get(),
- displayColor = '',
- hasChanged = !tinycolor.equals(color, colorOnShow);
-
- if (color) {
- displayColor = color.toString(currentPreferredFormat);
- // Update the selection palette with the current color
- addColorToSelectionPalette(color);
- }
-
- if (isInput) {
- boundElement.val(displayColor);
- }
-
- if (fireCallback && hasChanged) {
- callbacks.change(color);
- boundElement.trigger('change', [ color ]);
- }
- }
-
- function reflow() {
- if (!visible) {
- return; // Calculations would be useless and wouldn't be reliable anyways
- }
- dragWidth = dragger.width();
- dragHeight = dragger.height();
- dragHelperHeight = dragHelper.height();
- slideWidth = slider.width();
- slideHeight = slider.height();
- slideHelperHeight = slideHelper.height();
- alphaWidth = alphaSlider.width();
- alphaSlideHelperWidth = alphaSlideHelper.width();
-
- if (!flat) {
- container.css("position", "absolute");
- if (opts.offset) {
- container.offset(opts.offset);
- } else {
- container.offset(getOffset(container, offsetElement));
- }
- }
-
- updateHelperLocations();
-
- if (opts.showPalette) {
- drawPalette();
- }
-
- boundElement.trigger('reflow.spectrum');
- }
-
- function destroy() {
- boundElement.show();
- offsetElement.off("click.spectrum touchstart.spectrum");
- container.remove();
- replacer.remove();
- spectrums[spect.id] = null;
- }
-
- function option(optionName, optionValue) {
- if (optionName === undefined) {
- return $.extend({}, opts);
- }
- if (optionValue === undefined) {
- return opts[optionName];
- }
-
- opts[optionName] = optionValue;
-
- if (optionName === "preferredFormat") {
- currentPreferredFormat = opts.preferredFormat;
- }
- applyOptions();
- }
-
- function enable() {
- disabled = false;
- boundElement.attr("disabled", false);
- offsetElement.removeClass("sp-disabled");
- }
-
- function disable() {
- hide();
- disabled = true;
- boundElement.attr("disabled", true);
- offsetElement.addClass("sp-disabled");
- }
-
- function setOffset(coord) {
- opts.offset = coord;
- reflow();
- }
-
- initialize();
-
- var spect = {
- show: show,
- hide: hide,
- toggle: toggle,
- reflow: reflow,
- option: option,
- enable: enable,
- disable: disable,
- offset: setOffset,
- set: function (c) {
- set(c);
- updateOriginalInput();
- },
- get: get,
- destroy: destroy,
- container: container
- };
-
- spect.id = spectrums.push(spect) - 1;
-
- return spect;
- }
-
- /**
- * checkOffset - get the offset below/above and left/right element depending on screen position
- * Thanks https://github.com/jquery/jquery-ui/blob/master/ui/jquery.ui.datepicker.js
- */
- function getOffset(picker, input) {
- var extraY = 0;
- var dpWidth = picker.outerWidth();
- var dpHeight = picker.outerHeight();
- var inputHeight = input.outerHeight();
- var doc = picker[0].ownerDocument;
- var docElem = doc.documentElement;
- var viewWidth = docElem.clientWidth + $(doc).scrollLeft();
- var viewHeight = docElem.clientHeight + $(doc).scrollTop();
- var offset = input.offset();
- var offsetLeft = offset.left;
- var offsetTop = offset.top;
-
- offsetTop += inputHeight;
-
- offsetLeft -=
- Math.min(offsetLeft, (offsetLeft + dpWidth > viewWidth && viewWidth > dpWidth) ?
- Math.abs(offsetLeft + dpWidth - viewWidth) : 0);
-
- offsetTop -=
- Math.min(offsetTop, ((offsetTop + dpHeight > viewHeight && viewHeight > dpHeight) ?
- Math.abs(dpHeight + inputHeight - extraY) : extraY));
-
- return {
- top: offsetTop,
- bottom: offset.bottom,
- left: offsetLeft,
- right: offset.right,
- width: offset.width,
- height: offset.height
- };
- }
-
- /**
- * noop - do nothing
- */
- function noop() {
-
- }
-
- /**
- * stopPropagation - makes the code only doing this a little easier to read in line
- */
- function stopPropagation(e) {
- e.stopPropagation();
- }
-
- /**
- * Create a function bound to a given object
- * Thanks to underscore.js
- */
- function bind(func, obj) {
- var slice = Array.prototype.slice;
- var args = slice.call(arguments, 2);
- return function () {
- return func.apply(obj, args.concat(slice.call(arguments)));
- };
- }
-
- /**
- * Lightweight drag helper. Handles containment within the element, so that
- * when dragging, the x is within [0,element.width] and y is within [0,element.height]
- */
- function draggable(element, onmove, onstart, onstop) {
- onmove = onmove || function () { };
- onstart = onstart || function () { };
- onstop = onstop || function () { };
- var doc = document;
- var dragging = false;
- var offset = {};
- var maxHeight = 0;
- var maxWidth = 0;
- var hasTouch = ('ontouchstart' in window);
-
- var duringDragEvents = {};
- duringDragEvents["selectstart"] = prevent;
- duringDragEvents["dragstart"] = prevent;
- duringDragEvents["touchmove mousemove"] = move;
- duringDragEvents["touchend mouseup"] = stop;
-
- function prevent(e) {
- if (e.stopPropagation) {
- e.stopPropagation();
- }
- if (e.preventDefault) {
- e.preventDefault();
- }
- e.returnValue = false;
- }
-
- function move(e) {
- if (dragging) {
- // Mouseup happened outside of window
- if (IE && doc.documentMode < 9 && !e.button) {
- return stop();
- }
-
- var t0 = e.originalEvent && e.originalEvent.touches && e.originalEvent.touches[0];
- var pageX = t0 && t0.pageX || e.pageX;
- var pageY = t0 && t0.pageY || e.pageY;
-
- var dragX = Math.max(0, Math.min(pageX - offset.left, maxWidth));
- var dragY = Math.max(0, Math.min(pageY - offset.top, maxHeight));
-
- if (hasTouch) {
- // Stop scrolling in iOS
- prevent(e);
- }
-
- onmove.apply(element, [dragX, dragY, e]);
- }
- }
-
- function start(e) {
- var rightclick = (e.which) ? (e.which == 3) : (e.button == 2);
-
- if (!rightclick && !dragging) {
- if (onstart.apply(element, arguments) !== false) {
- dragging = true;
- maxHeight = $(element).height();
- maxWidth = $(element).width();
- offset = $(element).offset();
-
- $(doc).on(duringDragEvents);
- $(doc.body).addClass("sp-dragging");
-
- move(e);
-
- prevent(e);
- }
- }
- }
-
- function stop() {
- if (dragging) {
- $(doc).off(duringDragEvents);
- $(doc.body).removeClass("sp-dragging");
-
- // Wait a tick before notifying observers to allow the click event
- // to fire in Chrome.
- setTimeout(function() {
- onstop.apply(element, arguments);
- }, 0);
- }
- dragging = false;
- }
-
- $(element).on("touchstart mousedown", start);
- }
-
- function throttle(func, wait, debounce) {
- var timeout;
- return function () {
- var context = this, args = arguments;
- var throttler = function () {
- timeout = null;
- func.apply(context, args);
- };
- if (debounce) clearTimeout(timeout);
- if (debounce || !timeout) timeout = setTimeout(throttler, wait);
- };
- }
-
- function inputTypeColorSupport() {
- return $.fn.spectrum.inputTypeColorSupport();
- }
-
- /**
- * Define a jQuery plugin
- */
- var dataID = "spectrum.id";
- $.fn.spectrum = function (opts, extra) {
-
- if (typeof opts == "string") {
-
- var returnValue = this;
- var args = Array.prototype.slice.call( arguments, 1 );
-
- this.each(function () {
- var spect = spectrums[$(this).data(dataID)];
- if (spect) {
- var method = spect[opts];
- if (!method) {
- throw new Error( "Spectrum: no such method: '" + opts + "'" );
- }
-
- if (opts == "get") {
- returnValue = spect.get();
- }
- else if (opts == "container") {
- returnValue = spect.container;
- }
- else if (opts == "option") {
- returnValue = spect.option.apply(spect, args);
- }
- else if (opts == "destroy") {
- spect.destroy();
- $(this).removeData(dataID);
- }
- else {
- method.apply(spect, args);
- }
- }
- });
-
- return returnValue;
- }
-
- // Initializing a new instance of spectrum
- return this.spectrum("destroy").each(function () {
- var options = $.extend({}, $(this).data(), opts);
- var spect = spectrum(this, options);
- $(this).data(dataID, spect.id);
- });
- };
-
- $.fn.spectrum.load = true;
- $.fn.spectrum.loadOpts = {};
- $.fn.spectrum.draggable = draggable;
- $.fn.spectrum.defaults = defaultOpts;
- $.fn.spectrum.inputTypeColorSupport = function inputTypeColorSupport() {
- if (typeof inputTypeColorSupport._cachedResult === "undefined") {
- var colorInput = $("")[0]; // if color element is supported, value will default to not null
- inputTypeColorSupport._cachedResult = colorInput.type === "color" && colorInput.value !== "";
- }
- return inputTypeColorSupport._cachedResult;
- };
-
- $.spectrum = { };
- $.spectrum.localization = { };
- $.spectrum.palettes = { };
-
- $.fn.spectrum.processNativeColorInputs = function () {
- var colorInputs = $("input[type=color]");
- if (colorInputs.length && !inputTypeColorSupport()) {
- colorInputs.spectrum({
- preferredFormat: "hex6"
- });
- }
- };
-
- // TinyColor v1.1.2
- // https://github.com/bgrins/TinyColor
- // Brian Grinstead, MIT License
-
- (function() {
-
- var trimLeft = /^[\s,#]+/,
- trimRight = /\s+$/,
- tinyCounter = 0,
- math = Math,
- mathRound = math.round,
- mathMin = math.min,
- mathMax = math.max,
- mathRandom = math.random;
-
- var tinycolor = function(color, opts) {
-
- color = (color) ? color : '';
- opts = opts || { };
-
- // If input is already a tinycolor, return itself
- if (color instanceof tinycolor) {
- return color;
- }
- // If we are called as a function, call using new instead
- if (!(this instanceof tinycolor)) {
- return new tinycolor(color, opts);
- }
-
- var rgb = inputToRGB(color);
- this._originalInput = color;
- this._r = rgb.r;
- this._g = rgb.g;
- this._b = rgb.b;
- this._a = rgb.a;
- this._roundA = mathRound(1000 * this._a) / 1000;
- this._format = opts.format || rgb.format;
- this._gradientType = opts.gradientType;
-
- // Don't let the range of [0,255] come back in [0,1].
- // Potentially lose a little bit of precision here, but will fix issues where
- // .5 gets interpreted as half of the total, instead of half of 1
- // If it was supposed to be 128, this was already taken care of by `inputToRgb`
- if (this._r < 1) { this._r = mathRound(this._r); }
- if (this._g < 1) { this._g = mathRound(this._g); }
- if (this._b < 1) { this._b = mathRound(this._b); }
-
- this._ok = rgb.ok;
- this._tc_id = tinyCounter++;
- };
-
- tinycolor.prototype = {
- isDark: function() {
- return this.getBrightness() < 128;
- },
- isLight: function() {
- return !this.isDark();
- },
- isValid: function() {
- return this._ok;
- },
- getOriginalInput: function() {
- return this._originalInput;
- },
- getFormat: function() {
- return this._format;
- },
- getAlpha: function() {
- return this._a;
- },
- getBrightness: function() {
- var rgb = this.toRgb();
- return (rgb.r * 299 + rgb.g * 587 + rgb.b * 114) / 1000;
- },
- setAlpha: function(value) {
- this._a = boundAlpha(value);
- this._roundA = mathRound(1000 * this._a) / 1000;
- return this;
- },
- toHsv: function() {
- var hsv = rgbToHsv(this._r, this._g, this._b);
- return { h: hsv.h * 360, s: hsv.s, v: hsv.v, a: this._a };
- },
- toHsvString: function() {
- var hsv = rgbToHsv(this._r, this._g, this._b);
- var h = mathRound(hsv.h * 360), s = mathRound(hsv.s * 100), v = mathRound(hsv.v * 100);
- return (this._a == 1) ?
- "hsv(" + h + ", " + s + "%, " + v + "%)" :
- "hsva(" + h + ", " + s + "%, " + v + "%, "+ this._roundA + ")";
- },
- toHsl: function() {
- var hsl = rgbToHsl(this._r, this._g, this._b);
- return { h: hsl.h * 360, s: hsl.s, l: hsl.l, a: this._a };
- },
- toHslString: function() {
- var hsl = rgbToHsl(this._r, this._g, this._b);
- var h = mathRound(hsl.h * 360), s = mathRound(hsl.s * 100), l = mathRound(hsl.l * 100);
- return (this._a == 1) ?
- "hsl(" + h + ", " + s + "%, " + l + "%)" :
- "hsla(" + h + ", " + s + "%, " + l + "%, "+ this._roundA + ")";
- },
- toHex: function(allow3Char) {
- return rgbToHex(this._r, this._g, this._b, allow3Char);
- },
- toHexString: function(allow3Char) {
- return '#' + this.toHex(allow3Char);
- },
- toHex8: function() {
- return rgbaToHex(this._r, this._g, this._b, this._a);
- },
- toHex8String: function() {
- return '#' + this.toHex8();
- },
- toRgb: function() {
- return { r: mathRound(this._r), g: mathRound(this._g), b: mathRound(this._b), a: this._a };
- },
- toRgbString: function() {
- return (this._a == 1) ?
- "rgb(" + mathRound(this._r) + ", " + mathRound(this._g) + ", " + mathRound(this._b) + ")" :
- "rgba(" + mathRound(this._r) + ", " + mathRound(this._g) + ", " + mathRound(this._b) + ", " + this._roundA + ")";
- },
- toPercentageRgb: function() {
- return { r: mathRound(bound01(this._r, 255) * 100) + "%", g: mathRound(bound01(this._g, 255) * 100) + "%", b: mathRound(bound01(this._b, 255) * 100) + "%", a: this._a };
- },
- toPercentageRgbString: function() {
- return (this._a == 1) ?
- "rgb(" + mathRound(bound01(this._r, 255) * 100) + "%, " + mathRound(bound01(this._g, 255) * 100) + "%, " + mathRound(bound01(this._b, 255) * 100) + "%)" :
- "rgba(" + mathRound(bound01(this._r, 255) * 100) + "%, " + mathRound(bound01(this._g, 255) * 100) + "%, " + mathRound(bound01(this._b, 255) * 100) + "%, " + this._roundA + ")";
- },
- toName: function() {
- if (this._a === 0) {
- return "transparent";
- }
-
- if (this._a < 1) {
- return false;
- }
-
- return hexNames[rgbToHex(this._r, this._g, this._b, true)] || false;
- },
- toFilter: function(secondColor) {
- var hex8String = '#' + rgbaToHex(this._r, this._g, this._b, this._a);
- var secondHex8String = hex8String;
- var gradientType = this._gradientType ? "GradientType = 1, " : "";
-
- if (secondColor) {
- var s = tinycolor(secondColor);
- secondHex8String = s.toHex8String();
- }
-
- return "progid:DXImageTransform.Microsoft.gradient("+gradientType+"startColorstr="+hex8String+",endColorstr="+secondHex8String+")";
- },
- toString: function(format) {
- var formatSet = !!format;
- format = format || this._format;
-
- var formattedString = false;
- var hasAlpha = this._a < 1 && this._a >= 0;
- var needsAlphaFormat = !formatSet && hasAlpha && (format === "hex" || format === "hex6" || format === "hex3" || format === "name");
-
- if (needsAlphaFormat) {
- // Special case for "transparent", all other non-alpha formats
- // will return rgba when there is transparency.
- if (format === "name" && this._a === 0) {
- return this.toName();
- }
- return this.toRgbString();
- }
- if (format === "rgb") {
- formattedString = this.toRgbString();
- }
- if (format === "prgb") {
- formattedString = this.toPercentageRgbString();
- }
- if (format === "hex" || format === "hex6") {
- formattedString = this.toHexString();
- }
- if (format === "hex3") {
- formattedString = this.toHexString(true);
- }
- if (format === "hex8") {
- formattedString = this.toHex8String();
- }
- if (format === "name") {
- formattedString = this.toName();
- }
- if (format === "hsl") {
- formattedString = this.toHslString();
- }
- if (format === "hsv") {
- formattedString = this.toHsvString();
- }
-
- return formattedString || this.toHexString();
- },
-
- _applyModification: function(fn, args) {
- var color = fn.apply(null, [this].concat([].slice.call(args)));
- this._r = color._r;
- this._g = color._g;
- this._b = color._b;
- this.setAlpha(color._a);
- return this;
- },
- lighten: function() {
- return this._applyModification(lighten, arguments);
- },
- brighten: function() {
- return this._applyModification(brighten, arguments);
- },
- darken: function() {
- return this._applyModification(darken, arguments);
- },
- desaturate: function() {
- return this._applyModification(desaturate, arguments);
- },
- saturate: function() {
- return this._applyModification(saturate, arguments);
- },
- greyscale: function() {
- return this._applyModification(greyscale, arguments);
- },
- spin: function() {
- return this._applyModification(spin, arguments);
- },
-
- _applyCombination: function(fn, args) {
- return fn.apply(null, [this].concat([].slice.call(args)));
- },
- analogous: function() {
- return this._applyCombination(analogous, arguments);
- },
- complement: function() {
- return this._applyCombination(complement, arguments);
- },
- monochromatic: function() {
- return this._applyCombination(monochromatic, arguments);
- },
- splitcomplement: function() {
- return this._applyCombination(splitcomplement, arguments);
- },
- triad: function() {
- return this._applyCombination(triad, arguments);
- },
- tetrad: function() {
- return this._applyCombination(tetrad, arguments);
- }
- };
-
- // If input is an object, force 1 into "1.0" to handle ratios properly
- // String input requires "1.0" as input, so 1 will be treated as 1
- tinycolor.fromRatio = function(color, opts) {
- if (typeof color == "object") {
- var newColor = {};
- for (var i in color) {
- if (color.hasOwnProperty(i)) {
- if (i === "a") {
- newColor[i] = color[i];
- }
- else {
- newColor[i] = convertToPercentage(color[i]);
- }
- }
- }
- color = newColor;
- }
-
- return tinycolor(color, opts);
- };
-
- // Given a string or object, convert that input to RGB
- // Possible string inputs:
- //
- // "red"
- // "#f00" or "f00"
- // "#ff0000" or "ff0000"
- // "#ff000000" or "ff000000"
- // "rgb 255 0 0" or "rgb (255, 0, 0)"
- // "rgb 1.0 0 0" or "rgb (1, 0, 0)"
- // "rgba (255, 0, 0, 1)" or "rgba 255, 0, 0, 1"
- // "rgba (1.0, 0, 0, 1)" or "rgba 1.0, 0, 0, 1"
- // "hsl(0, 100%, 50%)" or "hsl 0 100% 50%"
- // "hsla(0, 100%, 50%, 1)" or "hsla 0 100% 50%, 1"
- // "hsv(0, 100%, 100%)" or "hsv 0 100% 100%"
- //
- function inputToRGB(color) {
-
- var rgb = { r: 0, g: 0, b: 0 };
- var a = 1;
- var ok = false;
- var format = false;
-
- if (typeof color == "string") {
- color = stringInputToObject(color);
- }
-
- if (typeof color == "object") {
- if (color.hasOwnProperty("r") && color.hasOwnProperty("g") && color.hasOwnProperty("b")) {
- rgb = rgbToRgb(color.r, color.g, color.b);
- ok = true;
- format = String(color.r).substr(-1) === "%" ? "prgb" : "rgb";
- }
- else if (color.hasOwnProperty("h") && color.hasOwnProperty("s") && color.hasOwnProperty("v")) {
- color.s = convertToPercentage(color.s);
- color.v = convertToPercentage(color.v);
- rgb = hsvToRgb(color.h, color.s, color.v);
- ok = true;
- format = "hsv";
- }
- else if (color.hasOwnProperty("h") && color.hasOwnProperty("s") && color.hasOwnProperty("l")) {
- color.s = convertToPercentage(color.s);
- color.l = convertToPercentage(color.l);
- rgb = hslToRgb(color.h, color.s, color.l);
- ok = true;
- format = "hsl";
- }
-
- if (color.hasOwnProperty("a")) {
- a = color.a;
- }
- }
-
- a = boundAlpha(a);
-
- return {
- ok: ok,
- format: color.format || format,
- r: mathMin(255, mathMax(rgb.r, 0)),
- g: mathMin(255, mathMax(rgb.g, 0)),
- b: mathMin(255, mathMax(rgb.b, 0)),
- a: a
- };
- }
-
-
- // Conversion Functions
- // --------------------
-
- // `rgbToHsl`, `rgbToHsv`, `hslToRgb`, `hsvToRgb` modified from:
- //
-
- // `rgbToRgb`
- // Handle bounds / percentage checking to conform to CSS color spec
- //
- // *Assumes:* r, g, b in [0, 255] or [0, 1]
- // *Returns:* { r, g, b } in [0, 255]
- function rgbToRgb(r, g, b){
- return {
- r: bound01(r, 255) * 255,
- g: bound01(g, 255) * 255,
- b: bound01(b, 255) * 255
- };
- }
-
- // `rgbToHsl`
- // Converts an RGB color value to HSL.
- // *Assumes:* r, g, and b are contained in [0, 255] or [0, 1]
- // *Returns:* { h, s, l } in [0,1]
- function rgbToHsl(r, g, b) {
-
- r = bound01(r, 255);
- g = bound01(g, 255);
- b = bound01(b, 255);
-
- var max = mathMax(r, g, b), min = mathMin(r, g, b);
- var h, s, l = (max + min) / 2;
-
- if(max == min) {
- h = s = 0; // achromatic
- }
- else {
- var d = max - min;
- s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
- switch(max) {
- case r: h = (g - b) / d + (g < b ? 6 : 0); break;
- case g: h = (b - r) / d + 2; break;
- case b: h = (r - g) / d + 4; break;
- }
-
- h /= 6;
- }
-
- return { h: h, s: s, l: l };
- }
-
- // `hslToRgb`
- // Converts an HSL color value to RGB.
- // *Assumes:* h is contained in [0, 1] or [0, 360] and s and l are contained [0, 1] or [0, 100]
- // *Returns:* { r, g, b } in the set [0, 255]
- function hslToRgb(h, s, l) {
- var r, g, b;
-
- h = bound01(h, 360);
- s = bound01(s, 100);
- l = bound01(l, 100);
-
- function hue2rgb(p, q, t) {
- if(t < 0) t += 1;
- if(t > 1) t -= 1;
- if(t < 1/6) return p + (q - p) * 6 * t;
- if(t < 1/2) return q;
- if(t < 2/3) return p + (q - p) * (2/3 - t) * 6;
- return p;
- }
-
- if(s === 0) {
- r = g = b = l; // achromatic
- }
- else {
- var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
- var p = 2 * l - q;
- r = hue2rgb(p, q, h + 1/3);
- g = hue2rgb(p, q, h);
- b = hue2rgb(p, q, h - 1/3);
- }
-
- return { r: r * 255, g: g * 255, b: b * 255 };
- }
-
- // `rgbToHsv`
- // Converts an RGB color value to HSV
- // *Assumes:* r, g, and b are contained in the set [0, 255] or [0, 1]
- // *Returns:* { h, s, v } in [0,1]
- function rgbToHsv(r, g, b) {
-
- r = bound01(r, 255);
- g = bound01(g, 255);
- b = bound01(b, 255);
-
- var max = mathMax(r, g, b), min = mathMin(r, g, b);
- var h, s, v = max;
-
- var d = max - min;
- s = max === 0 ? 0 : d / max;
-
- if(max == min) {
- h = 0; // achromatic
- }
- else {
- switch(max) {
- case r: h = (g - b) / d + (g < b ? 6 : 0); break;
- case g: h = (b - r) / d + 2; break;
- case b: h = (r - g) / d + 4; break;
- }
- h /= 6;
- }
- return { h: h, s: s, v: v };
- }
-
- // `hsvToRgb`
- // Converts an HSV color value to RGB.
- // *Assumes:* h is contained in [0, 1] or [0, 360] and s and v are contained in [0, 1] or [0, 100]
- // *Returns:* { r, g, b } in the set [0, 255]
- function hsvToRgb(h, s, v) {
-
- h = bound01(h, 360) * 6;
- s = bound01(s, 100);
- v = bound01(v, 100);
-
- var i = math.floor(h),
- f = h - i,
- p = v * (1 - s),
- q = v * (1 - f * s),
- t = v * (1 - (1 - f) * s),
- mod = i % 6,
- r = [v, q, p, p, t, v][mod],
- g = [t, v, v, q, p, p][mod],
- b = [p, p, t, v, v, q][mod];
-
- return { r: r * 255, g: g * 255, b: b * 255 };
- }
-
- // `rgbToHex`
- // Converts an RGB color to hex
- // Assumes r, g, and b are contained in the set [0, 255]
- // Returns a 3 or 6 character hex
- function rgbToHex(r, g, b, allow3Char) {
-
- var hex = [
- pad2(mathRound(r).toString(16)),
- pad2(mathRound(g).toString(16)),
- pad2(mathRound(b).toString(16))
- ];
-
- // Return a 3 character hex if possible
- if (allow3Char && hex[0].charAt(0) == hex[0].charAt(1) && hex[1].charAt(0) == hex[1].charAt(1) && hex[2].charAt(0) == hex[2].charAt(1)) {
- return hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0);
- }
-
- return hex.join("");
- }
- // `rgbaToHex`
- // Converts an RGBA color plus alpha transparency to hex
- // Assumes r, g, b and a are contained in the set [0, 255]
- // Returns an 8 character hex
- function rgbaToHex(r, g, b, a) {
-
- var hex = [
- pad2(convertDecimalToHex(a)),
- pad2(mathRound(r).toString(16)),
- pad2(mathRound(g).toString(16)),
- pad2(mathRound(b).toString(16))
- ];
-
- return hex.join("");
- }
-
- // `equals`
- // Can be called with any tinycolor input
- tinycolor.equals = function (color1, color2) {
- if (!color1 || !color2) { return false; }
- return tinycolor(color1).toRgbString() == tinycolor(color2).toRgbString();
- };
- tinycolor.random = function() {
- return tinycolor.fromRatio({
- r: mathRandom(),
- g: mathRandom(),
- b: mathRandom()
- });
- };
-
-
- // Modification Functions
- // ----------------------
- // Thanks to less.js for some of the basics here
- //
-
- function desaturate(color, amount) {
- amount = (amount === 0) ? 0 : (amount || 10);
- var hsl = tinycolor(color).toHsl();
- hsl.s -= amount / 100;
- hsl.s = clamp01(hsl.s);
- return tinycolor(hsl);
- }
-
- function saturate(color, amount) {
- amount = (amount === 0) ? 0 : (amount || 10);
- var hsl = tinycolor(color).toHsl();
- hsl.s += amount / 100;
- hsl.s = clamp01(hsl.s);
- return tinycolor(hsl);
- }
-
- function greyscale(color) {
- return tinycolor(color).desaturate(100);
- }
-
- function lighten (color, amount) {
- amount = (amount === 0) ? 0 : (amount || 10);
- var hsl = tinycolor(color).toHsl();
- hsl.l += amount / 100;
- hsl.l = clamp01(hsl.l);
- return tinycolor(hsl);
- }
-
- function brighten(color, amount) {
- amount = (amount === 0) ? 0 : (amount || 10);
- var rgb = tinycolor(color).toRgb();
- rgb.r = mathMax(0, mathMin(255, rgb.r - mathRound(255 * - (amount / 100))));
- rgb.g = mathMax(0, mathMin(255, rgb.g - mathRound(255 * - (amount / 100))));
- rgb.b = mathMax(0, mathMin(255, rgb.b - mathRound(255 * - (amount / 100))));
- return tinycolor(rgb);
- }
-
- function darken (color, amount) {
- amount = (amount === 0) ? 0 : (amount || 10);
- var hsl = tinycolor(color).toHsl();
- hsl.l -= amount / 100;
- hsl.l = clamp01(hsl.l);
- return tinycolor(hsl);
- }
-
- // Spin takes a positive or negative amount within [-360, 360] indicating the change of hue.
- // Values outside of this range will be wrapped into this range.
- function spin(color, amount) {
- var hsl = tinycolor(color).toHsl();
- var hue = (mathRound(hsl.h) + amount) % 360;
- hsl.h = hue < 0 ? 360 + hue : hue;
- return tinycolor(hsl);
- }
-
- // Combination Functions
- // ---------------------
- // Thanks to jQuery xColor for some of the ideas behind these
- //
-
- function complement(color) {
- var hsl = tinycolor(color).toHsl();
- hsl.h = (hsl.h + 180) % 360;
- return tinycolor(hsl);
- }
-
- function triad(color) {
- var hsl = tinycolor(color).toHsl();
- var h = hsl.h;
- return [
- tinycolor(color),
- tinycolor({ h: (h + 120) % 360, s: hsl.s, l: hsl.l }),
- tinycolor({ h: (h + 240) % 360, s: hsl.s, l: hsl.l })
- ];
- }
-
- function tetrad(color) {
- var hsl = tinycolor(color).toHsl();
- var h = hsl.h;
- return [
- tinycolor(color),
- tinycolor({ h: (h + 90) % 360, s: hsl.s, l: hsl.l }),
- tinycolor({ h: (h + 180) % 360, s: hsl.s, l: hsl.l }),
- tinycolor({ h: (h + 270) % 360, s: hsl.s, l: hsl.l })
- ];
- }
-
- function splitcomplement(color) {
- var hsl = tinycolor(color).toHsl();
- var h = hsl.h;
- return [
- tinycolor(color),
- tinycolor({ h: (h + 72) % 360, s: hsl.s, l: hsl.l}),
- tinycolor({ h: (h + 216) % 360, s: hsl.s, l: hsl.l})
- ];
- }
-
- function analogous(color, results, slices) {
- results = results || 6;
- slices = slices || 30;
-
- var hsl = tinycolor(color).toHsl();
- var part = 360 / slices;
- var ret = [tinycolor(color)];
-
- for (hsl.h = ((hsl.h - (part * results >> 1)) + 720) % 360; --results; ) {
- hsl.h = (hsl.h + part) % 360;
- ret.push(tinycolor(hsl));
- }
- return ret;
- }
-
- function monochromatic(color, results) {
- results = results || 6;
- var hsv = tinycolor(color).toHsv();
- var h = hsv.h, s = hsv.s, v = hsv.v;
- var ret = [];
- var modification = 1 / results;
-
- while (results--) {
- ret.push(tinycolor({ h: h, s: s, v: v}));
- v = (v + modification) % 1;
- }
-
- return ret;
- }
-
- // Utility Functions
- // ---------------------
-
- tinycolor.mix = function(color1, color2, amount) {
- amount = (amount === 0) ? 0 : (amount || 50);
-
- var rgb1 = tinycolor(color1).toRgb();
- var rgb2 = tinycolor(color2).toRgb();
-
- var p = amount / 100;
- var w = p * 2 - 1;
- var a = rgb2.a - rgb1.a;
-
- var w1;
-
- if (w * a == -1) {
- w1 = w;
- } else {
- w1 = (w + a) / (1 + w * a);
- }
-
- w1 = (w1 + 1) / 2;
-
- var w2 = 1 - w1;
-
- var rgba = {
- r: rgb2.r * w1 + rgb1.r * w2,
- g: rgb2.g * w1 + rgb1.g * w2,
- b: rgb2.b * w1 + rgb1.b * w2,
- a: rgb2.a * p + rgb1.a * (1 - p)
- };
-
- return tinycolor(rgba);
- };
-
-
- // Readability Functions
- // ---------------------
- //
-
- // `readability`
- // Analyze the 2 colors and returns an object with the following properties:
- // `brightness`: difference in brightness between the two colors
- // `color`: difference in color/hue between the two colors
- tinycolor.readability = function(color1, color2) {
- var c1 = tinycolor(color1);
- var c2 = tinycolor(color2);
- var rgb1 = c1.toRgb();
- var rgb2 = c2.toRgb();
- var brightnessA = c1.getBrightness();
- var brightnessB = c2.getBrightness();
- var colorDiff = (
- Math.max(rgb1.r, rgb2.r) - Math.min(rgb1.r, rgb2.r) +
- Math.max(rgb1.g, rgb2.g) - Math.min(rgb1.g, rgb2.g) +
- Math.max(rgb1.b, rgb2.b) - Math.min(rgb1.b, rgb2.b)
- );
-
- return {
- brightness: Math.abs(brightnessA - brightnessB),
- color: colorDiff
- };
- };
-
- // `readable`
- // http://www.w3.org/TR/AERT#color-contrast
- // Ensure that foreground and background color combinations provide sufficient contrast.
- // *Example*
- // tinycolor.isReadable("#000", "#111") => false
- tinycolor.isReadable = function(color1, color2) {
- var readability = tinycolor.readability(color1, color2);
- return readability.brightness > 125 && readability.color > 500;
- };
-
- // `mostReadable`
- // Given a base color and a list of possible foreground or background
- // colors for that base, returns the most readable color.
- // *Example*
- // tinycolor.mostReadable("#123", ["#fff", "#000"]) => "#000"
- tinycolor.mostReadable = function(baseColor, colorList) {
- var bestColor = null;
- var bestScore = 0;
- var bestIsReadable = false;
- for (var i=0; i < colorList.length; i++) {
-
- // We normalize both around the "acceptable" breaking point,
- // but rank brightness constrast higher than hue.
-
- var readability = tinycolor.readability(baseColor, colorList[i]);
- var readable = readability.brightness > 125 && readability.color > 500;
- var score = 3 * (readability.brightness / 125) + (readability.color / 500);
-
- if ((readable && ! bestIsReadable) ||
- (readable && bestIsReadable && score > bestScore) ||
- ((! readable) && (! bestIsReadable) && score > bestScore)) {
- bestIsReadable = readable;
- bestScore = score;
- bestColor = tinycolor(colorList[i]);
- }
- }
- return bestColor;
- };
-
-
- // Big List of Colors
- // ------------------
- //
- var names = tinycolor.names = {
- aliceblue: "f0f8ff",
- antiquewhite: "faebd7",
- aqua: "0ff",
- aquamarine: "7fffd4",
- azure: "f0ffff",
- beige: "f5f5dc",
- bisque: "ffe4c4",
- black: "000",
- blanchedalmond: "ffebcd",
- blue: "00f",
- blueviolet: "8a2be2",
- brown: "a52a2a",
- burlywood: "deb887",
- burntsienna: "ea7e5d",
- cadetblue: "5f9ea0",
- chartreuse: "7fff00",
- chocolate: "d2691e",
- coral: "ff7f50",
- cornflowerblue: "6495ed",
- cornsilk: "fff8dc",
- crimson: "dc143c",
- cyan: "0ff",
- darkblue: "00008b",
- darkcyan: "008b8b",
- darkgoldenrod: "b8860b",
- darkgray: "a9a9a9",
- darkgreen: "006400",
- darkgrey: "a9a9a9",
- darkkhaki: "bdb76b",
- darkmagenta: "8b008b",
- darkolivegreen: "556b2f",
- darkorange: "ff8c00",
- darkorchid: "9932cc",
- darkred: "8b0000",
- darksalmon: "e9967a",
- darkseagreen: "8fbc8f",
- darkslateblue: "483d8b",
- darkslategray: "2f4f4f",
- darkslategrey: "2f4f4f",
- darkturquoise: "00ced1",
- darkviolet: "9400d3",
- deeppink: "ff1493",
- deepskyblue: "00bfff",
- dimgray: "696969",
- dimgrey: "696969",
- dodgerblue: "1e90ff",
- firebrick: "b22222",
- floralwhite: "fffaf0",
- forestgreen: "228b22",
- fuchsia: "f0f",
- gainsboro: "dcdcdc",
- ghostwhite: "f8f8ff",
- gold: "ffd700",
- goldenrod: "daa520",
- gray: "808080",
- green: "008000",
- greenyellow: "adff2f",
- grey: "808080",
- honeydew: "f0fff0",
- hotpink: "ff69b4",
- indianred: "cd5c5c",
- indigo: "4b0082",
- ivory: "fffff0",
- khaki: "f0e68c",
- lavender: "e6e6fa",
- lavenderblush: "fff0f5",
- lawngreen: "7cfc00",
- lemonchiffon: "fffacd",
- lightblue: "add8e6",
- lightcoral: "f08080",
- lightcyan: "e0ffff",
- lightgoldenrodyellow: "fafad2",
- lightgray: "d3d3d3",
- lightgreen: "90ee90",
- lightgrey: "d3d3d3",
- lightpink: "ffb6c1",
- lightsalmon: "ffa07a",
- lightseagreen: "20b2aa",
- lightskyblue: "87cefa",
- lightslategray: "789",
- lightslategrey: "789",
- lightsteelblue: "b0c4de",
- lightyellow: "ffffe0",
- lime: "0f0",
- limegreen: "32cd32",
- linen: "faf0e6",
- magenta: "f0f",
- maroon: "800000",
- mediumaquamarine: "66cdaa",
- mediumblue: "0000cd",
- mediumorchid: "ba55d3",
- mediumpurple: "9370db",
- mediumseagreen: "3cb371",
- mediumslateblue: "7b68ee",
- mediumspringgreen: "00fa9a",
- mediumturquoise: "48d1cc",
- mediumvioletred: "c71585",
- midnightblue: "191970",
- mintcream: "f5fffa",
- mistyrose: "ffe4e1",
- moccasin: "ffe4b5",
- navajowhite: "ffdead",
- navy: "000080",
- oldlace: "fdf5e6",
- olive: "808000",
- olivedrab: "6b8e23",
- orange: "ffa500",
- orangered: "ff4500",
- orchid: "da70d6",
- palegoldenrod: "eee8aa",
- palegreen: "98fb98",
- paleturquoise: "afeeee",
- palevioletred: "db7093",
- papayawhip: "ffefd5",
- peachpuff: "ffdab9",
- peru: "cd853f",
- pink: "ffc0cb",
- plum: "dda0dd",
- powderblue: "b0e0e6",
- purple: "800080",
- rebeccapurple: "663399",
- red: "f00",
- rosybrown: "bc8f8f",
- royalblue: "4169e1",
- saddlebrown: "8b4513",
- salmon: "fa8072",
- sandybrown: "f4a460",
- seagreen: "2e8b57",
- seashell: "fff5ee",
- sienna: "a0522d",
- silver: "c0c0c0",
- skyblue: "87ceeb",
- slateblue: "6a5acd",
- slategray: "708090",
- slategrey: "708090",
- snow: "fffafa",
- springgreen: "00ff7f",
- steelblue: "4682b4",
- tan: "d2b48c",
- teal: "008080",
- thistle: "d8bfd8",
- tomato: "ff6347",
- turquoise: "40e0d0",
- violet: "ee82ee",
- wheat: "f5deb3",
- white: "fff",
- whitesmoke: "f5f5f5",
- yellow: "ff0",
- yellowgreen: "9acd32"
- };
-
- // Make it easy to access colors via `hexNames[hex]`
- var hexNames = tinycolor.hexNames = flip(names);
-
-
- // Utilities
- // ---------
-
- // `{ 'name1': 'val1' }` becomes `{ 'val1': 'name1' }`
- function flip(o) {
- var flipped = { };
- for (var i in o) {
- if (o.hasOwnProperty(i)) {
- flipped[o[i]] = i;
- }
- }
- return flipped;
- }
-
- // Return a valid alpha value [0,1] with all invalid values being set to 1
- function boundAlpha(a) {
- a = parseFloat(a);
-
- if (isNaN(a) || a < 0 || a > 1) {
- a = 1;
- }
-
- return a;
- }
-
- // Take input from [0, n] and return it as [0, 1]
- function bound01(n, max) {
- if (isOnePointZero(n)) { n = "100%"; }
-
- var processPercent = isPercentage(n);
- n = mathMin(max, mathMax(0, parseFloat(n)));
-
- // Automatically convert percentage into number
- if (processPercent) {
- n = parseInt(n * max, 10) / 100;
- }
-
- // Handle floating point rounding errors
- if ((math.abs(n - max) < 0.000001)) {
- return 1;
- }
-
- // Convert into [0, 1] range if it isn't already
- return (n % max) / parseFloat(max);
- }
-
- // Force a number between 0 and 1
- function clamp01(val) {
- return mathMin(1, mathMax(0, val));
- }
-
- // Parse a base-16 hex value into a base-10 integer
- function parseIntFromHex(val) {
- return parseInt(val, 16);
- }
-
- // Need to handle 1.0 as 100%, since once it is a number, there is no difference between it and 1
- //
- function isOnePointZero(n) {
- return typeof n == "string" && n.indexOf('.') != -1 && parseFloat(n) === 1;
- }
-
- // Check to see if string passed in is a percentage
- function isPercentage(n) {
- return typeof n === "string" && n.indexOf('%') != -1;
- }
-
- // Force a hex value to have 2 characters
- function pad2(c) {
- return c.length == 1 ? '0' + c : '' + c;
- }
-
- // Replace a decimal with it's percentage value
- function convertToPercentage(n) {
- if (n <= 1) {
- n = (n * 100) + "%";
- }
-
- return n;
- }
-
- // Converts a decimal to a hex value
- function convertDecimalToHex(d) {
- return Math.round(parseFloat(d) * 255).toString(16);
- }
- // Converts a hex value to a decimal
- function convertHexToDecimal(h) {
- return (parseIntFromHex(h) / 255);
- }
-
- var matchers = (function() {
-
- //
- var CSS_INTEGER = "[-\\+]?\\d+%?";
-
- //
- var CSS_NUMBER = "[-\\+]?\\d*\\.\\d+%?";
-
- // Allow positive/negative integer/number. Don't capture the either/or, just the entire outcome.
- var CSS_UNIT = "(?:" + CSS_NUMBER + ")|(?:" + CSS_INTEGER + ")";
-
- // Actual matching.
- // Parentheses and commas are optional, but not required.
- // Whitespace can take the place of commas or opening paren
- var PERMISSIVE_MATCH3 = "[\\s|\\(]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")\\s*\\)?";
- var PERMISSIVE_MATCH4 = "[\\s|\\(]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")\\s*\\)?";
-
- return {
- rgb: new RegExp("rgb" + PERMISSIVE_MATCH3),
- rgba: new RegExp("rgba" + PERMISSIVE_MATCH4),
- hsl: new RegExp("hsl" + PERMISSIVE_MATCH3),
- hsla: new RegExp("hsla" + PERMISSIVE_MATCH4),
- hsv: new RegExp("hsv" + PERMISSIVE_MATCH3),
- hsva: new RegExp("hsva" + PERMISSIVE_MATCH4),
- hex3: /^([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,
- hex6: /^([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/,
- hex8: /^([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/
- };
- })();
-
- // `stringInputToObject`
- // Permissive string parsing. Take in a number of formats, and output an object
- // based on detected format. Returns `{ r, g, b }` or `{ h, s, l }` or `{ h, s, v}`
- function stringInputToObject(color) {
-
- color = color.replace(trimLeft,'').replace(trimRight, '').toLowerCase();
- var named = false;
- if (names[color]) {
- color = names[color];
- named = true;
- }
- else if (color == 'transparent') {
- return { r: 0, g: 0, b: 0, a: 0, format: "name" };
- }
-
- // Try to match string input using regular expressions.
- // Keep most of the number bounding out of this function - don't worry about [0,1] or [0,100] or [0,360]
- // Just return an object and let the conversion functions handle that.
- // This way the result will be the same whether the tinycolor is initialized with string or object.
- var match;
- if ((match = matchers.rgb.exec(color))) {
- return { r: match[1], g: match[2], b: match[3] };
- }
- if ((match = matchers.rgba.exec(color))) {
- return { r: match[1], g: match[2], b: match[3], a: match[4] };
- }
- if ((match = matchers.hsl.exec(color))) {
- return { h: match[1], s: match[2], l: match[3] };
- }
- if ((match = matchers.hsla.exec(color))) {
- return { h: match[1], s: match[2], l: match[3], a: match[4] };
- }
- if ((match = matchers.hsv.exec(color))) {
- return { h: match[1], s: match[2], v: match[3] };
- }
- if ((match = matchers.hsva.exec(color))) {
- return { h: match[1], s: match[2], v: match[3], a: match[4] };
- }
- if ((match = matchers.hex8.exec(color))) {
- return {
- a: convertHexToDecimal(match[1]),
- r: parseIntFromHex(match[2]),
- g: parseIntFromHex(match[3]),
- b: parseIntFromHex(match[4]),
- format: named ? "name" : "hex8"
- };
- }
- if ((match = matchers.hex6.exec(color))) {
- return {
- r: parseIntFromHex(match[1]),
- g: parseIntFromHex(match[2]),
- b: parseIntFromHex(match[3]),
- format: named ? "name" : "hex"
- };
- }
- if ((match = matchers.hex3.exec(color))) {
- return {
- r: parseIntFromHex(match[1] + '' + match[1]),
- g: parseIntFromHex(match[2] + '' + match[2]),
- b: parseIntFromHex(match[3] + '' + match[3]),
- format: named ? "name" : "hex"
- };
- }
-
- return false;
- }
-
- window.tinycolor = tinycolor;
- })();
-
- $(function () {
- if ($.fn.spectrum.load) {
- $.fn.spectrum.processNativeColorInputs();
- }
- });
-
-});
diff --git a/anita_theme_setting/static/loadings/loading_style1.svg b/anita_theme_setting/static/loadings/loading_style1.svg
deleted file mode 100644
index c1039d174..000000000
--- a/anita_theme_setting/static/loadings/loading_style1.svg
+++ /dev/null
@@ -1,70 +0,0 @@
-
-
diff --git a/anita_theme_setting/static/loadings/loading_style10.svg b/anita_theme_setting/static/loadings/loading_style10.svg
deleted file mode 100644
index caf6fd228..000000000
--- a/anita_theme_setting/static/loadings/loading_style10.svg
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
\ No newline at end of file
diff --git a/anita_theme_setting/static/loadings/loading_style2.svg b/anita_theme_setting/static/loadings/loading_style2.svg
deleted file mode 100644
index e13668952..000000000
--- a/anita_theme_setting/static/loadings/loading_style2.svg
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
diff --git a/anita_theme_setting/static/loadings/loading_style3.svg b/anita_theme_setting/static/loadings/loading_style3.svg
deleted file mode 100644
index f85c0940c..000000000
--- a/anita_theme_setting/static/loadings/loading_style3.svg
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
\ No newline at end of file
diff --git a/anita_theme_setting/static/loadings/loading_style4.svg b/anita_theme_setting/static/loadings/loading_style4.svg
deleted file mode 100644
index d22c416ef..000000000
--- a/anita_theme_setting/static/loadings/loading_style4.svg
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
\ No newline at end of file
diff --git a/anita_theme_setting/static/loadings/loading_style5.svg b/anita_theme_setting/static/loadings/loading_style5.svg
deleted file mode 100644
index fe692c1bd..000000000
--- a/anita_theme_setting/static/loadings/loading_style5.svg
+++ /dev/null
@@ -1,31 +0,0 @@
-
-
diff --git a/anita_theme_setting/static/loadings/loading_style6.svg b/anita_theme_setting/static/loadings/loading_style6.svg
deleted file mode 100644
index 96378a7ce..000000000
--- a/anita_theme_setting/static/loadings/loading_style6.svg
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
diff --git a/anita_theme_setting/static/loadings/loading_style7.svg b/anita_theme_setting/static/loadings/loading_style7.svg
deleted file mode 100644
index 3a4414a5d..000000000
--- a/anita_theme_setting/static/loadings/loading_style7.svg
+++ /dev/null
@@ -1,37 +0,0 @@
-
-
\ No newline at end of file
diff --git a/anita_theme_setting/static/loadings/loading_style8.svg b/anita_theme_setting/static/loadings/loading_style8.svg
deleted file mode 100644
index 65440a557..000000000
--- a/anita_theme_setting/static/loadings/loading_style8.svg
+++ /dev/null
@@ -1,49 +0,0 @@
-
-
-
diff --git a/anita_theme_setting/static/loadings/loading_style9.svg b/anita_theme_setting/static/loadings/loading_style9.svg
deleted file mode 100644
index ace7202fb..000000000
--- a/anita_theme_setting/static/loadings/loading_style9.svg
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
diff --git a/anita_theme_setting/static/src/anita_icon.js b/anita_theme_setting/static/src/anita_icon.js
deleted file mode 100644
index 4298559a3..000000000
--- a/anita_theme_setting/static/src/anita_icon.js
+++ /dev/null
@@ -1,20 +0,0 @@
-/** @odoo-module alias=anita_theme_setting.icons **/
-
-const { markup, Component, xml } = owl;
-
-const clone_style = ''
-
-const edit_style = ''
-
-const edit_image = ''
-
-const delete_style = ''
-
-export default {
- icons: {
- clone_style: markup(clone_style),
- edit_style: markup(edit_style),
- edit_image: markup(edit_image),
- delete_style: markup(delete_style)
- }
-}
diff --git a/anita_theme_setting/static/src/anita_main.js b/anita_theme_setting/static/src/anita_main.js
deleted file mode 100644
index 667d8b35e..000000000
--- a/anita_theme_setting/static/src/anita_main.js
+++ /dev/null
@@ -1,6 +0,0 @@
-/** @odoo-module **/
-
-import { startWebClient } from "@web/start";
-import { AnitaWebClient } from "./components/webclient/webclient";
-
-startWebClient(AnitaWebClient);
diff --git a/anita_theme_setting/static/src/anita_theme_setting.js b/anita_theme_setting/static/src/anita_theme_setting.js
deleted file mode 100644
index 490b128e1..000000000
--- a/anita_theme_setting/static/src/anita_theme_setting.js
+++ /dev/null
@@ -1,7 +0,0 @@
-/** @odoo-module alias=anita_theme_setting.theme_setting**/
-
-let settings = {
- ...odoo.__theme_setting__
-};
-
-export default settings
\ No newline at end of file
diff --git a/anita_theme_setting/static/src/components/accordion/accordion.js b/anita_theme_setting/static/src/components/accordion/accordion.js
deleted file mode 100644
index 07313d62c..000000000
--- a/anita_theme_setting/static/src/components/accordion/accordion.js
+++ /dev/null
@@ -1,29 +0,0 @@
-/** @odoo-module **/
-
-import { Component, useState } from "@odoo/owl";
-
-export class AnitaAccordion extends Component {
-
- setup() {
- this.state = useState({
- 'collapse': true
- })
- }
-
- toggleDisplay() {
- this.state.collapse = !this.state.collapse;
- }
-};
-
-AnitaAccordion.props = {
- title: {
- type: String
- },
- slots: {
- type: Object,
- optional: true,
- },
-};
-
-AnitaAccordion.template = "anita_theme_setting.accordion";
-AnitaAccordion.components = {};
diff --git a/anita_theme_setting/static/src/components/accordion/accordion.scss b/anita_theme_setting/static/src/components/accordion/accordion.scss
deleted file mode 100644
index 33f161e53..000000000
--- a/anita_theme_setting/static/src/components/accordion/accordion.scss
+++ /dev/null
@@ -1,59 +0,0 @@
-.anita_accordion {
-
- display: flex;
- flex-direction: column;
-
- .card-title {
- border: 1px solid #dee2e6 !important;
- }
-
- .accordion_button {
- position: relative;
- display: flex;
- align-items: center;
- width: 100%;
- padding: .75rem 1.25rem;
- font-size: 1rem;
- color: #212529;
- text-align: left;
- background-color: #fff;
- border: 0;
- border-radius: 0;
- overflow-anchor: none;
- transition: color .15s ease-in-out, background-color .15s ease-in-out, border-color .15s ease-in-out,box-shadow .15s ease-in-out,border-radius .15s ease;
-
- &::after {
- flex-shrink: 0;
- width: 0.75rem;
- height: 0.75em;
- margin-left: auto;
- content: "";
- background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23212529'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
- background-repeat: no-repeat;
- background-size: 0.75rem;
- transition: transform .2s ease-in-out;
- }
-
- &:focus {
- outline: 1px dotted;
- }
- }
-
- &.collapsed {
- .accordion-body {
- display: none !important;
- }
- }
-
- &:not(.collapsed) {
- .accordion_button {
- color: #0c63e4;
- background-color: #e7f1ff;
- &::after {
- background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%230c63e4'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
- transform: rotate(-180deg);
- }
- }
- }
-}
-
diff --git a/anita_theme_setting/static/src/components/accordion/accordion.xml b/anita_theme_setting/static/src/components/accordion/accordion.xml
deleted file mode 100644
index caf276db6..000000000
--- a/anita_theme_setting/static/src/components/accordion/accordion.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-
-
-
"
- ].join(''),
- markup = (function () {
-
- // IE does not support gradients with multiple stops, so we need to simulate
- // that for the rainbow slider with 8 divs that each have a single gradient
- var gradientFix = "";
- if (IE) {
- for (var i = 1; i <= 6; i++) {
- gradientFix += "";
- }
- }
-
- return [
- "
",
- "
",
- "",
- "
",
- "",
- "
",
- "
",
- "
",
- "
",
- "",
- "
",
- "
",
- "
",
- "
",
- "",
- "
",
- "
",
- "
",
- "
",
- "
",
- "
",
- "",
- gradientFix,
- "
",
- "
",
- "
",
- "
",
- "
",
- "",
- "
",
- "",
- "
",
- "",
- "",
- "
",
- "
",
- "
"
- ].join("");
- })();
-
- function paletteTemplate (p, color, className, opts) {
- var html = [];
- for (var i = 0; i < p.length; i++) {
- var current = p[i];
- if(current) {
- var tiny = tinycolor(current);
- var c = tiny.toHsl().l < 0.5 ? "sp-thumb-el sp-thumb-dark" : "sp-thumb-el sp-thumb-light";
- c += (tinycolor.equals(color, current)) ? " sp-thumb-active" : "";
- var formattedString = tiny.toString(opts.preferredFormat || "rgb");
- var swatchStyle = rgbaSupport ? ("background-color:" + tiny.toRgbString()) : "filter:" + tiny.toFilter();
- html.push('');
- } else {
- var cls = 'sp-clear-display';
- html.push($('')
- .append($('')
- .attr('title', opts.noColorSelectedText)
- )
- .html()
- );
- }
- }
- return "
" + html.join('') + "
";
- }
-
- function hideAll() {
- for (var i = 0; i < spectrums.length; i++) {
- if (spectrums[i]) {
- spectrums[i].hide();
- }
- }
- }
-
- function instanceOptions(o, callbackContext) {
- var opts = $.extend({}, defaultOpts, o);
- opts.callbacks = {
- 'move': bind(opts.move, callbackContext),
- 'change': bind(opts.change, callbackContext),
- 'show': bind(opts.show, callbackContext),
- 'hide': bind(opts.hide, callbackContext),
- 'beforeShow': bind(opts.beforeShow, callbackContext)
- };
-
- return opts;
- }
-
- function spectrum(element, o) {
-
- var opts = instanceOptions(o, element),
- flat = opts.flat,
- showSelectionPalette = opts.showSelectionPalette,
- localStorageKey = opts.localStorageKey,
- theme = opts.theme,
- callbacks = opts.callbacks,
- resize = throttle(reflow, 10),
- visible = false,
- isDragging = false,
- dragWidth = 0,
- dragHeight = 0,
- dragHelperHeight = 0,
- slideHeight = 0,
- slideWidth = 0,
- alphaWidth = 0,
- alphaSlideHelperWidth = 0,
- slideHelperHeight = 0,
- currentHue = 0,
- currentSaturation = 0,
- currentValue = 0,
- currentAlpha = 1,
- palette = [],
- paletteArray = [],
- paletteLookup = {},
- selectionPalette = opts.selectionPalette.slice(0),
- maxSelectionSize = opts.maxSelectionSize,
- draggingClass = "sp-dragging",
- shiftMovementDirection = null;
-
- var doc = element.ownerDocument,
- body = doc.body,
- boundElement = $(element),
- disabled = false,
- container = $(markup, doc).addClass(theme),
- pickerContainer = container.find(".sp-picker-container"),
- dragger = container.find(".sp-color"),
- dragHelper = container.find(".sp-dragger"),
- slider = container.find(".sp-hue"),
- slideHelper = container.find(".sp-slider"),
- alphaSliderInner = container.find(".sp-alpha-inner"),
- alphaSlider = container.find(".sp-alpha"),
- alphaSlideHelper = container.find(".sp-alpha-handle"),
- textInput = container.find(".sp-input"),
- paletteContainer = container.find(".sp-palette"),
- initialColorContainer = container.find(".sp-initial"),
- cancelButton = container.find(".sp-cancel"),
- clearButton = container.find(".sp-clear"),
- chooseButton = container.find(".sp-choose"),
- toggleButton = container.find(".sp-palette-toggle"),
- isInput = boundElement.is("input"),
- isInputTypeColor = isInput && boundElement.attr("type") === "color" && inputTypeColorSupport(),
- shouldReplace = isInput && !flat,
- replacer = (shouldReplace) ? $(replaceInput).addClass(theme).addClass(opts.className).addClass(opts.replacerClassName) : $([]),
- offsetElement = (shouldReplace) ? replacer : boundElement,
- previewElement = replacer.find(".sp-preview-inner"),
- initialColor = opts.color || (isInput && boundElement.val()),
- colorOnShow = false,
- currentPreferredFormat = opts.preferredFormat,
- clickoutFiresChange = !opts.showButtons || opts.clickoutFiresChange,
- isEmpty = !initialColor,
- allowEmpty = opts.allowEmpty && !isInputTypeColor;
-
- function applyOptions() {
-
- if (opts.showPaletteOnly) {
- opts.showPalette = true;
- }
-
- toggleButton.text(opts.showPaletteOnly ? opts.togglePaletteMoreText : opts.togglePaletteLessText);
-
- if (opts.palette) {
- palette = opts.palette.slice(0);
- paletteArray = Array.isArray(palette[0]) ? palette : [palette];
- paletteLookup = {};
- for (var i = 0; i < paletteArray.length; i++) {
- for (var j = 0; j < paletteArray[i].length; j++) {
- var rgb = tinycolor(paletteArray[i][j]).toRgbString();
- paletteLookup[rgb] = true;
- }
- }
- }
-
- container.toggleClass("sp-flat", flat);
- container.toggleClass("sp-input-disabled", !opts.showInput);
- container.toggleClass("sp-alpha-enabled", opts.showAlpha);
- container.toggleClass("sp-clear-enabled", allowEmpty);
- container.toggleClass("sp-buttons-disabled", !opts.showButtons);
- container.toggleClass("sp-palette-buttons-disabled", !opts.togglePaletteOnly);
- container.toggleClass("sp-palette-disabled", !opts.showPalette);
- container.toggleClass("sp-palette-only", opts.showPaletteOnly);
- container.toggleClass("sp-initial-disabled", !opts.showInitial);
- container.addClass(opts.className).addClass(opts.containerClassName);
-
- reflow();
- }
-
- function initialize() {
-
- if (IE) {
- container.find("*:not(input)").attr("unselectable", "on");
- }
-
- applyOptions();
-
- if (shouldReplace) {
- boundElement.after(replacer).hide();
- }
-
- if (!allowEmpty) {
- clearButton.hide();
- }
-
- if (flat) {
- boundElement.after(container).hide();
- }
- else {
-
- var appendTo = opts.appendTo === "parent" ? boundElement.parent() : $(opts.appendTo);
- if (appendTo.length !== 1) {
- appendTo = $("body");
- }
-
- appendTo.append(container);
- }
-
- updateSelectionPaletteFromStorage();
-
- offsetElement.on("click.spectrum touchstart.spectrum", function (e) {
- if (!disabled) {
- toggle();
- }
-
- e.stopPropagation();
-
- if (!$(e.target).is("input")) {
- e.preventDefault();
- }
- });
-
- if(boundElement.is(":disabled") || (opts.disabled === true)) {
- disable();
- }
-
- // Prevent clicks from bubbling up to document. This would cause it to be hidden.
- container.on("click", stopPropagation);
-
- // Handle user typed input
- textInput.on("change", setFromTextInput);
- textInput.on("paste", function () {
- setTimeout(setFromTextInput, 1);
- });
- textInput.on("keydown", function (e) { if (e.keyCode == 13) { setFromTextInput(); } });
-
- cancelButton.text(opts.cancelText);
- cancelButton.on("click.spectrum", function (e) {
- e.stopPropagation();
- e.preventDefault();
- revert();
- hide();
- });
-
- clearButton.attr("title", opts.clearText);
- clearButton.on("click.spectrum", function (e) {
- e.stopPropagation();
- e.preventDefault();
- isEmpty = true;
- move();
-
- if(flat) {
- //for the flat style, this is a change event
- updateOriginalInput(true);
- }
- });
-
- chooseButton.text(opts.chooseText);
- chooseButton.on("click.spectrum", function (e) {
- e.stopPropagation();
- e.preventDefault();
-
- if (IE && textInput.is(":focus")) {
- textInput.trigger('change');
- }
-
- if (isValid()) {
- updateOriginalInput(true);
- hide();
- }
- });
-
- toggleButton.text(opts.showPaletteOnly ? opts.togglePaletteMoreText : opts.togglePaletteLessText);
- toggleButton.on("click.spectrum", function (e) {
- e.stopPropagation();
- e.preventDefault();
-
- opts.showPaletteOnly = !opts.showPaletteOnly;
-
- // To make sure the Picker area is drawn on the right, next to the
- // Palette area (and not below the palette), first move the Palette
- // to the left to make space for the picker, plus 5px extra.
- // The 'applyOptions' function puts the whole container back into place
- // and takes care of the button-text and the sp-palette-only CSS class.
- if (!opts.showPaletteOnly && !flat) {
- container.css('left', '-=' + (pickerContainer.outerWidth(true) + 5));
- }
- applyOptions();
- });
-
- draggable(alphaSlider, function (dragX, dragY, e) {
- currentAlpha = (dragX / alphaWidth);
- isEmpty = false;
- if (e.shiftKey) {
- currentAlpha = Math.round(currentAlpha * 10) / 10;
- }
-
- move();
- }, dragStart, dragStop);
-
- draggable(slider, function (dragX, dragY) {
- currentHue = parseFloat(dragY / slideHeight);
- isEmpty = false;
- if (!opts.showAlpha) {
- currentAlpha = 1;
- }
- move();
- }, dragStart, dragStop);
-
- draggable(dragger, function (dragX, dragY, e) {
-
- // shift+drag should snap the movement to either the x or y axis.
- if (!e.shiftKey) {
- shiftMovementDirection = null;
- }
- else if (!shiftMovementDirection) {
- var oldDragX = currentSaturation * dragWidth;
- var oldDragY = dragHeight - (currentValue * dragHeight);
- var furtherFromX = Math.abs(dragX - oldDragX) > Math.abs(dragY - oldDragY);
-
- shiftMovementDirection = furtherFromX ? "x" : "y";
- }
-
- var setSaturation = !shiftMovementDirection || shiftMovementDirection === "x";
- var setValue = !shiftMovementDirection || shiftMovementDirection === "y";
-
- if (setSaturation) {
- currentSaturation = parseFloat(dragX / dragWidth);
- }
- if (setValue) {
- currentValue = parseFloat((dragHeight - dragY) / dragHeight);
- }
-
- isEmpty = false;
- if (!opts.showAlpha) {
- currentAlpha = 1;
- }
-
- move();
-
- }, dragStart, dragStop);
-
- if (!!initialColor) {
- set(initialColor);
-
- // In case color was black - update the preview UI and set the format
- // since the set function will not run (default color is black).
- updateUI();
- currentPreferredFormat = opts.preferredFormat || tinycolor(initialColor).format;
-
- addColorToSelectionPalette(initialColor);
- }
- else {
- updateUI();
- }
-
- if (flat) {
- show();
- }
-
- function paletteElementClick(e) {
- if (e.data && e.data.ignore) {
- set($(e.target).closest(".sp-thumb-el").data("color"));
- move();
- }
- else {
- set($(e.target).closest(".sp-thumb-el").data("color"));
- move();
-
- // If the picker is going to close immediately, a palette selection
- // is a change. Otherwise, it's a move only.
- if (opts.hideAfterPaletteSelect) {
- updateOriginalInput(true);
- hide();
- } else {
- updateOriginalInput();
- }
- }
-
- return false;
- }
-
- var paletteEvent = IE ? "mousedown.spectrum" : "click.spectrum touchstart.spectrum";
- paletteContainer.on(paletteEvent, ".sp-thumb-el", paletteElementClick);
- initialColorContainer.on(paletteEvent, ".sp-thumb-el:nth-child(1)", { ignore: true }, paletteElementClick);
- }
-
- function updateSelectionPaletteFromStorage() {
-
- if (localStorageKey && window.localStorage) {
-
- // Migrate old palettes over to new format. May want to remove this eventually.
- try {
- var oldPalette = window.localStorage[localStorageKey].split(",#");
- if (oldPalette.length > 1) {
- delete window.localStorage[localStorageKey];
- $.each(oldPalette, function(i, c) {
- addColorToSelectionPalette(c);
- });
- }
- }
- catch(e) { }
-
- try {
- selectionPalette = window.localStorage[localStorageKey].split(";");
- }
- catch (e) { }
- }
- }
-
- function addColorToSelectionPalette(color) {
- if (showSelectionPalette) {
- var rgb = tinycolor(color).toRgbString();
- if (!paletteLookup[rgb] && $.inArray(rgb, selectionPalette) === -1) {
- selectionPalette.push(rgb);
- while(selectionPalette.length > maxSelectionSize) {
- selectionPalette.shift();
- }
- }
-
- if (localStorageKey && window.localStorage) {
- try {
- window.localStorage[localStorageKey] = selectionPalette.join(";");
- }
- catch(e) { }
- }
- }
- }
-
- function getUniqueSelectionPalette() {
- var unique = [];
- if (opts.showPalette) {
- for (var i = 0; i < selectionPalette.length; i++) {
- var rgb = tinycolor(selectionPalette[i]).toRgbString();
-
- if (!paletteLookup[rgb]) {
- unique.push(selectionPalette[i]);
- }
- }
- }
-
- return unique.reverse().slice(0, opts.maxSelectionSize);
- }
-
- function drawPalette() {
-
- var currentColor = get();
-
- var html = $.map(paletteArray, function (palette, i) {
- return paletteTemplate(palette, currentColor, "sp-palette-row sp-palette-row-" + i, opts);
- });
-
- updateSelectionPaletteFromStorage();
-
- if (selectionPalette) {
- html.push(paletteTemplate(getUniqueSelectionPalette(), currentColor, "sp-palette-row sp-palette-row-selection", opts));
- }
-
- paletteContainer.html(html.join(""));
- }
-
- function drawInitial() {
- if (opts.showInitial) {
- var initial = colorOnShow;
- var current = get();
- initialColorContainer.html(paletteTemplate([initial, current], current, "sp-palette-row-initial", opts));
- }
- }
-
- function dragStart() {
- if (dragHeight <= 0 || dragWidth <= 0 || slideHeight <= 0) {
- reflow();
- }
- isDragging = true;
- container.addClass(draggingClass);
- shiftMovementDirection = null;
- boundElement.trigger('dragstart.spectrum', [ get() ]);
- }
-
- function dragStop() {
- isDragging = false;
- container.removeClass(draggingClass);
- boundElement.trigger('dragstop.spectrum', [ get() ]);
- }
-
- function setFromTextInput() {
-
- var value = textInput.val();
-
- if ((value === null || value === "") && allowEmpty) {
- set(null);
- move();
- updateOriginalInput();
- }
- else {
- var tiny = tinycolor(value);
- if (tiny.isValid()) {
- set(tiny);
- move();
- updateOriginalInput();
- }
- else {
- textInput.addClass("sp-validation-error");
- }
- }
- }
-
- function toggle() {
- if (visible) {
- hide();
- }
- else {
- show();
- }
- }
-
- function show() {
- var event = $.Event('beforeShow.spectrum');
-
- if (visible) {
- reflow();
- return;
- }
-
- boundElement.trigger(event, [ get() ]);
-
- if (callbacks.beforeShow(get()) === false || event.isDefaultPrevented()) {
- return;
- }
-
- hideAll();
- visible = true;
-
- $(doc).on("keydown.spectrum", onkeydown);
- $(doc).on("click.spectrum", clickout);
- $(window).on("resize.spectrum", resize);
- replacer.addClass("sp-active");
- container.removeClass("sp-hidden");
-
- reflow();
- updateUI();
-
- colorOnShow = get();
-
- drawInitial();
- callbacks.show(colorOnShow);
- boundElement.trigger('show.spectrum', [ colorOnShow ]);
- }
-
- function onkeydown(e) {
- // Close on ESC
- if (e.keyCode === 27) {
- hide();
- }
- }
-
- function clickout(e) {
- // Return on right click.
- if (e.button == 2) { return; }
-
- // If a drag event was happening during the mouseup, don't hide
- // on click.
- if (isDragging) { return; }
-
- if (clickoutFiresChange) {
- updateOriginalInput(true);
- }
- else {
- revert();
- }
- hide();
- }
-
- function hide() {
- // Return if hiding is unnecessary
- if (!visible || flat) { return; }
- visible = false;
-
- $(doc).off("keydown.spectrum", onkeydown);
- $(doc).off("click.spectrum", clickout);
- $(window).off("resize.spectrum", resize);
-
- replacer.removeClass("sp-active");
- container.addClass("sp-hidden");
-
- callbacks.hide(get());
- boundElement.trigger('hide.spectrum', [ get() ]);
- }
-
- function revert() {
- set(colorOnShow, true);
- updateOriginalInput(true);
- }
-
- function set(color, ignoreFormatChange) {
- if (tinycolor.equals(color, get())) {
- // Update UI just in case a validation error needs
- // to be cleared.
- updateUI();
- return;
- }
-
- var newColor, newHsv;
- if (!color && allowEmpty) {
- isEmpty = true;
- } else {
- isEmpty = false;
- newColor = tinycolor(color);
- newHsv = newColor.toHsv();
-
- currentHue = (newHsv.h % 360) / 360;
- currentSaturation = newHsv.s;
- currentValue = newHsv.v;
- currentAlpha = newHsv.a;
- }
- updateUI();
-
- if (newColor && newColor.isValid() && !ignoreFormatChange) {
- currentPreferredFormat = opts.preferredFormat || newColor.getFormat();
- }
- }
-
- function get(opts) {
- opts = opts || { };
-
- if (allowEmpty && isEmpty) {
- return null;
- }
-
- return tinycolor.fromRatio({
- h: currentHue,
- s: currentSaturation,
- v: currentValue,
- a: Math.round(currentAlpha * 1000) / 1000
- }, { format: opts.format || currentPreferredFormat });
- }
-
- function isValid() {
- return !textInput.hasClass("sp-validation-error");
- }
-
- function move() {
- updateUI();
-
- callbacks.move(get());
- boundElement.trigger('move.spectrum', [ get() ]);
- }
-
- function updateUI() {
-
- textInput.removeClass("sp-validation-error");
-
- updateHelperLocations();
-
- // Update dragger background color (gradients take care of saturation and value).
- var flatColor = tinycolor.fromRatio({ h: currentHue, s: 1, v: 1 });
- dragger.css("background-color", flatColor.toHexString());
-
- // Get a format that alpha will be included in (hex and names ignore alpha)
- var format = currentPreferredFormat;
- if (currentAlpha < 1 && !(currentAlpha === 0 && format === "name")) {
- if (format === "hex" || format === "hex3" || format === "hex6" || format === "name") {
- format = "rgb";
- }
- }
-
- var realColor = get({ format: format }),
- displayColor = '';
-
- //reset background info for preview element
- previewElement.removeClass("sp-clear-display");
- previewElement.css('background-color', 'transparent');
-
- if (!realColor && allowEmpty) {
- // Update the replaced elements background with icon indicating no color selection
- previewElement.addClass("sp-clear-display");
- }
- else {
- var realHex = realColor.toHexString(),
- realRgb = realColor.toRgbString();
-
- // Update the replaced elements background color (with actual selected color)
- if (rgbaSupport || realColor.alpha === 1) {
- previewElement.css("background-color", realRgb);
- }
- else {
- previewElement.css("background-color", "transparent");
- previewElement.css("filter", realColor.toFilter());
- }
-
- if (opts.showAlpha) {
- var rgb = realColor.toRgb();
- rgb.a = 0;
- var realAlpha = tinycolor(rgb).toRgbString();
- var gradient = "linear-gradient(left, " + realAlpha + ", " + realHex + ")";
-
- if (IE) {
- alphaSliderInner.css("filter", tinycolor(realAlpha).toFilter({ gradientType: 1 }, realHex));
- }
- else {
- alphaSliderInner.css("background", "-webkit-" + gradient);
- alphaSliderInner.css("background", "-moz-" + gradient);
- alphaSliderInner.css("background", "-ms-" + gradient);
- // Use current syntax gradient on unprefixed property.
- alphaSliderInner.css("background",
- "linear-gradient(to right, " + realAlpha + ", " + realHex + ")");
- }
- }
-
- displayColor = realColor.toString(format);
- }
-
- // Update the text entry input as it changes happen
- if (opts.showInput) {
- textInput.val(displayColor);
- }
-
- if (opts.showPalette) {
- drawPalette();
- }
-
- drawInitial();
- }
-
- function updateHelperLocations() {
- var s = currentSaturation;
- var v = currentValue;
-
- if(allowEmpty && isEmpty) {
- //if selected color is empty, hide the helpers
- alphaSlideHelper.hide();
- slideHelper.hide();
- dragHelper.hide();
- }
- else {
- //make sure helpers are visible
- alphaSlideHelper.show();
- slideHelper.show();
- dragHelper.show();
-
- // Where to show the little circle in that displays your current selected color
- var dragX = s * dragWidth;
- var dragY = dragHeight - (v * dragHeight);
- dragX = Math.max(
- -dragHelperHeight,
- Math.min(dragWidth - dragHelperHeight, dragX - dragHelperHeight)
- );
- dragY = Math.max(
- -dragHelperHeight,
- Math.min(dragHeight - dragHelperHeight, dragY - dragHelperHeight)
- );
- dragHelper.css({
- "top": dragY + "px",
- "left": dragX + "px"
- });
-
- var alphaX = currentAlpha * alphaWidth;
- alphaSlideHelper.css({
- "left": (alphaX - (alphaSlideHelperWidth / 2)) + "px"
- });
-
- // Where to show the bar that displays your current selected hue
- var slideY = (currentHue) * slideHeight;
- slideHelper.css({
- "top": (slideY - slideHelperHeight) + "px"
- });
- }
- }
-
- function updateOriginalInput(fireCallback) {
- var color = get(),
- displayColor = '',
- hasChanged = !tinycolor.equals(color, colorOnShow);
-
- if (color) {
- displayColor = color.toString(currentPreferredFormat);
- // Update the selection palette with the current color
- addColorToSelectionPalette(color);
- }
-
- if (isInput) {
- boundElement.val(displayColor);
- }
-
- if (fireCallback && hasChanged) {
- callbacks.change(color);
- boundElement.trigger('change', [ color ]);
- }
- }
-
- function reflow() {
- if (!visible) {
- return; // Calculations would be useless and wouldn't be reliable anyways
- }
- dragWidth = dragger.width();
- dragHeight = dragger.height();
- dragHelperHeight = dragHelper.height();
- slideWidth = slider.width();
- slideHeight = slider.height();
- slideHelperHeight = slideHelper.height();
- alphaWidth = alphaSlider.width();
- alphaSlideHelperWidth = alphaSlideHelper.width();
-
- if (!flat) {
- container.css("position", "absolute");
- if (opts.offset) {
- container.offset(opts.offset);
- } else {
- container.offset(getOffset(container, offsetElement));
- }
- }
-
- updateHelperLocations();
-
- if (opts.showPalette) {
- drawPalette();
- }
-
- boundElement.trigger('reflow.spectrum');
- }
-
- function destroy() {
- boundElement.show();
- offsetElement.off("click.spectrum touchstart.spectrum");
- container.remove();
- replacer.remove();
- spectrums[spect.id] = null;
- }
-
- function option(optionName, optionValue) {
- if (optionName === undefined) {
- return $.extend({}, opts);
- }
- if (optionValue === undefined) {
- return opts[optionName];
- }
-
- opts[optionName] = optionValue;
-
- if (optionName === "preferredFormat") {
- currentPreferredFormat = opts.preferredFormat;
- }
- applyOptions();
- }
-
- function enable() {
- disabled = false;
- boundElement.attr("disabled", false);
- offsetElement.removeClass("sp-disabled");
- }
-
- function disable() {
- hide();
- disabled = true;
- boundElement.attr("disabled", true);
- offsetElement.addClass("sp-disabled");
- }
-
- function setOffset(coord) {
- opts.offset = coord;
- reflow();
- }
-
- initialize();
-
- var spect = {
- show: show,
- hide: hide,
- toggle: toggle,
- reflow: reflow,
- option: option,
- enable: enable,
- disable: disable,
- offset: setOffset,
- set: function (c) {
- set(c);
- updateOriginalInput();
- },
- get: get,
- destroy: destroy,
- container: container
- };
-
- spect.id = spectrums.push(spect) - 1;
-
- return spect;
- }
-
- /**
- * checkOffset - get the offset below/above and left/right element depending on screen position
- * Thanks https://github.com/jquery/jquery-ui/blob/master/ui/jquery.ui.datepicker.js
- */
- function getOffset(picker, input) {
- var extraY = 0;
- var dpWidth = picker.outerWidth();
- var dpHeight = picker.outerHeight();
- var inputHeight = input.outerHeight();
- var doc = picker[0].ownerDocument;
- var docElem = doc.documentElement;
- var viewWidth = docElem.clientWidth + $(doc).scrollLeft();
- var viewHeight = docElem.clientHeight + $(doc).scrollTop();
- var offset = input.offset();
- var offsetLeft = offset.left;
- var offsetTop = offset.top;
-
- offsetTop += inputHeight;
-
- offsetLeft -=
- Math.min(offsetLeft, (offsetLeft + dpWidth > viewWidth && viewWidth > dpWidth) ?
- Math.abs(offsetLeft + dpWidth - viewWidth) : 0);
-
- offsetTop -=
- Math.min(offsetTop, ((offsetTop + dpHeight > viewHeight && viewHeight > dpHeight) ?
- Math.abs(dpHeight + inputHeight - extraY) : extraY));
-
- return {
- top: offsetTop,
- bottom: offset.bottom,
- left: offsetLeft,
- right: offset.right,
- width: offset.width,
- height: offset.height
- };
- }
-
- /**
- * noop - do nothing
- */
- function noop() {
-
- }
-
- /**
- * stopPropagation - makes the code only doing this a little easier to read in line
- */
- function stopPropagation(e) {
- e.stopPropagation();
- }
-
- /**
- * Create a function bound to a given object
- * Thanks to underscore.js
- */
- function bind(func, obj) {
- var slice = Array.prototype.slice;
- var args = slice.call(arguments, 2);
- return function () {
- return func.apply(obj, args.concat(slice.call(arguments)));
- };
- }
-
- /**
- * Lightweight drag helper. Handles containment within the element, so that
- * when dragging, the x is within [0,element.width] and y is within [0,element.height]
- */
- function draggable(element, onmove, onstart, onstop) {
- onmove = onmove || function () { };
- onstart = onstart || function () { };
- onstop = onstop || function () { };
- var doc = document;
- var dragging = false;
- var offset = {};
- var maxHeight = 0;
- var maxWidth = 0;
- var hasTouch = ('ontouchstart' in window);
-
- var duringDragEvents = {};
- duringDragEvents["selectstart"] = prevent;
- duringDragEvents["dragstart"] = prevent;
- duringDragEvents["touchmove mousemove"] = move;
- duringDragEvents["touchend mouseup"] = stop;
-
- function prevent(e) {
- if (e.stopPropagation) {
- e.stopPropagation();
- }
- if (e.preventDefault) {
- e.preventDefault();
- }
- e.returnValue = false;
- }
-
- function move(e) {
- if (dragging) {
- // Mouseup happened outside of window
- if (IE && doc.documentMode < 9 && !e.button) {
- return stop();
- }
-
- var t0 = e.originalEvent && e.originalEvent.touches && e.originalEvent.touches[0];
- var pageX = t0 && t0.pageX || e.pageX;
- var pageY = t0 && t0.pageY || e.pageY;
-
- var dragX = Math.max(0, Math.min(pageX - offset.left, maxWidth));
- var dragY = Math.max(0, Math.min(pageY - offset.top, maxHeight));
-
- if (hasTouch) {
- // Stop scrolling in iOS
- prevent(e);
- }
-
- onmove.apply(element, [dragX, dragY, e]);
- }
- }
-
- function start(e) {
- var rightclick = (e.which) ? (e.which == 3) : (e.button == 2);
-
- if (!rightclick && !dragging) {
- if (onstart.apply(element, arguments) !== false) {
- dragging = true;
- maxHeight = $(element).height();
- maxWidth = $(element).width();
- offset = $(element).offset();
-
- $(doc).on(duringDragEvents);
- $(doc.body).addClass("sp-dragging");
-
- move(e);
-
- prevent(e);
- }
- }
- }
-
- function stop() {
- if (dragging) {
- $(doc).off(duringDragEvents);
- $(doc.body).removeClass("sp-dragging");
-
- // Wait a tick before notifying observers to allow the click event
- // to fire in Chrome.
- setTimeout(function() {
- onstop.apply(element, arguments);
- }, 0);
- }
- dragging = false;
- }
-
- $(element).on("touchstart mousedown", start);
- }
-
- function throttle(func, wait, debounce) {
- var timeout;
- return function () {
- var context = this, args = arguments;
- var throttler = function () {
- timeout = null;
- func.apply(context, args);
- };
- if (debounce) clearTimeout(timeout);
- if (debounce || !timeout) timeout = setTimeout(throttler, wait);
- };
- }
-
- function inputTypeColorSupport() {
- return $.fn.spectrum.inputTypeColorSupport();
- }
-
- /**
- * Define a jQuery plugin
- */
- var dataID = "spectrum.id";
- $.fn.spectrum = function (opts, extra) {
-
- if (typeof opts == "string") {
-
- var returnValue = this;
- var args = Array.prototype.slice.call( arguments, 1 );
-
- this.each(function () {
- var spect = spectrums[$(this).data(dataID)];
- if (spect) {
- var method = spect[opts];
- if (!method) {
- throw new Error( "Spectrum: no such method: '" + opts + "'" );
- }
-
- if (opts == "get") {
- returnValue = spect.get();
- }
- else if (opts == "container") {
- returnValue = spect.container;
- }
- else if (opts == "option") {
- returnValue = spect.option.apply(spect, args);
- }
- else if (opts == "destroy") {
- spect.destroy();
- $(this).removeData(dataID);
- }
- else {
- method.apply(spect, args);
- }
- }
- });
-
- return returnValue;
- }
-
- // Initializing a new instance of spectrum
- return this.spectrum("destroy").each(function () {
- var options = $.extend({}, $(this).data(), opts);
- var spect = spectrum(this, options);
- $(this).data(dataID, spect.id);
- });
- };
-
- $.fn.spectrum.load = true;
- $.fn.spectrum.loadOpts = {};
- $.fn.spectrum.draggable = draggable;
- $.fn.spectrum.defaults = defaultOpts;
- $.fn.spectrum.inputTypeColorSupport = function inputTypeColorSupport() {
- if (typeof inputTypeColorSupport._cachedResult === "undefined") {
- var colorInput = $("")[0]; // if color element is supported, value will default to not null
- inputTypeColorSupport._cachedResult = colorInput.type === "color" && colorInput.value !== "";
- }
- return inputTypeColorSupport._cachedResult;
- };
-
- $.spectrum = { };
- $.spectrum.localization = { };
- $.spectrum.palettes = { };
-
- $.fn.spectrum.processNativeColorInputs = function () {
- var colorInputs = $("input[type=color]");
- if (colorInputs.length && !inputTypeColorSupport()) {
- colorInputs.spectrum({
- preferredFormat: "hex6"
- });
- }
- };
-
- // TinyColor v1.1.2
- // https://github.com/bgrins/TinyColor
- // Brian Grinstead, MIT License
-
- (function() {
-
- var trimLeft = /^[\s,#]+/,
- trimRight = /\s+$/,
- tinyCounter = 0,
- math = Math,
- mathRound = math.round,
- mathMin = math.min,
- mathMax = math.max,
- mathRandom = math.random;
-
- var tinycolor = function(color, opts) {
-
- color = (color) ? color : '';
- opts = opts || { };
-
- // If input is already a tinycolor, return itself
- if (color instanceof tinycolor) {
- return color;
- }
- // If we are called as a function, call using new instead
- if (!(this instanceof tinycolor)) {
- return new tinycolor(color, opts);
- }
-
- var rgb = inputToRGB(color);
- this._originalInput = color;
- this._r = rgb.r;
- this._g = rgb.g;
- this._b = rgb.b;
- this._a = rgb.a;
- this._roundA = mathRound(1000 * this._a) / 1000;
- this._format = opts.format || rgb.format;
- this._gradientType = opts.gradientType;
-
- // Don't let the range of [0,255] come back in [0,1].
- // Potentially lose a little bit of precision here, but will fix issues where
- // .5 gets interpreted as half of the total, instead of half of 1
- // If it was supposed to be 128, this was already taken care of by `inputToRgb`
- if (this._r < 1) { this._r = mathRound(this._r); }
- if (this._g < 1) { this._g = mathRound(this._g); }
- if (this._b < 1) { this._b = mathRound(this._b); }
-
- this._ok = rgb.ok;
- this._tc_id = tinyCounter++;
- };
-
- tinycolor.prototype = {
- isDark: function() {
- return this.getBrightness() < 128;
- },
- isLight: function() {
- return !this.isDark();
- },
- isValid: function() {
- return this._ok;
- },
- getOriginalInput: function() {
- return this._originalInput;
- },
- getFormat: function() {
- return this._format;
- },
- getAlpha: function() {
- return this._a;
- },
- getBrightness: function() {
- var rgb = this.toRgb();
- return (rgb.r * 299 + rgb.g * 587 + rgb.b * 114) / 1000;
- },
- setAlpha: function(value) {
- this._a = boundAlpha(value);
- this._roundA = mathRound(1000 * this._a) / 1000;
- return this;
- },
- toHsv: function() {
- var hsv = rgbToHsv(this._r, this._g, this._b);
- return { h: hsv.h * 360, s: hsv.s, v: hsv.v, a: this._a };
- },
- toHsvString: function() {
- var hsv = rgbToHsv(this._r, this._g, this._b);
- var h = mathRound(hsv.h * 360), s = mathRound(hsv.s * 100), v = mathRound(hsv.v * 100);
- return (this._a == 1) ?
- "hsv(" + h + ", " + s + "%, " + v + "%)" :
- "hsva(" + h + ", " + s + "%, " + v + "%, "+ this._roundA + ")";
- },
- toHsl: function() {
- var hsl = rgbToHsl(this._r, this._g, this._b);
- return { h: hsl.h * 360, s: hsl.s, l: hsl.l, a: this._a };
- },
- toHslString: function() {
- var hsl = rgbToHsl(this._r, this._g, this._b);
- var h = mathRound(hsl.h * 360), s = mathRound(hsl.s * 100), l = mathRound(hsl.l * 100);
- return (this._a == 1) ?
- "hsl(" + h + ", " + s + "%, " + l + "%)" :
- "hsla(" + h + ", " + s + "%, " + l + "%, "+ this._roundA + ")";
- },
- toHex: function(allow3Char) {
- return rgbToHex(this._r, this._g, this._b, allow3Char);
- },
- toHexString: function(allow3Char) {
- return '#' + this.toHex(allow3Char);
- },
- toHex8: function() {
- return rgbaToHex(this._r, this._g, this._b, this._a);
- },
- toHex8String: function() {
- return '#' + this.toHex8();
- },
- toRgb: function() {
- return { r: mathRound(this._r), g: mathRound(this._g), b: mathRound(this._b), a: this._a };
- },
- toRgbString: function() {
- return (this._a == 1) ?
- "rgb(" + mathRound(this._r) + ", " + mathRound(this._g) + ", " + mathRound(this._b) + ")" :
- "rgba(" + mathRound(this._r) + ", " + mathRound(this._g) + ", " + mathRound(this._b) + ", " + this._roundA + ")";
- },
- toPercentageRgb: function() {
- return { r: mathRound(bound01(this._r, 255) * 100) + "%", g: mathRound(bound01(this._g, 255) * 100) + "%", b: mathRound(bound01(this._b, 255) * 100) + "%", a: this._a };
- },
- toPercentageRgbString: function() {
- return (this._a == 1) ?
- "rgb(" + mathRound(bound01(this._r, 255) * 100) + "%, " + mathRound(bound01(this._g, 255) * 100) + "%, " + mathRound(bound01(this._b, 255) * 100) + "%)" :
- "rgba(" + mathRound(bound01(this._r, 255) * 100) + "%, " + mathRound(bound01(this._g, 255) * 100) + "%, " + mathRound(bound01(this._b, 255) * 100) + "%, " + this._roundA + ")";
- },
- toName: function() {
- if (this._a === 0) {
- return "transparent";
- }
-
- if (this._a < 1) {
- return false;
- }
-
- return hexNames[rgbToHex(this._r, this._g, this._b, true)] || false;
- },
- toFilter: function(secondColor) {
- var hex8String = '#' + rgbaToHex(this._r, this._g, this._b, this._a);
- var secondHex8String = hex8String;
- var gradientType = this._gradientType ? "GradientType = 1, " : "";
-
- if (secondColor) {
- var s = tinycolor(secondColor);
- secondHex8String = s.toHex8String();
- }
-
- return "progid:DXImageTransform.Microsoft.gradient("+gradientType+"startColorstr="+hex8String+",endColorstr="+secondHex8String+")";
- },
- toString: function(format) {
- var formatSet = !!format;
- format = format || this._format;
-
- var formattedString = false;
- var hasAlpha = this._a < 1 && this._a >= 0;
- var needsAlphaFormat = !formatSet && hasAlpha && (format === "hex" || format === "hex6" || format === "hex3" || format === "name");
-
- if (needsAlphaFormat) {
- // Special case for "transparent", all other non-alpha formats
- // will return rgba when there is transparency.
- if (format === "name" && this._a === 0) {
- return this.toName();
- }
- return this.toRgbString();
- }
- if (format === "rgb") {
- formattedString = this.toRgbString();
- }
- if (format === "prgb") {
- formattedString = this.toPercentageRgbString();
- }
- if (format === "hex" || format === "hex6") {
- formattedString = this.toHexString();
- }
- if (format === "hex3") {
- formattedString = this.toHexString(true);
- }
- if (format === "hex8") {
- formattedString = this.toHex8String();
- }
- if (format === "name") {
- formattedString = this.toName();
- }
- if (format === "hsl") {
- formattedString = this.toHslString();
- }
- if (format === "hsv") {
- formattedString = this.toHsvString();
- }
-
- return formattedString || this.toHexString();
- },
-
- _applyModification: function(fn, args) {
- var color = fn.apply(null, [this].concat([].slice.call(args)));
- this._r = color._r;
- this._g = color._g;
- this._b = color._b;
- this.setAlpha(color._a);
- return this;
- },
- lighten: function() {
- return this._applyModification(lighten, arguments);
- },
- brighten: function() {
- return this._applyModification(brighten, arguments);
- },
- darken: function() {
- return this._applyModification(darken, arguments);
- },
- desaturate: function() {
- return this._applyModification(desaturate, arguments);
- },
- saturate: function() {
- return this._applyModification(saturate, arguments);
- },
- greyscale: function() {
- return this._applyModification(greyscale, arguments);
- },
- spin: function() {
- return this._applyModification(spin, arguments);
- },
-
- _applyCombination: function(fn, args) {
- return fn.apply(null, [this].concat([].slice.call(args)));
- },
- analogous: function() {
- return this._applyCombination(analogous, arguments);
- },
- complement: function() {
- return this._applyCombination(complement, arguments);
- },
- monochromatic: function() {
- return this._applyCombination(monochromatic, arguments);
- },
- splitcomplement: function() {
- return this._applyCombination(splitcomplement, arguments);
- },
- triad: function() {
- return this._applyCombination(triad, arguments);
- },
- tetrad: function() {
- return this._applyCombination(tetrad, arguments);
- }
- };
-
- // If input is an object, force 1 into "1.0" to handle ratios properly
- // String input requires "1.0" as input, so 1 will be treated as 1
- tinycolor.fromRatio = function(color, opts) {
- if (typeof color == "object") {
- var newColor = {};
- for (var i in color) {
- if (color.hasOwnProperty(i)) {
- if (i === "a") {
- newColor[i] = color[i];
- }
- else {
- newColor[i] = convertToPercentage(color[i]);
- }
- }
- }
- color = newColor;
- }
-
- return tinycolor(color, opts);
- };
-
- // Given a string or object, convert that input to RGB
- // Possible string inputs:
- //
- // "red"
- // "#f00" or "f00"
- // "#ff0000" or "ff0000"
- // "#ff000000" or "ff000000"
- // "rgb 255 0 0" or "rgb (255, 0, 0)"
- // "rgb 1.0 0 0" or "rgb (1, 0, 0)"
- // "rgba (255, 0, 0, 1)" or "rgba 255, 0, 0, 1"
- // "rgba (1.0, 0, 0, 1)" or "rgba 1.0, 0, 0, 1"
- // "hsl(0, 100%, 50%)" or "hsl 0 100% 50%"
- // "hsla(0, 100%, 50%, 1)" or "hsla 0 100% 50%, 1"
- // "hsv(0, 100%, 100%)" or "hsv 0 100% 100%"
- //
- function inputToRGB(color) {
-
- var rgb = { r: 0, g: 0, b: 0 };
- var a = 1;
- var ok = false;
- var format = false;
-
- if (typeof color == "string") {
- color = stringInputToObject(color);
- }
-
- if (typeof color == "object") {
- if (color.hasOwnProperty("r") && color.hasOwnProperty("g") && color.hasOwnProperty("b")) {
- rgb = rgbToRgb(color.r, color.g, color.b);
- ok = true;
- format = String(color.r).substr(-1) === "%" ? "prgb" : "rgb";
- }
- else if (color.hasOwnProperty("h") && color.hasOwnProperty("s") && color.hasOwnProperty("v")) {
- color.s = convertToPercentage(color.s);
- color.v = convertToPercentage(color.v);
- rgb = hsvToRgb(color.h, color.s, color.v);
- ok = true;
- format = "hsv";
- }
- else if (color.hasOwnProperty("h") && color.hasOwnProperty("s") && color.hasOwnProperty("l")) {
- color.s = convertToPercentage(color.s);
- color.l = convertToPercentage(color.l);
- rgb = hslToRgb(color.h, color.s, color.l);
- ok = true;
- format = "hsl";
- }
-
- if (color.hasOwnProperty("a")) {
- a = color.a;
- }
- }
-
- a = boundAlpha(a);
-
- return {
- ok: ok,
- format: color.format || format,
- r: mathMin(255, mathMax(rgb.r, 0)),
- g: mathMin(255, mathMax(rgb.g, 0)),
- b: mathMin(255, mathMax(rgb.b, 0)),
- a: a
- };
- }
-
-
- // Conversion Functions
- // --------------------
-
- // `rgbToHsl`, `rgbToHsv`, `hslToRgb`, `hsvToRgb` modified from:
- //
-
- // `rgbToRgb`
- // Handle bounds / percentage checking to conform to CSS color spec
- //
- // *Assumes:* r, g, b in [0, 255] or [0, 1]
- // *Returns:* { r, g, b } in [0, 255]
- function rgbToRgb(r, g, b){
- return {
- r: bound01(r, 255) * 255,
- g: bound01(g, 255) * 255,
- b: bound01(b, 255) * 255
- };
- }
-
- // `rgbToHsl`
- // Converts an RGB color value to HSL.
- // *Assumes:* r, g, and b are contained in [0, 255] or [0, 1]
- // *Returns:* { h, s, l } in [0,1]
- function rgbToHsl(r, g, b) {
-
- r = bound01(r, 255);
- g = bound01(g, 255);
- b = bound01(b, 255);
-
- var max = mathMax(r, g, b), min = mathMin(r, g, b);
- var h, s, l = (max + min) / 2;
-
- if(max == min) {
- h = s = 0; // achromatic
- }
- else {
- var d = max - min;
- s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
- switch(max) {
- case r: h = (g - b) / d + (g < b ? 6 : 0); break;
- case g: h = (b - r) / d + 2; break;
- case b: h = (r - g) / d + 4; break;
- }
-
- h /= 6;
- }
-
- return { h: h, s: s, l: l };
- }
-
- // `hslToRgb`
- // Converts an HSL color value to RGB.
- // *Assumes:* h is contained in [0, 1] or [0, 360] and s and l are contained [0, 1] or [0, 100]
- // *Returns:* { r, g, b } in the set [0, 255]
- function hslToRgb(h, s, l) {
- var r, g, b;
-
- h = bound01(h, 360);
- s = bound01(s, 100);
- l = bound01(l, 100);
-
- function hue2rgb(p, q, t) {
- if(t < 0) t += 1;
- if(t > 1) t -= 1;
- if(t < 1/6) return p + (q - p) * 6 * t;
- if(t < 1/2) return q;
- if(t < 2/3) return p + (q - p) * (2/3 - t) * 6;
- return p;
- }
-
- if(s === 0) {
- r = g = b = l; // achromatic
- }
- else {
- var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
- var p = 2 * l - q;
- r = hue2rgb(p, q, h + 1/3);
- g = hue2rgb(p, q, h);
- b = hue2rgb(p, q, h - 1/3);
- }
-
- return { r: r * 255, g: g * 255, b: b * 255 };
- }
-
- // `rgbToHsv`
- // Converts an RGB color value to HSV
- // *Assumes:* r, g, and b are contained in the set [0, 255] or [0, 1]
- // *Returns:* { h, s, v } in [0,1]
- function rgbToHsv(r, g, b) {
-
- r = bound01(r, 255);
- g = bound01(g, 255);
- b = bound01(b, 255);
-
- var max = mathMax(r, g, b), min = mathMin(r, g, b);
- var h, s, v = max;
-
- var d = max - min;
- s = max === 0 ? 0 : d / max;
-
- if(max == min) {
- h = 0; // achromatic
- }
- else {
- switch(max) {
- case r: h = (g - b) / d + (g < b ? 6 : 0); break;
- case g: h = (b - r) / d + 2; break;
- case b: h = (r - g) / d + 4; break;
- }
- h /= 6;
- }
- return { h: h, s: s, v: v };
- }
-
- // `hsvToRgb`
- // Converts an HSV color value to RGB.
- // *Assumes:* h is contained in [0, 1] or [0, 360] and s and v are contained in [0, 1] or [0, 100]
- // *Returns:* { r, g, b } in the set [0, 255]
- function hsvToRgb(h, s, v) {
-
- h = bound01(h, 360) * 6;
- s = bound01(s, 100);
- v = bound01(v, 100);
-
- var i = math.floor(h),
- f = h - i,
- p = v * (1 - s),
- q = v * (1 - f * s),
- t = v * (1 - (1 - f) * s),
- mod = i % 6,
- r = [v, q, p, p, t, v][mod],
- g = [t, v, v, q, p, p][mod],
- b = [p, p, t, v, v, q][mod];
-
- return { r: r * 255, g: g * 255, b: b * 255 };
- }
-
- // `rgbToHex`
- // Converts an RGB color to hex
- // Assumes r, g, and b are contained in the set [0, 255]
- // Returns a 3 or 6 character hex
- function rgbToHex(r, g, b, allow3Char) {
-
- var hex = [
- pad2(mathRound(r).toString(16)),
- pad2(mathRound(g).toString(16)),
- pad2(mathRound(b).toString(16))
- ];
-
- // Return a 3 character hex if possible
- if (allow3Char && hex[0].charAt(0) == hex[0].charAt(1) && hex[1].charAt(0) == hex[1].charAt(1) && hex[2].charAt(0) == hex[2].charAt(1)) {
- return hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0);
- }
-
- return hex.join("");
- }
- // `rgbaToHex`
- // Converts an RGBA color plus alpha transparency to hex
- // Assumes r, g, b and a are contained in the set [0, 255]
- // Returns an 8 character hex
- function rgbaToHex(r, g, b, a) {
-
- var hex = [
- pad2(convertDecimalToHex(a)),
- pad2(mathRound(r).toString(16)),
- pad2(mathRound(g).toString(16)),
- pad2(mathRound(b).toString(16))
- ];
-
- return hex.join("");
- }
-
- // `equals`
- // Can be called with any tinycolor input
- tinycolor.equals = function (color1, color2) {
- if (!color1 || !color2) { return false; }
- return tinycolor(color1).toRgbString() == tinycolor(color2).toRgbString();
- };
- tinycolor.random = function() {
- return tinycolor.fromRatio({
- r: mathRandom(),
- g: mathRandom(),
- b: mathRandom()
- });
- };
-
-
- // Modification Functions
- // ----------------------
- // Thanks to less.js for some of the basics here
- //
-
- function desaturate(color, amount) {
- amount = (amount === 0) ? 0 : (amount || 10);
- var hsl = tinycolor(color).toHsl();
- hsl.s -= amount / 100;
- hsl.s = clamp01(hsl.s);
- return tinycolor(hsl);
- }
-
- function saturate(color, amount) {
- amount = (amount === 0) ? 0 : (amount || 10);
- var hsl = tinycolor(color).toHsl();
- hsl.s += amount / 100;
- hsl.s = clamp01(hsl.s);
- return tinycolor(hsl);
- }
-
- function greyscale(color) {
- return tinycolor(color).desaturate(100);
- }
-
- function lighten (color, amount) {
- amount = (amount === 0) ? 0 : (amount || 10);
- var hsl = tinycolor(color).toHsl();
- hsl.l += amount / 100;
- hsl.l = clamp01(hsl.l);
- return tinycolor(hsl);
- }
-
- function brighten(color, amount) {
- amount = (amount === 0) ? 0 : (amount || 10);
- var rgb = tinycolor(color).toRgb();
- rgb.r = mathMax(0, mathMin(255, rgb.r - mathRound(255 * - (amount / 100))));
- rgb.g = mathMax(0, mathMin(255, rgb.g - mathRound(255 * - (amount / 100))));
- rgb.b = mathMax(0, mathMin(255, rgb.b - mathRound(255 * - (amount / 100))));
- return tinycolor(rgb);
- }
-
- function darken (color, amount) {
- amount = (amount === 0) ? 0 : (amount || 10);
- var hsl = tinycolor(color).toHsl();
- hsl.l -= amount / 100;
- hsl.l = clamp01(hsl.l);
- return tinycolor(hsl);
- }
-
- // Spin takes a positive or negative amount within [-360, 360] indicating the change of hue.
- // Values outside of this range will be wrapped into this range.
- function spin(color, amount) {
- var hsl = tinycolor(color).toHsl();
- var hue = (mathRound(hsl.h) + amount) % 360;
- hsl.h = hue < 0 ? 360 + hue : hue;
- return tinycolor(hsl);
- }
-
- // Combination Functions
- // ---------------------
- // Thanks to jQuery xColor for some of the ideas behind these
- //
-
- function complement(color) {
- var hsl = tinycolor(color).toHsl();
- hsl.h = (hsl.h + 180) % 360;
- return tinycolor(hsl);
- }
-
- function triad(color) {
- var hsl = tinycolor(color).toHsl();
- var h = hsl.h;
- return [
- tinycolor(color),
- tinycolor({ h: (h + 120) % 360, s: hsl.s, l: hsl.l }),
- tinycolor({ h: (h + 240) % 360, s: hsl.s, l: hsl.l })
- ];
- }
-
- function tetrad(color) {
- var hsl = tinycolor(color).toHsl();
- var h = hsl.h;
- return [
- tinycolor(color),
- tinycolor({ h: (h + 90) % 360, s: hsl.s, l: hsl.l }),
- tinycolor({ h: (h + 180) % 360, s: hsl.s, l: hsl.l }),
- tinycolor({ h: (h + 270) % 360, s: hsl.s, l: hsl.l })
- ];
- }
-
- function splitcomplement(color) {
- var hsl = tinycolor(color).toHsl();
- var h = hsl.h;
- return [
- tinycolor(color),
- tinycolor({ h: (h + 72) % 360, s: hsl.s, l: hsl.l}),
- tinycolor({ h: (h + 216) % 360, s: hsl.s, l: hsl.l})
- ];
- }
-
- function analogous(color, results, slices) {
- results = results || 6;
- slices = slices || 30;
-
- var hsl = tinycolor(color).toHsl();
- var part = 360 / slices;
- var ret = [tinycolor(color)];
-
- for (hsl.h = ((hsl.h - (part * results >> 1)) + 720) % 360; --results; ) {
- hsl.h = (hsl.h + part) % 360;
- ret.push(tinycolor(hsl));
- }
- return ret;
- }
-
- function monochromatic(color, results) {
- results = results || 6;
- var hsv = tinycolor(color).toHsv();
- var h = hsv.h, s = hsv.s, v = hsv.v;
- var ret = [];
- var modification = 1 / results;
-
- while (results--) {
- ret.push(tinycolor({ h: h, s: s, v: v}));
- v = (v + modification) % 1;
- }
-
- return ret;
- }
-
- // Utility Functions
- // ---------------------
-
- tinycolor.mix = function(color1, color2, amount) {
- amount = (amount === 0) ? 0 : (amount || 50);
-
- var rgb1 = tinycolor(color1).toRgb();
- var rgb2 = tinycolor(color2).toRgb();
-
- var p = amount / 100;
- var w = p * 2 - 1;
- var a = rgb2.a - rgb1.a;
-
- var w1;
-
- if (w * a == -1) {
- w1 = w;
- } else {
- w1 = (w + a) / (1 + w * a);
- }
-
- w1 = (w1 + 1) / 2;
-
- var w2 = 1 - w1;
-
- var rgba = {
- r: rgb2.r * w1 + rgb1.r * w2,
- g: rgb2.g * w1 + rgb1.g * w2,
- b: rgb2.b * w1 + rgb1.b * w2,
- a: rgb2.a * p + rgb1.a * (1 - p)
- };
-
- return tinycolor(rgba);
- };
-
-
- // Readability Functions
- // ---------------------
- //
-
- // `readability`
- // Analyze the 2 colors and returns an object with the following properties:
- // `brightness`: difference in brightness between the two colors
- // `color`: difference in color/hue between the two colors
- tinycolor.readability = function(color1, color2) {
- var c1 = tinycolor(color1);
- var c2 = tinycolor(color2);
- var rgb1 = c1.toRgb();
- var rgb2 = c2.toRgb();
- var brightnessA = c1.getBrightness();
- var brightnessB = c2.getBrightness();
- var colorDiff = (
- Math.max(rgb1.r, rgb2.r) - Math.min(rgb1.r, rgb2.r) +
- Math.max(rgb1.g, rgb2.g) - Math.min(rgb1.g, rgb2.g) +
- Math.max(rgb1.b, rgb2.b) - Math.min(rgb1.b, rgb2.b)
- );
-
- return {
- brightness: Math.abs(brightnessA - brightnessB),
- color: colorDiff
- };
- };
-
- // `readable`
- // http://www.w3.org/TR/AERT#color-contrast
- // Ensure that foreground and background color combinations provide sufficient contrast.
- // *Example*
- // tinycolor.isReadable("#000", "#111") => false
- tinycolor.isReadable = function(color1, color2) {
- var readability = tinycolor.readability(color1, color2);
- return readability.brightness > 125 && readability.color > 500;
- };
-
- // `mostReadable`
- // Given a base color and a list of possible foreground or background
- // colors for that base, returns the most readable color.
- // *Example*
- // tinycolor.mostReadable("#123", ["#fff", "#000"]) => "#000"
- tinycolor.mostReadable = function(baseColor, colorList) {
- var bestColor = null;
- var bestScore = 0;
- var bestIsReadable = false;
- for (var i=0; i < colorList.length; i++) {
-
- // We normalize both around the "acceptable" breaking point,
- // but rank brightness constrast higher than hue.
-
- var readability = tinycolor.readability(baseColor, colorList[i]);
- var readable = readability.brightness > 125 && readability.color > 500;
- var score = 3 * (readability.brightness / 125) + (readability.color / 500);
-
- if ((readable && ! bestIsReadable) ||
- (readable && bestIsReadable && score > bestScore) ||
- ((! readable) && (! bestIsReadable) && score > bestScore)) {
- bestIsReadable = readable;
- bestScore = score;
- bestColor = tinycolor(colorList[i]);
- }
- }
- return bestColor;
- };
-
-
- // Big List of Colors
- // ------------------
- //
- var names = tinycolor.names = {
- aliceblue: "f0f8ff",
- antiquewhite: "faebd7",
- aqua: "0ff",
- aquamarine: "7fffd4",
- azure: "f0ffff",
- beige: "f5f5dc",
- bisque: "ffe4c4",
- black: "000",
- blanchedalmond: "ffebcd",
- blue: "00f",
- blueviolet: "8a2be2",
- brown: "a52a2a",
- burlywood: "deb887",
- burntsienna: "ea7e5d",
- cadetblue: "5f9ea0",
- chartreuse: "7fff00",
- chocolate: "d2691e",
- coral: "ff7f50",
- cornflowerblue: "6495ed",
- cornsilk: "fff8dc",
- crimson: "dc143c",
- cyan: "0ff",
- darkblue: "00008b",
- darkcyan: "008b8b",
- darkgoldenrod: "b8860b",
- darkgray: "a9a9a9",
- darkgreen: "006400",
- darkgrey: "a9a9a9",
- darkkhaki: "bdb76b",
- darkmagenta: "8b008b",
- darkolivegreen: "556b2f",
- darkorange: "ff8c00",
- darkorchid: "9932cc",
- darkred: "8b0000",
- darksalmon: "e9967a",
- darkseagreen: "8fbc8f",
- darkslateblue: "483d8b",
- darkslategray: "2f4f4f",
- darkslategrey: "2f4f4f",
- darkturquoise: "00ced1",
- darkviolet: "9400d3",
- deeppink: "ff1493",
- deepskyblue: "00bfff",
- dimgray: "696969",
- dimgrey: "696969",
- dodgerblue: "1e90ff",
- firebrick: "b22222",
- floralwhite: "fffaf0",
- forestgreen: "228b22",
- fuchsia: "f0f",
- gainsboro: "dcdcdc",
- ghostwhite: "f8f8ff",
- gold: "ffd700",
- goldenrod: "daa520",
- gray: "808080",
- green: "008000",
- greenyellow: "adff2f",
- grey: "808080",
- honeydew: "f0fff0",
- hotpink: "ff69b4",
- indianred: "cd5c5c",
- indigo: "4b0082",
- ivory: "fffff0",
- khaki: "f0e68c",
- lavender: "e6e6fa",
- lavenderblush: "fff0f5",
- lawngreen: "7cfc00",
- lemonchiffon: "fffacd",
- lightblue: "add8e6",
- lightcoral: "f08080",
- lightcyan: "e0ffff",
- lightgoldenrodyellow: "fafad2",
- lightgray: "d3d3d3",
- lightgreen: "90ee90",
- lightgrey: "d3d3d3",
- lightpink: "ffb6c1",
- lightsalmon: "ffa07a",
- lightseagreen: "20b2aa",
- lightskyblue: "87cefa",
- lightslategray: "789",
- lightslategrey: "789",
- lightsteelblue: "b0c4de",
- lightyellow: "ffffe0",
- lime: "0f0",
- limegreen: "32cd32",
- linen: "faf0e6",
- magenta: "f0f",
- maroon: "800000",
- mediumaquamarine: "66cdaa",
- mediumblue: "0000cd",
- mediumorchid: "ba55d3",
- mediumpurple: "9370db",
- mediumseagreen: "3cb371",
- mediumslateblue: "7b68ee",
- mediumspringgreen: "00fa9a",
- mediumturquoise: "48d1cc",
- mediumvioletred: "c71585",
- midnightblue: "191970",
- mintcream: "f5fffa",
- mistyrose: "ffe4e1",
- moccasin: "ffe4b5",
- navajowhite: "ffdead",
- navy: "000080",
- oldlace: "fdf5e6",
- olive: "808000",
- olivedrab: "6b8e23",
- orange: "ffa500",
- orangered: "ff4500",
- orchid: "da70d6",
- palegoldenrod: "eee8aa",
- palegreen: "98fb98",
- paleturquoise: "afeeee",
- palevioletred: "db7093",
- papayawhip: "ffefd5",
- peachpuff: "ffdab9",
- peru: "cd853f",
- pink: "ffc0cb",
- plum: "dda0dd",
- powderblue: "b0e0e6",
- purple: "800080",
- rebeccapurple: "663399",
- red: "f00",
- rosybrown: "bc8f8f",
- royalblue: "4169e1",
- saddlebrown: "8b4513",
- salmon: "fa8072",
- sandybrown: "f4a460",
- seagreen: "2e8b57",
- seashell: "fff5ee",
- sienna: "a0522d",
- silver: "c0c0c0",
- skyblue: "87ceeb",
- slateblue: "6a5acd",
- slategray: "708090",
- slategrey: "708090",
- snow: "fffafa",
- springgreen: "00ff7f",
- steelblue: "4682b4",
- tan: "d2b48c",
- teal: "008080",
- thistle: "d8bfd8",
- tomato: "ff6347",
- turquoise: "40e0d0",
- violet: "ee82ee",
- wheat: "f5deb3",
- white: "fff",
- whitesmoke: "f5f5f5",
- yellow: "ff0",
- yellowgreen: "9acd32"
- };
-
- // Make it easy to access colors via `hexNames[hex]`
- var hexNames = tinycolor.hexNames = flip(names);
-
-
- // Utilities
- // ---------
-
- // `{ 'name1': 'val1' }` becomes `{ 'val1': 'name1' }`
- function flip(o) {
- var flipped = { };
- for (var i in o) {
- if (o.hasOwnProperty(i)) {
- flipped[o[i]] = i;
- }
- }
- return flipped;
- }
-
- // Return a valid alpha value [0,1] with all invalid values being set to 1
- function boundAlpha(a) {
- a = parseFloat(a);
-
- if (isNaN(a) || a < 0 || a > 1) {
- a = 1;
- }
-
- return a;
- }
-
- // Take input from [0, n] and return it as [0, 1]
- function bound01(n, max) {
- if (isOnePointZero(n)) { n = "100%"; }
-
- var processPercent = isPercentage(n);
- n = mathMin(max, mathMax(0, parseFloat(n)));
-
- // Automatically convert percentage into number
- if (processPercent) {
- n = parseInt(n * max, 10) / 100;
- }
-
- // Handle floating point rounding errors
- if ((math.abs(n - max) < 0.000001)) {
- return 1;
- }
-
- // Convert into [0, 1] range if it isn't already
- return (n % max) / parseFloat(max);
- }
-
- // Force a number between 0 and 1
- function clamp01(val) {
- return mathMin(1, mathMax(0, val));
- }
-
- // Parse a base-16 hex value into a base-10 integer
- function parseIntFromHex(val) {
- return parseInt(val, 16);
- }
-
- // Need to handle 1.0 as 100%, since once it is a number, there is no difference between it and 1
- //
- function isOnePointZero(n) {
- return typeof n == "string" && n.indexOf('.') != -1 && parseFloat(n) === 1;
- }
-
- // Check to see if string passed in is a percentage
- function isPercentage(n) {
- return typeof n === "string" && n.indexOf('%') != -1;
- }
-
- // Force a hex value to have 2 characters
- function pad2(c) {
- return c.length == 1 ? '0' + c : '' + c;
- }
-
- // Replace a decimal with it's percentage value
- function convertToPercentage(n) {
- if (n <= 1) {
- n = (n * 100) + "%";
- }
-
- return n;
- }
-
- // Converts a decimal to a hex value
- function convertDecimalToHex(d) {
- return Math.round(parseFloat(d) * 255).toString(16);
- }
- // Converts a hex value to a decimal
- function convertHexToDecimal(h) {
- return (parseIntFromHex(h) / 255);
- }
-
- var matchers = (function() {
-
- //
- var CSS_INTEGER = "[-\\+]?\\d+%?";
-
- //
- var CSS_NUMBER = "[-\\+]?\\d*\\.\\d+%?";
-
- // Allow positive/negative integer/number. Don't capture the either/or, just the entire outcome.
- var CSS_UNIT = "(?:" + CSS_NUMBER + ")|(?:" + CSS_INTEGER + ")";
-
- // Actual matching.
- // Parentheses and commas are optional, but not required.
- // Whitespace can take the place of commas or opening paren
- var PERMISSIVE_MATCH3 = "[\\s|\\(]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")\\s*\\)?";
- var PERMISSIVE_MATCH4 = "[\\s|\\(]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")\\s*\\)?";
-
- return {
- rgb: new RegExp("rgb" + PERMISSIVE_MATCH3),
- rgba: new RegExp("rgba" + PERMISSIVE_MATCH4),
- hsl: new RegExp("hsl" + PERMISSIVE_MATCH3),
- hsla: new RegExp("hsla" + PERMISSIVE_MATCH4),
- hsv: new RegExp("hsv" + PERMISSIVE_MATCH3),
- hsva: new RegExp("hsva" + PERMISSIVE_MATCH4),
- hex3: /^([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,
- hex6: /^([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/,
- hex8: /^([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/
- };
- })();
-
- // `stringInputToObject`
- // Permissive string parsing. Take in a number of formats, and output an object
- // based on detected format. Returns `{ r, g, b }` or `{ h, s, l }` or `{ h, s, v}`
- function stringInputToObject(color) {
-
- color = color.replace(trimLeft,'').replace(trimRight, '').toLowerCase();
- var named = false;
- if (names[color]) {
- color = names[color];
- named = true;
- }
- else if (color == 'transparent') {
- return { r: 0, g: 0, b: 0, a: 0, format: "name" };
- }
-
- // Try to match string input using regular expressions.
- // Keep most of the number bounding out of this function - don't worry about [0,1] or [0,100] or [0,360]
- // Just return an object and let the conversion functions handle that.
- // This way the result will be the same whether the tinycolor is initialized with string or object.
- var match;
- if ((match = matchers.rgb.exec(color))) {
- return { r: match[1], g: match[2], b: match[3] };
- }
- if ((match = matchers.rgba.exec(color))) {
- return { r: match[1], g: match[2], b: match[3], a: match[4] };
- }
- if ((match = matchers.hsl.exec(color))) {
- return { h: match[1], s: match[2], l: match[3] };
- }
- if ((match = matchers.hsla.exec(color))) {
- return { h: match[1], s: match[2], l: match[3], a: match[4] };
- }
- if ((match = matchers.hsv.exec(color))) {
- return { h: match[1], s: match[2], v: match[3] };
- }
- if ((match = matchers.hsva.exec(color))) {
- return { h: match[1], s: match[2], v: match[3], a: match[4] };
- }
- if ((match = matchers.hex8.exec(color))) {
- return {
- a: convertHexToDecimal(match[1]),
- r: parseIntFromHex(match[2]),
- g: parseIntFromHex(match[3]),
- b: parseIntFromHex(match[4]),
- format: named ? "name" : "hex8"
- };
- }
- if ((match = matchers.hex6.exec(color))) {
- return {
- r: parseIntFromHex(match[1]),
- g: parseIntFromHex(match[2]),
- b: parseIntFromHex(match[3]),
- format: named ? "name" : "hex"
- };
- }
- if ((match = matchers.hex3.exec(color))) {
- return {
- r: parseIntFromHex(match[1] + '' + match[1]),
- g: parseIntFromHex(match[2] + '' + match[2]),
- b: parseIntFromHex(match[3] + '' + match[3]),
- format: named ? "name" : "hex"
- };
- }
-
- return false;
- }
-
- window.tinycolor = tinycolor;
- })();
-
- $(function () {
- if ($.fn.spectrum.load) {
- $.fn.spectrum.processNativeColorInputs();
- }
- });
-
-});
diff --git a/awesome_theme/static/scss/action_manager.scss b/awesome_theme/static/scss/action_manager.scss
deleted file mode 100644
index 17244e2ee..000000000
--- a/awesome_theme/static/scss/action_manager.scss
+++ /dev/null
@@ -1,19 +0,0 @@
-
-.o_action_manager {
- margin-top: $header_height;
- margin-left: $sidebar_width;
-
- display: flex;
- flex-direction: column;
-
- overflow-y: auto;
- background: #F1F2FA;
-
- transition: margin-left 0.3s ease-in-out 0s, margin-right 0.3s ease-in-out 0s;
-}
-
-@include media-breakpoint-down(sm) {
- .o_action_manager {
- margin-left: 0px;
- }
-}
diff --git a/awesome_theme/static/scss/awesome_form_view.scss b/awesome_theme/static/scss/awesome_form_view.scss
deleted file mode 100644
index eaff00a87..000000000
--- a/awesome_theme/static/scss/awesome_form_view.scss
+++ /dev/null
@@ -1,89 +0,0 @@
-.o_form_view {
-
- .o_field_widget {
- .o_input_dropdown {
- .o_dropdown_arrow {
- display: none;
- position: absolute;
- line-height: 27px;
- top: 0px;
- bottom: 0px;
- left: auto;
- bottom: auto;
- right: 8px;
- color: #c0c4cc;
- font-size: 14px;
- cursor: pointer;
- pointer-events: none;
- -webkit-transition: -webkit-transform .3s;
- transition: -webkit-transform .3s;
- transition: transform .3s;
- transition: transform .3s, -webkit-transform .3s;
- -webkit-transform: rotateZ(180deg);
- transform: rotateZ(180deg);
-
- &.anita_reverse {
- -webkit-transform: rotateZ(0);
- transform: rotateZ(0)
- }
-
- &.dropdown_reverse {
- -webkit-transform: rotateZ(0);
- transform: rotateZ(0)
- }
- }
-
- input:hover + .o_dropdown_arrow, input:focus + .o_dropdown_arrow {
- display: block;
- }
- }
-
- &.o_field_many2manytags {
- overflow: hidden;
- align-items: center;
-
- .o_input_dropdown {
- .o_dropdown_arrow {
- right: 3px;
- }
- }
- }
- }
-}
-
-.o-autocomplete {
- .o_dropdown_arrow {
- display: none;
- position: absolute;
- line-height: 27px;
- top: 0px;
- bottom: 0px;
- left: auto;
- bottom: auto;
- right: 8px;
- color: #c0c4cc;
- font-size: 14px;
- cursor: pointer;
- pointer-events: none;
- -webkit-transition: -webkit-transform .3s;
- transition: -webkit-transform .3s;
- transition: transform .3s;
- transition: transform .3s, -webkit-transform .3s;
- -webkit-transform: rotateZ(180deg);
- transform: rotateZ(180deg);
-
- &.anita_reverse {
- -webkit-transform: rotateZ(0);
- transform: rotateZ(0)
- }
-
- &.dropdown_reverse {
- -webkit-transform: rotateZ(0);
- transform: rotateZ(0)
- }
- }
-
- input:hover + .o_dropdown_arrow, input:focus + .o_dropdown_arrow {
- display: block;
- }
-}
diff --git a/awesome_theme/static/scss/awesome_kanban.scss b/awesome_theme/static/scss/awesome_kanban.scss
deleted file mode 100644
index 92cdfaa2f..000000000
--- a/awesome_theme/static/scss/awesome_kanban.scss
+++ /dev/null
@@ -1,58 +0,0 @@
-
-/* kanban */
-.o_kanban_view {
- .o_kanban_record:focus, .o_kanban_record:focus-within, .o_kanban_quick_create:focus, .o_kanban_quick_create:focus-within {
- -webkit-box-shadow: 1px 1px 1px 0px #6c757d;
- -moz-box-shadow: 1px 1px 1px 0px #6c757d;
- box-shadow: 1px 1px 1px 0px #6c757d;
- z-index: 1;
- outline: none;
- }
-}
-
-.o_kanban_view {
- .o_kanban_record {
- background: #fff;
- position: relative;
- display: inline-block;
- border: 1px #d9d9d9 solid;
- margin: 0 15px 15px 0;
- min-width: 150px;
- margin: 0 0 -1px;
-
- // @include awesome-trainsition-all(.2s);
-
- &:hover {
- box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
- }
- }
-}
-
-.o_kanban_view {
- .oe_kanban_card, .o_kanban_record {
- .o_dropdown_kanban .dropdown-toggle {
- border-radius: 0px;
- }
- }
-
- .o_kanban_record:focus,
- .o_kanban_record:focus-within,
- .o_kanban_quick_create:focus,
- .o_kanban_quick_create:focus-within {
- box-shadow: none;
- -webkit-box-shadow: none;
- }
-
- .oe_kanban_card.oe_kanban_global_click:focus,
- .oe_kanban_card.oe_kanban_global_click:focus-within,
- .oe_kanban_card.oe_kanban_global_click_edit:focus,
- .oe_kanban_card.oe_kanban_global_click_edit:focus-within,
- .o_kanban_record.oe_kanban_global_click:focus,
- .o_kanban_record.oe_kanban_global_click:focus-within,
- .o_kanban_record.oe_kanban_global_click_edit:focus,
- .o_kanban_record.oe_kanban_global_click_edit:focus-within {
- -webkit-box-shadow: none;
- -moz-box-shadow: none;
- box-shadow: none;
- }
-}
diff --git a/awesome_theme/static/scss/awesome_misc.scss b/awesome_theme/static/scss/awesome_misc.scss
deleted file mode 100644
index 9830c3a48..000000000
--- a/awesome_theme/static/scss/awesome_misc.scss
+++ /dev/null
@@ -1,151 +0,0 @@
-
-.o_filter_condition {
- select:not(:first-child) {
- margin-top: 5px;
- }
-}
-
-.row {
- .o_field_widget.o_readonly_modifier {
- padding-top: calc(0.375rem + 1px);
- padding-bottom: calc(0.375rem + 1px - 5px);
- }
-}
-
-.o_list_selection_box {
- margin-right: 5px;
-}
-
-.o_filter_condition {
- select {
- margin-top: 5px;
- }
-}
-
-.o_add_condition {
- i {
- margin-right: 5px;
- }
-}
-
-.o_favorite_menu {
- .custom-checkbox {
- margin-top: 5px;
- }
-}
-
-.awesome_empty_row {
- height: 36px;
-}
-
-.modal-header {
- border-bottom: none !important;
-}
-
-.modal-footer {
- border-top: none !important;
-}
-
-.anita_list_config {
- .iconfont {
- font-family: "iconfont" !important;
- }
-}
-
-.o_field_binary {
- button {
- margin-left: 5px;
- }
-}
-
-.o_input_dropdown {
- .o_dropdown_button {
- display: none !important
- }
-}
-
-.btn-odoo {
- color: #fff;
- border-color: #006fe6;
- background-color: #006fe6;
-}
-
-.btn-outline-primary {
- background-color: transparent;
- background-image: none;
- border-color: #006fe6;
- color: color-yiq(#fff);
-
- &:hover {
- color: #fff;
- border-color: #006fe6;
- background-color: #006fe6;
- }
-}
-
-.o_cp_action_menus {
- > div {
- margin-right: 5px;
- }
-}
-
-.o_field_statusbar > .o_statusbar_status > .o_arrow_button.o_arrow_button_current.disabled {
- background-color: #006fe6;
- color: #FFFFFF;
-}
-
-.o_control_panel .o_cp_bottom_right {
- justify-content: flex-end;
-}
-
-.awesome_header {
- .o_user_menu {
- display: none !important
- }
-}
-
-.akl_multi_tab_container {
- border-bottom: $awesome-border;
-}
-
-.o_mobile_menu_toggle {
- display: none !important;
-}
-
-.o-mail-Chatter-top {
- z-index: 1;
-}
-
-// scroll bar
-::-webkit-scrollbar {
- width: 6px;
- height: 6px;
-}
-
-::-webkit-scrollbar-track {
- background: #FFFFFF;
-}
-
-::-webkit-scrollbar-thumb {
- background: #cdcdcd;
- border-radius: 3px;
-}
-
-::-webkit-scrollbar-thumb:increment,
-::-webkit-scrollbar-thumb:decrement {
- background: #000;
-}
-
-::-webkit-scrollbar-thumb:hover {
- background: #555;
-}
-
-.o-mail-Discuss {
- border-top: none !important;
-}
-
-.akl_multi_tab_container {
- z-index: 3;
-}
-
-
diff --git a/awesome_theme/static/scss/modal.scss b/awesome_theme/static/scss/modal.scss
deleted file mode 100644
index e2c73a84a..000000000
--- a/awesome_theme/static/scss/modal.scss
+++ /dev/null
@@ -1,66 +0,0 @@
-
-// // Title text within header
-// .modal-title {
-// margin-top: 0;
-// }
-
-// // Modal full width
-// .modal-full-width {
-// width: 95%;
-// max-width: none;
-// }
-
-// // Modal Positions
-// .modal-top {
-// margin: 0 auto;
-// }
-
-// // Right Modal
-// .modal-right {
-// position: absolute;
-// right: 0;
-// display: flex;
-// flex-flow: column nowrap;
-// justify-content: center;
-// height: 100%;
-// margin: 0;
-// background-color: $modal-content-bg;
-// align-content: center;
-// transform: translate(25%,0) !important;
-
-// button.btn-close {
-// position: fixed;
-// top: 20px;
-// right: 20px;
-// z-index: 1;
-// }
-// }
-
-// .modal {
-// &.show {
-// .modal-right, .modal-left {
-// transform: translate(0,0) !important;
-// }
-// }
-// }
-
-// // Bottom modal
-// .modal-bottom {
-// display: flex;
-// flex-flow: column nowrap;
-// -ms-flex-pack: end;
-// justify-content: flex-end;
-// height: 100%;
-// margin: 0 auto;
-// align-content: center;
-// }
-
-// // Colored modal header
-// .modal-colored-header {
-// color: $white;
-// border-radius: 0;
-
-// .btn-close {
-// color: $white !important;
-// }
-// }
\ No newline at end of file
diff --git a/awesome_theme/static/scss/variables/variables.scss b/awesome_theme/static/scss/variables/variables.scss
deleted file mode 100644
index c08f87941..000000000
--- a/awesome_theme/static/scss/variables/variables.scss
+++ /dev/null
@@ -1,19 +0,0 @@
-
-// theme vars
-$sidebar_width: 265px;
-$sidebar_sm_width: 64px;
-$header_height: 60px;
-
-// Home menu
-$o-home-menu-container-size: 850px;
-$o-home-menu-app-icon-max-width: 70px;
-
-// awesome
-$sidebar_toggle_one_width: 64px;
-$sidebar_toggle_two_width: 265px;
-
-$o-font-size-base-touch: 12px;
-$custom-file-height: 30px;
-$custom-file-width: 200px;
-
-$awesome-border: 1px solid #dcdfe6;
\ No newline at end of file
diff --git a/awesome_theme/static/src/components/accordion/awesome_accordion.js b/awesome_theme/static/src/components/accordion/awesome_accordion.js
deleted file mode 100644
index 8eca6c984..000000000
--- a/awesome_theme/static/src/components/accordion/awesome_accordion.js
+++ /dev/null
@@ -1,30 +0,0 @@
-/** @odoo-module **/
-
-import { Component, useState } from "@odoo/owl";
-
-export class AwesomeAccordion extends Component {
-
- setup() {
- this.state = useState({
- 'collapse': true
- })
- }
-
- toggleDisplay() {
- this.state.collapse = !this.state.collapse;
- }
-}
-
-AwesomeAccordion.props = {
- title: {
- type: String
- },
- slots: {
- type: Object,
- optional: true,
- },
-};
-
-AwesomeAccordion.template = "awesome_theme.accordion";
-AwesomeAccordion.components = {};
-
diff --git a/awesome_theme/static/src/components/accordion/awesome_accordion.scss b/awesome_theme/static/src/components/accordion/awesome_accordion.scss
deleted file mode 100644
index ee22447e7..000000000
--- a/awesome_theme/static/src/components/accordion/awesome_accordion.scss
+++ /dev/null
@@ -1,56 +0,0 @@
-.awesome_accordion {
-
- display: flex;
- flex-direction: column;
-
- .accordion_button {
- position: relative;
- display: flex;
- align-items: center;
- width: 100%;
- padding: .75rem 1.25rem;
- font-size: 1rem;
- color: #212529;
- text-align: left;
- background-color: #fff;
- border: 0;
- border-radius: 0;
- overflow-anchor: none;
- transition: color .15s ease-in-out, background-color .15s ease-in-out, border-color .15s ease-in-out,box-shadow .15s ease-in-out,border-radius .15s ease;
-
- &::after {
- flex-shrink: 0;
- width: .75rem;
- height: .75rem;
- margin-left: auto;
- content: "";
- background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23212529'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
- background-repeat: no-repeat;
- background-size: .75rem;
- transition: transform .2s ease-in-out;
- }
-
- &:focus {
- outline: 1px dotted;
- }
- }
-
- &.collapsed {
- .accordion-body {
- display: none !important;
- }
- }
-
- &:not(.collapsed) {
- .accordion_button {
- color: #0c63e4;
- background-color: #e7f1ff;
- box-shadow: inset 0 -1px 0 #00000020;
- &::after {
- background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%230c63e4'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
- transform: rotate(-180deg);
- }
- }
- }
-}
-
diff --git a/awesome_theme/static/src/components/accordion/awesome_accordion.xml b/awesome_theme/static/src/components/accordion/awesome_accordion.xml
deleted file mode 100644
index 8e17c0712..000000000
--- a/awesome_theme/static/src/components/accordion/awesome_accordion.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-
-
-