From 511364b1583f9e739b721c4b7803bbdad09efac6 Mon Sep 17 00:00:00 2001 From: AjmalCybro Date: Wed, 20 Dec 2023 16:54:12 +0530 Subject: [PATCH] Dec 20 : [ADD] Initial Commit 'packers_and_movers_management' --- packers_and_movers_management/README.rst | 45 + packers_and_movers_management/__init__.py | 25 + packers_and_movers_management/__manifest__.py | 80 + .../controllers/__init__.py | 22 + .../packers_and_movers_management.py | 112 + .../data/fleet_truck_data.xml | 30 + .../data/goods_type_data.xml | 27 + .../data/ir_sequence_data.xml | 13 + .../data/truck_type_data.xml | 42 + .../data/website_form_data.xml | 24 + .../doc/RELEASE_NOTES.md | 6 + .../models/__init__.py | 27 + .../models/account_move.py | 40 + .../models/fleet_vehicle_model.py | 34 + .../models/goods_type.py | 34 + .../models/res_config_settings.py | 38 + .../models/truck_booking.py | 427 + .../models/truck_type.py | 44 + .../report/__init__.py | 22 + .../report/booking_form_report_templates.xml | 91 + .../report/booking_report_templates.xml | 99 + .../report/booking_report_views.xml | 24 + .../report/form_truck_booking_report.py | 42 + .../security/ir.model.access.csv | 9 + .../security/packers_and_movers_security.xml | 20 + .../static/description/assets/icons/check.png | Bin 0 -> 3676 bytes .../description/assets/icons/chevron.png | Bin 0 -> 310 bytes .../static/description/assets/icons/cogs.png | Bin 0 -> 1377 bytes .../description/assets/icons/consultation.png | Bin 0 -> 1458 bytes .../description/assets/icons/ecom-black.png | Bin 0 -> 576 bytes .../assets/icons/education-black.png | Bin 0 -> 733 bytes .../description/assets/icons/hotel-black.png | Bin 0 -> 911 bytes .../description/assets/icons/license.png | Bin 0 -> 1095 bytes .../description/assets/icons/lifebuoy.png | Bin 0 -> 1199 bytes .../assets/icons/manufacturing-black.png | Bin 0 -> 673 bytes .../description/assets/icons/pos-black.png | Bin 0 -> 878 bytes .../description/assets/icons/puzzle.png | Bin 0 -> 653 bytes .../assets/icons/restaurant-black.png | Bin 0 -> 905 bytes .../assets/icons/service-black.png | Bin 0 -> 839 bytes .../assets/icons/trading-black.png | Bin 0 -> 427 bytes .../description/assets/icons/training.png | Bin 0 -> 627 bytes .../description/assets/icons/update.png | Bin 0 -> 1225 bytes .../static/description/assets/icons/user.png | Bin 0 -> 988 bytes .../description/assets/icons/wrench.png | Bin 0 -> 1205 bytes .../description/assets/misc/categories.png | Bin 0 -> 1532 bytes .../description/assets/misc/check-box.png | Bin 0 -> 1118 bytes .../description/assets/misc/compass.png | Bin 0 -> 1931 bytes .../description/assets/misc/corporate.png | Bin 0 -> 1177 bytes .../assets/misc/customer-support.png | Bin 0 -> 2136 bytes .../description/assets/misc/cybrosys-logo.png | Bin 0 -> 4496 bytes .../description/assets/misc/features.png | Bin 0 -> 589 bytes .../static/description/assets/misc/logo.png | Bin 0 -> 3452 bytes .../description/assets/misc/pictures.png | Bin 0 -> 1692 bytes .../description/assets/misc/pie-chart.png | Bin 0 -> 2338 bytes .../description/assets/misc/right-arrow.png | Bin 0 -> 967 bytes .../static/description/assets/misc/star.png | Bin 0 -> 1642 bytes .../description/assets/misc/support.png | Bin 0 -> 3892 bytes .../description/assets/misc/whatsapp.png | Bin 0 -> 5097 bytes .../static/description/assets/modules/1.png | Bin 0 -> 90143 bytes .../static/description/assets/modules/2.png | Bin 0 -> 58088 bytes .../static/description/assets/modules/3.png | Bin 0 -> 60299 bytes .../static/description/assets/modules/4.png | Bin 0 -> 61770 bytes .../static/description/assets/modules/5.png | Bin 0 -> 61393 bytes .../static/description/assets/modules/6.png | Bin 0 -> 58382 bytes .../description/assets/screenshots/10.png | Bin 0 -> 46112 bytes .../description/assets/screenshots/11.png | Bin 0 -> 45695 bytes .../description/assets/screenshots/12.png | Bin 0 -> 68324 bytes .../description/assets/screenshots/13.png | Bin 0 -> 103483 bytes .../description/assets/screenshots/14.png | Bin 0 -> 51538 bytes .../description/assets/screenshots/2.png | Bin 0 -> 50960 bytes .../description/assets/screenshots/3.png | Bin 0 -> 66349 bytes .../description/assets/screenshots/4.png | Bin 0 -> 55409 bytes .../description/assets/screenshots/5.png | Bin 0 -> 129539 bytes .../description/assets/screenshots/6.png | Bin 0 -> 104344 bytes .../description/assets/screenshots/7.png | Bin 0 -> 66744 bytes .../description/assets/screenshots/9.png | Bin 0 -> 56346 bytes .../description/assets/screenshots/f8.png | Bin 0 -> 80278 bytes .../description/assets/screenshots/hero.gif | Bin 0 -> 244625 bytes .../static/description/banner.png | Bin 0 -> 89094 bytes .../static/description/icon.png | Bin 0 -> 9848 bytes .../static/description/index.html | 614 + .../static/src/css/dashboard.css | 102 + .../static/src/css/website_page.css | 125 + .../static/src/img/loader2.gif | Bin 0 -> 177862 bytes .../static/src/img/order_track.jpg | Bin 0 -> 91031 bytes .../static/src/js/dashboard_action.js | 798 + .../static/src/js/lib/chart_bundle.js | 19287 ++++++++++++++++ .../static/src/js/website_page.js | 57 + .../static/src/scss/style.scss | 237 + .../static/src/xml/dashboard_templates.xml | 312 + .../views/dashboard_views.xml | 12 + .../views/fleet_vehicle_model_views.xml | 69 + .../views/goods_type_views.xml | 50 + .../views/res_config_settings_views.xml | 54 + .../views/truck_booking_views.xml | 125 + .../views/website_page_booking_templates.xml | 168 + .../views/website_page_goods_templates.xml | 39 + .../views/website_page_truck_templates.xml | 59 + .../wizard/__init__.py | 22 + .../wizard/make_truck_booking_pdf.py | 67 + .../wizard/make_truck_booking_pdf_views.xml | 39 + 101 files changed, 23613 insertions(+) create mode 100644 packers_and_movers_management/README.rst create mode 100644 packers_and_movers_management/__init__.py create mode 100644 packers_and_movers_management/__manifest__.py create mode 100644 packers_and_movers_management/controllers/__init__.py create mode 100644 packers_and_movers_management/controllers/packers_and_movers_management.py create mode 100644 packers_and_movers_management/data/fleet_truck_data.xml create mode 100644 packers_and_movers_management/data/goods_type_data.xml create mode 100644 packers_and_movers_management/data/ir_sequence_data.xml create mode 100644 packers_and_movers_management/data/truck_type_data.xml create mode 100644 packers_and_movers_management/data/website_form_data.xml create mode 100644 packers_and_movers_management/doc/RELEASE_NOTES.md create mode 100644 packers_and_movers_management/models/__init__.py create mode 100644 packers_and_movers_management/models/account_move.py create mode 100644 packers_and_movers_management/models/fleet_vehicle_model.py create mode 100644 packers_and_movers_management/models/goods_type.py create mode 100644 packers_and_movers_management/models/res_config_settings.py create mode 100644 packers_and_movers_management/models/truck_booking.py create mode 100644 packers_and_movers_management/models/truck_type.py create mode 100644 packers_and_movers_management/report/__init__.py create mode 100644 packers_and_movers_management/report/booking_form_report_templates.xml create mode 100644 packers_and_movers_management/report/booking_report_templates.xml create mode 100644 packers_and_movers_management/report/booking_report_views.xml create mode 100644 packers_and_movers_management/report/form_truck_booking_report.py create mode 100644 packers_and_movers_management/security/ir.model.access.csv create mode 100644 packers_and_movers_management/security/packers_and_movers_security.xml create mode 100644 packers_and_movers_management/static/description/assets/icons/check.png create mode 100644 packers_and_movers_management/static/description/assets/icons/chevron.png create mode 100644 packers_and_movers_management/static/description/assets/icons/cogs.png create mode 100644 packers_and_movers_management/static/description/assets/icons/consultation.png create mode 100644 packers_and_movers_management/static/description/assets/icons/ecom-black.png create mode 100644 packers_and_movers_management/static/description/assets/icons/education-black.png create mode 100644 packers_and_movers_management/static/description/assets/icons/hotel-black.png create mode 100644 packers_and_movers_management/static/description/assets/icons/license.png create mode 100644 packers_and_movers_management/static/description/assets/icons/lifebuoy.png create mode 100644 packers_and_movers_management/static/description/assets/icons/manufacturing-black.png create mode 100644 packers_and_movers_management/static/description/assets/icons/pos-black.png create mode 100644 packers_and_movers_management/static/description/assets/icons/puzzle.png create mode 100644 packers_and_movers_management/static/description/assets/icons/restaurant-black.png create mode 100644 packers_and_movers_management/static/description/assets/icons/service-black.png create mode 100644 packers_and_movers_management/static/description/assets/icons/trading-black.png create mode 100644 packers_and_movers_management/static/description/assets/icons/training.png create mode 100644 packers_and_movers_management/static/description/assets/icons/update.png create mode 100644 packers_and_movers_management/static/description/assets/icons/user.png create mode 100644 packers_and_movers_management/static/description/assets/icons/wrench.png create mode 100644 packers_and_movers_management/static/description/assets/misc/categories.png create mode 100644 packers_and_movers_management/static/description/assets/misc/check-box.png create mode 100644 packers_and_movers_management/static/description/assets/misc/compass.png create mode 100644 packers_and_movers_management/static/description/assets/misc/corporate.png create mode 100644 packers_and_movers_management/static/description/assets/misc/customer-support.png create mode 100644 packers_and_movers_management/static/description/assets/misc/cybrosys-logo.png create mode 100644 packers_and_movers_management/static/description/assets/misc/features.png create mode 100644 packers_and_movers_management/static/description/assets/misc/logo.png create mode 100644 packers_and_movers_management/static/description/assets/misc/pictures.png create mode 100644 packers_and_movers_management/static/description/assets/misc/pie-chart.png create mode 100644 packers_and_movers_management/static/description/assets/misc/right-arrow.png create mode 100644 packers_and_movers_management/static/description/assets/misc/star.png create mode 100644 packers_and_movers_management/static/description/assets/misc/support.png create mode 100644 packers_and_movers_management/static/description/assets/misc/whatsapp.png create mode 100644 packers_and_movers_management/static/description/assets/modules/1.png create mode 100644 packers_and_movers_management/static/description/assets/modules/2.png create mode 100644 packers_and_movers_management/static/description/assets/modules/3.png create mode 100644 packers_and_movers_management/static/description/assets/modules/4.png create mode 100644 packers_and_movers_management/static/description/assets/modules/5.png create mode 100644 packers_and_movers_management/static/description/assets/modules/6.png create mode 100644 packers_and_movers_management/static/description/assets/screenshots/10.png create mode 100644 packers_and_movers_management/static/description/assets/screenshots/11.png create mode 100644 packers_and_movers_management/static/description/assets/screenshots/12.png create mode 100644 packers_and_movers_management/static/description/assets/screenshots/13.png create mode 100644 packers_and_movers_management/static/description/assets/screenshots/14.png create mode 100644 packers_and_movers_management/static/description/assets/screenshots/2.png create mode 100644 packers_and_movers_management/static/description/assets/screenshots/3.png create mode 100644 packers_and_movers_management/static/description/assets/screenshots/4.png create mode 100644 packers_and_movers_management/static/description/assets/screenshots/5.png create mode 100644 packers_and_movers_management/static/description/assets/screenshots/6.png create mode 100644 packers_and_movers_management/static/description/assets/screenshots/7.png create mode 100644 packers_and_movers_management/static/description/assets/screenshots/9.png create mode 100644 packers_and_movers_management/static/description/assets/screenshots/f8.png create mode 100644 packers_and_movers_management/static/description/assets/screenshots/hero.gif create mode 100644 packers_and_movers_management/static/description/banner.png create mode 100644 packers_and_movers_management/static/description/icon.png create mode 100644 packers_and_movers_management/static/description/index.html create mode 100644 packers_and_movers_management/static/src/css/dashboard.css create mode 100644 packers_and_movers_management/static/src/css/website_page.css create mode 100644 packers_and_movers_management/static/src/img/loader2.gif create mode 100644 packers_and_movers_management/static/src/img/order_track.jpg create mode 100644 packers_and_movers_management/static/src/js/dashboard_action.js create mode 100644 packers_and_movers_management/static/src/js/lib/chart_bundle.js create mode 100644 packers_and_movers_management/static/src/js/website_page.js create mode 100644 packers_and_movers_management/static/src/scss/style.scss create mode 100644 packers_and_movers_management/static/src/xml/dashboard_templates.xml create mode 100644 packers_and_movers_management/views/dashboard_views.xml create mode 100644 packers_and_movers_management/views/fleet_vehicle_model_views.xml create mode 100644 packers_and_movers_management/views/goods_type_views.xml create mode 100644 packers_and_movers_management/views/res_config_settings_views.xml create mode 100644 packers_and_movers_management/views/truck_booking_views.xml create mode 100644 packers_and_movers_management/views/website_page_booking_templates.xml create mode 100644 packers_and_movers_management/views/website_page_goods_templates.xml create mode 100644 packers_and_movers_management/views/website_page_truck_templates.xml create mode 100644 packers_and_movers_management/wizard/__init__.py create mode 100644 packers_and_movers_management/wizard/make_truck_booking_pdf.py create mode 100644 packers_and_movers_management/wizard/make_truck_booking_pdf_views.xml diff --git a/packers_and_movers_management/README.rst b/packers_and_movers_management/README.rst new file mode 100644 index 000000000..a93fe7c85 --- /dev/null +++ b/packers_and_movers_management/README.rst @@ -0,0 +1,45 @@ +.. image:: https://img.shields.io/badge/license-LGPL--3-blue.svg + :target: https://www.gnu.org/licenses/lgpl-3.0-standalone.html + :alt: License: LGPL-3 + +Packers & Movers Management +=========================== +* Packers & Movers Management module helps Users to book the trucks through online. + +Installation +============ + - www.odoo.com/documentation/16.0/setup/install.html + - Install our custom addon + +License +------- +General Public License, Version 3 (LGPL v3). +( https://www.gnu.org/licenses/lgpl-3.0-standalone.html) + +Company +------- +* `Cybrosys Techno Solutions `__ + +Credits +------- +* Developer: (V15) Subina P, Contact: odoo@cybrosys.com + +Contacts +-------- +* Mail Contact : odoo@cybrosys.com + +Bug Tracker +----------- +Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. + +Maintainer +========== +.. image:: https://cybrosys.com/images/logo.png + :target: https://cybrosys.com +This module is maintained by Cybrosys Technologies. + +For support and more information, please visit https://www.cybrosys.com + +Further information +=================== +HTML Description: ``__ diff --git a/packers_and_movers_management/__init__.py b/packers_and_movers_management/__init__.py new file mode 100644 index 000000000..aa115d91d --- /dev/null +++ b/packers_and_movers_management/__init__.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies() +# Author: Subina P (odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# (LGPL v3) along with this program. +# If not, see . +# +############################################################################# +from . import controllers +from . import models +from . import report +from . import wizard diff --git a/packers_and_movers_management/__manifest__.py b/packers_and_movers_management/__manifest__.py new file mode 100644 index 000000000..db9c7c618 --- /dev/null +++ b/packers_and_movers_management/__manifest__.py @@ -0,0 +1,80 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies() +# Author: Subina P (odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# (LGPL v3) along with this program. +# If not, see . +# +############################################################################# +{ + 'name': 'Packers & Movers Management', + 'version': '15.0.1.0.0', + 'category': 'Industries,Website', + 'summary': """Users can reserve trucks online with the help of the Packers + & Movers Management module.""", + 'description': """The Packers & Movers Management module helps Users to + book the trucks through online""", + 'author': 'Cybrosys Techno Solutions', + 'company': 'Cybrosys Techno Solutions', + 'maintainer': 'Cybrosys Techno Solutions', + 'website': "https://www.cybrosys.com", + 'depends': ['website', 'fleet', 'account'], + 'data': [ + 'security/packers_and_movers_security.xml', + 'security/ir.model.access.csv', + 'data/ir_sequence_data.xml', + 'data/website_form_data.xml', + 'data/goods_type_data.xml', + 'data/truck_type_data.xml', + 'data/fleet_truck_data.xml', + 'report/booking_form_report_templates.xml', + 'report/booking_report_templates.xml', + 'report/booking_report_views.xml', + 'views/website_page_booking_templates.xml', + 'views/goods_type_views.xml', + 'views/truck_booking_views.xml', + 'views/website_page_goods_templates.xml', + 'views/website_page_truck_templates.xml', + 'views/fleet_vehicle_model_views.xml', + 'views/res_config_settings_views.xml', + 'views/dashboard_views.xml', + 'wizard/make_truck_booking_pdf_views.xml' + ], + 'assets': { + 'web.assets_frontend': [ + 'packers_and_movers_management/static/src/js/website_page.js', + 'packers_and_movers_management/static/src/css/website_page.css', + ], + 'web.assets_backend': [ + 'packers_and_movers_management/static/src/css/dashboard.css', + 'packers_and_movers_management/static/src/scss/style.scss', + 'packers_and_movers_management/static/src/js/lib/chart_bundle.js', + 'packers_and_movers_management/static/src/js/dashboard_action.js', + ], + 'web.assets_qweb': [ + 'packers_and_movers_management/static/src/xml/' + 'dashboard_templates.xml' + ], + }, + 'external_dependencies': { + 'python': ['geopy'], + }, + 'images': ['static/description/banner.png'], + 'license': 'LGPL-3', + 'installable': True, + 'auto_install': False, + 'application': True, +} diff --git a/packers_and_movers_management/controllers/__init__.py b/packers_and_movers_management/controllers/__init__.py new file mode 100644 index 000000000..654a64cc7 --- /dev/null +++ b/packers_and_movers_management/controllers/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies() +# Author: Subina p (odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# (LGPL v3) along with this program. +# If not, see . +# +############################################################################# +from . import packers_and_movers_management diff --git a/packers_and_movers_management/controllers/packers_and_movers_management.py b/packers_and_movers_management/controllers/packers_and_movers_management.py new file mode 100644 index 000000000..4d1df50bc --- /dev/null +++ b/packers_and_movers_management/controllers/packers_and_movers_management.py @@ -0,0 +1,112 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies() +# Author: Subina P (odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# (LGPL v3) along with this program. +# If not, see . +# +############################################################################# +from math import cos, sin, asin, sqrt, radians +from geopy import Nominatim +from odoo import http +from odoo.http import request + + +class PackersAndMoversManagement(http.Controller): + """Class to add truck booking menu in website""" + + @http.route('/booking', type='http', auth='public', website=True) + def truck_booking(self): + """Function to render truck booking values to XML""" + truck_ids = request.env['fleet.vehicle.model'].sudo().search([('vehicle_type', '=', 'truck')]) + goods_ids = request.env['goods.type'].sudo().search([]) + country_ids = request.env['res.country'].sudo().search([]) + state_ids = request.env['res.country.state'].sudo().search([]) + return http.request.render( + 'packers_and_movers_management.truck_booking_page', + {'truck_ids': truck_ids, + 'goods_ids': goods_ids, + 'state_ids': state_ids, + 'country_ids': country_ids}) + + @http.route('/booking/submit', type='http', auth='public', website=True) + def booking_success_page(self, **post): + """Function to create booking and return to success page""" + existing_partner = request.env['res.partner'].sudo().search( + [('mobile', '=', post.get('mobile_no'))], limit=1) + if existing_partner: + partner_id = existing_partner + else: + partner_id = request.env['res.partner'].sudo().create({ + 'name': post.get('name'), + 'mobile': post.get('mobile_no'), + 'city': post.get('city'), + }) + booking_id = request.env['truck.booking'].sudo().create({ + 'partner_id': partner_id.id, + 'from_location': post.get('pickup_location'), + 'to_location': post.get('drop_location'), + 'truck_id': post.get('truck_type'), + 'date': post.get('date'), + 'goods_type_id': post.get('goods_type'), + 'weight': post.get('weight'), + 'unit': post.get('unit') + }) + return request.render( + 'packers_and_movers_management.truck_booking_success_page', + {'partner_id': partner_id, + 'booking_id': booking_id}) + + @http.route('/goods', type='http', auth='public', website=True) + def goods_type(self): + """Function to return values to xml""" + goods_ids = request.env['goods.type'].sudo().search([]) + return http.request.render('packers_and_movers_management.goods_page', + {'goods_ids': goods_ids}) + + @http.route('/truck', type='http', auth='public', website=True) + def truck_details(self): + """Function to render values to XML""" + truck_type_ids = request.env['truck.type'].sudo().search([]) + return http.request.render('packers_and_movers_management.truck_page', + {'truck_type_ids': truck_type_ids}) + + @http.route('/get_states/', type='json', + auth='public', website=True) + def get_states(self, country): + """Function to get the selected country""" + state_ids = request.env['res.country.state'].sudo().search( + [('country_id', '=', country.id)]) + states_data = [{'id': state.id, 'name': state.name} for state in + state_ids] + return states_data + + @http.route(['/geo//'], type='json', + auth="none", website=False, csrf=False) + def geo_location(self, from_location, to_location): + """Function to Calculate distance between from and to location""" + locator = Nominatim(user_agent="my_distance_app") + from_location = locator.geocode(from_location) + to_location = locator.geocode(to_location) + from_lat = radians(from_location.latitude) + from_long = radians(from_location.longitude) + to_lat = radians(to_location.latitude) + to_long = radians(to_location.longitude) + dist_long = to_long - from_long + dist_lat = to_lat - from_lat + comp = sin(dist_lat / 2) ** 2 + cos(from_lat) * cos(to_lat) * sin( + dist_long / 2) ** 2 + return int(2 * asin(sqrt(comp)) * 6371) diff --git a/packers_and_movers_management/data/fleet_truck_data.xml b/packers_and_movers_management/data/fleet_truck_data.xml new file mode 100644 index 000000000..459fd010c --- /dev/null +++ b/packers_and_movers_management/data/fleet_truck_data.xml @@ -0,0 +1,30 @@ + + + + + + TATA + + + EICHER + + + Tata Ace gold + + truck + + + + Tata Ace EV + + truck + + + + Eicher Pro 3015 + + truck + + + + diff --git a/packers_and_movers_management/data/goods_type_data.xml b/packers_and_movers_management/data/goods_type_data.xml new file mode 100644 index 000000000..924affbd2 --- /dev/null +++ b/packers_and_movers_management/data/goods_type_data.xml @@ -0,0 +1,27 @@ + + + + + + Industrial Machinery + + + Household Goods + + + Healthcare/Pharmacy Products/Medicines + + + Electrical Wires/Cables + + + Scrap + + + Plants + + + Other + + + diff --git a/packers_and_movers_management/data/ir_sequence_data.xml b/packers_and_movers_management/data/ir_sequence_data.xml new file mode 100644 index 000000000..6310fee3d --- /dev/null +++ b/packers_and_movers_management/data/ir_sequence_data.xml @@ -0,0 +1,13 @@ + + + + + + Truck Booking Sequence + truck.booking + TR + 5 + + + + diff --git a/packers_and_movers_management/data/truck_type_data.xml b/packers_and_movers_management/data/truck_type_data.xml new file mode 100644 index 000000000..ef6dd0a30 --- /dev/null +++ b/packers_and_movers_management/data/truck_type_data.xml @@ -0,0 +1,42 @@ + + + + + + TATA ACE + 1 + 850 + kg + 7 + 4.8 + 4.8 + + + TATA 407 + 1.5 + 2.5 + tons + 9 + 5.5 + 5 + + + EICHER 17 FEET + 2.5 + 5 + tons + 17 + 6 + 7 + + + CONTAINER 20 FT + 4 + 6.5 + tons + 20 + 8 + 8 + + + diff --git a/packers_and_movers_management/data/website_form_data.xml b/packers_and_movers_management/data/website_form_data.xml new file mode 100644 index 000000000..2e625fae8 --- /dev/null +++ b/packers_and_movers_management/data/website_form_data.xml @@ -0,0 +1,24 @@ + + + + + + Booking + /booking + + 50 + + + Truck + /truck + + 51 + + + Goods + /goods + + 52 + + + diff --git a/packers_and_movers_management/doc/RELEASE_NOTES.md b/packers_and_movers_management/doc/RELEASE_NOTES.md new file mode 100644 index 000000000..df82098c8 --- /dev/null +++ b/packers_and_movers_management/doc/RELEASE_NOTES.md @@ -0,0 +1,6 @@ +## Module + +#### 01.12.2023 +#### Version 15.0.1.0.0 +#### ADD +- Initial commit for Packers & Movers Management diff --git a/packers_and_movers_management/models/__init__.py b/packers_and_movers_management/models/__init__.py new file mode 100644 index 000000000..e15daf494 --- /dev/null +++ b/packers_and_movers_management/models/__init__.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies() +# Author: Subina p (odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# (LGPL v3) along with this program. +# If not, see . +# +############################################################################# +from . import account_move +from . import fleet_vehicle_model +from . import goods_type +from . import res_config_settings +from . import truck_booking +from . import truck_type diff --git a/packers_and_movers_management/models/account_move.py b/packers_and_movers_management/models/account_move.py new file mode 100644 index 000000000..7d1e09b3e --- /dev/null +++ b/packers_and_movers_management/models/account_move.py @@ -0,0 +1,40 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies() +# Author: Subina p (odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# (LGPL v3) along with this program. +# If not, see . +# +############################################################################# +from odoo import models + + +class AccountMove(models.Model): + """Inherit the class account_move""" + _inherit = 'account.move' + + def action_post(self): + """Super the action_post() to change truck_booking state into invoice""" + res = super(AccountMove, self).action_post() + if self: + booking_id = self.env['truck.booking']\ + .browse(self.env.context.get('active_id')) + amount = sum(self.search([ + ('invoice_origin', '=', booking_id.reference_no), + ('state', '!=', 'cancel')]).mapped('amount_untaxed_signed')) + if booking_id.amount == amount: + booking_id.write({'state': 'invoice'}) + return res diff --git a/packers_and_movers_management/models/fleet_vehicle_model.py b/packers_and_movers_management/models/fleet_vehicle_model.py new file mode 100644 index 000000000..aba5030a3 --- /dev/null +++ b/packers_and_movers_management/models/fleet_vehicle_model.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies() +# Author: Subina P (odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# (LGPL v3) along with this program. +# If not, see . +# +############################################################################# +from odoo import fields, models + + +class FleetVehicleModel(models.Model): + """Inherit fleet.vehicle.model to add a vehicle type""" + _inherit = 'fleet.vehicle.model' + + vehicle_type = fields.Selection(selection_add=[('truck', 'Truck')], + ondelete={'truck': 'cascade'}, + help="Select the type of the vehicle") + truck_type_id = fields.Many2one('truck.type', + string='Truck Type', + required=True, help='Select truck type') diff --git a/packers_and_movers_management/models/goods_type.py b/packers_and_movers_management/models/goods_type.py new file mode 100644 index 000000000..ec2d20d57 --- /dev/null +++ b/packers_and_movers_management/models/goods_type.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies() +# Author: Subina P (odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# (LGPL v3) along with this program. +# If not, see . +# +############################################################################# +from odoo import fields, models + + +class GoodsType(models.Model): + """Class to add goods_type menu in the module""" + _name = 'goods.type' + _description = 'Goods Type' + + name = fields.Char(string='Type', help='Name of the goods') + company_id = fields.Many2one('res.company', string='Company', + default=lambda self: self.env.user.company_id.id, + help='Select the company to which this' + 'record belongs.') diff --git a/packers_and_movers_management/models/res_config_settings.py b/packers_and_movers_management/models/res_config_settings.py new file mode 100644 index 000000000..aac25b4a9 --- /dev/null +++ b/packers_and_movers_management/models/res_config_settings.py @@ -0,0 +1,38 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies() +# Author: Subina P (odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# (LGPL v3) along with this program. +# If not, see . +# +############################################################################# +from odoo import fields, models + + +class ResConfigSettings(models.TransientModel): + """Inherit the model res.config.settings to add distance amount""" + _inherit = 'res.config.settings' + + distance_amount = fields.Float(string='Distance Amount/KM', + config_parameter='packers_and_movers_management.distance_amount', + help="Enter the distance amount/KM") + is_extra = fields.Boolean(string='Apply Extra Amount', + config_parameter='packers_and_movers_management.is_extra', + default=False, + help="Enable, if extra charge want to add") + extra_amount = fields.Float(string='Extra Amount', + config_parameter='packers_and_movers_management.extra_amount', + help='Enter extra amount/KM') diff --git a/packers_and_movers_management/models/truck_booking.py b/packers_and_movers_management/models/truck_booking.py new file mode 100644 index 000000000..63773da7f --- /dev/null +++ b/packers_and_movers_management/models/truck_booking.py @@ -0,0 +1,427 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies() +# Author: Subina P (odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# (LGPL v3) along with this program. +# If not, see . +# +############################################################################# +from math import cos, sin, asin, sqrt, radians +from geopy import Nominatim +from odoo import api, fields, models, _ +from odoo.exceptions import ValidationError + + +class TruckBooking(models.Model): + """Class to add truck_booking menu to view all truck_booking""" + _name = "truck.booking" + _inherit = 'mail.thread', 'mail.activity.mixin' + _description = "Truck Booking" + _rec_name = 'reference_no' + + reference_no = fields.Char(string='Order Reference', readonly=True, + default=lambda self: _('New'), copy=False, + help='Order reference number') + partner_id = fields.Many2one('res.partner', string='Customer', + required=True, help='Customer Name') + company_id = fields.Many2one('res.company', string='Company', + default=lambda self: self.env.user.company_id.id, + help='Select the company to which this record' + 'belongs.') + currency_id = fields.Many2one('res.currency', + related='company_id.currency_id', + help="Currency ") + from_location = fields.Char(string='Pickup City', required=True, + help='Goods source location') + to_location = fields.Char(string='Drop City', required=True, + help='Goods destination location') + distance = fields.Float(string='Distance(KM)', compute='_compute_distance', + store=True, help='Total distance to travel') + truck_id = fields.Many2one('fleet.vehicle.model', + string='Truck Type', + domain=[('vehicle_type', '=', 'truck')], + required=True, help='Select the truck type') + goods_type_id = fields.Many2one('goods.type', + string='Goods Type', + help='Select goods type', required=True) + weight = fields.Integer(string='Weight', help='Total weight of goods') + amount = fields.Float(string='Amount', compute='_compute_amount', + store=True, + help='Total amount is the distance travelled by the' + 'truck') + date = fields.Date(string='Date', help='Delivery date') + unit = fields.Selection(selection=[('kg', 'KG'), ('tons', 'Tons')], + string='Unit', default='kg', help='Select unit') + state = fields.Selection(selection=[('draft', 'Draft'), + ('confirm', 'Confirm'), + ('invoice', 'Invoiced')], + string='State', default="draft", + help="Booking State") + invoice_count = fields.Integer(string="Invoice Count", + compute='_compute_invoice_count', + help='Total invoice count') + invoiced_amount = fields.Float(string='Invoiced amount', + compute='_compute_invoiced_amount', + help='Total invoiced amount') + hide_invoice = fields.Boolean(string='Hide Invoice', + help="To hide create invoice button", + default=False) + + @api.model + def create(self, vals_list): + """Function to create sequence""" + if vals_list.get('reference_no', _('New')) == _('New'): + vals_list['reference_no'] = self.env['ir.sequence'].next_by_code( + 'truck.booking') or _('New') + return super(TruckBooking, self).create(vals_list) + + def action_confirm(self): + """Function to change state to confirm""" + self.write({'state': 'confirm'}) + + @api.depends('from_location', 'to_location') + def _compute_distance(self): + """Function to calculate distance between from and to location""" + for location in self: + # locator = Nominatim(user_agent="myGeocoder") + locator = Nominatim(user_agent="my_distance_app") + from_location = locator.geocode(location.from_location) + to_location = locator.geocode(location.to_location) + if from_location is None or to_location is None: + raise ValidationError(_("Please enter valid city.")) + from_lat = radians(from_location.latitude) + from_long = radians(from_location.longitude) + to_lat = radians(to_location.latitude) + to_long = radians(to_location.longitude) + dist_long = to_long - from_long + dist_lat = to_lat - from_lat + comp = sin(dist_lat / 2) ** 2 + cos(from_lat) * cos(to_lat) * sin(dist_long / 2) ** 2 + location.distance = int(2 * asin(sqrt(comp)) * 6371) + + @api.depends('distance') + def _compute_amount(self): + """Function to calculate amount for booking""" + for record in self: + amount = record.env['ir.config_parameter'].sudo().\ + get_param('packers_and_movers_management.distance_amount') + total = float(amount) * record.distance + is_extra = record.env['ir.config_parameter'].sudo().\ + get_param('packers_and_movers_management.is_extra') + if is_extra: + extra_amount = record.env['ir.config_parameter'].sudo(). \ + get_param('packers_and_movers_management.extra_amount') + total *= float(extra_amount) + record.amount = total + + def action_create_invoice(self): + """Function to create invoice for the booking""" + invoice_id = self.env['account.move'].search( + [('invoice_origin', '=', self.reference_no), + ('state', '=', 'draft')]) + if not invoice_id: + invoice = self.env['account.move'].create([{ + 'move_type': 'out_invoice', + 'partner_id': self.partner_id.id, + 'invoice_origin': self.reference_no, + 'invoice_line_ids': [(0, 0, { + 'name': "{} to {}".format(self.from_location, self.to_location), + 'quantity': 1, + 'price_unit': self.amount - self.invoiced_amount, + 'price_subtotal': self.amount})]}]) + return { + 'name': 'Invoice', + 'view_mode': 'form', + 'res_id': invoice.id, + 'res_model': 'account.move', + 'type': 'ir.actions.act_window', + 'target': 'current', + } + else: + invoice_id.write({'invoice_line_ids': [(0, 0, { + 'name': "{} to {}".format(self.from_location, self.to_location), + 'quantity': 1, + 'price_unit': self.amount - self.invoiced_amount, + 'price_subtotal': self.amount})]}) + return { + 'name': 'Invoice', + 'view_mode': 'form', + 'res_id': invoice_id.id, + 'res_model': 'account.move', + 'type': 'ir.actions.act_window', + 'target': 'current', + } + + def _compute_invoice_count(self): + """Function to count invoice""" + for record in self: + record.invoice_count = self.env['account.move'].\ + search_count([('invoice_origin', '=', self.reference_no)]) + + def _compute_invoiced_amount(self): + """Function to add invoiced amount""" + for record in self: + invoices = record.env['account.move'].search([ + ('invoice_origin', '=', record.reference_no), + ('state', '!=', 'cancel')]) + record.invoiced_amount = sum(invoices.mapped('amount_untaxed_signed')) + record.hide_invoice = sum( + invoices.mapped('amount_untaxed_signed')) == record.amount + + def action_view_invoice(self): + """Smart button to view the Invoices for the truck_booking""" + return { + 'type': 'ir.actions.act_window', + 'name': 'Invoice', + 'view_mode': 'tree,form', + 'res_model': 'account.move', + 'target': 'current', + 'domain': [('invoice_origin', '=', self.reference_no)], + 'context': {"create": False}, + } + + @api.model + def get_total_booking(self): + """Function to get total booking, distance and invoice amount details""" + total_booking = self.env['truck.booking'].search_count([]) + booking_ids = self.env['truck.booking'].search([]) + invoice_ids = self.env['truck.booking'].\ + search([('state', '=', 'invoice')]).mapped('amount') + return {'total_booking': total_booking, + 'total_distance_count': sum(booking_ids.mapped('distance')), + 'total_invoice': sum(invoice_ids), + 'total_amount': sum(booking_ids.mapped('amount'))} + + @api.model + def get_top_truck(self): + """Function to return top truck and customer details query to js""" + self.env.cr.execute('''select fv.name,count(name) + from truck_booking as tb + inner join fleet_vehicle_model as fv on fv.id = tb.truck_id + group by name order by count desc limit 10''') + truck = self.env.cr.dictfetchall() + self.env.cr.execute('''select pr.name,count(name) + from truck_booking as tb + inner join res_partner as pr on pr.id = tb.partner_id + group by name order by count desc limit 10''') + customer = self.env.cr.dictfetchall() + self.env.cr.execute('''select tb.reference_no,pr.name,tb.date from + truck_booking as tb + inner join res_partner as pr on pr.id = tb.partner_id + where tb.date >= '%s' and tb.state = 'invoice' + order by tb.date''' % fields.date.today()) + upcoming = self.env.cr.dictfetchall() + return {'truck': truck, 'customer': customer, 'upcoming': upcoming} + + @api.model + def get_booking_analysis(self): + """Function to return customer details to js for graph view""" + self.env.cr.execute('''select pr.name,sum(tb.amount) + from truck_booking as tb + inner join res_partner as pr on pr.id = tb.partner_id + group by name''') + booking = self.env.cr.dictfetchall() + count = [] + customer = [] + for record in booking: + customer.append(record.get('name')) + count.append(record.get('sum')) + value = {'name': customer, 'count': count} + return value + + @api.model + def get_truck_analysis(self): + """Function to return truck details to js for graph view""" + self.env.cr.execute('''select fv.name,sum(tb.amount) + from truck_booking as tb + inner join fleet_vehicle_model as fv on fv.id = tb.truck_id + group by name''') + booking = self.env.cr.dictfetchall() + count = [] + customer = [] + for record in booking: + customer.append(record.get('name')) + count.append(record.get('sum')) + return {'name': customer, 'count': count} + + @api.model + def get_distance(self): + """Function to return total distance on the basis of customer + and truck""" + self.env.cr.execute('''select pr.name,sum(tb.distance) + from truck_booking as tb + inner join res_partner as pr on pr.id = tb.partner_id + group by name''') + customer = self.env.cr.dictfetchall() + cust_sum = [] + cust = [] + for record in customer: + cust.append(record.get('name')) + cust_sum.append(record.get('sum')) + self.env.cr.execute('''select fv.name,sum(tb.distance) + from truck_booking as tb + inner join fleet_vehicle_model as fv on fv.id = tb.truck_id + group by name''') + + truck = self.env.cr.dictfetchall() + truck_sum = [] + truck_name = [] + for record in truck: + truck_name.append(record.get('name')) + truck_sum.append(record.get('sum')) + return {'cust': cust, 'cust_sum': cust_sum, 'truck_name': truck_name, + 'truck_sum': truck_sum} + + @api.model + def get_weight(self): + """Function to get total weight of the goods""" + self.env.cr.execute('''select pr.name,sum(tb.weight) + from truck_booking as tb + inner join res_partner as pr on pr.id = tb.partner_id + group by name''') + customer = self.env.cr.dictfetchall() + self.env.cr.execute('''select fv.name,sum(tb.weight) + from truck_booking as tb + inner join fleet_vehicle_model as fv on fv.id = tb.truck_id + group by name''') + truck = self.env.cr.dictfetchall() + cust_sum = [] + cust = [] + for record in customer: + cust.append(record.get('name')) + cust_sum.append(record.get('sum')) + truck_sum = [] + truck_name = [] + for record in truck: + truck_name.append(record.get('name')) + truck_sum.append(record.get('sum')) + return {'cust': cust, 'cust_sum': cust_sum, 'truck_name': truck_name, + 'truck_sum': truck_sum} + + @api.model + def get_select_filter(self, option): + """Function to filter data on the bases of the year""" + if option == 'year': + create_date = '''create_date between (now() - interval '1 year') + and now()''' + elif option == 'month': + create_date = '''create_date between (now() - interval '1 months') + and now()''' + elif option == 'week': + create_date = '''create_date between (now() - interval '7 day') + and now()''' + elif option == 'day': + create_date = '''create_date between (now() - interval '1 day') + and now()''' + self.env.cr.execute('''select count(*) from truck_booking + where %s''' % create_date) + booking = self.env.cr.dictfetchall() + self.env.cr.execute('''select sum(distance) from truck_booking + where %s''' % create_date) + distance = self.env.cr.dictfetchall() + self.env.cr.execute('''select sum(amount) from truck_booking + where %s''' % create_date) + amount = self.env.cr.dictfetchall() + self.env.cr.execute('''select sum(amount) from truck_booking + where state = 'invoice' and %s''' % create_date) + invoice = self.env.cr.dictfetchall() + self.env.cr.execute('''select fv.name,count(name) + from truck_booking as tb + inner join fleet_vehicle_model as fv on fv.id = tb.truck_id + where tb.%s + group by name + order by count desc + limit 10''' % create_date) + truck = self.env.cr.dictfetchall() + self.env.cr.execute('''select pr.name,count(name) + from truck_booking as tb + inner join res_partner as pr on pr.id = tb.partner_id + where tb.%s group by name + order by count desc limit 10''' % create_date) + customer = self.env.cr.dictfetchall() + self.env.cr.execute('''select pr.name,sum(tb.amount) from + truck_booking as tb + inner join res_partner as pr on pr.id = tb.partner_id + where tb.%s group by name''' % create_date) + cust_invoice = self.env.cr.dictfetchall() + cust_invoice_name = [] + cust_invoice_sum = [] + for record in cust_invoice: + cust_invoice_name.append(record.get('name')) + cust_invoice_sum.append(record.get('sum')) + self.env.cr.execute('''select fv.name,sum(tb.amount) + from truck_booking as tb + inner join fleet_vehicle_model as fv on fv.id = tb.truck_id + where tb.%s group by name''' % create_date) + truck_invoice = self.env.cr.dictfetchall() + truck_invoice_name = [] + truck_invoice_count = [] + for record in truck_invoice: + truck_invoice_name.append(record.get('name')) + truck_invoice_count.append(record.get('sum')) + self.env.cr.execute('''select pr.name,sum(tb.distance) + from truck_booking as tb + inner join res_partner as pr on pr.id = tb.partner_id + where tb.%s + group by name''' % create_date) + cust_distance = self.env.cr.dictfetchall() + cust_distance_name = [] + cust_distance_count = [] + for record in cust_distance: + cust_distance_name.append(record.get('name')) + cust_distance_count.append(record.get('sum')) + self.env.cr.execute('''select fv.name,sum(tb.distance) + from truck_booking as tb + inner join fleet_vehicle_model as fv on fv.id = tb.truck_id + where tb.%s + group by name''' % create_date) + truck_distance = self.env.cr.dictfetchall() + truck_distance_name = [] + truck_distance_count = [] + for record in truck_distance: + truck_distance_name.append(record.get('name')) + truck_distance_count.append(record.get('sum')) + self.env.cr.execute('''select pr.name,sum(tb.weight) + from truck_booking as tb + inner join res_partner as pr on pr.id = tb.partner_id + where tb.%s group by name''' % create_date) + cust_weight = self.env.cr.dictfetchall() + cust_weight_name = [] + cust_weight_count = [] + for record in cust_weight: + cust_weight_name.append(record.get('name')) + cust_weight_count.append(record.get('sum')) + self.env.cr.execute('''select fv.name,sum(tb.weight) + from truck_booking as tb + inner join fleet_vehicle_model as fv on fv.id = tb.truck_id + where tb.%s group by name''' % create_date) + truck_weight = self.env.cr.dictfetchall() + truck_weight_name = [] + truck_weight_count = [] + for record in truck_weight: + truck_weight_name.append(record.get('name')) + truck_weight_count.append(record.get('sum')) + return {'booking': booking, 'distance': distance, 'amount': amount, + 'invoice': invoice, 'truck': truck, 'customer': customer, + 'cust_invoice_name': cust_invoice_name, 'cust_invoice_sum': + cust_invoice_sum, 'truck_invoice_name': truck_invoice_name, + 'truck_invoice_count': truck_invoice_count, + 'cust_distance_name': + cust_distance_name, 'cust_distance_count': cust_distance_count, + 'truck_distance_name': truck_distance_name, + 'truck_distance_count': truck_distance_count, + 'cust_weight_name': cust_weight_name, 'cust_weight_count': + cust_weight_count, 'truck_weight_name': truck_weight_name, + 'truck_weight_count': truck_weight_count} diff --git a/packers_and_movers_management/models/truck_type.py b/packers_and_movers_management/models/truck_type.py new file mode 100644 index 000000000..88eae2bf9 --- /dev/null +++ b/packers_and_movers_management/models/truck_type.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies() +# Author: Subina P (odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# (LGPL v3) along with this program. +# If not, see . +# +############################################################################# +from odoo import fields, models + + +class TruckType(models.Model): + """Add new menu truck_type model in the fleet model to select truck type""" + _name = 'truck.type' + _description = 'Truck Type' + + name = fields.Char(string='Truck Type', required=True, + help='Truck type name') + length = fields.Float(string='Length', help='Length of the container') + width = fields.Float(string='Width', help='Width of the container') + height = fields.Float(string='Height', help='Height of the container') + capacity = fields.Float(string='House Hold Capacity', required=True, + help='Suitable for house size') + weight = fields.Float(string='Max Weight', required=True, + help='Max Load of container') + company_id = fields.Many2one('res.company', string='Company', + default=lambda self: self.env.user.company_id.id, + help='Select the company to which this record' + 'belongs.') + unit = fields.Selection(selection=[('kg', 'KG'), ('tons', 'Tons')], + default='kg', help='Select unit', string="Unit") diff --git a/packers_and_movers_management/report/__init__.py b/packers_and_movers_management/report/__init__.py new file mode 100644 index 000000000..fa36b8b67 --- /dev/null +++ b/packers_and_movers_management/report/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies() +# Author: Subina P (odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# (LGPL v3) along with this program. +# If not, see . +# +############################################################################# +from . import form_truck_booking_report diff --git a/packers_and_movers_management/report/booking_form_report_templates.xml b/packers_and_movers_management/report/booking_form_report_templates.xml new file mode 100644 index 000000000..6eca4024f --- /dev/null +++ b/packers_and_movers_management/report/booking_form_report_templates.xml @@ -0,0 +1,91 @@ + + + + + diff --git a/packers_and_movers_management/report/booking_report_templates.xml b/packers_and_movers_management/report/booking_report_templates.xml new file mode 100644 index 000000000..d998a282b --- /dev/null +++ b/packers_and_movers_management/report/booking_report_templates.xml @@ -0,0 +1,99 @@ + + + + + diff --git a/packers_and_movers_management/report/booking_report_views.xml b/packers_and_movers_management/report/booking_report_views.xml new file mode 100644 index 000000000..dc802331e --- /dev/null +++ b/packers_and_movers_management/report/booking_report_views.xml @@ -0,0 +1,24 @@ + + + + + Truck Booking + make.truck.booking.pdf + qweb-pdf + packers_and_movers_management.report_truck_booking + packers_and_movers_management.report_truck_booking + + + Truck Booking + truck.booking + qweb-pdf + + report.packers_and_movers_management.form_truck_booking_report + + + report.packers_and_movers_management.form_truck_booking_report + + + report + + diff --git a/packers_and_movers_management/report/form_truck_booking_report.py b/packers_and_movers_management/report/form_truck_booking_report.py new file mode 100644 index 000000000..7ac287f1e --- /dev/null +++ b/packers_and_movers_management/report/form_truck_booking_report.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies() +# Author: Subina P (odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# (LGPL v3) along with this program. +# If not, see . +# +############################################################################# +from odoo import api, models + + +class FormTruckBookingReport(models.AbstractModel): + """Class is used to print pdf report for the truck_booking module + form view""" + _name = 'report.packers_and_movers_management.form_truck_booking_report' + + @api.model + def _get_report_values(self, docids, data=None): + """Function to return values for the report, + docids: it will provide the current id the model""" + query = """select tb.reference_no,pr.name,fv.name as truck,gt.name as goods,tb.from_location,tb.to_location, + tb.distance,tb.weight,tb.unit,amount,tb.date,tb.state from truck_booking as tb + inner join res_partner as pr on pr.id = tb.partner_id + inner join fleet_vehicle_model as fv on fv.id = tb.truck_id + inner join goods_type as gt on gt.id = tb.goods_type_id + where tb.id = %d""" % docids + self.env.cr.execute(query) + report = self.env.cr.dictfetchall() + return {'doc_ids': docids, 'report': report} diff --git a/packers_and_movers_management/security/ir.model.access.csv b/packers_and_movers_management/security/ir.model.access.csv new file mode 100644 index 000000000..2a1eee20f --- /dev/null +++ b/packers_and_movers_management/security/ir.model.access.csv @@ -0,0 +1,9 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_goods_type,access.goods.type,model_goods_type,fleet.fleet_group_user,1,0,0,0 +access_truck_booking,access.truck.booking,model_truck_booking,fleet.fleet_group_user,1,0,0,0 +access_truck_type,access.truck.type,model_truck_type,fleet.fleet_group_user,1,0,0,0 +access_make_truck_booking_pdf_user,access.make.truck.booking.pdf.user,model_make_truck_booking_pdf,fleet.fleet_group_user,1,0,0,0 +access_goods_type,access.goods.type,model_goods_type,fleet.fleet_group_manager,1,1,1,1 +access_truck_booking,access.truck.booking,model_truck_booking,fleet.fleet_group_manager,1,1,1,1 +access_truck_type,access.truck.type,model_truck_type,fleet.fleet_group_manager,1,1,1,1 +access_make_truck_booking_pdf_manager,access.make.truck.booking.pdf.manager,model_make_truck_booking_pdf,fleet.fleet_group_manager,1,1,1,1 diff --git a/packers_and_movers_management/security/packers_and_movers_security.xml b/packers_and_movers_management/security/packers_and_movers_security.xml new file mode 100644 index 000000000..31815cfc5 --- /dev/null +++ b/packers_and_movers_management/security/packers_and_movers_security.xml @@ -0,0 +1,20 @@ + + + + + Truck Booking multi company rule + + ['|',('company_id','=',False),('company_id', 'in', company_ids)] + + + Goods Type multi company rule + + ['|',('company_id','=',False),('company_id', 'in', company_ids)] + + + Truck Type multi company rule + + ['|',('company_id','=',False),('company_id', 'in', company_ids)] + + + diff --git a/packers_and_movers_management/static/description/assets/icons/check.png b/packers_and_movers_management/static/description/assets/icons/check.png new file mode 100644 index 0000000000000000000000000000000000000000..c8e85f51d612c626d167e4def7bccdbe1d6d17bd GIT binary patch literal 3676 zcmcgvdsGuw8jpg4iY%zK;)6~HwPkUVnaO)JDiRS~W01#+Tdm%CgiJ{?ab|#k+GElB zs)m`Fq^5i_*c#09+YQPFKr}nwM5Uo-TAL;V~rhtuFtx>&0g#C#25Hk&m#sUb-WA~31MBLg4ikrG=iSUHIid9Tb1 z9z?MSXrWNHppa=`3T|)6tVasU1O?OhfLBAPab-$=Aj^bs-a^skcg`{z&c(Sok1Rnf z5yC>1Y_<@*U9)a?2rbEDiXfxl+}cG;IVE0Blf_9wp~!G!ilE2DR$`Kz#XXhg1%^X- zXt38Q$b#e)IuIe${frbc@94mx((??I^YI-(m7WmPOQnh&kOeVE5L~UXliA7*Aqh2! zygrHdutKqvq)a?GfU^Rbv!F1L2n;u3q&9~jDV>4R8gLYj5g8$Gdf5;PM8e91VHO}tH2a0L8XijPj4WT@OfXUAT zJnhf*@K9tDMU;r4{0y>T@q!c#dc9U3Y|rFt)F2wJDdXk4$u2;9M#3=B({jWE?ZT8AH% zg#Ynm7{OD-iERSQ3q%07QcjdCs6!Oo2=IDcJmb$VO_7HU?ogqWL}USZT7WtfjpanX zO$@a45~6_o7yUgq;$EyC{@)i#qZ|N_R=_bJvw}bMOMXYUaeIWvk1PbW5LY2pwz5%~)8GxdCY^PssXRx5eoz zoO^~fem~r``@rOd6TkZU8il$gE8}Oz-;cgl{mIK`Pdv;QZ%-|s z|GM{J*isd7WKnONICtpgNp#AiUeQbceyF&&T9d++kK5LH+xFP3BM=)2;)S)A$sTiU6of)b*Y#j{o#0g@7kQ@$&^?Xwd#C) z*?`OMhxblls7-52Hx9e<G~?b~~OYW?LWQyXXH zri{BfJ2omM>(N5CCh8@jy!2dILd_cwrrn5}-u1H`e?0w$}WEW5P9XVW2;W}-E(N#mKb@>!_?9;7EcMc z{$}01S5Kra9GY1>s2abs9zQ>M^!2#Wa|ZgdtCP$7HxD_{=b{ky&9Q_CH6!ldap(T* zf}8Jcd_*M`3GY@f|5wb3WaRUu4KwLk^ZH)Cx@g9Gqrd$0VaEMIzioWH^;l}xdpp8T z8}{xXW=4I#;LY(#$DH;dANHu-yZ<(gnNzG17ONUnb$vS3 zb*fD2Tp8xe4);ae*%)~z`kF2F+Q6#SXw|Se#$N^e?zR2i*OIq99+Iy7|H~LN!Mc6) H^s@f|!zCx= literal 0 HcmV?d00001 diff --git a/packers_and_movers_management/static/description/assets/icons/chevron.png b/packers_and_movers_management/static/description/assets/icons/chevron.png new file mode 100644 index 0000000000000000000000000000000000000000..2089293d6ad94cfc015cc0a8c07bb03efd4a689e GIT binary patch literal 310 zcmV-60m=S}P)fLA$g5CzAh99{FF(tp zz^tD4))$4c^0SZV9_X~njUYum@4i`~v!i=obU%PG(6q`OMK>{HG>r}*tHKc2@w+qg z7|l>B76qkX(U2E&K_1Nf!JbCtpGzwGSJ~CkU>QcDY&q>lnbwQm<|2>>iH5vL6qJIP zp;W{K-Snrb@Z2gLMVZAQQ5jU>DXT)0mtk@hpq-Sb{2q6{0V4Z;tNXT3P5=M^07*qo IM6N<$f_?6Y+W-In literal 0 HcmV?d00001 diff --git a/packers_and_movers_management/static/description/assets/icons/cogs.png b/packers_and_movers_management/static/description/assets/icons/cogs.png new file mode 100644 index 0000000000000000000000000000000000000000..95d0bad62cf22361b148e1d6cefe2ceab605955d GIT binary patch literal 1377 zcmV-n1)lneP)lH5n~Zj$eiG;8wLI!*reT1_VfljL=sA}=JrOptsX2RfC&)+l61t|6JPeb$mZ z6v1wNClWXiLSlOh+mR64U7bjvhva*zJ0HRRaDbgl@(q$*^PYf*$fE&7)c&&!Rfm?&yLyFbQ?2&R6W6v@rWu!;bZU9|_! z4Je^Q5$r!vH2{)*ok-wK1%Wz7TG;LgvHhtN39JtxLC&_yAzs|bhFaWtFLrukMR}l_ zP~>z0rF26#(W+H@aXx?6lf(f454Uv()R+QrlZafX3t}g5wp6-Blj;u$XaE#h->+xC z005Fp0GtMpYoBiuo)VG0UP0_GltOix%1(%-bKgbA0o1pB3&6VoRs+}%fFWUi1MmQV zmjH~{WZwYT7ng4njIz1iD4PuYIM&NvU6NVO4kNuj`IZ(nzL#XTM^~@uFGT>-aT6dh zAgaP68%9MDu}+cu7uohT0RHqW9d8lhD-kJqd^i9;Rw)OT!X*D$Y?MvID9;=%I@23T z$~m4}V3f^0BG}d<_%@?#emG&81LI_NvTQ!T$gzGzil=|K?VCM%e*mZ`d`!0R--N(> zX_T!|fX{f;z6ZDfz>JL{bFu7UqLI0BExN7c!HmOYg;$V?QB4==-_|4!R<1p=W!b zXM0?cbrc+q5buUe#ZpdV?VzCxk-Rm+);3(wb8q`(#{e8FI_3z8RwJLQk>}&nRHK0| zNhvzkFo4$qbT=sr4i@y>Bdr`7j(HfwmH^uc7xH9%r%nnDB_ty3>&opGxGMoP9kf;< zd%_$N;{SC3V62>WZcCaxpx6frT|FlOj5R5zGbh3vrqY>j1H`{Bkt_d-PcIzGcOeS& z0OimpMB04AZ5M$FkksHx)9_uX*rDTKrDER^Aij2r>}i8vD4G(OFwKFYV|^yVP5w23 z`asH~GaMjZ={ojt!?Lb#lcy352^1ZBLpqIV|5 zLfz5N09ce%03XI(J-h5`5#>QuTr`wWt<}xj9|=Odm?U{1pyiQF6&>pYfaOUB0`PfX zSMHvKeKvO?5vfw7-bq{v4vAnDh^?3%L|Q@w6Pmd9iD(;0IfB{ww?bB5NS1mno@&9c zXC4%!P8Bklxq~Ew%%g071mXR`&iMY{dhWR!JtLt}njRD_-Cxi%N0X&qj~Nq_rI}Yn za8e0TJ(H#J00000NkvXXu0mjfE=YKA literal 0 HcmV?d00001 diff --git a/packers_and_movers_management/static/description/assets/icons/consultation.png b/packers_and_movers_management/static/description/assets/icons/consultation.png new file mode 100644 index 0000000000000000000000000000000000000000..8319d4baa09d6afac9362dff318f63a0f96f555e GIT binary patch literal 1458 zcmV;j1x@;iP)fo-7eN@Nx;}%h)9e^5-C?E zsEH&b3Z#%2B-}L7v^LRRD&QZ8A<7MshM0yxF7rU)x4)gW;*vW;3 z#hX3&)M|C@Hzy`0dbVF71Cp#6E*?;(1E5ZgN|t#IpsRseZTS;fmL2OZ%G1F2%+iN5 z?1unK-3Ni+4&6W$B|ic7=Z$mSG;E8PyRX^_00(R zZhUjoBfjtdy_aS#1FePDP8??a5dOFCh z*MWRv)G@zc9y@oAQ6L5)gF{}MFZh1tt%7=2kn>q6`mgJDye)VpNyeX>nXy(;k)8%5c~P{u8)+YKOVK2Ka7pM_X}a`O zk#~c24MYp^y)u3b+*+!2>R#%t}=?wy_< zpYKn-%7CQNC`x``VuKC^f_Kx@zC4JDHDk0HCO^O4#RC{@^;{j6<{9 literal 0 HcmV?d00001 diff --git a/packers_and_movers_management/static/description/assets/icons/ecom-black.png b/packers_and_movers_management/static/description/assets/icons/ecom-black.png new file mode 100644 index 0000000000000000000000000000000000000000..a9385ff13f696e96d517a56ce2b2ff7d282c748a GIT binary patch literal 576 zcmV-G0>Ax5}Z)a!cc0ra5uqqg5lnhXD zTbP_`oKdQ!!sJxrjN&KdC#M>hn6H53Z@_@W06J)|I<5r7bODP7TpFfK@D$$y9ro1J z_#n7|3NU9+Eg3t67i6kk1G7mAm}&y~>LPq;59$DNz9rz_PKFAe2JQYcbvs+lNHw^F+;#7cCP*z(AJ2&$C0H1W+ddn*~CoC?@7snGmV!9 z<==r}6|tyA>`?)>6k{b=2d<=(_5rWxzxsKgUs~Q{+du)!y5s>SG|Pu>T2kaR7OcV&-NYURtom{p?~^a9V+ z7O-a3C?=EC%HIJ!R*hUb72^tZzf-`AuuDDSkJJnF?!xs=oN3JbnbTGPz&Os^S>dl1 z(84w;APbb-b_k@KC|~4YkNmz@^KPH*e34{*2J>2yF9_24A}NIoShST-^{Ye_(vLmm zd~pgm3F$kIkw;g)NYXe9tbV#5fWaonr$h>8ffe1h+u&f*`C7F2cl-b`l5Ye!`u+O= O0000##3Xw+{I#MbTYoZ-I?3FUBiCh!QRfyd*8S0 zzBhAFP*6~?-lzdrfLY+Hwprk^9?LDGz;$2=SdFk>z#U*LBaI?QQKD9e7VcUbxCb21 zK<^(;Xc0+8N7+;0G_au`qDwm1ixh;r_7XS;lzSn3Ks%r7fpFK}0T+SIX$T+G&OY=( zxNCJ_5*Q8nGpO{QD=gKm=?w>jvsI4EeCbfxmVgL)==l)8DLS{4AE!e?Z8#kPQdt|>qP=~ z0Jlc(3Gg?f*M1lL)`j_1YkWB%UdQh2b66h*ZnCzsy7n_B0ckvzW`}^r+Q1XwyiR6N z+Zb>`kF^u{kzSF3ZWCxE2%MHJ3h_5t<4fjdNthVL50AOsk~o%60t*2`LXkdVyV0$h z3!el&2Fvm1lW@sw^on`m-Vx`wwB6`P4R}rO zE6^)ow-A5YnfJ&y0Ye!WLUqzpz$M^$fY4`p?Mdxxh|Yg2?gAd7ipc|DXJ`UZ90Kkq z5IzMQOgng*oJH-CT;UDiOoqC=IL6w|-va-Bgt_N1s&c*2*98Ry1?!OCgV~htO4sqyP_dDm_d+wti*Wu|Jegr#e_!#{@68vYp!)bLlu6Zk`LG>4b) zEtVJfV|c&7EyFk1UEqgt9*;Njw1VZ>g|{(-Ih??2*p8dxr0-%j^2hNC#&IhqaU^nc z@$+Ql#-r}>$jwGuyQA&xajp}QpNYQgQvRX3un9j@9GJrg7>xWw!mm^1U#(2=6#lMo z|KQokEyJGV*$a3$^4H^V!vBQLO`Y#xXJTY1;rCX!>CE#}6@DtiPgnT82{)9?y|d)x z(wYD^;79DoMQqIQU*HgKi6iBw;@FUI9sNVmM#^uDbMB8mr2J(psR`f_e2lfYQ^?Pc zD*O(-j!VKyGmVpx8^nFlK|*>Q!@2nVHmt#iLfSnlYCO2 zdFMZq-%%fsUm+%4DcBAM@nlB#OJUtlu?=@5vKyk0-(~c{nEb2TSI|FD&|jC)U02XO zP_VtPpg&ess@n%zfz}7m^l)@9-pa_g6!iB9hqNkI7IY^HwJpfkw1vjiEIS#Wpt0?`HcKIp}DC=(*S1hNk)FAp#M3(Ph`2hp<^Rwd!~tF ztxuuW2aq1-#_&}}?@!(9I-!5fU3;7r`rs;-;>L{bUqXMKVkK5&4iq?1871GE)(+iE(2hg+zdgWT>s_5?n3yszX(6k07r<#7z+xi};Iw>y+AElqG*-EPDTmCjr_EtL l9oc+vR{1Wfk3Rkj{so);rk=IPI$i((002ovPDHLkV1j5u&D{V1 literal 0 HcmV?d00001 diff --git a/packers_and_movers_management/static/description/assets/icons/license.png b/packers_and_movers_management/static/description/assets/icons/license.png new file mode 100644 index 0000000000000000000000000000000000000000..a5869797ecaa7583c552c3bb7c9bce5910df78e0 GIT binary patch literal 1095 zcmV-N1i1T&P)?DLX z+1Y*BO%2WWvTu05Ki}`p`@J{sJ=nx1)&%L)P@|a%i#deKSU(9Ndee~mRtn|o9hqkt zsH)g_?j-1Oz*{rH&X9nd_6n5~S%#SclCXXhkhBHYOR<={+%T9HHm_+Rj=iH!?az_sX`LfziH+4|52SPxCd(lFQ#& zy}6O4ybXVUJ6qGPGqH9kZO+TqO1)ZNXdyA~iK zjU@8F177OZcQq)~$=N9vU#B7D6{_#K`1J!DzKA!x0H-08MD^1m@!Cu1^1Ay68A9JiW%_ zS;VTfBGKSzreWdMUn09>mmHnKrHDNn2a^cnnZ|MXDzMjuSf_9uLfT_HXSmEliE3?k zXG5qm?Zm1JIMsm2cnJK_V=hkE@UzgSfJcoDFQBI%WSu~xnTe+6cI1o%43w{m$eK<( z*6j^w>_69x>X$9vq!B%D)n2i2Fx3eCH`fw(T?A+}`>a(i3QK#4M*6$U2tPE#;4RnK z>mxwS8DJZNZzlfX70^76^jmNLyX*lJ7YEWlH{ zcu!SGBHwAI5D}|zA|-av#xj{i{y7^5SAdUFv(H6FZ!P*Haqu>f2gqsj_qOq~2-w*F zS(Vp;I|v^e^)8@E=esPmmg4ZVjs4>wpR8c|FGJSOYN$8)|IM@rI3xAI#QT>#L{?m_|*Crlo{0DLwqmu7G?&JUf N002ovPDHLkV1nf|8?OKW literal 0 HcmV?d00001 diff --git a/packers_and_movers_management/static/description/assets/icons/lifebuoy.png b/packers_and_movers_management/static/description/assets/icons/lifebuoy.png new file mode 100644 index 0000000000000000000000000000000000000000..658d56cccfbc0e46060ad4850b9fc60c656baf18 GIT binary patch literal 1199 zcmV;g1W@~lP)K~!jg?OD%n8$}d;Z#;H3_Ux`{Y$>IOhC`GK2Z&mUBGl%91P8y|S)kfJ7y@Fv(h8fJTCuS1y-dl~V3Bn@u?h-V-e;5wUK!dy#X#2mo{Oe@Ws202*N! zUYebq1*Oz(7=|0J>pn(AT~tHi06fpT5Cp+8=UfzYF~>QdlTyCudEUcDqp?-Q3ClZy zh`8_jS1ilAN<>A)|0jSkVOiEy-}kQ++2pw<5YcQ91S^cOdS0R|Fvb>wAgB}3_lVdx zo@Z(pi+`PnCN6%2qaJh2n$9r_fQWby1S^wxWem84@B1sJuai*#Qp(HIeDX(8DwXO| z%F8CUnE~{Az4MH*g_Fz52gcZf=Xn=0?a~H`hylQ*oZNq<_}k0ls8Xpc6H#iiO$}f$ z7+lQz-Xr3jB4gvg7!%!YH+A(>1Bjw%(UgpcwAQ*+tJSUpz&ZeoCZ;U_SQA3r;GDOJ z$T;)HSw0bo%R@wVuh)CagoKDRBK{zR*fFtJO3f3|HAFNzMEd>yw@I~AqJ#bY{dp7T z002bv$W%N4fDmGbh<-J-uT(0DT8^y%5pku|M*#3XBv+M(*h9qcYPH&RL>!t5ih0Vt zUhhjHdIJES%P?;Pz-K~;bwmtD2ac^kEdHi}cmRNNMD(sw>ZYmi5uOi;=pD!w4*<{v zfK{c`>d}E?De;q!JM+w*2G6)Xkk{#{&dFU)|KBh!fb9Z)o)nlf5uR}Y zd|trusm)0`Mppsg1Ndk6r(q8O?g$}n6g)=1h>y{88Rl&O_*4k-$x*rHnJTQfhuU9KK{~ ze{gV+s3kFgxc1mJAwWb%MAv-ZUm~J%N@uP-7z~#3)Ik8So7O{0t+hLy&I_FLR}6^` z@phbH$Kh*4{3egHFbsdG*XzG0ji){Z*L5FjtyLbvcvB|f%{;ykQM#_XnP!t303zyA zsq`QZDWumnCUwuh==b}N5RuYsGT*~mt@c!Fo%$4}0j>3>Nw>~uBiXinKZ>Hx$z_=# zilR=d)w*wDYuue4X>6r_BNNeAsf38{WsIw8wR+FAJ7-+XA!5H;t=^mFN<>lA$s-;h zXEln5eaCU`PGe7Ktv4OVxtm8kK!NspT#NkddEOtDN@bZbcA|D8B1!;w=r~T1>a_U% zK%>#vBBJeXx4STU!I1-p7aW^eM`ao&dc|bh_WW=-{0Wl3r~lMizvej3Q$);_Ad@h$ zFS2H{DJ{#|0D#*mX186}-I$d4sUW^)U5g92(PHl7XX2Xm3}<-8@HhS0PsfeRnq&X~ N002ovPDHLkV1i;vH)8+* literal 0 HcmV?d00001 diff --git a/packers_and_movers_management/static/description/assets/icons/manufacturing-black.png b/packers_and_movers_management/static/description/assets/icons/manufacturing-black.png new file mode 100644 index 0000000000000000000000000000000000000000..697eb0e9f2c06e40c9c720df7b80b8f6fac63b34 GIT binary patch literal 673 zcmV;S0$%-zP)xK~!jg?U=D^6hRope;$f(2!dRQAe>DQQeT=B*H{T+6R=CPGo?i; zwb3GCV`G=p7B(h-MB0d*S1Kujl2}+MniNSfJM7zGW^Qgb$r_ypLnbqCci)@+?wfB1 zGBPqU+Qfwk`Okp9XM78I>x?Y|Ll1WcSarsR1>c9|Nd%6=HgM!=YaZ@efV=JCJ_>M; z#tG_7>fmofHqbV*fwqwi6!_g1x2b_In2ly7f%_eJ0o+aC9sujWOnqs7*p2KnX7jli z;o6OCA9xO2jd1No_NTb+#z~0v;T`Z0zwl|`n*9F~cmiDUaJy7Xk_W&W{K7lHtvX^; z(Zj6p4`48cdl|FZyT#uaI>0^PBmPpQF;uv%TS5j@xaEcnsPI^=RU1CxAp>3Du_HWW zz$g4f4a9`I24ccp10CQ#@F~J=WS|GU0)9pwVB0W3xNXY`!W$Ww23{u$x9zmJwG4zl zNZM#Y1GyGz8>t31fw`hBIdgN;Ml!xCHr9#=MoC1iB|&YhBqA8G zu?X7OSOnBURJ8DgX)FXmEY-qi6Qc+|;sZf^#TXGy#8}J>ckeKJckY?{hP0VaJzj0X8RhK^60Y~Xz{&a9?$@^ z`*!wmV5Zy_F}!tF1}J$Bj0DI7)BwvuZXk8w60j{qaRkSJJyKzx5OU#xRG|a+LWHFb zOd6COC^gCslp0b8n(}BvP?neGfxW0~`7uN}P!H_L!mj|jfWyE~sgms!uaGmXN9#VL z&o{&wH`(XFRQ($pDUuL+1@xib4Gb0l2lVkR;3DeD8LS7k>f__UV1%mzx>4a$5ZEDf zFs9!N;)lCQb0feM2j7i5gwE^pjd8|FLg;tGbr&DyCbIB3L*hWI<61T88h);WH`i)_ z#w>i!kj#Nyz$P-ET7zx?XMsbOOtb!-1`Gk8B3ufXFR%lU=Ye?%_gs{PuhlItkT`G~ z*iYsNGy_*qE6PdWv?bF996`l@7wT=!Aca~OHVbSKIdC1d{b6GWSPEPQ9$MUMlmo*+ zzeDyaLI);$B1?p11lFKJCR&>;B)yV!00U$$m*(l#18adt5v~eYC$PgCrL2V#6Pa`s z8YOcQ*O0DT0KSqr0(GRrbsYE};VKANl_YcE0xA?5BdrDarup5doDk*PG&c?`vA8VaO=C>m4%I|X)lqm$yVLT0P+oIdY}GtOrO29vww9VSooqbBNnh zcu(I|YQ)0zb`*zp)aRe-TomMhG1NxyHQX;fPUPZ16kAXwMG|^ZYrnxPV4v0J8EW^T zsOZBl9Hv`x%N>1ggc$PASEFSIN{zAurN)2jfOsd(fgd5lQU?Y?lv>E=CtGh+0(VGG zWW%UGZ@o!Njc1h3(oB}@JmzAS!6!o=#PN)%o0h~rfH{E-AX#fBK07*qoM6N<$ Eg49ZXX8-^I literal 0 HcmV?d00001 diff --git a/packers_and_movers_management/static/description/assets/icons/puzzle.png b/packers_and_movers_management/static/description/assets/icons/puzzle.png new file mode 100644 index 0000000000000000000000000000000000000000..65cf854e7ea72e36142ffc1a407bf2b8355cc85c GIT binary patch literal 653 zcmV;80&@L{P)9a`;n_Do>R91)@YfrZ;WIBYI)WE@w%y z7IC%30~nX`B(&|Bi6!}ZGuBf8IAM^ zQA&SX2=P2@*<+`kI7+k$-1A&gaYV-{Ks?g2#0TH?II!as;HNYK-X1sS_e0Z#CLzvF_5wZZ}7k)9y#mQhdC00000NkvXXu0mjfog*sX literal 0 HcmV?d00001 diff --git a/packers_and_movers_management/static/description/assets/icons/restaurant-black.png b/packers_and_movers_management/static/description/assets/icons/restaurant-black.png new file mode 100644 index 0000000000000000000000000000000000000000..4a35eb939cf065c6f8cf83781a15f357348769da GIT binary patch literal 905 zcmV;419tq0P)?`PC*pLe{WG*jTWtl`Uu)I!h(oI7q&uZZ6pM-kw|Ur zMPftz3s_jOvBN@wkko<{5h@lmjYJTFNYSdk7WZDgxt))5&f8mkk}hV>Idh-qo-=c2 z<}K*Z0h|JE0{hdxYd{s)k+v@ZXMrAIo@0zw;4N@F7c(R11%8u|tpdl>{-S`voX=~= zI9qe}3E(2Iz)Gr4;kyl(s~mqF&>XN=fMdX2piMb8pcAmd@&I7Dz-K#&h$ije8Ud@c zgQt)P0N6-UPAX^wv}*@XAr$~{fXT%{gxOL;d7J^}NS&nu>IqNA5SA(ZHvoI3&Qbww zBrApmt%jI`Qb(zPr3MliEX(6AgxqFAfF%PhK$pZ(DxlHPm#x|JJ?#vOh0iFWL*gX; zvNkySP6D04&a{0VI7IUG&7=5n`XhX%X!6%0pdIMTwKt`IMHB^02%jlh^`s@_+Eq$X zUua7+@KNF<74Svq=fdYgTbhAkiIY^oW1*i5PYP{`fFHnsWN@i~VW3~=Tf~(@TO!~V ziHK=MH!#NJVMOxR&(xQ+UJ$o$y2)oaLNW;@b@MoYxa>1*DRX}LjYb1P&7s^nlmWWk=>z*h>g|NU{%5MtF5CHx% zsv|6})E_wVDBiwF?G1#>YfMYTD&SYd?mLjjCb;?_Zxs-Gkk1|~y%8;uG6am{&rq!N z-f4+g1^f)yLT_-QuCw0J!G4)Cg3XY f0eA)+t%bl}x(3Cqe?`Zc00000NkvXXu0mjfu`-q5 literal 0 HcmV?d00001 diff --git a/packers_and_movers_management/static/description/assets/icons/service-black.png b/packers_and_movers_management/static/description/assets/icons/service-black.png new file mode 100644 index 0000000000000000000000000000000000000000..301ab51cb1363cb8a0063c4f9f7cb9cf73c91e10 GIT binary patch literal 839 zcmV-N1GxN&P)wG}3wsU*IR)z|Z&+>zafrqJwCq*x@FjvNVI2F^z|C zN%{bO#A+2K9mjI&psYL^8b1O*HWO0*iAfK zwBzye?BGqTEZN2s-YR-iRRhR^{{@@H!rmxCX)mp)h^Mf|a7g;p*wW?ud=J0RL?CEP zkEcMj#QI2Tc@Mv*2kEq`DKw7vdi=Jb&-aer)!-Z0qjz+QFK@N1&aRXO}`izA!9+A#$97UmLtKG(#D$V@JG;R0Xua%1u4_kNMazOP^ayYznp(_+pa zmHp&*7l9|T=r9&<9@|?Ko;a_$GXn6R3= z-_eWeE8>!NN6sWQh>p|@{|B~~h0NN}OyO(k|0o{Eevvy?ir79Q%G}xZ=i2u5tSHu2 zwf(N(bFnYJT6O^a^n}=lCZF8Nx;w2}uUkB4XPd5v`7Z>im~HzdJMCK7trz|-8@38>5jc3xX@h`{ zh@iEj_%)@#V~J@-!i)2n-XCy!_SC5Qyigi**PVuC+h<}!~>FElyR+PxP0svs|A}^vKikR z#>I0>S!0;4UyI{*IK1PzbOF;IshL(A_k5A?+#7WY^+>e^YX;p z=xW)DcRQbIOIo!~v-$kABZfD^J?Ag~CjG!0N_ye{SWo@7I2vn7n(V-R~kb-3M9=yBBG68O-n8v2ber%t!Zu Pq0ivy>gTe~DWM4f&Ev8V literal 0 HcmV?d00001 diff --git a/packers_and_movers_management/static/description/assets/icons/training.png b/packers_and_movers_management/static/description/assets/icons/training.png new file mode 100644 index 0000000000000000000000000000000000000000..884ca024d71ca9127a5393134632ee92a61b07c4 GIT binary patch literal 627 zcmV-(0*w8MP)Ji_yZ6G zgCi9sC+SZOF3B?A-3o?c9a^B`5B^xi{atdGlsx zfu5coC)9d9*W)+29w+CYx6HE5(7FIXTmz`}IuU&auvT&%3np6<$3JExZ8|Qv1`yF6 z{uK`ZBO-bN;C9iN>oGlP1At#74phASP()5l1Dq?6>v00$qR~ktYISg_G~Q>PN9l*Pyjm+=0joaxS5K;Rj(=Ddy)iyD^P2j9tz7$MRPPN-6X6Ic< zC{O?T4(yVQo5t(DjmAqa0UQ-9Bj}SmO~ZA+0wO7a=S3S8?~`nFrw($EDaoG!IQ?TF zt|2?U(I}QLQFZXyQiDB8SX$~v-8kVA@YGU+KFk?f>fJUiwWsHQ*BQQneoi* zIdjgY7w2;~&-47A-}lQiGr#AVfgU}2^thi$w2V8gP8xe`iYA|^nQ(?HLC@=`7Uk<}) zLeWEQiU$yZ^@<(}ZFDXOrZ=@2KTECwL3TGYp{o5;VR!&Zenfb(Y~lunk>o@WhF_@a z!ghmmZ=oQx3ZUrTMV_|@z*@URl_LrpnuMspmx02LayE1`&DBGH7 zIB$fJR!y{I;6E2v5gyA7yJ&>%uIrAsk}Qk0c3q+z1eRyI&Umi#qKMSynj`laxQDEG z$>9=BWqAjWxCde)_&ZYtQ_uHfppNAb)C&iMgDG4Yayz-APl492qWnZ z+2s4qPerk;Qd zRTxgcUKCf(0QEW%Si8S$d^23v9Y;Bm$|Jh7D5kUlU|v?DQjz!5DcCSIHI;o!&C;0x zy1x?jTA~w;DMb2S$s6C7*Wr6^*LJGyqHt8;>Dg;xBk)zTu^q3#d?0F4bwS{Xys;0Y z0b}%PxF6sy{*u>yU@TD!7kg>wn=-H#OA+vz;H27KSYpwM_&kp%X2ny`^Yp0@|(y-wyRtOEu) zkZMr2S!>sIk}ylBD^a-LQPoOlqjSJ;L-U^%BWoPTxn4GDGXiV(qm1VDmv{z1L}Jvu zn`vGi$NH_RE@&E5g2~Cr0o8JExjDBIzCUyV^vhJEFcOB*@hFO_Ws){xtzG=^;Lve_ zQnzMHdm+ztcL8TpjlxKr=$THQiK!@hAyIz4N4%2V3+2+10THPgVGEG`aJ3>)#)7~e zj-qI|S!^?IMA7OXjJ}pce+C{;_v(adyt>r~yRAcuwRTCOd=IQ`K0+rHj*6O7#^_|N zR=ZNIR{yzq^QL#_j;<2XwFs{P&o>X}q=;_wJnsh7KQIfj8}c9GwohHEy0HGyN#1EU zwtz&CPhEFtR77q!cFdS4^%iP|h}3+~+kwg^h2P66zKc$%k(WHr*_9O!^)V)55l)iG=bkroSVWSt8oK?9X|oC&>t|S94mi~JQz6J@L4Q+~({Wt+ nVe#UD%iYS|qeqV(_m6)8sc^)gW+q6200000NkvXXu0mjfv*t}m literal 0 HcmV?d00001 diff --git a/packers_and_movers_management/static/description/assets/icons/user.png b/packers_and_movers_management/static/description/assets/icons/user.png new file mode 100644 index 0000000000000000000000000000000000000000..6ffb23d9f036834a32954f83bcfeca00790ee443 GIT binary patch literal 988 zcmV<210(#2P)cAU zg%n1_!UO~hi=Zajq!7VI@CUR>p`!Rx*a$&o3k`~bXb@RtC1&nyR*WQ@xp&s=+|MHZ z%qBDA%sD6P7W>?P9RqF}kWv6&A-zOAepFK7 zn%moe*=$Tc@)I0INT*#4Q(tpt!c>;Iw0DH*Nr(MZj6)>|hd7}=D`NRPh zXvGuSy!q^~M868;^;_^453rHAwcCa0XTYMJUi@XTxY>o~XCPvW7k?SF)lGsQoZDZQ zP)=G_j{)g77n-L5oA={)hSIDH&Cfs)ee1>VM9F4cXnqDNc7ia=s32eb!iDI$gsOi4 zLvKEpLvw7Jbc*9=pw+k^81;$)fYoTt-RZ*gtblIt<9DK%bYb~+p`ZNt9gylSG|w)y z^f7S3E5=1EFtYA*7owK|ZMZhYc+MxrUpVY~%?xuR%hGp%`<%$)6(zO(uDSg$G#5pD z;K6<0FLeNz{gRNEPQuWq)1OJI*Gp=<<_=N;X(Gq;tOM~GAMp_MS;a)29s}JqVCIjM z)b8=k8|EJXBpK4+2QuS_5P5?c0HB~e#B8sn^Ebj8h&ak%8{2szdo@hTfKXDKM!FmH zW1nf?P!ziqZws=70=&$bXf^g?93W~xqS9P$i-O)xkbdQkw>_W_=3j zHL&MZ+4h#Vli`J@6>FxCSeAZmS!$N0X3g}h<>^5?bLOg^ymRRmYovK~+eD>9insPXvj3+6Gb@v&hmf9xq1t2!EP|dQ8Gk{Nb(_%F zfZ2)l~DhpZ1%x!dRjm zO=;u!cb$X1D_}gv>Jbl6rqq7)(!s6*&8$S;I1dcnm#;8RsZyKh9Ozzw#ra8ApLl@n zmu`~X4VYcGB63`?zPU_W_r4w%$5|}xSP?5ge^6@en%S9MO4}qmpBLGc z+0FjUY-Um~^1{NNbKdiv_nq_2d}juhaAqNAYGGAPQ!by+?CdIx=|Q!EF@IoLzlew* zHqN3N&|>jiL`D#~5!H3TiYBy2#kO~cjhT*5UTf&o)WxJyJAvB(gK7(+j!7;TT0A7Y z1FE_V&)W$+3}iZx$0V2A6?Kio3}~@vBQg$L-C2d~l5BRYn{^UNAuSXJ5cvdH*O{zi zV%uGb2Qb}EY>Q0hdBTeCB5i_*J%!Y9hB4-|&cua_ha`5unC%@oF^Pv{Qs|lv<4<)f zUXLH|SJ!zQN!xgltnuI zA*#cGrK&x(v3Ly_Q|`zSxko)OA2y^qPL@<^KO#f_bvjN$1}w`3PIqAS3hH^A zP<=n*vz)54C3ehdJM0g+#tCDPU9e*A9n+;vw!rRxEBni5 z)-Ry*UUp(jA$8sBfPFx3TrnGPh-`L9MCxAWV%Y)pyc>XbNlyG}DwX>i#X}4RsyFRk zVEIC0wZTI&IM}qlEXaTsi?^UUPIBUXU{q}T#a4t=w~?!r^mSlaglPrljv8T7?RP}( z65D>Q9jU9ESY3A%*b`~K>IAlZtB6c%p|F}v<_biHP`wm58|VX$0ly;h9+vfvh)j11 z8_9sG3ZAzI7>zOy_>^pRvxuCEIIkl@7qaR%o>zf8Bd&3X>FJx35Dy`DKpiKGG2_6- zi1EL|_pg8qr_|L-ofg+klMsFq4s0+U^c|Cvl? zW76WGjRAGt5q$puurgxIe=ugV^!5FI`VHxE7Je0$oQCSazOkXL=HEJ@iy7)<8ccM zi$(+ef&T;QIOo)jsy2Ql_>yw@-e%|Y#X_Tj-|AYa)EhMu>Nvyr{xgBmKbe`?Dr?r9 zOju)E)IDj`^R}b-mDwQojt1IgQcl=+(LyKais%c845mdJTs}XVW{eu|uie$6SB5Pd25|YHf6OMZB Tt+q0v00000NkvXXu0mjf(ZE2? literal 0 HcmV?d00001 diff --git a/packers_and_movers_management/static/description/assets/misc/categories.png b/packers_and_movers_management/static/description/assets/misc/categories.png new file mode 100644 index 0000000000000000000000000000000000000000..bedf1e0b189ab85a0800d2bf16f8907ae0f9b225 GIT binary patch literal 1532 zcmZ{keKgZ+9Kav<&g)v_b;hk!gv>VTU}Ro~txRZnf7vk1>ts^0E+H?ytaOVCAAtJwqh7z>jo|))?0E=;^I0L}r!q@1EP`)*ij%*d2<}K;)isHiUuO(K8sRsh z-Pis3{YvV^@OQmmNs&NQU=)KXv{AlE^1MknPJ@r9OQ`&Nj0POs^TNY&qa1m>k$^h9D8PU8DqJ&&5k(K{sH@ z>V&X6c_01q(%2SvYvLlvZnd>@@hKBUnCj~2ChNaWzfP;#&qp?|WQ{%Kh@)Q3?|Ni0 z=(zu3N5auKDLJw+J9M|2X2;&ImwC4Jf<@^EEM+385H^D2h1?zJ3CZs;Z5fLh)hk%5 z92LCeycC`uoi_YZVuu}XVj@bJ4%>5%sl%Pd2NlL!H`UvThTU6LJEXe^gn}6qo&D*^ zm^{E}_)%2m+Lg7mTKSD%vkXWsw?3^(z8CV2X1=Ih+$)FISZ`Q1W>#&(U;Pf3754az zInOwxDLL*iQ+nNfq^Y+ffJ{jKv)@>P_0P3jxYZ!D3cFG&Z(+^{gBw2KslvLZ6k9pp zcav^CwSZWm8XpNq>1*NKY-M4jgw>z=OfFMf(-%Ced^p_UI?=L>ul247laA={vAc40 z&MbkA zQp*daY+?&xt97XHt%JJN_4~;wCD(^h2BpL1xp@X^wlU;+cG@IQw(58Lm3j6ZZ+dn9) zlL|m@Tzt8QBUiJiT2oW)3o_`6!%f0b4fhFzCeI?t)lB#3@yOj}Mt_vsQ;lPFV#O6{ z#%pHl7`Xv@3G+~0gf4=9HDk7006U7#X5b?aGavvftd$iSYlF73p<;LAaeMIAHoLG` zJQn*_0WSNWkeD3Bj6U{lp)90@1PP}9O<*$<8L4b~BJ10ZkX&2>Ie_fuMQn7To%{z~ C2BR$i literal 0 HcmV?d00001 diff --git a/packers_and_movers_management/static/description/assets/misc/check-box.png b/packers_and_movers_management/static/description/assets/misc/check-box.png new file mode 100644 index 0000000000000000000000000000000000000000..42caf24b98062c6ea6bb4a636808964262e04e64 GIT binary patch literal 1118 zcmeAS@N?(olHy`uVBq!ia0vp^3Lq@N1|*eVE!z&HSkfJR9T^xl_H+M9WCckkdj$D1 zFjT2AFf_Cwy$! zfk$L9kWK*O57|!VfeiK%PhVH|XY8`f{5%sry}!V~z%1$M;uw-~@9oTZkKjO=CD^jHr2-Ky_r{i?)~S7_ckB4oN(g5tYF>c zecgT2?!-)3&U=-W^}*{P+mk1&m|2o@3`DB-E~qm~>F;-*yYrll;YLQry_@%LUb%8X zSjE+IehQ%>T3iJ@vm@Fq_A2$CQg(Ju_%mzI0*!##akKYr_)x8V`IhX8_~|jz^_hE> zd;=LayyV?Fk7K&Tx^-+XW2{W<-~V5`@89>ZwyFGC>#fe-*%zH$M9~KbEpB%kplhyQx`MYlUcye6W&9GPaJX2i3?bob^ z=exg^9ZxCxM3D_VHl^jeHY`!8c)H5wMZp^0bDUnQR~=%Q|1hPlj^%al zjs`O?=kPw+Mb0anZ@pqaf4bYWLWeaYbK%J(#?C)E8yU{u zTrOT_@NtibABP9W1^0$+d-vQ_D(lYg?oQ;m@a?L(Z{C9mLOf|(k3Z&gc6i`$@X)`5 zj(b<%uQ*aR(a3;d>&tK7gM$+}IPUzKI3?xtd={Saa$y6>?~&_*ZG>w7{#DSM$re73 zo#ji*{q@_{ugldxe*4`p0=f4`+#~FJYD@<);T3K0RTVZ(~IOI{J%W8*u9*WnXM%N#3}+n;w=F9$v#T_3ILHv09f$= z0PI5mfQA&b*x=X~-2b*97_-TaA4aVSZ19GdIft|9@!#C?$B(cJPz2G^1hfc}=H!$h z9#k8!MN^`&p}kYjYbSq_s3S!GnwCdX;-6K?>A^MlW~@W+hr1_WWGxPgd2V{r)k%}8 z`@Nt`HpQ1%gw>PhZxP~)DeN26sL+QQU{ z8=X<#AL%T$&gkq?(a0b{u))BWK7;|3><4RK5J@RX$ z(S}Z}XkyR`Cl$7Nme&@zL{?CO(=SFeS?(Ug7^y~jPwq$Bhw-+z)>A7RpO*1e4MwGS z!?tam!3yiN^P^z==2Ymif^Sn_MMZt9@54&BgyW9J6EEZ>7oa+7Fgzx|yzbw307XYE*cD0uWM1t?sq(m z9jBP~NW{6Df?8;77_ai$)T`wdKc0X%#E)|{;eJcBhe@f@T)URJue+whDml1xN zmNk61-cbkNU1R|d;RSR}>Pp7Y?F>1OlNfN&=47KVbsz1e6&y8Bh{?cg&1Ig3W01Gv zC7=XiEH4Ov!QLP$LC5WJ9~lk#6lZ-T{B=vW=D7F#K=!-_N+yGmza~Cwnx=Xj)mX7z zOsJg`XhOIrpF3Ee5$Y!;&7`H-MHfA>{W(gimR9q3_d@AdIN>y^r~!^0L3@6yh{FJA z>EzuGB&7WeZtLNXZwe!lM@J>y-=h7@#@G- zXgt!HYgpi<3cuG<_PM-k4z6eGo;5Ik&8_$?xGvg!@iwHsU`34@

a z(_>eoHv$BXzpXj*;mu^oFsud6dmu+nts~s0GR4&i8>u2*lJ&g^edi)~L&fHF`xcb0 zRlm0+k!#^FXzcS(1Dbo z$w>yEMeASDt3M;-pnjYJ>FFYMSz%vE_BlG&wtWOzk0YpLW_ylg*ur|DWJUI- zU)0fQZnn~}h6#n}$U_9+RPq(KPbG9#r((|D*X_Q+&VaPaRJWHX1B2uOm}D=-pSeA| zhR@8Pilur$blSs}?7K9JcXk=E*Z4~AQ7G7zH%im$c?x$uW#moLkeS4Kfc<^9^U;isYM_8gVGaIzUR9D~IL)2H9n;n!s9NnmY0<<$#aIf_ z`1IjLOIEqGlv~ty7hQ-3Ebo$wPp@<3xx1PBd|)vPllIi*+^yybG1)n4@Mow`iQ~Uk zy<3a?txUP6(@-+g^=ESCVr9z5h=VmQOtWOqo((UBFr%t!*&o7(FaJV_`3sQ{TRiTD zv`Pd(%Ff8mjsBE)?T$<2r4-GI#KuNn z(2Sl_&rj`XC@hfYH=O_Gj$UEV6uRI@`+_7??vmT^vIq4!;eH_XsW&`FAcf z`)trP=Z9;=n-^8BSaF~wXW^FzvVoq?r#GnVowU%m=ET&lgZHZWw2N0vw*Sn&eTUcO)m2MAyUGU) ztFN@bO4u;(?)s-!+S+EmdX?6&T~StD&SpW3(ZPHZrVnT1&5b^#`sbL5DCkYz*86jB zTvlL>)4dlOc`p}BZ*`X8(>k6L5`JOJ`M4{*9F8`Q`;IQs3le9Rlw|nuve2pN+to)= z^Wt{x%3WyHzdL^0)hh>>(={sIEEiFKP{6>DQ?>Hnp@zL4K9i4xuiwC__DVwH!Xuf6 z(66(7JX&T?x|63{w?un&XjWFHqmbl<9R&+NIq8NMadAC*^gO5kv~tkdc->WBAG!Xp z>^SuOz5nw2TTZfCT1MHjCZyKquKhbnLrl88-MRNm(v0ovVj|yXy`Ok{x=!bfnSbZb zP+0r^#SE$cm#=5+u&c9fT&ZzCDOPoBSlBAYZJX?^t6#Aw)jl|68*z(e-|H<~Tem&Q z7ud+yyFn+gMyoLY{rBvYqN7v1s&sp1oMmEgD=)X*I@xEk@TIUQM#qMmJnS4MnGM1Z zmo4e)vg)6m5}lsDq}H{D`)0LE{Kg%{%P(+izkBw~ElRvlS$NN^zISXbhra~+%1Jb^ zv+p$J`mZItCu{zu>3QG3zs`GbMfp41^w&3yziO0C`14`my}#Lec-!+T&-eeVnRu-= z&P6@{VU3vtQ|;&W=epXuOUvFo4)jz~Z@8*AecJKw3>HB_512Emy|`pqEWVzbTktX9 zE^EWP^t2?_1J~KvGmRTw9XtpWj1_HI?&_-Zi0kO-qDQyb!h4Ys2yS-RmR&eE-4bEi!Md z#`oePV3t!Yag8WRNi0dVN-jzTQVd20Mn<{@=DJ4aAqFN^MwV8FCfWuDRt5&LLK9}A yXvob^$xN%nts%!>Lmj9=18ze}W^QV6Nn&mRZavmfoIiki7(8A5T-G@yGywnv4>=zge+s5Ox9s!oiLUVG4_2M+cCB?%1$wM z35BAREmKO#J|*5c?}zug-Vf)#uKW4j&;4A#>-ls)PqLMTF&Fzeb^rjlOic`J=oI=V z!7TK(g}TyB2h$xrb3Fj~JDua$jhVie@G!A42Y`qR01y)o06*!im`?x@q6`3=NC42t z2Y|DI#a-4~^aB=mGh;(K=|MB-j;7;Gpov2;oyh;@wvYZ4y2zl(;*#HW-B+ZU=P zB}2dsV24HBu>?1;z;#Eh9yt|?k=;eTY!cEb@0K1Pezig}iAh5}_{F#MZ_`~Z_H5WM zht&5U)((Fiz(3Hg3~&;3`Airp>SE*eMZVE`PBat;y;nD=55DwgK?4JYEg2Y-|6*^+1h{6-B&!SBe5E!SDN3fp!U|+<*0HElltJPGMb2?$>mdjTQQ3Mqo_(|wl3C-(8CMUw8T%-yS zDLLqp!S7=7)+lf1la3^}gDt78Fm`^U^Y!9}*=u>O1L?;j)34rmZ_6fVh&0(ra(6K zJ=A1PP9x(ih6CAgn4;n)0$DZawSV_W(_i1X7rx}!Xg6v7R}ECxx{@Ft+}fJV<~|A? zT#CQIM-GxXBXR9m8-wXdbCPRV=nh?Es5CeZh+ix$;up!#EzWwCHSF?;%g0A*_o}eE zS@rODuIXUI&~%>=BeTDO-{ak(dP&UNJQW#k3?f3q&%YKh zj}8p+oTqknw4m|3D2ESG2DE4XHe;BL+gnd7yRtHYZE#h7p%}cu?v9ssl)5bl4Hqcs zjQsg)Mc|0RKfg$1C&O%-Ns&h^|1j7uzj0=?xk1$ZUPouzJ~f?WqK^36@=wtfO|p1> za8L`rc)&O$WF1$kHujFpY~RER*JX;aRh2o_v1b!LQcGbFFE-c=*Kz^*aC{Vxer~kF za&$=c0%o1-Z$pmfjy5LGSkk9*ZS~~7dR%P=g|R|GD+(K_J*y8b(~+x?!|&+{ zgwxtPh~cLbaf``1!NC!cBR|vlGd74Wu%e z`#rd~NyJNCse4$c7#`W)tb{SXwVIv1_qpB6rM`G^5%aP1ZnY=lB~jj$uc_~=lDctU z^KU+EFZewa@@4oD(~b!yW&K?;zfc+lF}=|GE_iyhZDizh@kvh)r_?CYnKB=#W@ZKo zo9saqaK=oo?F>*%ho{-UxxNN{6uBnT`lM5vWZRyJ`vZ%e?Q zv>M#LLI?u0V|e`&oeEN)Utq8)ElVHL66eGIaHra288b%v`Cs{C*WKA9> zriVh>?^EI?gQ=OdEzWl&1$lN998+JD=B&BhrO-a8npM^`3))VBswx~r6Nn(J8%AkC zOc}-6$>*;0eW&!2qn|>lKilj7Eb*_GRp-qYEj^EVKp@aa2V>yE!W8Ghq6kv6CB}Xi zA0%-#d>lmd^_E3Jqz&&U^hs6Uf$!cB2rB7F=`1dUelVb#$>ZZ>$s&hR4==JusF6np z@V-*lk1f6H=2V(#_q0v%|RYgqWP3 zfQ)Z`wWK5;x3mt&aI*<@>-2G04>CN;FWhnE8+3fk&IE&95(P2zm&wMO$4Uan+^d}@ zKfdFCtnE?lK?R}Tyh*Wvd9AIdTB{ym3f0Fe=wMXI ld?;Oj{O<-V+RrN(>*g2u?@lP8bD!=2rbZTqP5Maue*i?K%;o?9 literal 0 HcmV?d00001 diff --git a/packers_and_movers_management/static/description/assets/misc/cybrosys-logo.png b/packers_and_movers_management/static/description/assets/misc/cybrosys-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..cc3cc0ccfdaf8dff2e8ebcb010e24ad9e636b494 GIT binary patch literal 4496 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 B&Kv*$ literal 0 HcmV?d00001 diff --git a/packers_and_movers_management/static/description/assets/misc/logo.png b/packers_and_movers_management/static/description/assets/misc/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..478462d3e73d73cc9bae9fea8e7f8fac84fab049 GIT binary patch literal 3452 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 e!*|2?|H>Z_>p))&1OWs90000l? zWKy}bLYpqAEQ(GYLL;Gb(D`-#IL~wb=zX5=`+48*`+lDHkMH++vpn2fWTn-m0RWIC z9Kam{srDn};o#iz@f{BYjOs*k0)QL&sI?$TaIX_`;1CG_67>Kel?4EQfvMC#0pJ80 z0A>OKz_uI!ROyu+p7!7YJlNF*2NE3LoOvlAr055ZFhBlyRK=FmTchU@1VS5t^%)rBQM9x$MwS_ zIXL28E0Jutq+4j;o%BRKk^5frRo5||pMzOotWxt7e`AC8&_%_GFa5wg4|BIgM?sHX}t!3?X6PLp4$UBYR*G4H& zMWX78_VXrTlyZUMxJRvzIRlyY?ck;R``%gwo;iG&QYPkRhHGmxV&U|J?Y^rE3saY1 zG~M-*5Q7+U3lPx5rh}=!OE26Gy*noAY^$SS1z(p>+80-3tY&2q4P(pi=oiXZbv==y zXNz%@hg?y+v5^*UM&psGr?#W?#oy?vVT!Nq;xo2R2u5H<#RL5qj7dO4ac@0F^!ngf z&PKr*uOm|Ap(E|9ZzYaPLWnC%tr3r8Ip>Osz(!1gNeva3Mwcv72UG3Cw(^a2VSqj+ zi^Gw7-K8=_q3X|GY3d)JcoS`y2fuJ>cPr!LN#P&A2aWB|#WZhQ72J@Mi-2%_f2*#Y zN>HTSP7l8m-qvJ*mJe2QXf)d?xw#rCH_dEO(a3Z^O8y(8pbhe*mx~XuA}pYj%F=G$6K(s;ly_O+L&wbDL`GV~pO~%~ zb-PH}OteCdwx9+4m(buZi#6EN`j}3e6EiuG#AL|cKo&hdUL+J{m?}#zsV1<9ax%nz zu6S>pFkEA{-8Z>oTkYo&~Ct(r52;n35<_46W44SR|=yRZb>u`vCFL|O%y zvHd+g6~vOiaEwWo&Gx1)vM`!ybp5j9d~a2FcK#-HcUG{IW9kF$JJMax#<6T@tbvx@ z$jqUkmA=~0F9J@|)1nwszzpy4gMpl7U8}JtE7}@?iFZV zi%UJkou|bMX>_Z&mia{Gm1ER8qI{S!4wYU=N;1}ifE8wL*nd%HI-fmC8l2CMv-R~u zvLDDM5}tj44JzEQ*b$bs1|hT<=)srdA^a+{tvf8CrMN979i}O4ehAemf%4cedr{mn zGO;GJJ6*4d5f{8kimVX0tGi;q66V;a5r+ll#Tf1JQR?ITA_3c#FgN#Z&wSd7rsk1# zz@rm(^=;c#Bj>sSsWVIc7rsY+Ik(`8u_yE!zp6Cn)=S25Z^cV3AX(?Dbv!U6gQlBt zNC{m%*Y<{X>)BW2u_SzBEef}Y{Dt+>dGfohq3m#N@KS^KHSx!Gg!cfYpwHXRC9@B$ z4an`Ay4?85=X%4ZN>1Uk%ZcT8LJ)2eT3WnQW+Lo>r(h_TX1>tfcWOr&Dyk3?X=J36 zKdbY6a*BJb<@)(GsIql|R|Wyu3I4h}nRq`YC5Rbn8xj`^0>Gd#7-O`RF~;gJ+QJrX zZHvb2LZfZbXvv51_x~qE|3ZlfOZd6KWD8G&g28_;Fe9Qv8O)$)`p=ymdGocP0}$|T JxMpl%+CQV6u!vJ6b2LQ+{ z08k|5Hl8;V48(lSS)m0K*v8qWXaU4Y)|bKr#QoPfLFWB}1Vpy6w*bw8ppr_kLt{~G zg3c!!^cfdyd+o&tj0-_-IqKL|DT#v*Tt(VR^p4|6prn%In@+FjDyl+Ba-xF~Di*o1 zx1guX{>c}`ffisl;XpCP%2;L>T(T8x-gJ;p+_7=b(m`FN+@eG_S^4z(swp$6AOG}(RGqLPX`>E|>w!|QLqhG3-1qHCT)(Q)h~`IeQAoQ|B(Fe(k=IQDJyJ-)3slV5N9QB$+< zu4?=JxT>vkq}G80CL?V-ntJN=@c2yUm&LetGTO2T(#j^OseJ*DCoC?G5Q?B&pWvkm zOYoE;DdcSqJUen1_q3ZEmgOznZDExTJ)V_&Rh)`E95GzJ4&G^q{F$r}|7E&o>+(ec z64CLp)6^!M!3fo%=MZluDcd<1WlhCFjp4Bl4#q!@b*1&Xwa{w%sl7v6O-=ScLhV0; z47)u%PF004qYRdY9GTLSaf>OCK~;YtPt6V3z-srmem%XD3*m0au-^8>2S>(GiYsD) zpO-i4^Dmc2^2iIJL37{IB_*OpP`gM*{r#;A#$k<&;^~d;9KudWS?k0v&zimPlH?|J z;knX-i?W2q)DsQlGC4*m`V4HUu4;M&+t4(GUC+0%aXetc60Y;`z{a8cy)H|gYm={j z;l{W9T$SPNFVBC(rBJ#sc(pp-rX=*iu67=eLx|jWLQcNE{{sE{`T7@1Z)9bD8zf0( zjj~_mT4SZ%t3rjZ)!{+2vp?nO{UgKK5#yNL>do)RTlsz2bB}HLdTS3{kkn^F2U7gp zeaCg}X@l?hW~nDsTvy+m_*r&&mzT4%)(9!}{CMT15>^6t%fNQzma@FX@aRa|1l0z*qvGe-ASXo+H75MF{hm1@$B`s6e`mtp!u{1kM23&ZI?Q~aH zN9c6V;=6*9!4dO;r|zZd$_WOZQV@&;NNnA|Q?IR?yF8?du)`6$l_(0$V9J1RKmcV* zL8?eOFOMC}v{Q;TXr?v4(8$Y*4M*d5teg-LQu7*+Szj~fKj&n^&=_#Bn>!WDNFV)p zKhqa@bvz1L=JLch`E!DQQi`PCX&pZg7N>Eq;&or4tJE-I1D?u=@o}LTUVUV9Z1x9K zl-W1V4UY3U$sz7&6*jVHxCmv$zDA`E312662$dQQFCCh1p7TfJ34T$BgE}dRTB|LT-;YEoNK7ViA>jCqdQH zKBcB6G4S@&$Lel2T2^;NazX~5d1xAxU`Q7a_L)UzJ8>v}+Nh30S#B5{KE{W0 z#*57t-V&9JQeIkH6N@r-4+)waqjM8>2F_r#b(0B(>Dx`rM_;dK`EU>?=Qro7lB?mj zx7S_n@%OR(i)Ai{8Me<&+UvtElV8*v3lri0qIr4s zu+es*p>Y-FhM%-{8Q?+x5Ci4jtTNiRdwT3D*)8iinnteUB|-VY!51KxoFN{psB7JI zKNn5!NMef%;b~SiLeB68D2@4D9cerQV-6f;Tjg~E` z?bzd}7Tt$!x1AqrR-WumDLffbZQ^=ao6`5U;WZ~2%Nx&p^xjAh*d9)kkNG}$%5A+VOdR^iev6_9*0mc5>s>W({cMY*pr&6E+Y%Cnm&&+Xg{{c=MKK%dy literal 0 HcmV?d00001 diff --git a/packers_and_movers_management/static/description/assets/misc/right-arrow.png b/packers_and_movers_management/static/description/assets/misc/right-arrow.png new file mode 100644 index 0000000000000000000000000000000000000000..730984a0635c971661c6ccafc2fec83a2dee1632 GIT binary patch literal 967 zcmeAS@N?(olHy`uVBq!ia0vp^4j?SR1|)y|Tss#?v7|ftIx;Y9?C1WI$O_~uBzpw; zGB8xBF)%c=0965n8eT9klo~KFyh>nTu$sZZAYL$MSD+10f-TA0-33Sk!B6Mi^+1ZV zz$3C4NGE{this?wKn8n>r>`sfGj=I%4b4g4AADwDU~2MoaSW-r_4bZ!MsT3Sv5((f zj=RO|;#kCS=}}7XL8tDJKN>$74xU}fF>8v}j2jEzPD!~~B4D&6V6&)t;iMZW0#n(z zM5Ri70$rZ#WgS)W=yTpFs=aW@vwOvPpZ>4?exP>p_lE`Vt_v~(ZHIzC=1bq*>z0|h zL$rJ5x+8)Hu@2<{TBXXnCcMxU`O+qJVZYbXC(k_;P{=m zoy94kwEF;O_c>0rrT6}e&e$-V*P8MWRF-G>B-@r{Pc42%%tE>x>1&hK=0!iJj_bFU=Io=^F7{M7dD=9_DxO9dJFZ;G)nC3NUIDloLooN-(2f)V94EWEpbZ~Z zma#f64Z4`2v~cT7d6xV)e1{w_vmT7DkGCt5Ur=3pHLa;*5f zc07h}=2!o+4~gCP*(>6B_RmB<{nj$JXpjQAjcb8g9~ebTzfTZ+G3jl;^Y7o%?q9u4 zqt|+Q)SXiP9{zRhqs#@~+wA#bT zfk+J(R@O0J6qFZ;eYtTmFny?&xJHzuB$lLFB^RXvDF!10BO_e{b6q2|5JN*N69X#~ zLu~^CD+2>trOB!&8glbfGSez?Yw)Spo(a^T0k@$fGdH!kBr&%Dw;t&%E;pba22WQ% Jmvv4FO#tlhdcptz literal 0 HcmV?d00001 diff --git a/packers_and_movers_management/static/description/assets/misc/star.png b/packers_and_movers_management/static/description/assets/misc/star.png new file mode 100644 index 0000000000000000000000000000000000000000..2eb9ab29f722b495b4ab0ece3ad21e7b82394f3a GIT binary patch literal 1642 zcmZ{kX;cze6o8)_%zz{|jy5T_nC3DXlBrQ{D7dhQ;$CJZkW?-u8k#BY>10{CONm2j zS(=t;$2D_paV=a*EprsoO3bpw(qZPuoHIYV=iK|<`|kP9`*+i+6h{PXBMbn5aCUNV zmvO^CiG;{%wRoyg2F1g6WIF(A&cnY2D#_-}K~C;u0Aln2;3fm`RrbV{01$}=VD2CQ z*n9vq!g&pDdu0pAA)=#$jI#J*-xx2$&*4tK5i%b9H>F2${jvtib|&MYvrtXNjmD2) z)OG-rbe$dSJbcS0T_J9h7=ba)GD@Y)Z4%I{m53aoBzyMi|aQIi2zE_#N__+%0Hh141 zV)v5xuhe>IzQVca4VwMpL#TJ;||e=cM%{MUEOMwYghQ!59{b=zmX~BHv&X<2eM{7 zJT{LNN4icLnLvP!Ewik?>43_Xk-W6c`%|~N(~8YTkzAaqSziUr9cx*2f;C`S`~LK_)qAtD+(@_ z6v)gsESJaedKJd zzMz`=g#GSPA~$k=udY|Ck-;UK7mXS^iJi>UHmr|=+dAkFfWO*vQtF3n``AUWOpI3? zEF}hZww+i>%gM19tGjo*w3hd8vdUn+qao=`9HKDAWo2bhnFHc|DnA>=!aD;R&9l;G zrwWa{zm=aejS%-0j~v5vqoQM1>P{-W3`>n-jAv(FHm_W(Z&AkG=F|jOSK(ic-5I2q zp)4Nr(r>kMkR2V|4FR2FtE>9(`mG_+yRU7hY2+g&CU!hL`;9QIiA=8G?$yohE_xEw)9HD{!>f`iy!}WHSiub;MVCN)k+@T?13yj(M z(wU){=%JR=)P$>47q{kzQ08MINlTgk`ZK3+cJZm))tuKtzop@eZ`mK)k_5)%yT-<7 z9>}Gn-m+S!GDG8%lC}JoekmU2LoW3`l}DF}z68$8dut|51%IB1IJv-dbq-=RL+?-g z=H}ajB8^x1x2RWPoD5kp^ImzQ|4BH!2EX=(xl8!F0Zc!ydxizbxY`!bGQy8pW&lifskd_1( zFYZ(53wrAabdp3|dUg+}e8=5%A|-3}=ymk=whX)8wAK1OEL4xj(R3@wdMT7sJC|V^ z|CRlxnxbWERUd83oF(h=9O)w4%Br^=^;tdl>2P8Jr}${b9}yZ0%ebU-feJ@{fnBBz zfGa-!2#}ixv)1#}|2o?*cE3B2V4sr0LpUbrqX$H{3T>_F7mKZQOx9b)1)$F|JAE&Q zk~~ENSjzTiKU4itCzMx8>g>~i?O)fwAEN9c)Q;mH+0mFo`w+J z!*=e&?(uBBSn&Qnk5{r7?c-OxFaJUbhB{pk_WapsiU)LORr3U6oHn`k4GMwBkwiW3 zD*crDtFt&2UOG^Vq{eP>JGmCMJ#_qOG1MYg^(i+MY4Mb~cg zU!IW~3F^Z|k&AaZ6EokH)C$R2*K0o-%WkMH8}GxW2eKL1pc4!k00xc07^5wWF%}+Z zGc3j&YqrY>jmDzU^5^=x{wIWl(OJys9}5vrqGDu%{(nEPSs{!Fc3?>OkDYB@-lZ}J NIO8b}Rk(wRe*?eI-Sq$f literal 0 HcmV?d00001 diff --git a/packers_and_movers_management/static/description/assets/misc/support.png b/packers_and_movers_management/static/description/assets/misc/support.png new file mode 100644 index 0000000000000000000000000000000000000000..4f18b8b8201e3a268ab1d8ceb8bf46d7a7a37dd9 GIT binary patch literal 3892 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 literal 0 HcmV?d00001 diff --git a/packers_and_movers_management/static/description/assets/misc/whatsapp.png b/packers_and_movers_management/static/description/assets/misc/whatsapp.png new file mode 100644 index 0000000000000000000000000000000000000000..d513a5356b2564f545f2edcb0b80dd3dbff9629b GIT binary patch literal 5097 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 literal 0 HcmV?d00001 diff --git a/packers_and_movers_management/static/description/assets/modules/1.png b/packers_and_movers_management/static/description/assets/modules/1.png new file mode 100644 index 0000000000000000000000000000000000000000..3415917c2450b42a0881e130cd472533ea903434 GIT binary patch literal 90143 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�O&lGR=R-`yO4<$3oEOF=b> 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 literal 0 HcmV?d00001 diff --git a/packers_and_movers_management/static/description/assets/modules/2.png b/packers_and_movers_management/static/description/assets/modules/2.png new file mode 100644 index 0000000000000000000000000000000000000000..7f2815273236d2a0fd4d03352002f9efba1ee010 GIT binary patch literal 58088 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

Mt6O*v7-xe#EpXe3kOBzbQ9*uK(@(~bF`)f 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�D5q^{%|*j&M0Oz~!2~q-qaA<7{K=hy0fWPg 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 QU044v<^R8b1OAx#AHvgEZvX%Q literal 0 HcmV?d00001 diff --git a/packers_and_movers_management/static/description/icon.png b/packers_and_movers_management/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..951c08bf14eaef253b2748d70e46db5eeda0d92a GIT binary patch literal 9848 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 + +

+ +
+
+
+ +

+ Packers & Movers Management

+

Detailed + Packers & Movers Management View.

+ + +
+
+
+ + + +
+
+ +



+

Explore This + Module

+
+
+ + + +
+
+ +
+

Overview +

+
+
+
+ The Packers & Movers Management module helps Users to book the trucks through online, + you can Manage all the orders, print the PDF report, create truck types and goods type also. + This module include a Dashboard menu to see all report. +
+ Furthermore, we can view the different types of reports in the form of graphs + according to the values and operations. +
+
+ + + +
+
+ +
+

Features +

+
+
+
+
+ + Dedicated Website + Views + for Users. +
+
+ + Users can Easily Book Truck +
+
+ + + Available in Odoo 16.0 Community and Enterprise. +
+
+ + Truck Type and Goods Menu in Website. +
+
+ + Distance/KM Amount can set in Configuration Settings, +
+
+
+ +
+ + Dashboard View. +
+ +
+ + Print PDF Report. +
+ +
+
+ + + +
+
+ +
+

Screenshots +

+
+
+
+ +
+

Dashboard view with filtration. +

+ + + +
+

In Configuration Settings you can set the amount per KM, and if you have any + extra amount you can add in extra amount field. +

+
+ +
+ +
+

Truck Booking Tree view. +

+ + +
+ +
+

+ Truck Booking Form view. +

+

Add the Customer name and the pickup city and the drop city. then automatically calculate the + distance and amount. set the date, truck, goods type and weight, and it's unit.

+ +
+ +
+

Create Goods Type. +

+ +
+ +
+

Create Truck Type. +

+

Add truck type and length, width and height of the container.

+ +
+ +
+

Create Truck. +

+

Create model in fleet module and set vehicle type truck. And in information page set + truck type

+ + +
+ +
+

Create PDF report. +

+ +
+ +
+

Truck Booking Form +

+

Add the pickup city and drop city. So, it automatically fills the distance in KM + . In this form, the user can select the truck type, goods type, and weight of the object in units. + And users can fill in their personal details in the form.

+ + +
+ +
+

Truck Type Menu +

+ +
+ +
+

Goods Type Menu +

+ +
+ +
+
+ + + +
+
+

Related Modules

+

Explore our related modules

+
+
+
+ +
+
+ + + + +
+
+ +
+

Our Services +

+
+ +
+
+
+
+ +
+
+ Odoo + Customization
+
+ +
+
+ +
+
+ Odoo + Implementation
+
+ +
+
+ +
+
+ Odoo + Support
+
+ + +
+
+ +
+
+ Hire + Odoo + Developer
+
+ +
+
+ +
+
+ Odoo + Integration
+
+ +
+
+ +
+
+ Odoo + Migration
+
+ + +
+
+ +
+
+ Odoo + Consultancy
+
+ +
+
+ +
+
+ Odoo + Implementation
+
+ +
+
+ +
+
+ Odoo + Licensing Consultancy
+
+
+ +
+ + + + + +
+
+ +
+

Our + Industries +

+
+ +
+
+
+
+ +
+ Trading +
+

+ Easily procure + and + sell your products

+
+
+ +
+
+ +
+ POS +
+

+ Easy + configuration + and convivial experience

+
+
+ +
+
+ +
+ Education +
+

+ A platform for + educational management

+
+
+ +
+
+ +
+ Manufacturing +
+

+ Plan, track and + schedule your operations

+
+
+ +
+
+ +
+ E-commerce & Website +
+

+ Mobile + friendly, + awe-inspiring product pages

+
+
+ +
+
+ +
+ Service Management +
+

+ Keep track of + services and invoice

+
+
+ +
+
+ +
+ Restaurant +
+

+ Run your bar or + restaurant methodically

+
+
+ +
+
+ +
+ Hotel Management +
+

+ An + all-inclusive + hotel management application

+
+
+
+
+ + + + +
+
+ +
+

Support +

+
+
+
+
+
+
+ +
+
+

Need Help?

+

Got questions or need help? Get in touch.

+ +

+ odoo@cybrosys.com

+
+
+
+
+
+
+
+ +
+
+

WhatsApp

+

Say hi to us on WhatsApp!

+ +

+91 86068 + 27707

+
+
+
+
+
+
+
+ +
+
+
+ diff --git a/packers_and_movers_management/static/src/css/dashboard.css b/packers_and_movers_management/static/src/css/dashboard.css new file mode 100644 index 000000000..92fea442d --- /dev/null +++ b/packers_and_movers_management/static/src/css/dashboard.css @@ -0,0 +1,102 @@ + +.o_action_manager { + overflow: auto !important; +} + +.help_dashboards { + padding-top: 10px; + background-color: #f8faff !important; +} + +.dashboard_card h4 { +font-size: 21px; +} + +.main-section { + margin-left: 6px; +} + +.breadcrumbs { + margin-top: 0; +} + +/* Widget One +---------------------------*/ +.stat-content { + display: inline-block; + width: 66%; +} + +.stat-icon { + display: inline-block; +} + +.stat-widget-one .stat-icon { + vertical-align: top; + margin: auto; + width: 100%; + color: #01c490; +} + +.stat-widget-one .stat-text { + font-size: 11px; + color: #868e96; + font-weight: bold; +} + +.stat-widget-one .stat-digit { + font-size: 24px; + color: #02448b; +} + +/*=====================Dashboard===========================*/ + +.customer{ +margin-top: 15px; +backgroud: #fff; +transition: transform 0.2s ease, box-shadow 0.2s ease; +will-change: transform, box-shadow; +box-shadow: 0 10px 40px 0 rgba(62,57,107,0.07), 0 2px 9px 0 rgba(62,57,107,0.06); +height: 316px; +overflow-y: auto; +margin-bottom: 15px; +border-radius:10px; +} + +.customer_head{ +font-size: 17px; +padding: 12px; +color: #7d7eaf; +background-color: #e5e5ef; +} +.padding{ +margin-bottom:75px; +} +.graph{ +padding: 10px; +box-shadow: 0 10px 40px 0 rgba(62,57,107,0.07), 0 2px 9px 0 rgba(62,57,107,0.06); +background: #fff; +margin-bottom: 15px; +border-radius:15px; +} +.left{ + margin-top: -740px; + margin-left: 800px; +} +.circle{ +border-radius: 50%; +border-color:#fff; + padding: 10px; + color: #7d7eaf; + background-color: #e5e5ef; + font: 20px arial, sans-serif; + height: 44px; + width: 44px; + text-align:center; + margin:auto; +} +.head{ +font-size: 18px; +color: #7d7eaf; +font-family: cursive; +} \ No newline at end of file diff --git a/packers_and_movers_management/static/src/css/website_page.css b/packers_and_movers_management/static/src/css/website_page.css new file mode 100644 index 000000000..80ca69f8c --- /dev/null +++ b/packers_and_movers_management/static/src/css/website_page.css @@ -0,0 +1,125 @@ +#loader{ +height:137px; +width:131px; +margin-top:-42px; +margin-left:143px; +margin-bottom:-66px; +background-image:url("/packers_and_movers_management/static/src/img/loader2.gif"); +background-repeat:no-repeat; +background-size:cover; +} +.head{ +margin-top:25px; +margin-left:20px; +} +.image{ +background-image:url("/packers_and_movers_management/static/src/img/order_track.jpg"); +background-size:cover; +height:300px; +width:600px; +margin-left:-20px; +} +h1{ +color:gray; +font-family:"Lucida consol","Courier Nem",monospace; +} +.body{ +margin-top:-365px; +margin-left:875px; +margin-bottom:10px; +} +.select{ +position:relative; +} +.unit{ +position:absolute; +right:145px; +top:0; +height: 50px; +border-color:#ed8115; +} +.link-style{ +width:500px; +height:50px; +border-color:#ed8115; +} +.button{ +width:500px; +height:50px; +background-color:#ed8115; +color:white; +border-color:#ed8115; +} +.input{ +width:500px; +height:50px; +border-color:#ed8115; +} +table{ +border-collapse:collapse; +width:100%; +} +th,td{ +text_align:left; +padding:8px; +border: 1px solid white; +} +thead{ +background-color:#ed8115; +color:#fcfcfc; +} +tr:nth-child(even){ +background-color:#a9aaab; +} +.success{ +font-size:20px; +color:white; +text-align:center; +background-color:#ed8115; +height:75px; +padding:15px; +margin-bottom:10px; +} +.link{ +color:#ed8115; +} +.form-group{ +padding-bottom:10px; +padding-top:10px; +} +.wrap{ +min-height: 450px; +overflow:auto; +} + +@media(max-width:790px){ + +.head{ +margin-top:15px; +margin-left:11px; +} +.image{ +height:190px; +width:360px; +margin-left:-21px; +} +.body{ +margin-top:25px; +margin-left:2px; +} +.input{ +width:332px; +} +.button{ +width:332px; +} +.link-style{ +width:332px; +} +.unit{ +right:-7px; +} +#loader{ +margin-left:64px; +} +} diff --git a/packers_and_movers_management/static/src/img/loader2.gif b/packers_and_movers_management/static/src/img/loader2.gif new file mode 100644 index 0000000000000000000000000000000000000000..d95b6cd38efa6b8dc0b5e5e785e56e1123fbfde7 GIT binary patch literal 177862 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'); + return text.join(''); + }, + legend: { + labels: { + generateLabels: function(chart) { + var data = chart.data; + if (data.labels.length && data.datasets.length) { + return data.labels.map(function(label, i) { + var meta = chart.getDatasetMeta(0); + var ds = data.datasets[0]; + var arc = meta.data[i]; + var custom = arc && arc.custom || {}; + var arcOpts = chart.options.elements.arc; + var fill = resolve$3([custom.backgroundColor, ds.backgroundColor, arcOpts.backgroundColor], undefined, i); + var stroke = resolve$3([custom.borderColor, ds.borderColor, arcOpts.borderColor], undefined, i); + var bw = resolve$3([custom.borderWidth, ds.borderWidth, arcOpts.borderWidth], undefined, i); + + return { + text: label, + fillStyle: fill, + strokeStyle: stroke, + lineWidth: bw, + hidden: isNaN(ds.data[i]) || meta.data[i].hidden, + + // Extra data used for toggling the correct item + index: i + }; + }); + } + return []; + } + }, + + onClick: function(e, legendItem) { + var index = legendItem.index; + var chart = this.chart; + var i, ilen, meta; + + for (i = 0, ilen = (chart.data.datasets || []).length; i < ilen; ++i) { + meta = chart.getDatasetMeta(i); + // toggle visibility of index if exists + if (meta.data[index]) { + meta.data[index].hidden = !meta.data[index].hidden; + } + } + + chart.update(); + } + }, + + // The percentage of the chart that we cut out of the middle. + cutoutPercentage: 50, + + // The rotation of the chart, where the first data arc begins. + rotation: Math.PI * -0.5, + + // The total circumference of the chart. + circumference: Math.PI * 2.0, + + // Need to override these to give a nice default + tooltips: { + callbacks: { + title: function() { + return ''; + }, + label: function(tooltipItem, data) { + var dataLabel = data.labels[tooltipItem.index]; + var value = ': ' + data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index]; + + if (helpers$1.isArray(dataLabel)) { + // show value on first line of multiline label + // need to clone because we are changing the value + dataLabel = dataLabel.slice(); + dataLabel[0] += value; + } else { + dataLabel += value; + } + + return dataLabel; + } + } + } +}); + +var controller_doughnut = core_datasetController.extend({ + + dataElementType: elements.Arc, + + linkScales: helpers$1.noop, + + // Get index of the dataset in relation to the visible datasets. This allows determining the inner and outer radius correctly + getRingIndex: function(datasetIndex) { + var ringIndex = 0; + + for (var j = 0; j < datasetIndex; ++j) { + if (this.chart.isDatasetVisible(j)) { + ++ringIndex; + } + } + + return ringIndex; + }, + + update: function(reset) { + var me = this; + var chart = me.chart; + var chartArea = chart.chartArea; + var opts = chart.options; + var availableWidth = chartArea.right - chartArea.left; + var availableHeight = chartArea.bottom - chartArea.top; + var minSize = Math.min(availableWidth, availableHeight); + var offset = {x: 0, y: 0}; + var meta = me.getMeta(); + var arcs = meta.data; + var cutoutPercentage = opts.cutoutPercentage; + var circumference = opts.circumference; + var chartWeight = me._getRingWeight(me.index); + var i, ilen; + + // If the chart's circumference isn't a full circle, calculate minSize as a ratio of the width/height of the arc + if (circumference < Math.PI * 2.0) { + var startAngle = opts.rotation % (Math.PI * 2.0); + startAngle += Math.PI * 2.0 * (startAngle >= Math.PI ? -1 : startAngle < -Math.PI ? 1 : 0); + var endAngle = startAngle + circumference; + var start = {x: Math.cos(startAngle), y: Math.sin(startAngle)}; + var end = {x: Math.cos(endAngle), y: Math.sin(endAngle)}; + var contains0 = (startAngle <= 0 && endAngle >= 0) || (startAngle <= Math.PI * 2.0 && Math.PI * 2.0 <= endAngle); + var contains90 = (startAngle <= Math.PI * 0.5 && Math.PI * 0.5 <= endAngle) || (startAngle <= Math.PI * 2.5 && Math.PI * 2.5 <= endAngle); + var contains180 = (startAngle <= -Math.PI && -Math.PI <= endAngle) || (startAngle <= Math.PI && Math.PI <= endAngle); + var contains270 = (startAngle <= -Math.PI * 0.5 && -Math.PI * 0.5 <= endAngle) || (startAngle <= Math.PI * 1.5 && Math.PI * 1.5 <= endAngle); + var cutout = cutoutPercentage / 100.0; + var min = {x: contains180 ? -1 : Math.min(start.x * (start.x < 0 ? 1 : cutout), end.x * (end.x < 0 ? 1 : cutout)), y: contains270 ? -1 : Math.min(start.y * (start.y < 0 ? 1 : cutout), end.y * (end.y < 0 ? 1 : cutout))}; + var max = {x: contains0 ? 1 : Math.max(start.x * (start.x > 0 ? 1 : cutout), end.x * (end.x > 0 ? 1 : cutout)), y: contains90 ? 1 : Math.max(start.y * (start.y > 0 ? 1 : cutout), end.y * (end.y > 0 ? 1 : cutout))}; + var size = {width: (max.x - min.x) * 0.5, height: (max.y - min.y) * 0.5}; + minSize = Math.min(availableWidth / size.width, availableHeight / size.height); + offset = {x: (max.x + min.x) * -0.5, y: (max.y + min.y) * -0.5}; + } + + for (i = 0, ilen = arcs.length; i < ilen; ++i) { + arcs[i]._options = me._resolveElementOptions(arcs[i], i); + } + + chart.borderWidth = me.getMaxBorderWidth(); + chart.outerRadius = Math.max((minSize - chart.borderWidth) / 2, 0); + chart.innerRadius = Math.max(cutoutPercentage ? (chart.outerRadius / 100) * (cutoutPercentage) : 0, 0); + chart.radiusLength = (chart.outerRadius - chart.innerRadius) / (me._getVisibleDatasetWeightTotal() || 1); + chart.offsetX = offset.x * chart.outerRadius; + chart.offsetY = offset.y * chart.outerRadius; + + meta.total = me.calculateTotal(); + + me.outerRadius = chart.outerRadius - chart.radiusLength * me._getRingWeightOffset(me.index); + me.innerRadius = Math.max(me.outerRadius - chart.radiusLength * chartWeight, 0); + + for (i = 0, ilen = arcs.length; i < ilen; ++i) { + me.updateElement(arcs[i], i, reset); + } + }, + + updateElement: function(arc, index, reset) { + var me = this; + var chart = me.chart; + var chartArea = chart.chartArea; + var opts = chart.options; + var animationOpts = opts.animation; + var centerX = (chartArea.left + chartArea.right) / 2; + var centerY = (chartArea.top + chartArea.bottom) / 2; + var startAngle = opts.rotation; // non reset case handled later + var endAngle = opts.rotation; // non reset case handled later + var dataset = me.getDataset(); + var circumference = reset && animationOpts.animateRotate ? 0 : arc.hidden ? 0 : me.calculateCircumference(dataset.data[index]) * (opts.circumference / (2.0 * Math.PI)); + var innerRadius = reset && animationOpts.animateScale ? 0 : me.innerRadius; + var outerRadius = reset && animationOpts.animateScale ? 0 : me.outerRadius; + var options = arc._options || {}; + + helpers$1.extend(arc, { + // Utility + _datasetIndex: me.index, + _index: index, + + // Desired view properties + _model: { + backgroundColor: options.backgroundColor, + borderColor: options.borderColor, + borderWidth: options.borderWidth, + borderAlign: options.borderAlign, + x: centerX + chart.offsetX, + y: centerY + chart.offsetY, + startAngle: startAngle, + endAngle: endAngle, + circumference: circumference, + outerRadius: outerRadius, + innerRadius: innerRadius, + label: helpers$1.valueAtIndexOrDefault(dataset.label, index, chart.data.labels[index]) + } + }); + + var model = arc._model; + + // Set correct angles if not resetting + if (!reset || !animationOpts.animateRotate) { + if (index === 0) { + model.startAngle = opts.rotation; + } else { + model.startAngle = me.getMeta().data[index - 1]._model.endAngle; + } + + model.endAngle = model.startAngle + model.circumference; + } + + arc.pivot(); + }, + + calculateTotal: function() { + var dataset = this.getDataset(); + var meta = this.getMeta(); + var total = 0; + var value; + + helpers$1.each(meta.data, function(element, index) { + value = dataset.data[index]; + if (!isNaN(value) && !element.hidden) { + total += Math.abs(value); + } + }); + + /* if (total === 0) { + total = NaN; + }*/ + + return total; + }, + + calculateCircumference: function(value) { + var total = this.getMeta().total; + if (total > 0 && !isNaN(value)) { + return (Math.PI * 2.0) * (Math.abs(value) / total); + } + return 0; + }, + + // gets the max border or hover width to properly scale pie charts + getMaxBorderWidth: function(arcs) { + var me = this; + var max = 0; + var chart = me.chart; + var i, ilen, meta, arc, controller, options, borderWidth, hoverWidth; + + if (!arcs) { + // Find the outmost visible dataset + for (i = 0, ilen = chart.data.datasets.length; i < ilen; ++i) { + if (chart.isDatasetVisible(i)) { + meta = chart.getDatasetMeta(i); + arcs = meta.data; + if (i !== me.index) { + controller = meta.controller; + } + break; + } + } + } + + if (!arcs) { + return 0; + } + + for (i = 0, ilen = arcs.length; i < ilen; ++i) { + arc = arcs[i]; + options = controller ? controller._resolveElementOptions(arc, i) : arc._options; + if (options.borderAlign !== 'inner') { + borderWidth = options.borderWidth; + hoverWidth = options.hoverBorderWidth; + + max = borderWidth > max ? borderWidth : max; + max = hoverWidth > max ? hoverWidth : max; + } + } + return max; + }, + + /** + * @protected + */ + setHoverStyle: function(arc) { + var model = arc._model; + var options = arc._options; + var getHoverColor = helpers$1.getHoverColor; + + arc.$previousStyle = { + backgroundColor: model.backgroundColor, + borderColor: model.borderColor, + borderWidth: model.borderWidth, + }; + + model.backgroundColor = valueOrDefault$4(options.hoverBackgroundColor, getHoverColor(options.backgroundColor)); + model.borderColor = valueOrDefault$4(options.hoverBorderColor, getHoverColor(options.borderColor)); + model.borderWidth = valueOrDefault$4(options.hoverBorderWidth, options.borderWidth); + }, + + /** + * @private + */ + _resolveElementOptions: function(arc, index) { + var me = this; + var chart = me.chart; + var dataset = me.getDataset(); + var custom = arc.custom || {}; + var options = chart.options.elements.arc; + var values = {}; + var i, ilen, key; + + // Scriptable options + var context = { + chart: chart, + dataIndex: index, + dataset: dataset, + datasetIndex: me.index + }; + + var keys = [ + 'backgroundColor', + 'borderColor', + 'borderWidth', + 'borderAlign', + 'hoverBackgroundColor', + 'hoverBorderColor', + 'hoverBorderWidth', + ]; + + for (i = 0, ilen = keys.length; i < ilen; ++i) { + key = keys[i]; + values[key] = resolve$3([ + custom[key], + dataset[key], + options[key] + ], context, index); + } + + return values; + }, + + /** + * Get radius length offset of the dataset in relation to the visible datasets weights. This allows determining the inner and outer radius correctly + * @private + */ + _getRingWeightOffset: function(datasetIndex) { + var ringWeightOffset = 0; + + for (var i = 0; i < datasetIndex; ++i) { + if (this.chart.isDatasetVisible(i)) { + ringWeightOffset += this._getRingWeight(i); + } + } + + return ringWeightOffset; + }, + + /** + * @private + */ + _getRingWeight: function(dataSetIndex) { + return Math.max(valueOrDefault$4(this.chart.data.datasets[dataSetIndex].weight, 1), 0); + }, + + /** + * Returns the sum of all visibile data set weights. This value can be 0. + * @private + */ + _getVisibleDatasetWeightTotal: function() { + return this._getRingWeightOffset(this.chart.data.datasets.length); + } +}); + +core_defaults._set('horizontalBar', { + hover: { + mode: 'index', + axis: 'y' + }, + + scales: { + xAxes: [{ + type: 'linear', + position: 'bottom' + }], + + yAxes: [{ + type: 'category', + position: 'left', + categoryPercentage: 0.8, + barPercentage: 0.9, + offset: true, + gridLines: { + offsetGridLines: true + } + }] + }, + + elements: { + rectangle: { + borderSkipped: 'left' + } + }, + + tooltips: { + mode: 'index', + axis: 'y' + } +}); + +var controller_horizontalBar = controller_bar.extend({ + /** + * @private + */ + _getValueScaleId: function() { + return this.getMeta().xAxisID; + }, + + /** + * @private + */ + _getIndexScaleId: function() { + return this.getMeta().yAxisID; + } +}); + +var valueOrDefault$5 = helpers$1.valueOrDefault; +var resolve$4 = helpers$1.options.resolve; +var isPointInArea = helpers$1.canvas._isPointInArea; + +core_defaults._set('line', { + showLines: true, + spanGaps: false, + + hover: { + mode: 'label' + }, + + scales: { + xAxes: [{ + type: 'category', + id: 'x-axis-0' + }], + yAxes: [{ + type: 'linear', + id: 'y-axis-0' + }] + } +}); + +function lineEnabled(dataset, options) { + return valueOrDefault$5(dataset.showLine, options.showLines); +} + +var controller_line = core_datasetController.extend({ + + datasetElementType: elements.Line, + + dataElementType: elements.Point, + + update: function(reset) { + var me = this; + var meta = me.getMeta(); + var line = meta.dataset; + var points = meta.data || []; + var scale = me.getScaleForId(meta.yAxisID); + var dataset = me.getDataset(); + var showLine = lineEnabled(dataset, me.chart.options); + var i, ilen; + + // Update Line + if (showLine) { + // Compatibility: If the properties are defined with only the old name, use those values + if ((dataset.tension !== undefined) && (dataset.lineTension === undefined)) { + dataset.lineTension = dataset.tension; + } + + // Utility + line._scale = scale; + line._datasetIndex = me.index; + // Data + line._children = points; + // Model + line._model = me._resolveLineOptions(line); + + line.pivot(); + } + + // Update Points + for (i = 0, ilen = points.length; i < ilen; ++i) { + me.updateElement(points[i], i, reset); + } + + if (showLine && line._model.tension !== 0) { + me.updateBezierControlPoints(); + } + + // Now pivot the point for animation + for (i = 0, ilen = points.length; i < ilen; ++i) { + points[i].pivot(); + } + }, + + updateElement: function(point, index, reset) { + var me = this; + var meta = me.getMeta(); + var custom = point.custom || {}; + var dataset = me.getDataset(); + var datasetIndex = me.index; + var value = dataset.data[index]; + var yScale = me.getScaleForId(meta.yAxisID); + var xScale = me.getScaleForId(meta.xAxisID); + var lineModel = meta.dataset._model; + var x, y; + + var options = me._resolvePointOptions(point, index); + + x = xScale.getPixelForValue(typeof value === 'object' ? value : NaN, index, datasetIndex); + y = reset ? yScale.getBasePixel() : me.calculatePointY(value, index, datasetIndex); + + // Utility + point._xScale = xScale; + point._yScale = yScale; + point._options = options; + point._datasetIndex = datasetIndex; + point._index = index; + + // Desired view properties + point._model = { + x: x, + y: y, + skip: custom.skip || isNaN(x) || isNaN(y), + // Appearance + radius: options.radius, + pointStyle: options.pointStyle, + rotation: options.rotation, + backgroundColor: options.backgroundColor, + borderColor: options.borderColor, + borderWidth: options.borderWidth, + tension: valueOrDefault$5(custom.tension, lineModel ? lineModel.tension : 0), + steppedLine: lineModel ? lineModel.steppedLine : false, + // Tooltip + hitRadius: options.hitRadius + }; + }, + + /** + * @private + */ + _resolvePointOptions: function(element, index) { + var me = this; + var chart = me.chart; + var dataset = chart.data.datasets[me.index]; + var custom = element.custom || {}; + var options = chart.options.elements.point; + var values = {}; + var i, ilen, key; + + // Scriptable options + var context = { + chart: chart, + dataIndex: index, + dataset: dataset, + datasetIndex: me.index + }; + + var ELEMENT_OPTIONS = { + backgroundColor: 'pointBackgroundColor', + borderColor: 'pointBorderColor', + borderWidth: 'pointBorderWidth', + hitRadius: 'pointHitRadius', + hoverBackgroundColor: 'pointHoverBackgroundColor', + hoverBorderColor: 'pointHoverBorderColor', + hoverBorderWidth: 'pointHoverBorderWidth', + hoverRadius: 'pointHoverRadius', + pointStyle: 'pointStyle', + radius: 'pointRadius', + rotation: 'pointRotation' + }; + var keys = Object.keys(ELEMENT_OPTIONS); + + for (i = 0, ilen = keys.length; i < ilen; ++i) { + key = keys[i]; + values[key] = resolve$4([ + custom[key], + dataset[ELEMENT_OPTIONS[key]], + dataset[key], + options[key] + ], context, index); + } + + return values; + }, + + /** + * @private + */ + _resolveLineOptions: function(element) { + var me = this; + var chart = me.chart; + var dataset = chart.data.datasets[me.index]; + var custom = element.custom || {}; + var options = chart.options; + var elementOptions = options.elements.line; + var values = {}; + var i, ilen, key; + + var keys = [ + 'backgroundColor', + 'borderWidth', + 'borderColor', + 'borderCapStyle', + 'borderDash', + 'borderDashOffset', + 'borderJoinStyle', + 'fill', + 'cubicInterpolationMode' + ]; + + for (i = 0, ilen = keys.length; i < ilen; ++i) { + key = keys[i]; + values[key] = resolve$4([ + custom[key], + dataset[key], + elementOptions[key] + ]); + } + + // The default behavior of lines is to break at null values, according + // to https://github.com/chartjs/Chart.js/issues/2435#issuecomment-216718158 + // This option gives lines the ability to span gaps + values.spanGaps = valueOrDefault$5(dataset.spanGaps, options.spanGaps); + values.tension = valueOrDefault$5(dataset.lineTension, elementOptions.tension); + values.steppedLine = resolve$4([custom.steppedLine, dataset.steppedLine, elementOptions.stepped]); + + return values; + }, + + calculatePointY: function(value, index, datasetIndex) { + var me = this; + var chart = me.chart; + var meta = me.getMeta(); + var yScale = me.getScaleForId(meta.yAxisID); + var sumPos = 0; + var sumNeg = 0; + var i, ds, dsMeta; + + if (yScale.options.stacked) { + for (i = 0; i < datasetIndex; i++) { + ds = chart.data.datasets[i]; + dsMeta = chart.getDatasetMeta(i); + if (dsMeta.type === 'line' && dsMeta.yAxisID === yScale.id && chart.isDatasetVisible(i)) { + var stackedRightValue = Number(yScale.getRightValue(ds.data[index])); + if (stackedRightValue < 0) { + sumNeg += stackedRightValue || 0; + } else { + sumPos += stackedRightValue || 0; + } + } + } + + var rightValue = Number(yScale.getRightValue(value)); + if (rightValue < 0) { + return yScale.getPixelForValue(sumNeg + rightValue); + } + return yScale.getPixelForValue(sumPos + rightValue); + } + + return yScale.getPixelForValue(value); + }, + + updateBezierControlPoints: function() { + var me = this; + var chart = me.chart; + var meta = me.getMeta(); + var lineModel = meta.dataset._model; + var area = chart.chartArea; + var points = meta.data || []; + var i, ilen, model, controlPoints; + + // Only consider points that are drawn in case the spanGaps option is used + if (lineModel.spanGaps) { + points = points.filter(function(pt) { + return !pt._model.skip; + }); + } + + function capControlPoint(pt, min, max) { + return Math.max(Math.min(pt, max), min); + } + + if (lineModel.cubicInterpolationMode === 'monotone') { + helpers$1.splineCurveMonotone(points); + } else { + for (i = 0, ilen = points.length; i < ilen; ++i) { + model = points[i]._model; + controlPoints = helpers$1.splineCurve( + helpers$1.previousItem(points, i)._model, + model, + helpers$1.nextItem(points, i)._model, + lineModel.tension + ); + model.controlPointPreviousX = controlPoints.previous.x; + model.controlPointPreviousY = controlPoints.previous.y; + model.controlPointNextX = controlPoints.next.x; + model.controlPointNextY = controlPoints.next.y; + } + } + + if (chart.options.elements.line.capBezierPoints) { + for (i = 0, ilen = points.length; i < ilen; ++i) { + model = points[i]._model; + if (isPointInArea(model, area)) { + if (i > 0 && isPointInArea(points[i - 1]._model, area)) { + model.controlPointPreviousX = capControlPoint(model.controlPointPreviousX, area.left, area.right); + model.controlPointPreviousY = capControlPoint(model.controlPointPreviousY, area.top, area.bottom); + } + if (i < points.length - 1 && isPointInArea(points[i + 1]._model, area)) { + model.controlPointNextX = capControlPoint(model.controlPointNextX, area.left, area.right); + model.controlPointNextY = capControlPoint(model.controlPointNextY, area.top, area.bottom); + } + } + } + } + }, + + draw: function() { + var me = this; + var chart = me.chart; + var meta = me.getMeta(); + var points = meta.data || []; + var area = chart.chartArea; + var ilen = points.length; + var halfBorderWidth; + var i = 0; + + if (lineEnabled(me.getDataset(), chart.options)) { + halfBorderWidth = (meta.dataset._model.borderWidth || 0) / 2; + + helpers$1.canvas.clipArea(chart.ctx, { + left: area.left, + right: area.right, + top: area.top - halfBorderWidth, + bottom: area.bottom + halfBorderWidth + }); + + meta.dataset.draw(); + + helpers$1.canvas.unclipArea(chart.ctx); + } + + // Draw the points + for (; i < ilen; ++i) { + points[i].draw(area); + } + }, + + /** + * @protected + */ + setHoverStyle: function(point) { + var model = point._model; + var options = point._options; + var getHoverColor = helpers$1.getHoverColor; + + point.$previousStyle = { + backgroundColor: model.backgroundColor, + borderColor: model.borderColor, + borderWidth: model.borderWidth, + radius: model.radius + }; + + model.backgroundColor = valueOrDefault$5(options.hoverBackgroundColor, getHoverColor(options.backgroundColor)); + model.borderColor = valueOrDefault$5(options.hoverBorderColor, getHoverColor(options.borderColor)); + model.borderWidth = valueOrDefault$5(options.hoverBorderWidth, options.borderWidth); + model.radius = valueOrDefault$5(options.hoverRadius, options.radius); + }, +}); + +var resolve$5 = helpers$1.options.resolve; + +core_defaults._set('polarArea', { + scale: { + type: 'radialLinear', + angleLines: { + display: false + }, + gridLines: { + circular: true + }, + pointLabels: { + display: false + }, + ticks: { + beginAtZero: true + } + }, + + // Boolean - Whether to animate the rotation of the chart + animation: { + animateRotate: true, + animateScale: true + }, + + startAngle: -0.5 * Math.PI, + legendCallback: function(chart) { + var text = []; + text.push('
    '); + + var data = chart.data; + var datasets = data.datasets; + var labels = data.labels; + + if (datasets.length) { + for (var i = 0; i < datasets[0].data.length; ++i) { + text.push('
  • '); + if (labels[i]) { + text.push(labels[i]); + } + text.push('
  • '); + } + } + + text.push('
'); + return text.join(''); + }, + legend: { + labels: { + generateLabels: function(chart) { + var data = chart.data; + if (data.labels.length && data.datasets.length) { + return data.labels.map(function(label, i) { + var meta = chart.getDatasetMeta(0); + var ds = data.datasets[0]; + var arc = meta.data[i]; + var custom = arc.custom || {}; + var arcOpts = chart.options.elements.arc; + var fill = resolve$5([custom.backgroundColor, ds.backgroundColor, arcOpts.backgroundColor], undefined, i); + var stroke = resolve$5([custom.borderColor, ds.borderColor, arcOpts.borderColor], undefined, i); + var bw = resolve$5([custom.borderWidth, ds.borderWidth, arcOpts.borderWidth], undefined, i); + + return { + text: label, + fillStyle: fill, + strokeStyle: stroke, + lineWidth: bw, + hidden: isNaN(ds.data[i]) || meta.data[i].hidden, + + // Extra data used for toggling the correct item + index: i + }; + }); + } + return []; + } + }, + + onClick: function(e, legendItem) { + var index = legendItem.index; + var chart = this.chart; + var i, ilen, meta; + + for (i = 0, ilen = (chart.data.datasets || []).length; i < ilen; ++i) { + meta = chart.getDatasetMeta(i); + meta.data[index].hidden = !meta.data[index].hidden; + } + + chart.update(); + } + }, + + // Need to override these to give a nice default + tooltips: { + callbacks: { + title: function() { + return ''; + }, + label: function(item, data) { + return data.labels[item.index] + ': ' + item.yLabel; + } + } + } +}); + +var controller_polarArea = core_datasetController.extend({ + + dataElementType: elements.Arc, + + linkScales: helpers$1.noop, + + update: function(reset) { + var me = this; + var dataset = me.getDataset(); + var meta = me.getMeta(); + var start = me.chart.options.startAngle || 0; + var starts = me._starts = []; + var angles = me._angles = []; + var arcs = meta.data; + var i, ilen, angle; + + me._updateRadius(); + + meta.count = me.countVisibleElements(); + + for (i = 0, ilen = dataset.data.length; i < ilen; i++) { + starts[i] = start; + angle = me._computeAngle(i); + angles[i] = angle; + start += angle; + } + + for (i = 0, ilen = arcs.length; i < ilen; ++i) { + arcs[i]._options = me._resolveElementOptions(arcs[i], i); + me.updateElement(arcs[i], i, reset); + } + }, + + /** + * @private + */ + _updateRadius: function() { + var me = this; + var chart = me.chart; + var chartArea = chart.chartArea; + var opts = chart.options; + var minSize = Math.min(chartArea.right - chartArea.left, chartArea.bottom - chartArea.top); + + chart.outerRadius = Math.max(minSize / 2, 0); + chart.innerRadius = Math.max(opts.cutoutPercentage ? (chart.outerRadius / 100) * (opts.cutoutPercentage) : 1, 0); + chart.radiusLength = (chart.outerRadius - chart.innerRadius) / chart.getVisibleDatasetCount(); + + me.outerRadius = chart.outerRadius - (chart.radiusLength * me.index); + me.innerRadius = me.outerRadius - chart.radiusLength; + }, + + updateElement: function(arc, index, reset) { + var me = this; + var chart = me.chart; + var dataset = me.getDataset(); + var opts = chart.options; + var animationOpts = opts.animation; + var scale = chart.scale; + var labels = chart.data.labels; + + var centerX = scale.xCenter; + var centerY = scale.yCenter; + + // var negHalfPI = -0.5 * Math.PI; + var datasetStartAngle = opts.startAngle; + var distance = arc.hidden ? 0 : scale.getDistanceFromCenterForValue(dataset.data[index]); + var startAngle = me._starts[index]; + var endAngle = startAngle + (arc.hidden ? 0 : me._angles[index]); + + var resetRadius = animationOpts.animateScale ? 0 : scale.getDistanceFromCenterForValue(dataset.data[index]); + var options = arc._options || {}; + + helpers$1.extend(arc, { + // Utility + _datasetIndex: me.index, + _index: index, + _scale: scale, + + // Desired view properties + _model: { + backgroundColor: options.backgroundColor, + borderColor: options.borderColor, + borderWidth: options.borderWidth, + borderAlign: options.borderAlign, + x: centerX, + y: centerY, + innerRadius: 0, + outerRadius: reset ? resetRadius : distance, + startAngle: reset && animationOpts.animateRotate ? datasetStartAngle : startAngle, + endAngle: reset && animationOpts.animateRotate ? datasetStartAngle : endAngle, + label: helpers$1.valueAtIndexOrDefault(labels, index, labels[index]) + } + }); + + arc.pivot(); + }, + + countVisibleElements: function() { + var dataset = this.getDataset(); + var meta = this.getMeta(); + var count = 0; + + helpers$1.each(meta.data, function(element, index) { + if (!isNaN(dataset.data[index]) && !element.hidden) { + count++; + } + }); + + return count; + }, + + /** + * @protected + */ + setHoverStyle: function(arc) { + var model = arc._model; + var options = arc._options; + var getHoverColor = helpers$1.getHoverColor; + var valueOrDefault = helpers$1.valueOrDefault; + + arc.$previousStyle = { + backgroundColor: model.backgroundColor, + borderColor: model.borderColor, + borderWidth: model.borderWidth, + }; + + model.backgroundColor = valueOrDefault(options.hoverBackgroundColor, getHoverColor(options.backgroundColor)); + model.borderColor = valueOrDefault(options.hoverBorderColor, getHoverColor(options.borderColor)); + model.borderWidth = valueOrDefault(options.hoverBorderWidth, options.borderWidth); + }, + + /** + * @private + */ + _resolveElementOptions: function(arc, index) { + var me = this; + var chart = me.chart; + var dataset = me.getDataset(); + var custom = arc.custom || {}; + var options = chart.options.elements.arc; + var values = {}; + var i, ilen, key; + + // Scriptable options + var context = { + chart: chart, + dataIndex: index, + dataset: dataset, + datasetIndex: me.index + }; + + var keys = [ + 'backgroundColor', + 'borderColor', + 'borderWidth', + 'borderAlign', + 'hoverBackgroundColor', + 'hoverBorderColor', + 'hoverBorderWidth', + ]; + + for (i = 0, ilen = keys.length; i < ilen; ++i) { + key = keys[i]; + values[key] = resolve$5([ + custom[key], + dataset[key], + options[key] + ], context, index); + } + + return values; + }, + + /** + * @private + */ + _computeAngle: function(index) { + var me = this; + var count = this.getMeta().count; + var dataset = me.getDataset(); + var meta = me.getMeta(); + + if (isNaN(dataset.data[index]) || meta.data[index].hidden) { + return 0; + } + + // Scriptable options + var context = { + chart: me.chart, + dataIndex: index, + dataset: dataset, + datasetIndex: me.index + }; + + return resolve$5([ + me.chart.options.elements.arc.angle, + (2 * Math.PI) / count + ], context, index); + } +}); + +core_defaults._set('pie', helpers$1.clone(core_defaults.doughnut)); +core_defaults._set('pie', { + cutoutPercentage: 0 +}); + +// Pie charts are Doughnut chart with different defaults +var controller_pie = controller_doughnut; + +var valueOrDefault$6 = helpers$1.valueOrDefault; +var resolve$6 = helpers$1.options.resolve; + +core_defaults._set('radar', { + scale: { + type: 'radialLinear' + }, + elements: { + line: { + tension: 0 // no bezier in radar + } + } +}); + +var controller_radar = core_datasetController.extend({ + + datasetElementType: elements.Line, + + dataElementType: elements.Point, + + linkScales: helpers$1.noop, + + update: function(reset) { + var me = this; + var meta = me.getMeta(); + var line = meta.dataset; + var points = meta.data || []; + var scale = me.chart.scale; + var dataset = me.getDataset(); + var i, ilen; + + // Compatibility: If the properties are defined with only the old name, use those values + if ((dataset.tension !== undefined) && (dataset.lineTension === undefined)) { + dataset.lineTension = dataset.tension; + } + + // Utility + line._scale = scale; + line._datasetIndex = me.index; + // Data + line._children = points; + line._loop = true; + // Model + line._model = me._resolveLineOptions(line); + + line.pivot(); + + // Update Points + for (i = 0, ilen = points.length; i < ilen; ++i) { + me.updateElement(points[i], i, reset); + } + + // Update bezier control points + me.updateBezierControlPoints(); + + // Now pivot the point for animation + for (i = 0, ilen = points.length; i < ilen; ++i) { + points[i].pivot(); + } + }, + + updateElement: function(point, index, reset) { + var me = this; + var custom = point.custom || {}; + var dataset = me.getDataset(); + var scale = me.chart.scale; + var pointPosition = scale.getPointPositionForValue(index, dataset.data[index]); + var options = me._resolvePointOptions(point, index); + var lineModel = me.getMeta().dataset._model; + var x = reset ? scale.xCenter : pointPosition.x; + var y = reset ? scale.yCenter : pointPosition.y; + + // Utility + point._scale = scale; + point._options = options; + point._datasetIndex = me.index; + point._index = index; + + // Desired view properties + point._model = { + x: x, // value not used in dataset scale, but we want a consistent API between scales + y: y, + skip: custom.skip || isNaN(x) || isNaN(y), + // Appearance + radius: options.radius, + pointStyle: options.pointStyle, + rotation: options.rotation, + backgroundColor: options.backgroundColor, + borderColor: options.borderColor, + borderWidth: options.borderWidth, + tension: valueOrDefault$6(custom.tension, lineModel ? lineModel.tension : 0), + + // Tooltip + hitRadius: options.hitRadius + }; + }, + + /** + * @private + */ + _resolvePointOptions: function(element, index) { + var me = this; + var chart = me.chart; + var dataset = chart.data.datasets[me.index]; + var custom = element.custom || {}; + var options = chart.options.elements.point; + var values = {}; + var i, ilen, key; + + // Scriptable options + var context = { + chart: chart, + dataIndex: index, + dataset: dataset, + datasetIndex: me.index + }; + + var ELEMENT_OPTIONS = { + backgroundColor: 'pointBackgroundColor', + borderColor: 'pointBorderColor', + borderWidth: 'pointBorderWidth', + hitRadius: 'pointHitRadius', + hoverBackgroundColor: 'pointHoverBackgroundColor', + hoverBorderColor: 'pointHoverBorderColor', + hoverBorderWidth: 'pointHoverBorderWidth', + hoverRadius: 'pointHoverRadius', + pointStyle: 'pointStyle', + radius: 'pointRadius', + rotation: 'pointRotation' + }; + var keys = Object.keys(ELEMENT_OPTIONS); + + for (i = 0, ilen = keys.length; i < ilen; ++i) { + key = keys[i]; + values[key] = resolve$6([ + custom[key], + dataset[ELEMENT_OPTIONS[key]], + dataset[key], + options[key] + ], context, index); + } + + return values; + }, + + /** + * @private + */ + _resolveLineOptions: function(element) { + var me = this; + var chart = me.chart; + var dataset = chart.data.datasets[me.index]; + var custom = element.custom || {}; + var options = chart.options.elements.line; + var values = {}; + var i, ilen, key; + + var keys = [ + 'backgroundColor', + 'borderWidth', + 'borderColor', + 'borderCapStyle', + 'borderDash', + 'borderDashOffset', + 'borderJoinStyle', + 'fill' + ]; + + for (i = 0, ilen = keys.length; i < ilen; ++i) { + key = keys[i]; + values[key] = resolve$6([ + custom[key], + dataset[key], + options[key] + ]); + } + + values.tension = valueOrDefault$6(dataset.lineTension, options.tension); + + return values; + }, + + updateBezierControlPoints: function() { + var me = this; + var meta = me.getMeta(); + var area = me.chart.chartArea; + var points = meta.data || []; + var i, ilen, model, controlPoints; + + function capControlPoint(pt, min, max) { + return Math.max(Math.min(pt, max), min); + } + + for (i = 0, ilen = points.length; i < ilen; ++i) { + model = points[i]._model; + controlPoints = helpers$1.splineCurve( + helpers$1.previousItem(points, i, true)._model, + model, + helpers$1.nextItem(points, i, true)._model, + model.tension + ); + + // Prevent the bezier going outside of the bounds of the graph + model.controlPointPreviousX = capControlPoint(controlPoints.previous.x, area.left, area.right); + model.controlPointPreviousY = capControlPoint(controlPoints.previous.y, area.top, area.bottom); + model.controlPointNextX = capControlPoint(controlPoints.next.x, area.left, area.right); + model.controlPointNextY = capControlPoint(controlPoints.next.y, area.top, area.bottom); + } + }, + + setHoverStyle: function(point) { + var model = point._model; + var options = point._options; + var getHoverColor = helpers$1.getHoverColor; + + point.$previousStyle = { + backgroundColor: model.backgroundColor, + borderColor: model.borderColor, + borderWidth: model.borderWidth, + radius: model.radius + }; + + model.backgroundColor = valueOrDefault$6(options.hoverBackgroundColor, getHoverColor(options.backgroundColor)); + model.borderColor = valueOrDefault$6(options.hoverBorderColor, getHoverColor(options.borderColor)); + model.borderWidth = valueOrDefault$6(options.hoverBorderWidth, options.borderWidth); + model.radius = valueOrDefault$6(options.hoverRadius, options.radius); + } +}); + +core_defaults._set('scatter', { + hover: { + mode: 'single' + }, + + scales: { + xAxes: [{ + id: 'x-axis-1', // need an ID so datasets can reference the scale + type: 'linear', // scatter should not use a category axis + position: 'bottom' + }], + yAxes: [{ + id: 'y-axis-1', + type: 'linear', + position: 'left' + }] + }, + + showLines: false, + + tooltips: { + callbacks: { + title: function() { + return ''; // doesn't make sense for scatter since data are formatted as a point + }, + label: function(item) { + return '(' + item.xLabel + ', ' + item.yLabel + ')'; + } + } + } +}); + +// Scatter charts use line controllers +var controller_scatter = controller_line; + +// NOTE export a map in which the key represents the controller type, not +// the class, and so must be CamelCase in order to be correctly retrieved +// by the controller in core.controller.js (`controllers[meta.type]`). + +var controllers = { + bar: controller_bar, + bubble: controller_bubble, + doughnut: controller_doughnut, + horizontalBar: controller_horizontalBar, + line: controller_line, + polarArea: controller_polarArea, + pie: controller_pie, + radar: controller_radar, + scatter: controller_scatter +}; + +/** + * Helper function to get relative position for an event + * @param {Event|IEvent} event - The event to get the position for + * @param {Chart} chart - The chart + * @returns {object} the event position + */ +function getRelativePosition(e, chart) { + if (e.native) { + return { + x: e.x, + y: e.y + }; + } + + return helpers$1.getRelativePosition(e, chart); +} + +/** + * Helper function to traverse all of the visible elements in the chart + * @param {Chart} chart - the chart + * @param {function} handler - the callback to execute for each visible item + */ +function parseVisibleItems(chart, handler) { + var datasets = chart.data.datasets; + var meta, i, j, ilen, jlen; + + for (i = 0, ilen = datasets.length; i < ilen; ++i) { + if (!chart.isDatasetVisible(i)) { + continue; + } + + meta = chart.getDatasetMeta(i); + for (j = 0, jlen = meta.data.length; j < jlen; ++j) { + var element = meta.data[j]; + if (!element._view.skip) { + handler(element); + } + } + } +} + +/** + * Helper function to get the items that intersect the event position + * @param {ChartElement[]} items - elements to filter + * @param {object} position - the point to be nearest to + * @return {ChartElement[]} the nearest items + */ +function getIntersectItems(chart, position) { + var elements = []; + + parseVisibleItems(chart, function(element) { + if (element.inRange(position.x, position.y)) { + elements.push(element); + } + }); + + return elements; +} + +/** + * Helper function to get the items nearest to the event position considering all visible items in teh chart + * @param {Chart} chart - the chart to look at elements from + * @param {object} position - the point to be nearest to + * @param {boolean} intersect - if true, only consider items that intersect the position + * @param {function} distanceMetric - function to provide the distance between points + * @return {ChartElement[]} the nearest items + */ +function getNearestItems(chart, position, intersect, distanceMetric) { + var minDistance = Number.POSITIVE_INFINITY; + var nearestItems = []; + + parseVisibleItems(chart, function(element) { + if (intersect && !element.inRange(position.x, position.y)) { + return; + } + + var center = element.getCenterPoint(); + var distance = distanceMetric(position, center); + if (distance < minDistance) { + nearestItems = [element]; + minDistance = distance; + } else if (distance === minDistance) { + // Can have multiple items at the same distance in which case we sort by size + nearestItems.push(element); + } + }); + + return nearestItems; +} + +/** + * Get a distance metric function for two points based on the + * axis mode setting + * @param {string} axis - the axis mode. x|y|xy + */ +function getDistanceMetricForAxis(axis) { + var useX = axis.indexOf('x') !== -1; + var useY = axis.indexOf('y') !== -1; + + return function(pt1, pt2) { + var deltaX = useX ? Math.abs(pt1.x - pt2.x) : 0; + var deltaY = useY ? Math.abs(pt1.y - pt2.y) : 0; + return Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY, 2)); + }; +} + +function indexMode(chart, e, options) { + var position = getRelativePosition(e, chart); + // Default axis for index mode is 'x' to match old behaviour + options.axis = options.axis || 'x'; + var distanceMetric = getDistanceMetricForAxis(options.axis); + var items = options.intersect ? getIntersectItems(chart, position) : getNearestItems(chart, position, false, distanceMetric); + var elements = []; + + if (!items.length) { + return []; + } + + chart.data.datasets.forEach(function(dataset, datasetIndex) { + if (chart.isDatasetVisible(datasetIndex)) { + var meta = chart.getDatasetMeta(datasetIndex); + var element = meta.data[items[0]._index]; + + // don't count items that are skipped (null data) + if (element && !element._view.skip) { + elements.push(element); + } + } + }); + + return elements; +} + +/** + * @interface IInteractionOptions + */ +/** + * If true, only consider items that intersect the point + * @name IInterfaceOptions#boolean + * @type Boolean + */ + +/** + * Contains interaction related functions + * @namespace Chart.Interaction + */ +var core_interaction = { + // Helper function for different modes + modes: { + single: function(chart, e) { + var position = getRelativePosition(e, chart); + var elements = []; + + parseVisibleItems(chart, function(element) { + if (element.inRange(position.x, position.y)) { + elements.push(element); + return elements; + } + }); + + return elements.slice(0, 1); + }, + + /** + * @function Chart.Interaction.modes.label + * @deprecated since version 2.4.0 + * @todo remove at version 3 + * @private + */ + label: indexMode, + + /** + * Returns items at the same index. If the options.intersect parameter is true, we only return items if we intersect something + * If the options.intersect mode is false, we find the nearest item and return the items at the same index as that item + * @function Chart.Interaction.modes.index + * @since v2.4.0 + * @param {Chart} chart - the chart we are returning items from + * @param {Event} e - the event we are find things at + * @param {IInteractionOptions} options - options to use during interaction + * @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned + */ + index: indexMode, + + /** + * Returns items in the same dataset. If the options.intersect parameter is true, we only return items if we intersect something + * If the options.intersect is false, we find the nearest item and return the items in that dataset + * @function Chart.Interaction.modes.dataset + * @param {Chart} chart - the chart we are returning items from + * @param {Event} e - the event we are find things at + * @param {IInteractionOptions} options - options to use during interaction + * @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned + */ + dataset: function(chart, e, options) { + var position = getRelativePosition(e, chart); + options.axis = options.axis || 'xy'; + var distanceMetric = getDistanceMetricForAxis(options.axis); + var items = options.intersect ? getIntersectItems(chart, position) : getNearestItems(chart, position, false, distanceMetric); + + if (items.length > 0) { + items = chart.getDatasetMeta(items[0]._datasetIndex).data; + } + + return items; + }, + + /** + * @function Chart.Interaction.modes.x-axis + * @deprecated since version 2.4.0. Use index mode and intersect == true + * @todo remove at version 3 + * @private + */ + 'x-axis': function(chart, e) { + return indexMode(chart, e, {intersect: false}); + }, + + /** + * Point mode returns all elements that hit test based on the event position + * of the event + * @function Chart.Interaction.modes.intersect + * @param {Chart} chart - the chart we are returning items from + * @param {Event} e - the event we are find things at + * @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned + */ + point: function(chart, e) { + var position = getRelativePosition(e, chart); + return getIntersectItems(chart, position); + }, + + /** + * nearest mode returns the element closest to the point + * @function Chart.Interaction.modes.intersect + * @param {Chart} chart - the chart we are returning items from + * @param {Event} e - the event we are find things at + * @param {IInteractionOptions} options - options to use + * @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned + */ + nearest: function(chart, e, options) { + var position = getRelativePosition(e, chart); + options.axis = options.axis || 'xy'; + var distanceMetric = getDistanceMetricForAxis(options.axis); + return getNearestItems(chart, position, options.intersect, distanceMetric); + }, + + /** + * x mode returns the elements that hit-test at the current x coordinate + * @function Chart.Interaction.modes.x + * @param {Chart} chart - the chart we are returning items from + * @param {Event} e - the event we are find things at + * @param {IInteractionOptions} options - options to use + * @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned + */ + x: function(chart, e, options) { + var position = getRelativePosition(e, chart); + var items = []; + var intersectsItem = false; + + parseVisibleItems(chart, function(element) { + if (element.inXRange(position.x)) { + items.push(element); + } + + if (element.inRange(position.x, position.y)) { + intersectsItem = true; + } + }); + + // If we want to trigger on an intersect and we don't have any items + // that intersect the position, return nothing + if (options.intersect && !intersectsItem) { + items = []; + } + return items; + }, + + /** + * y mode returns the elements that hit-test at the current y coordinate + * @function Chart.Interaction.modes.y + * @param {Chart} chart - the chart we are returning items from + * @param {Event} e - the event we are find things at + * @param {IInteractionOptions} options - options to use + * @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned + */ + y: function(chart, e, options) { + var position = getRelativePosition(e, chart); + var items = []; + var intersectsItem = false; + + parseVisibleItems(chart, function(element) { + if (element.inYRange(position.y)) { + items.push(element); + } + + if (element.inRange(position.x, position.y)) { + intersectsItem = true; + } + }); + + // If we want to trigger on an intersect and we don't have any items + // that intersect the position, return nothing + if (options.intersect && !intersectsItem) { + items = []; + } + return items; + } + } +}; + +function filterByPosition(array, position) { + return helpers$1.where(array, function(v) { + return v.position === position; + }); +} + +function sortByWeight(array, reverse) { + array.forEach(function(v, i) { + v._tmpIndex_ = i; + return v; + }); + array.sort(function(a, b) { + var v0 = reverse ? b : a; + var v1 = reverse ? a : b; + return v0.weight === v1.weight ? + v0._tmpIndex_ - v1._tmpIndex_ : + v0.weight - v1.weight; + }); + array.forEach(function(v) { + delete v._tmpIndex_; + }); +} + +function findMaxPadding(boxes) { + var top = 0; + var left = 0; + var bottom = 0; + var right = 0; + helpers$1.each(boxes, function(box) { + if (box.getPadding) { + var boxPadding = box.getPadding(); + top = Math.max(top, boxPadding.top); + left = Math.max(left, boxPadding.left); + bottom = Math.max(bottom, boxPadding.bottom); + right = Math.max(right, boxPadding.right); + } + }); + return { + top: top, + left: left, + bottom: bottom, + right: right + }; +} + +function addSizeByPosition(boxes, size) { + helpers$1.each(boxes, function(box) { + size[box.position] += box.isHorizontal() ? box.height : box.width; + }); +} + +core_defaults._set('global', { + layout: { + padding: { + top: 0, + right: 0, + bottom: 0, + left: 0 + } + } +}); + +/** + * @interface ILayoutItem + * @prop {string} position - The position of the item in the chart layout. Possible values are + * 'left', 'top', 'right', 'bottom', and 'chartArea' + * @prop {number} weight - The weight used to sort the item. Higher weights are further away from the chart area + * @prop {boolean} fullWidth - if true, and the item is horizontal, then push vertical boxes down + * @prop {function} isHorizontal - returns true if the layout item is horizontal (ie. top or bottom) + * @prop {function} update - Takes two parameters: width and height. Returns size of item + * @prop {function} getPadding - Returns an object with padding on the edges + * @prop {number} width - Width of item. Must be valid after update() + * @prop {number} height - Height of item. Must be valid after update() + * @prop {number} left - Left edge of the item. Set by layout system and cannot be used in update + * @prop {number} top - Top edge of the item. Set by layout system and cannot be used in update + * @prop {number} right - Right edge of the item. Set by layout system and cannot be used in update + * @prop {number} bottom - Bottom edge of the item. Set by layout system and cannot be used in update + */ + +// The layout service is very self explanatory. It's responsible for the layout within a chart. +// Scales, Legends and Plugins all rely on the layout service and can easily register to be placed anywhere they need +// It is this service's responsibility of carrying out that layout. +var core_layouts = { + defaults: {}, + + /** + * Register a box to a chart. + * A box is simply a reference to an object that requires layout. eg. Scales, Legend, Title. + * @param {Chart} chart - the chart to use + * @param {ILayoutItem} item - the item to add to be layed out + */ + addBox: function(chart, item) { + if (!chart.boxes) { + chart.boxes = []; + } + + // initialize item with default values + item.fullWidth = item.fullWidth || false; + item.position = item.position || 'top'; + item.weight = item.weight || 0; + + chart.boxes.push(item); + }, + + /** + * Remove a layoutItem from a chart + * @param {Chart} chart - the chart to remove the box from + * @param {ILayoutItem} layoutItem - the item to remove from the layout + */ + removeBox: function(chart, layoutItem) { + var index = chart.boxes ? chart.boxes.indexOf(layoutItem) : -1; + if (index !== -1) { + chart.boxes.splice(index, 1); + } + }, + + /** + * Sets (or updates) options on the given `item`. + * @param {Chart} chart - the chart in which the item lives (or will be added to) + * @param {ILayoutItem} item - the item to configure with the given options + * @param {object} options - the new item options. + */ + configure: function(chart, item, options) { + var props = ['fullWidth', 'position', 'weight']; + var ilen = props.length; + var i = 0; + var prop; + + for (; i < ilen; ++i) { + prop = props[i]; + if (options.hasOwnProperty(prop)) { + item[prop] = options[prop]; + } + } + }, + + /** + * Fits boxes of the given chart into the given size by having each box measure itself + * then running a fitting algorithm + * @param {Chart} chart - the chart + * @param {number} width - the width to fit into + * @param {number} height - the height to fit into + */ + update: function(chart, width, height) { + if (!chart) { + return; + } + + var layoutOptions = chart.options.layout || {}; + var padding = helpers$1.options.toPadding(layoutOptions.padding); + var leftPadding = padding.left; + var rightPadding = padding.right; + var topPadding = padding.top; + var bottomPadding = padding.bottom; + + var leftBoxes = filterByPosition(chart.boxes, 'left'); + var rightBoxes = filterByPosition(chart.boxes, 'right'); + var topBoxes = filterByPosition(chart.boxes, 'top'); + var bottomBoxes = filterByPosition(chart.boxes, 'bottom'); + var chartAreaBoxes = filterByPosition(chart.boxes, 'chartArea'); + + // Sort boxes by weight. A higher weight is further away from the chart area + sortByWeight(leftBoxes, true); + sortByWeight(rightBoxes, false); + sortByWeight(topBoxes, true); + sortByWeight(bottomBoxes, false); + + var verticalBoxes = leftBoxes.concat(rightBoxes); + var horizontalBoxes = topBoxes.concat(bottomBoxes); + var outerBoxes = verticalBoxes.concat(horizontalBoxes); + + // Essentially we now have any number of boxes on each of the 4 sides. + // Our canvas looks like the following. + // The areas L1 and L2 are the left axes. R1 is the right axis, T1 is the top axis and + // B1 is the bottom axis + // There are also 4 quadrant-like locations (left to right instead of clockwise) reserved for chart overlays + // These locations are single-box locations only, when trying to register a chartArea location that is already taken, + // an error will be thrown. + // + // |----------------------------------------------------| + // | T1 (Full Width) | + // |----------------------------------------------------| + // | | | T2 | | + // | |----|-------------------------------------|----| + // | | | C1 | | C2 | | + // | | |----| |----| | + // | | | | | + // | L1 | L2 | ChartArea (C0) | R1 | + // | | | | | + // | | |----| |----| | + // | | | C3 | | C4 | | + // | |----|-------------------------------------|----| + // | | | B1 | | + // |----------------------------------------------------| + // | B2 (Full Width) | + // |----------------------------------------------------| + // + // What we do to find the best sizing, we do the following + // 1. Determine the minimum size of the chart area. + // 2. Split the remaining width equally between each vertical axis + // 3. Split the remaining height equally between each horizontal axis + // 4. Give each layout the maximum size it can be. The layout will return it's minimum size + // 5. Adjust the sizes of each axis based on it's minimum reported size. + // 6. Refit each axis + // 7. Position each axis in the final location + // 8. Tell the chart the final location of the chart area + // 9. Tell any axes that overlay the chart area the positions of the chart area + + // Step 1 + var chartWidth = width - leftPadding - rightPadding; + var chartHeight = height - topPadding - bottomPadding; + var chartAreaWidth = chartWidth / 2; // min 50% + + // Step 2 + var verticalBoxWidth = (width - chartAreaWidth) / verticalBoxes.length; + + // Step 3 + // TODO re-limit horizontal axis height (this limit has affected only padding calculation since PR 1837) + // var horizontalBoxHeight = (height - chartAreaHeight) / horizontalBoxes.length; + + // Step 4 + var maxChartAreaWidth = chartWidth; + var maxChartAreaHeight = chartHeight; + var outerBoxSizes = {top: topPadding, left: leftPadding, bottom: bottomPadding, right: rightPadding}; + var minBoxSizes = []; + var maxPadding; + + function getMinimumBoxSize(box) { + var minSize; + var isHorizontal = box.isHorizontal(); + + if (isHorizontal) { + minSize = box.update(box.fullWidth ? chartWidth : maxChartAreaWidth, chartHeight / 2); + maxChartAreaHeight -= minSize.height; + } else { + minSize = box.update(verticalBoxWidth, maxChartAreaHeight); + maxChartAreaWidth -= minSize.width; + } + + minBoxSizes.push({ + horizontal: isHorizontal, + width: minSize.width, + box: box, + }); + } + + helpers$1.each(outerBoxes, getMinimumBoxSize); + + // If a horizontal box has padding, we move the left boxes over to avoid ugly charts (see issue #2478) + maxPadding = findMaxPadding(outerBoxes); + + // At this point, maxChartAreaHeight and maxChartAreaWidth are the size the chart area could + // be if the axes are drawn at their minimum sizes. + // Steps 5 & 6 + + // Function to fit a box + function fitBox(box) { + var minBoxSize = helpers$1.findNextWhere(minBoxSizes, function(minBox) { + return minBox.box === box; + }); + + if (minBoxSize) { + if (minBoxSize.horizontal) { + var scaleMargin = { + left: Math.max(outerBoxSizes.left, maxPadding.left), + right: Math.max(outerBoxSizes.right, maxPadding.right), + top: 0, + bottom: 0 + }; + + // Don't use min size here because of label rotation. When the labels are rotated, their rotation highly depends + // on the margin. Sometimes they need to increase in size slightly + box.update(box.fullWidth ? chartWidth : maxChartAreaWidth, chartHeight / 2, scaleMargin); + } else { + box.update(minBoxSize.width, maxChartAreaHeight); + } + } + } + + // Update, and calculate the left and right margins for the horizontal boxes + helpers$1.each(verticalBoxes, fitBox); + addSizeByPosition(verticalBoxes, outerBoxSizes); + + // Set the Left and Right margins for the horizontal boxes + helpers$1.each(horizontalBoxes, fitBox); + addSizeByPosition(horizontalBoxes, outerBoxSizes); + + function finalFitVerticalBox(box) { + var minBoxSize = helpers$1.findNextWhere(minBoxSizes, function(minSize) { + return minSize.box === box; + }); + + var scaleMargin = { + left: 0, + right: 0, + top: outerBoxSizes.top, + bottom: outerBoxSizes.bottom + }; + + if (minBoxSize) { + box.update(minBoxSize.width, maxChartAreaHeight, scaleMargin); + } + } + + // Let the left layout know the final margin + helpers$1.each(verticalBoxes, finalFitVerticalBox); + + // Recalculate because the size of each layout might have changed slightly due to the margins (label rotation for instance) + outerBoxSizes = {top: topPadding, left: leftPadding, bottom: bottomPadding, right: rightPadding}; + addSizeByPosition(outerBoxes, outerBoxSizes); + + // We may be adding some padding to account for rotated x axis labels + var leftPaddingAddition = Math.max(maxPadding.left - outerBoxSizes.left, 0); + outerBoxSizes.left += leftPaddingAddition; + outerBoxSizes.right += Math.max(maxPadding.right - outerBoxSizes.right, 0); + + var topPaddingAddition = Math.max(maxPadding.top - outerBoxSizes.top, 0); + outerBoxSizes.top += topPaddingAddition; + outerBoxSizes.bottom += Math.max(maxPadding.bottom - outerBoxSizes.bottom, 0); + + // Figure out if our chart area changed. This would occur if the dataset layout label rotation + // changed due to the application of the margins in step 6. Since we can only get bigger, this is safe to do + // without calling `fit` again + var newMaxChartAreaHeight = height - outerBoxSizes.top - outerBoxSizes.bottom; + var newMaxChartAreaWidth = width - outerBoxSizes.left - outerBoxSizes.right; + + if (newMaxChartAreaWidth !== maxChartAreaWidth || newMaxChartAreaHeight !== maxChartAreaHeight) { + helpers$1.each(verticalBoxes, function(box) { + box.height = newMaxChartAreaHeight; + }); + + helpers$1.each(horizontalBoxes, function(box) { + if (!box.fullWidth) { + box.width = newMaxChartAreaWidth; + } + }); + + maxChartAreaHeight = newMaxChartAreaHeight; + maxChartAreaWidth = newMaxChartAreaWidth; + } + + // Step 7 - Position the boxes + var left = leftPadding + leftPaddingAddition; + var top = topPadding + topPaddingAddition; + + function placeBox(box) { + if (box.isHorizontal()) { + box.left = box.fullWidth ? leftPadding : outerBoxSizes.left; + box.right = box.fullWidth ? width - rightPadding : outerBoxSizes.left + maxChartAreaWidth; + box.top = top; + box.bottom = top + box.height; + + // Move to next point + top = box.bottom; + + } else { + + box.left = left; + box.right = left + box.width; + box.top = outerBoxSizes.top; + box.bottom = outerBoxSizes.top + maxChartAreaHeight; + + // Move to next point + left = box.right; + } + } + + helpers$1.each(leftBoxes.concat(topBoxes), placeBox); + + // Account for chart width and height + left += maxChartAreaWidth; + top += maxChartAreaHeight; + + helpers$1.each(rightBoxes, placeBox); + helpers$1.each(bottomBoxes, placeBox); + + // Step 8 + chart.chartArea = { + left: outerBoxSizes.left, + top: outerBoxSizes.top, + right: outerBoxSizes.left + maxChartAreaWidth, + bottom: outerBoxSizes.top + maxChartAreaHeight + }; + + // Step 9 + helpers$1.each(chartAreaBoxes, function(box) { + box.left = chart.chartArea.left; + box.top = chart.chartArea.top; + box.right = chart.chartArea.right; + box.bottom = chart.chartArea.bottom; + + box.update(maxChartAreaWidth, maxChartAreaHeight); + }); + } +}; + +/** + * Platform fallback implementation (minimal). + * @see https://github.com/chartjs/Chart.js/pull/4591#issuecomment-319575939 + */ + +var platform_basic = { + acquireContext: function(item) { + if (item && item.canvas) { + // Support for any object associated to a canvas (including a context2d) + item = item.canvas; + } + + return item && item.getContext('2d') || null; + } +}; + +var platform_dom = "/*\n * DOM element rendering detection\n * https://davidwalsh.name/detect-node-insertion\n */\n@keyframes chartjs-render-animation {\n\tfrom { opacity: 0.99; }\n\tto { opacity: 1; }\n}\n\n.chartjs-render-monitor {\n\tanimation: chartjs-render-animation 0.001s;\n}\n\n/*\n * DOM element resizing detection\n * https://github.com/marcj/css-element-queries\n */\n.chartjs-size-monitor,\n.chartjs-size-monitor-expand,\n.chartjs-size-monitor-shrink {\n\tposition: absolute;\n\tdirection: ltr;\n\tleft: 0;\n\ttop: 0;\n\tright: 0;\n\tbottom: 0;\n\toverflow: hidden;\n\tpointer-events: none;\n\tvisibility: hidden;\n\tz-index: -1;\n}\n\n.chartjs-size-monitor-expand > div {\n\tposition: absolute;\n\twidth: 1000000px;\n\theight: 1000000px;\n\tleft: 0;\n\ttop: 0;\n}\n\n.chartjs-size-monitor-shrink > div {\n\tposition: absolute;\n\twidth: 200%;\n\theight: 200%;\n\tleft: 0;\n\ttop: 0;\n}\n"; + +var platform_dom$1 = /*#__PURE__*/Object.freeze({ +default: platform_dom +}); + +var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; + +function commonjsRequire () { + throw new Error('Dynamic requires are not currently supported by rollup-plugin-commonjs'); +} + +function createCommonjsModule(fn, module) { + return module = { exports: {} }, fn(module, module.exports), module.exports; +} + +function getCjsExportFromNamespace (n) { + return n && n.default || n; +} + +var stylesheet = getCjsExportFromNamespace(platform_dom$1); + +var EXPANDO_KEY = '$chartjs'; +var CSS_PREFIX = 'chartjs-'; +var CSS_SIZE_MONITOR = CSS_PREFIX + 'size-monitor'; +var CSS_RENDER_MONITOR = CSS_PREFIX + 'render-monitor'; +var CSS_RENDER_ANIMATION = CSS_PREFIX + 'render-animation'; +var ANIMATION_START_EVENTS = ['animationstart', 'webkitAnimationStart']; + +/** + * DOM event types -> Chart.js event types. + * Note: only events with different types are mapped. + * @see https://developer.mozilla.org/en-US/docs/Web/Events + */ +var EVENT_TYPES = { + touchstart: 'mousedown', + touchmove: 'mousemove', + touchend: 'mouseup', + pointerenter: 'mouseenter', + pointerdown: 'mousedown', + pointermove: 'mousemove', + pointerup: 'mouseup', + pointerleave: 'mouseout', + pointerout: 'mouseout' +}; + +/** + * The "used" size is the final value of a dimension property after all calculations have + * been performed. This method uses the computed style of `element` but returns undefined + * if the computed style is not expressed in pixels. That can happen in some cases where + * `element` has a size relative to its parent and this last one is not yet displayed, + * for example because of `display: none` on a parent node. + * @see https://developer.mozilla.org/en-US/docs/Web/CSS/used_value + * @returns {number} Size in pixels or undefined if unknown. + */ +function readUsedSize(element, property) { + var value = helpers$1.getStyle(element, property); + var matches = value && value.match(/^(\d+)(\.\d+)?px$/); + return matches ? Number(matches[1]) : undefined; +} + +/** + * Initializes the canvas style and render size without modifying the canvas display size, + * since responsiveness is handled by the controller.resize() method. The config is used + * to determine the aspect ratio to apply in case no explicit height has been specified. + */ +function initCanvas(canvas, config) { + var style = canvas.style; + + // NOTE(SB) canvas.getAttribute('width') !== canvas.width: in the first case it + // returns null or '' if no explicit value has been set to the canvas attribute. + var renderHeight = canvas.getAttribute('height'); + var renderWidth = canvas.getAttribute('width'); + + // Chart.js modifies some canvas values that we want to restore on destroy + canvas[EXPANDO_KEY] = { + initial: { + height: renderHeight, + width: renderWidth, + style: { + display: style.display, + height: style.height, + width: style.width + } + } + }; + + // Force canvas to display as block to avoid extra space caused by inline + // elements, which would interfere with the responsive resize process. + // https://github.com/chartjs/Chart.js/issues/2538 + style.display = style.display || 'block'; + + if (renderWidth === null || renderWidth === '') { + var displayWidth = readUsedSize(canvas, 'width'); + if (displayWidth !== undefined) { + canvas.width = displayWidth; + } + } + + if (renderHeight === null || renderHeight === '') { + if (canvas.style.height === '') { + // If no explicit render height and style height, let's apply the aspect ratio, + // which one can be specified by the user but also by charts as default option + // (i.e. options.aspectRatio). If not specified, use canvas aspect ratio of 2. + canvas.height = canvas.width / (config.options.aspectRatio || 2); + } else { + var displayHeight = readUsedSize(canvas, 'height'); + if (displayWidth !== undefined) { + canvas.height = displayHeight; + } + } + } + + return canvas; +} + +/** + * Detects support for options object argument in addEventListener. + * https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#Safely_detecting_option_support + * @private + */ +var supportsEventListenerOptions = (function() { + var supports = false; + try { + var options = Object.defineProperty({}, 'passive', { + // eslint-disable-next-line getter-return + get: function() { + supports = true; + } + }); + window.addEventListener('e', null, options); + } catch (e) { + // continue regardless of error + } + return supports; +}()); + +// Default passive to true as expected by Chrome for 'touchstart' and 'touchend' events. +// https://github.com/chartjs/Chart.js/issues/4287 +var eventListenerOptions = supportsEventListenerOptions ? {passive: true} : false; + +function addListener(node, type, listener) { + node.addEventListener(type, listener, eventListenerOptions); +} + +function removeListener(node, type, listener) { + node.removeEventListener(type, listener, eventListenerOptions); +} + +function createEvent(type, chart, x, y, nativeEvent) { + return { + type: type, + chart: chart, + native: nativeEvent || null, + x: x !== undefined ? x : null, + y: y !== undefined ? y : null, + }; +} + +function fromNativeEvent(event, chart) { + var type = EVENT_TYPES[event.type] || event.type; + var pos = helpers$1.getRelativePosition(event, chart); + return createEvent(type, chart, pos.x, pos.y, event); +} + +function throttled(fn, thisArg) { + var ticking = false; + var args = []; + + return function() { + args = Array.prototype.slice.call(arguments); + thisArg = thisArg || this; + + if (!ticking) { + ticking = true; + helpers$1.requestAnimFrame.call(window, function() { + ticking = false; + fn.apply(thisArg, args); + }); + } + }; +} + +function createDiv(cls) { + var el = document.createElement('div'); + el.className = cls || ''; + return el; +} + +// Implementation based on https://github.com/marcj/css-element-queries +function createResizer(handler) { + var maxSize = 1000000; + + // NOTE(SB) Don't use innerHTML because it could be considered unsafe. + // https://github.com/chartjs/Chart.js/issues/5902 + var resizer = createDiv(CSS_SIZE_MONITOR); + var expand = createDiv(CSS_SIZE_MONITOR + '-expand'); + var shrink = createDiv(CSS_SIZE_MONITOR + '-shrink'); + + expand.appendChild(createDiv()); + shrink.appendChild(createDiv()); + + resizer.appendChild(expand); + resizer.appendChild(shrink); + resizer._reset = function() { + expand.scrollLeft = maxSize; + expand.scrollTop = maxSize; + shrink.scrollLeft = maxSize; + shrink.scrollTop = maxSize; + }; + + var onScroll = function() { + resizer._reset(); + handler(); + }; + + addListener(expand, 'scroll', onScroll.bind(expand, 'expand')); + addListener(shrink, 'scroll', onScroll.bind(shrink, 'shrink')); + + return resizer; +} + +// https://davidwalsh.name/detect-node-insertion +function watchForRender(node, handler) { + var expando = node[EXPANDO_KEY] || (node[EXPANDO_KEY] = {}); + var proxy = expando.renderProxy = function(e) { + if (e.animationName === CSS_RENDER_ANIMATION) { + handler(); + } + }; + + helpers$1.each(ANIMATION_START_EVENTS, function(type) { + addListener(node, type, proxy); + }); + + // #4737: Chrome might skip the CSS animation when the CSS_RENDER_MONITOR class + // is removed then added back immediately (same animation frame?). Accessing the + // `offsetParent` property will force a reflow and re-evaluate the CSS animation. + // https://gist.github.com/paulirish/5d52fb081b3570c81e3a#box-metrics + // https://github.com/chartjs/Chart.js/issues/4737 + expando.reflow = !!node.offsetParent; + + node.classList.add(CSS_RENDER_MONITOR); +} + +function unwatchForRender(node) { + var expando = node[EXPANDO_KEY] || {}; + var proxy = expando.renderProxy; + + if (proxy) { + helpers$1.each(ANIMATION_START_EVENTS, function(type) { + removeListener(node, type, proxy); + }); + + delete expando.renderProxy; + } + + node.classList.remove(CSS_RENDER_MONITOR); +} + +function addResizeListener(node, listener, chart) { + var expando = node[EXPANDO_KEY] || (node[EXPANDO_KEY] = {}); + + // Let's keep track of this added resizer and thus avoid DOM query when removing it. + var resizer = expando.resizer = createResizer(throttled(function() { + if (expando.resizer) { + var container = chart.options.maintainAspectRatio && node.parentNode; + var w = container ? container.clientWidth : 0; + listener(createEvent('resize', chart)); + if (container && container.clientWidth < w && chart.canvas) { + // If the container size shrank during chart resize, let's assume + // scrollbar appeared. So we resize again with the scrollbar visible - + // effectively making chart smaller and the scrollbar hidden again. + // Because we are inside `throttled`, and currently `ticking`, scroll + // events are ignored during this whole 2 resize process. + // If we assumed wrong and something else happened, we are resizing + // twice in a frame (potential performance issue) + listener(createEvent('resize', chart)); + } + } + })); + + // The resizer needs to be attached to the node parent, so we first need to be + // sure that `node` is attached to the DOM before injecting the resizer element. + watchForRender(node, function() { + if (expando.resizer) { + var container = node.parentNode; + if (container && container !== resizer.parentNode) { + container.insertBefore(resizer, container.firstChild); + } + + // The container size might have changed, let's reset the resizer state. + resizer._reset(); + } + }); +} + +function removeResizeListener(node) { + var expando = node[EXPANDO_KEY] || {}; + var resizer = expando.resizer; + + delete expando.resizer; + unwatchForRender(node); + + if (resizer && resizer.parentNode) { + resizer.parentNode.removeChild(resizer); + } +} + +function injectCSS(platform, css) { + // https://stackoverflow.com/q/3922139 + var style = platform._style || document.createElement('style'); + if (!platform._style) { + platform._style = style; + css = '/* Chart.js */\n' + css; + style.setAttribute('type', 'text/css'); + document.getElementsByTagName('head')[0].appendChild(style); + } + + style.appendChild(document.createTextNode(css)); +} + +var platform_dom$2 = { + /** + * When `true`, prevents the automatic injection of the stylesheet required to + * correctly detect when the chart is added to the DOM and then resized. This + * switch has been added to allow external stylesheet (`dist/Chart(.min)?.js`) + * to be manually imported to make this library compatible with any CSP. + * See https://github.com/chartjs/Chart.js/issues/5208 + */ + disableCSSInjection: false, + + /** + * This property holds whether this platform is enabled for the current environment. + * Currently used by platform.js to select the proper implementation. + * @private + */ + _enabled: typeof window !== 'undefined' && typeof document !== 'undefined', + + /** + * @private + */ + _ensureLoaded: function() { + if (this._loaded) { + return; + } + + this._loaded = true; + + // https://github.com/chartjs/Chart.js/issues/5208 + if (!this.disableCSSInjection) { + injectCSS(this, stylesheet); + } + }, + + acquireContext: function(item, config) { + if (typeof item === 'string') { + item = document.getElementById(item); + } else if (item.length) { + // Support for array based queries (such as jQuery) + item = item[0]; + } + + if (item && item.canvas) { + // Support for any object associated to a canvas (including a context2d) + item = item.canvas; + } + + // To prevent canvas fingerprinting, some add-ons undefine the getContext + // method, for example: https://github.com/kkapsner/CanvasBlocker + // https://github.com/chartjs/Chart.js/issues/2807 + var context = item && item.getContext && item.getContext('2d'); + + // Load platform resources on first chart creation, to make possible to change + // platform options after importing the library (e.g. `disableCSSInjection`). + this._ensureLoaded(); + + // `instanceof HTMLCanvasElement/CanvasRenderingContext2D` fails when the item is + // inside an iframe or when running in a protected environment. We could guess the + // types from their toString() value but let's keep things flexible and assume it's + // a sufficient condition if the item has a context2D which has item as `canvas`. + // https://github.com/chartjs/Chart.js/issues/3887 + // https://github.com/chartjs/Chart.js/issues/4102 + // https://github.com/chartjs/Chart.js/issues/4152 + if (context && context.canvas === item) { + initCanvas(item, config); + return context; + } + + return null; + }, + + releaseContext: function(context) { + var canvas = context.canvas; + if (!canvas[EXPANDO_KEY]) { + return; + } + + var initial = canvas[EXPANDO_KEY].initial; + ['height', 'width'].forEach(function(prop) { + var value = initial[prop]; + if (helpers$1.isNullOrUndef(value)) { + canvas.removeAttribute(prop); + } else { + canvas.setAttribute(prop, value); + } + }); + + helpers$1.each(initial.style || {}, function(value, key) { + canvas.style[key] = value; + }); + + // The canvas render size might have been changed (and thus the state stack discarded), + // we can't use save() and restore() to restore the initial state. So make sure that at + // least the canvas context is reset to the default state by setting the canvas width. + // https://www.w3.org/TR/2011/WD-html5-20110525/the-canvas-element.html + // eslint-disable-next-line no-self-assign + canvas.width = canvas.width; + + delete canvas[EXPANDO_KEY]; + }, + + addEventListener: function(chart, type, listener) { + var canvas = chart.canvas; + if (type === 'resize') { + // Note: the resize event is not supported on all browsers. + addResizeListener(canvas, listener, chart); + return; + } + + var expando = listener[EXPANDO_KEY] || (listener[EXPANDO_KEY] = {}); + var proxies = expando.proxies || (expando.proxies = {}); + var proxy = proxies[chart.id + '_' + type] = function(event) { + listener(fromNativeEvent(event, chart)); + }; + + addListener(canvas, type, proxy); + }, + + removeEventListener: function(chart, type, listener) { + var canvas = chart.canvas; + if (type === 'resize') { + // Note: the resize event is not supported on all browsers. + removeResizeListener(canvas); + return; + } + + var expando = listener[EXPANDO_KEY] || {}; + var proxies = expando.proxies || {}; + var proxy = proxies[chart.id + '_' + type]; + if (!proxy) { + return; + } + + removeListener(canvas, type, proxy); + } +}; + +// DEPRECATIONS + +/** + * Provided for backward compatibility, use EventTarget.addEventListener instead. + * EventTarget.addEventListener compatibility: Chrome, Opera 7, Safari, FF1.5+, IE9+ + * @see https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener + * @function Chart.helpers.addEvent + * @deprecated since version 2.7.0 + * @todo remove at version 3 + * @private + */ +helpers$1.addEvent = addListener; + +/** + * Provided for backward compatibility, use EventTarget.removeEventListener instead. + * EventTarget.removeEventListener compatibility: Chrome, Opera 7, Safari, FF1.5+, IE9+ + * @see https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/removeEventListener + * @function Chart.helpers.removeEvent + * @deprecated since version 2.7.0 + * @todo remove at version 3 + * @private + */ +helpers$1.removeEvent = removeListener; + +// @TODO Make possible to select another platform at build time. +var implementation = platform_dom$2._enabled ? platform_dom$2 : platform_basic; + +/** + * @namespace Chart.platform + * @see https://chartjs.gitbooks.io/proposals/content/Platform.html + * @since 2.4.0 + */ +var platform = helpers$1.extend({ + /** + * @since 2.7.0 + */ + initialize: function() {}, + + /** + * Called at chart construction time, returns a context2d instance implementing + * the [W3C Canvas 2D Context API standard]{@link https://www.w3.org/TR/2dcontext/}. + * @param {*} item - The native item from which to acquire context (platform specific) + * @param {object} options - The chart options + * @returns {CanvasRenderingContext2D} context2d instance + */ + acquireContext: function() {}, + + /** + * Called at chart destruction time, releases any resources associated to the context + * previously returned by the acquireContext() method. + * @param {CanvasRenderingContext2D} context - The context2d instance + * @returns {boolean} true if the method succeeded, else false + */ + releaseContext: function() {}, + + /** + * Registers the specified listener on the given chart. + * @param {Chart} chart - Chart from which to listen for event + * @param {string} type - The ({@link IEvent}) type to listen for + * @param {function} listener - Receives a notification (an object that implements + * the {@link IEvent} interface) when an event of the specified type occurs. + */ + addEventListener: function() {}, + + /** + * Removes the specified listener previously registered with addEventListener. + * @param {Chart} chart - Chart from which to remove the listener + * @param {string} type - The ({@link IEvent}) type to remove + * @param {function} listener - The listener function to remove from the event target. + */ + removeEventListener: function() {} + +}, implementation); + +core_defaults._set('global', { + plugins: {} +}); + +/** + * The plugin service singleton + * @namespace Chart.plugins + * @since 2.1.0 + */ +var core_plugins = { + /** + * Globally registered plugins. + * @private + */ + _plugins: [], + + /** + * This identifier is used to invalidate the descriptors cache attached to each chart + * when a global plugin is registered or unregistered. In this case, the cache ID is + * incremented and descriptors are regenerated during following API calls. + * @private + */ + _cacheId: 0, + + /** + * Registers the given plugin(s) if not already registered. + * @param {IPlugin[]|IPlugin} plugins plugin instance(s). + */ + register: function(plugins) { + var p = this._plugins; + ([]).concat(plugins).forEach(function(plugin) { + if (p.indexOf(plugin) === -1) { + p.push(plugin); + } + }); + + this._cacheId++; + }, + + /** + * Unregisters the given plugin(s) only if registered. + * @param {IPlugin[]|IPlugin} plugins plugin instance(s). + */ + unregister: function(plugins) { + var p = this._plugins; + ([]).concat(plugins).forEach(function(plugin) { + var idx = p.indexOf(plugin); + if (idx !== -1) { + p.splice(idx, 1); + } + }); + + this._cacheId++; + }, + + /** + * Remove all registered plugins. + * @since 2.1.5 + */ + clear: function() { + this._plugins = []; + this._cacheId++; + }, + + /** + * Returns the number of registered plugins? + * @returns {number} + * @since 2.1.5 + */ + count: function() { + return this._plugins.length; + }, + + /** + * Returns all registered plugin instances. + * @returns {IPlugin[]} array of plugin objects. + * @since 2.1.5 + */ + getAll: function() { + return this._plugins; + }, + + /** + * Calls enabled plugins for `chart` on the specified hook and with the given args. + * This method immediately returns as soon as a plugin explicitly returns false. The + * returned value can be used, for instance, to interrupt the current action. + * @param {Chart} chart - The chart instance for which plugins should be called. + * @param {string} hook - The name of the plugin method to call (e.g. 'beforeUpdate'). + * @param {Array} [args] - Extra arguments to apply to the hook call. + * @returns {boolean} false if any of the plugins return false, else returns true. + */ + notify: function(chart, hook, args) { + var descriptors = this.descriptors(chart); + var ilen = descriptors.length; + var i, descriptor, plugin, params, method; + + for (i = 0; i < ilen; ++i) { + descriptor = descriptors[i]; + plugin = descriptor.plugin; + method = plugin[hook]; + if (typeof method === 'function') { + params = [chart].concat(args || []); + params.push(descriptor.options); + if (method.apply(plugin, params) === false) { + return false; + } + } + } + + return true; + }, + + /** + * Returns descriptors of enabled plugins for the given chart. + * @returns {object[]} [{ plugin, options }] + * @private + */ + descriptors: function(chart) { + var cache = chart.$plugins || (chart.$plugins = {}); + if (cache.id === this._cacheId) { + return cache.descriptors; + } + + var plugins = []; + var descriptors = []; + var config = (chart && chart.config) || {}; + var options = (config.options && config.options.plugins) || {}; + + this._plugins.concat(config.plugins || []).forEach(function(plugin) { + var idx = plugins.indexOf(plugin); + if (idx !== -1) { + return; + } + + var id = plugin.id; + var opts = options[id]; + if (opts === false) { + return; + } + + if (opts === true) { + opts = helpers$1.clone(core_defaults.global.plugins[id]); + } + + plugins.push(plugin); + descriptors.push({ + plugin: plugin, + options: opts || {} + }); + }); + + cache.descriptors = descriptors; + cache.id = this._cacheId; + return descriptors; + }, + + /** + * Invalidates cache for the given chart: descriptors hold a reference on plugin option, + * but in some cases, this reference can be changed by the user when updating options. + * https://github.com/chartjs/Chart.js/issues/5111#issuecomment-355934167 + * @private + */ + _invalidate: function(chart) { + delete chart.$plugins; + } +}; + +var core_scaleService = { + // Scale registration object. Extensions can register new scale types (such as log or DB scales) and then + // use the new chart options to grab the correct scale + constructors: {}, + // Use a registration function so that we can move to an ES6 map when we no longer need to support + // old browsers + + // Scale config defaults + defaults: {}, + registerScaleType: function(type, scaleConstructor, scaleDefaults) { + this.constructors[type] = scaleConstructor; + this.defaults[type] = helpers$1.clone(scaleDefaults); + }, + getScaleConstructor: function(type) { + return this.constructors.hasOwnProperty(type) ? this.constructors[type] : undefined; + }, + getScaleDefaults: function(type) { + // Return the scale defaults merged with the global settings so that we always use the latest ones + return this.defaults.hasOwnProperty(type) ? helpers$1.merge({}, [core_defaults.scale, this.defaults[type]]) : {}; + }, + updateScaleDefaults: function(type, additions) { + var me = this; + if (me.defaults.hasOwnProperty(type)) { + me.defaults[type] = helpers$1.extend(me.defaults[type], additions); + } + }, + addScalesToLayout: function(chart) { + // Adds each scale to the chart.boxes array to be sized accordingly + helpers$1.each(chart.scales, function(scale) { + // Set ILayoutItem parameters for backwards compatibility + scale.fullWidth = scale.options.fullWidth; + scale.position = scale.options.position; + scale.weight = scale.options.weight; + core_layouts.addBox(chart, scale); + }); + } +}; + +var valueOrDefault$7 = helpers$1.valueOrDefault; + +core_defaults._set('global', { + tooltips: { + enabled: true, + custom: null, + mode: 'nearest', + position: 'average', + intersect: true, + backgroundColor: 'rgba(0,0,0,0.8)', + titleFontStyle: 'bold', + titleSpacing: 2, + titleMarginBottom: 6, + titleFontColor: '#fff', + titleAlign: 'left', + bodySpacing: 2, + bodyFontColor: '#fff', + bodyAlign: 'left', + footerFontStyle: 'bold', + footerSpacing: 2, + footerMarginTop: 6, + footerFontColor: '#fff', + footerAlign: 'left', + yPadding: 6, + xPadding: 6, + caretPadding: 2, + caretSize: 5, + cornerRadius: 6, + multiKeyBackground: '#fff', + displayColors: true, + borderColor: 'rgba(0,0,0,0)', + borderWidth: 0, + callbacks: { + // Args are: (tooltipItems, data) + beforeTitle: helpers$1.noop, + title: function(tooltipItems, data) { + var title = ''; + var labels = data.labels; + var labelCount = labels ? labels.length : 0; + + if (tooltipItems.length > 0) { + var item = tooltipItems[0]; + if (item.label) { + title = item.label; + } else if (item.xLabel) { + title = item.xLabel; + } else if (labelCount > 0 && item.index < labelCount) { + title = labels[item.index]; + } + } + + return title; + }, + afterTitle: helpers$1.noop, + + // Args are: (tooltipItems, data) + beforeBody: helpers$1.noop, + + // Args are: (tooltipItem, data) + beforeLabel: helpers$1.noop, + label: function(tooltipItem, data) { + var label = data.datasets[tooltipItem.datasetIndex].label || ''; + + if (label) { + label += ': '; + } + if (!helpers$1.isNullOrUndef(tooltipItem.value)) { + label += tooltipItem.value; + } else { + label += tooltipItem.yLabel; + } + return label; + }, + labelColor: function(tooltipItem, chart) { + var meta = chart.getDatasetMeta(tooltipItem.datasetIndex); + var activeElement = meta.data[tooltipItem.index]; + var view = activeElement._view; + return { + borderColor: view.borderColor, + backgroundColor: view.backgroundColor + }; + }, + labelTextColor: function() { + return this._options.bodyFontColor; + }, + afterLabel: helpers$1.noop, + + // Args are: (tooltipItems, data) + afterBody: helpers$1.noop, + + // Args are: (tooltipItems, data) + beforeFooter: helpers$1.noop, + footer: helpers$1.noop, + afterFooter: helpers$1.noop + } + } +}); + +var positioners = { + /** + * Average mode places the tooltip at the average position of the elements shown + * @function Chart.Tooltip.positioners.average + * @param elements {ChartElement[]} the elements being displayed in the tooltip + * @returns {object} tooltip position + */ + average: function(elements) { + if (!elements.length) { + return false; + } + + var i, len; + var x = 0; + var y = 0; + var count = 0; + + for (i = 0, len = elements.length; i < len; ++i) { + var el = elements[i]; + if (el && el.hasValue()) { + var pos = el.tooltipPosition(); + x += pos.x; + y += pos.y; + ++count; + } + } + + return { + x: x / count, + y: y / count + }; + }, + + /** + * Gets the tooltip position nearest of the item nearest to the event position + * @function Chart.Tooltip.positioners.nearest + * @param elements {Chart.Element[]} the tooltip elements + * @param eventPosition {object} the position of the event in canvas coordinates + * @returns {object} the tooltip position + */ + nearest: function(elements, eventPosition) { + var x = eventPosition.x; + var y = eventPosition.y; + var minDistance = Number.POSITIVE_INFINITY; + var i, len, nearestElement; + + for (i = 0, len = elements.length; i < len; ++i) { + var el = elements[i]; + if (el && el.hasValue()) { + var center = el.getCenterPoint(); + var d = helpers$1.distanceBetweenPoints(eventPosition, center); + + if (d < minDistance) { + minDistance = d; + nearestElement = el; + } + } + } + + if (nearestElement) { + var tp = nearestElement.tooltipPosition(); + x = tp.x; + y = tp.y; + } + + return { + x: x, + y: y + }; + } +}; + +// Helper to push or concat based on if the 2nd parameter is an array or not +function pushOrConcat(base, toPush) { + if (toPush) { + if (helpers$1.isArray(toPush)) { + // base = base.concat(toPush); + Array.prototype.push.apply(base, toPush); + } else { + base.push(toPush); + } + } + + return base; +} + +/** + * Returns array of strings split by newline + * @param {string} value - The value to split by newline. + * @returns {string[]} value if newline present - Returned from String split() method + * @function + */ +function splitNewlines(str) { + if ((typeof str === 'string' || str instanceof String) && str.indexOf('\n') > -1) { + return str.split('\n'); + } + return str; +} + + +/** + * Private helper to create a tooltip item model + * @param element - the chart element (point, arc, bar) to create the tooltip item for + * @return new tooltip item + */ +function createTooltipItem(element) { + var xScale = element._xScale; + var yScale = element._yScale || element._scale; // handle radar || polarArea charts + var index = element._index; + var datasetIndex = element._datasetIndex; + var controller = element._chart.getDatasetMeta(datasetIndex).controller; + var indexScale = controller._getIndexScale(); + var valueScale = controller._getValueScale(); + + return { + xLabel: xScale ? xScale.getLabelForIndex(index, datasetIndex) : '', + yLabel: yScale ? yScale.getLabelForIndex(index, datasetIndex) : '', + label: indexScale ? '' + indexScale.getLabelForIndex(index, datasetIndex) : '', + value: valueScale ? '' + valueScale.getLabelForIndex(index, datasetIndex) : '', + index: index, + datasetIndex: datasetIndex, + x: element._model.x, + y: element._model.y + }; +} + +/** + * Helper to get the reset model for the tooltip + * @param tooltipOpts {object} the tooltip options + */ +function getBaseModel(tooltipOpts) { + var globalDefaults = core_defaults.global; + + return { + // Positioning + xPadding: tooltipOpts.xPadding, + yPadding: tooltipOpts.yPadding, + xAlign: tooltipOpts.xAlign, + yAlign: tooltipOpts.yAlign, + + // Body + bodyFontColor: tooltipOpts.bodyFontColor, + _bodyFontFamily: valueOrDefault$7(tooltipOpts.bodyFontFamily, globalDefaults.defaultFontFamily), + _bodyFontStyle: valueOrDefault$7(tooltipOpts.bodyFontStyle, globalDefaults.defaultFontStyle), + _bodyAlign: tooltipOpts.bodyAlign, + bodyFontSize: valueOrDefault$7(tooltipOpts.bodyFontSize, globalDefaults.defaultFontSize), + bodySpacing: tooltipOpts.bodySpacing, + + // Title + titleFontColor: tooltipOpts.titleFontColor, + _titleFontFamily: valueOrDefault$7(tooltipOpts.titleFontFamily, globalDefaults.defaultFontFamily), + _titleFontStyle: valueOrDefault$7(tooltipOpts.titleFontStyle, globalDefaults.defaultFontStyle), + titleFontSize: valueOrDefault$7(tooltipOpts.titleFontSize, globalDefaults.defaultFontSize), + _titleAlign: tooltipOpts.titleAlign, + titleSpacing: tooltipOpts.titleSpacing, + titleMarginBottom: tooltipOpts.titleMarginBottom, + + // Footer + footerFontColor: tooltipOpts.footerFontColor, + _footerFontFamily: valueOrDefault$7(tooltipOpts.footerFontFamily, globalDefaults.defaultFontFamily), + _footerFontStyle: valueOrDefault$7(tooltipOpts.footerFontStyle, globalDefaults.defaultFontStyle), + footerFontSize: valueOrDefault$7(tooltipOpts.footerFontSize, globalDefaults.defaultFontSize), + _footerAlign: tooltipOpts.footerAlign, + footerSpacing: tooltipOpts.footerSpacing, + footerMarginTop: tooltipOpts.footerMarginTop, + + // Appearance + caretSize: tooltipOpts.caretSize, + cornerRadius: tooltipOpts.cornerRadius, + backgroundColor: tooltipOpts.backgroundColor, + opacity: 0, + legendColorBackground: tooltipOpts.multiKeyBackground, + displayColors: tooltipOpts.displayColors, + borderColor: tooltipOpts.borderColor, + borderWidth: tooltipOpts.borderWidth + }; +} + +/** + * Get the size of the tooltip + */ +function getTooltipSize(tooltip, model) { + var ctx = tooltip._chart.ctx; + + var height = model.yPadding * 2; // Tooltip Padding + var width = 0; + + // Count of all lines in the body + var body = model.body; + var combinedBodyLength = body.reduce(function(count, bodyItem) { + return count + bodyItem.before.length + bodyItem.lines.length + bodyItem.after.length; + }, 0); + combinedBodyLength += model.beforeBody.length + model.afterBody.length; + + var titleLineCount = model.title.length; + var footerLineCount = model.footer.length; + var titleFontSize = model.titleFontSize; + var bodyFontSize = model.bodyFontSize; + var footerFontSize = model.footerFontSize; + + height += titleLineCount * titleFontSize; // Title Lines + height += titleLineCount ? (titleLineCount - 1) * model.titleSpacing : 0; // Title Line Spacing + height += titleLineCount ? model.titleMarginBottom : 0; // Title's bottom Margin + height += combinedBodyLength * bodyFontSize; // Body Lines + height += combinedBodyLength ? (combinedBodyLength - 1) * model.bodySpacing : 0; // Body Line Spacing + height += footerLineCount ? model.footerMarginTop : 0; // Footer Margin + height += footerLineCount * (footerFontSize); // Footer Lines + height += footerLineCount ? (footerLineCount - 1) * model.footerSpacing : 0; // Footer Line Spacing + + // Title width + var widthPadding = 0; + var maxLineWidth = function(line) { + width = Math.max(width, ctx.measureText(line).width + widthPadding); + }; + + ctx.font = helpers$1.fontString(titleFontSize, model._titleFontStyle, model._titleFontFamily); + helpers$1.each(model.title, maxLineWidth); + + // Body width + ctx.font = helpers$1.fontString(bodyFontSize, model._bodyFontStyle, model._bodyFontFamily); + helpers$1.each(model.beforeBody.concat(model.afterBody), maxLineWidth); + + // Body lines may include some extra width due to the color box + widthPadding = model.displayColors ? (bodyFontSize + 2) : 0; + helpers$1.each(body, function(bodyItem) { + helpers$1.each(bodyItem.before, maxLineWidth); + helpers$1.each(bodyItem.lines, maxLineWidth); + helpers$1.each(bodyItem.after, maxLineWidth); + }); + + // Reset back to 0 + widthPadding = 0; + + // Footer width + ctx.font = helpers$1.fontString(footerFontSize, model._footerFontStyle, model._footerFontFamily); + helpers$1.each(model.footer, maxLineWidth); + + // Add padding + width += 2 * model.xPadding; + + return { + width: width, + height: height + }; +} + +/** + * Helper to get the alignment of a tooltip given the size + */ +function determineAlignment(tooltip, size) { + var model = tooltip._model; + var chart = tooltip._chart; + var chartArea = tooltip._chart.chartArea; + var xAlign = 'center'; + var yAlign = 'center'; + + if (model.y < size.height) { + yAlign = 'top'; + } else if (model.y > (chart.height - size.height)) { + yAlign = 'bottom'; + } + + var lf, rf; // functions to determine left, right alignment + var olf, orf; // functions to determine if left/right alignment causes tooltip to go outside chart + var yf; // function to get the y alignment if the tooltip goes outside of the left or right edges + var midX = (chartArea.left + chartArea.right) / 2; + var midY = (chartArea.top + chartArea.bottom) / 2; + + if (yAlign === 'center') { + lf = function(x) { + return x <= midX; + }; + rf = function(x) { + return x > midX; + }; + } else { + lf = function(x) { + return x <= (size.width / 2); + }; + rf = function(x) { + return x >= (chart.width - (size.width / 2)); + }; + } + + olf = function(x) { + return x + size.width + model.caretSize + model.caretPadding > chart.width; + }; + orf = function(x) { + return x - size.width - model.caretSize - model.caretPadding < 0; + }; + yf = function(y) { + return y <= midY ? 'top' : 'bottom'; + }; + + if (lf(model.x)) { + xAlign = 'left'; + + // Is tooltip too wide and goes over the right side of the chart.? + if (olf(model.x)) { + xAlign = 'center'; + yAlign = yf(model.y); + } + } else if (rf(model.x)) { + xAlign = 'right'; + + // Is tooltip too wide and goes outside left edge of canvas? + if (orf(model.x)) { + xAlign = 'center'; + yAlign = yf(model.y); + } + } + + var opts = tooltip._options; + return { + xAlign: opts.xAlign ? opts.xAlign : xAlign, + yAlign: opts.yAlign ? opts.yAlign : yAlign + }; +} + +/** + * Helper to get the location a tooltip needs to be placed at given the initial position (via the vm) and the size and alignment + */ +function getBackgroundPoint(vm, size, alignment, chart) { + // Background Position + var x = vm.x; + var y = vm.y; + + var caretSize = vm.caretSize; + var caretPadding = vm.caretPadding; + var cornerRadius = vm.cornerRadius; + var xAlign = alignment.xAlign; + var yAlign = alignment.yAlign; + var paddingAndSize = caretSize + caretPadding; + var radiusAndPadding = cornerRadius + caretPadding; + + if (xAlign === 'right') { + x -= size.width; + } else if (xAlign === 'center') { + x -= (size.width / 2); + if (x + size.width > chart.width) { + x = chart.width - size.width; + } + if (x < 0) { + x = 0; + } + } + + if (yAlign === 'top') { + y += paddingAndSize; + } else if (yAlign === 'bottom') { + y -= size.height + paddingAndSize; + } else { + y -= (size.height / 2); + } + + if (yAlign === 'center') { + if (xAlign === 'left') { + x += paddingAndSize; + } else if (xAlign === 'right') { + x -= paddingAndSize; + } + } else if (xAlign === 'left') { + x -= radiusAndPadding; + } else if (xAlign === 'right') { + x += radiusAndPadding; + } + + return { + x: x, + y: y + }; +} + +function getAlignedX(vm, align) { + return align === 'center' + ? vm.x + vm.width / 2 + : align === 'right' + ? vm.x + vm.width - vm.xPadding + : vm.x + vm.xPadding; +} + +/** + * Helper to build before and after body lines + */ +function getBeforeAfterBodyLines(callback) { + return pushOrConcat([], splitNewlines(callback)); +} + +var exports$3 = core_element.extend({ + initialize: function() { + this._model = getBaseModel(this._options); + this._lastActive = []; + }, + + // Get the title + // Args are: (tooltipItem, data) + getTitle: function() { + var me = this; + var opts = me._options; + var callbacks = opts.callbacks; + + var beforeTitle = callbacks.beforeTitle.apply(me, arguments); + var title = callbacks.title.apply(me, arguments); + var afterTitle = callbacks.afterTitle.apply(me, arguments); + + var lines = []; + lines = pushOrConcat(lines, splitNewlines(beforeTitle)); + lines = pushOrConcat(lines, splitNewlines(title)); + lines = pushOrConcat(lines, splitNewlines(afterTitle)); + + return lines; + }, + + // Args are: (tooltipItem, data) + getBeforeBody: function() { + return getBeforeAfterBodyLines(this._options.callbacks.beforeBody.apply(this, arguments)); + }, + + // Args are: (tooltipItem, data) + getBody: function(tooltipItems, data) { + var me = this; + var callbacks = me._options.callbacks; + var bodyItems = []; + + helpers$1.each(tooltipItems, function(tooltipItem) { + var bodyItem = { + before: [], + lines: [], + after: [] + }; + pushOrConcat(bodyItem.before, splitNewlines(callbacks.beforeLabel.call(me, tooltipItem, data))); + pushOrConcat(bodyItem.lines, callbacks.label.call(me, tooltipItem, data)); + pushOrConcat(bodyItem.after, splitNewlines(callbacks.afterLabel.call(me, tooltipItem, data))); + + bodyItems.push(bodyItem); + }); + + return bodyItems; + }, + + // Args are: (tooltipItem, data) + getAfterBody: function() { + return getBeforeAfterBodyLines(this._options.callbacks.afterBody.apply(this, arguments)); + }, + + // Get the footer and beforeFooter and afterFooter lines + // Args are: (tooltipItem, data) + getFooter: function() { + var me = this; + var callbacks = me._options.callbacks; + + var beforeFooter = callbacks.beforeFooter.apply(me, arguments); + var footer = callbacks.footer.apply(me, arguments); + var afterFooter = callbacks.afterFooter.apply(me, arguments); + + var lines = []; + lines = pushOrConcat(lines, splitNewlines(beforeFooter)); + lines = pushOrConcat(lines, splitNewlines(footer)); + lines = pushOrConcat(lines, splitNewlines(afterFooter)); + + return lines; + }, + + update: function(changed) { + var me = this; + var opts = me._options; + + // Need to regenerate the model because its faster than using extend and it is necessary due to the optimization in Chart.Element.transition + // that does _view = _model if ease === 1. This causes the 2nd tooltip update to set properties in both the view and model at the same time + // which breaks any animations. + var existingModel = me._model; + var model = me._model = getBaseModel(opts); + var active = me._active; + + var data = me._data; + + // In the case where active.length === 0 we need to keep these at existing values for good animations + var alignment = { + xAlign: existingModel.xAlign, + yAlign: existingModel.yAlign + }; + var backgroundPoint = { + x: existingModel.x, + y: existingModel.y + }; + var tooltipSize = { + width: existingModel.width, + height: existingModel.height + }; + var tooltipPosition = { + x: existingModel.caretX, + y: existingModel.caretY + }; + + var i, len; + + if (active.length) { + model.opacity = 1; + + var labelColors = []; + var labelTextColors = []; + tooltipPosition = positioners[opts.position].call(me, active, me._eventPosition); + + var tooltipItems = []; + for (i = 0, len = active.length; i < len; ++i) { + tooltipItems.push(createTooltipItem(active[i])); + } + + // If the user provided a filter function, use it to modify the tooltip items + if (opts.filter) { + tooltipItems = tooltipItems.filter(function(a) { + return opts.filter(a, data); + }); + } + + // If the user provided a sorting function, use it to modify the tooltip items + if (opts.itemSort) { + tooltipItems = tooltipItems.sort(function(a, b) { + return opts.itemSort(a, b, data); + }); + } + + // Determine colors for boxes + helpers$1.each(tooltipItems, function(tooltipItem) { + labelColors.push(opts.callbacks.labelColor.call(me, tooltipItem, me._chart)); + labelTextColors.push(opts.callbacks.labelTextColor.call(me, tooltipItem, me._chart)); + }); + + + // Build the Text Lines + model.title = me.getTitle(tooltipItems, data); + model.beforeBody = me.getBeforeBody(tooltipItems, data); + model.body = me.getBody(tooltipItems, data); + model.afterBody = me.getAfterBody(tooltipItems, data); + model.footer = me.getFooter(tooltipItems, data); + + // Initial positioning and colors + model.x = tooltipPosition.x; + model.y = tooltipPosition.y; + model.caretPadding = opts.caretPadding; + model.labelColors = labelColors; + model.labelTextColors = labelTextColors; + + // data points + model.dataPoints = tooltipItems; + + // We need to determine alignment of the tooltip + tooltipSize = getTooltipSize(this, model); + alignment = determineAlignment(this, tooltipSize); + // Final Size and Position + backgroundPoint = getBackgroundPoint(model, tooltipSize, alignment, me._chart); + } else { + model.opacity = 0; + } + + model.xAlign = alignment.xAlign; + model.yAlign = alignment.yAlign; + model.x = backgroundPoint.x; + model.y = backgroundPoint.y; + model.width = tooltipSize.width; + model.height = tooltipSize.height; + + // Point where the caret on the tooltip points to + model.caretX = tooltipPosition.x; + model.caretY = tooltipPosition.y; + + me._model = model; + + if (changed && opts.custom) { + opts.custom.call(me, model); + } + + return me; + }, + + drawCaret: function(tooltipPoint, size) { + var ctx = this._chart.ctx; + var vm = this._view; + var caretPosition = this.getCaretPosition(tooltipPoint, size, vm); + + ctx.lineTo(caretPosition.x1, caretPosition.y1); + ctx.lineTo(caretPosition.x2, caretPosition.y2); + ctx.lineTo(caretPosition.x3, caretPosition.y3); + }, + getCaretPosition: function(tooltipPoint, size, vm) { + var x1, x2, x3, y1, y2, y3; + var caretSize = vm.caretSize; + var cornerRadius = vm.cornerRadius; + var xAlign = vm.xAlign; + var yAlign = vm.yAlign; + var ptX = tooltipPoint.x; + var ptY = tooltipPoint.y; + var width = size.width; + var height = size.height; + + if (yAlign === 'center') { + y2 = ptY + (height / 2); + + if (xAlign === 'left') { + x1 = ptX; + x2 = x1 - caretSize; + x3 = x1; + + y1 = y2 + caretSize; + y3 = y2 - caretSize; + } else { + x1 = ptX + width; + x2 = x1 + caretSize; + x3 = x1; + + y1 = y2 - caretSize; + y3 = y2 + caretSize; + } + } else { + if (xAlign === 'left') { + x2 = ptX + cornerRadius + (caretSize); + x1 = x2 - caretSize; + x3 = x2 + caretSize; + } else if (xAlign === 'right') { + x2 = ptX + width - cornerRadius - caretSize; + x1 = x2 - caretSize; + x3 = x2 + caretSize; + } else { + x2 = vm.caretX; + x1 = x2 - caretSize; + x3 = x2 + caretSize; + } + if (yAlign === 'top') { + y1 = ptY; + y2 = y1 - caretSize; + y3 = y1; + } else { + y1 = ptY + height; + y2 = y1 + caretSize; + y3 = y1; + // invert drawing order + var tmp = x3; + x3 = x1; + x1 = tmp; + } + } + return {x1: x1, x2: x2, x3: x3, y1: y1, y2: y2, y3: y3}; + }, + + drawTitle: function(pt, vm, ctx) { + var title = vm.title; + + if (title.length) { + pt.x = getAlignedX(vm, vm._titleAlign); + + ctx.textAlign = vm._titleAlign; + ctx.textBaseline = 'top'; + + var titleFontSize = vm.titleFontSize; + var titleSpacing = vm.titleSpacing; + + ctx.fillStyle = vm.titleFontColor; + ctx.font = helpers$1.fontString(titleFontSize, vm._titleFontStyle, vm._titleFontFamily); + + var i, len; + for (i = 0, len = title.length; i < len; ++i) { + ctx.fillText(title[i], pt.x, pt.y); + pt.y += titleFontSize + titleSpacing; // Line Height and spacing + + if (i + 1 === title.length) { + pt.y += vm.titleMarginBottom - titleSpacing; // If Last, add margin, remove spacing + } + } + } + }, + + drawBody: function(pt, vm, ctx) { + var bodyFontSize = vm.bodyFontSize; + var bodySpacing = vm.bodySpacing; + var bodyAlign = vm._bodyAlign; + var body = vm.body; + var drawColorBoxes = vm.displayColors; + var labelColors = vm.labelColors; + var xLinePadding = 0; + var colorX = drawColorBoxes ? getAlignedX(vm, 'left') : 0; + var textColor; + + ctx.textAlign = bodyAlign; + ctx.textBaseline = 'top'; + ctx.font = helpers$1.fontString(bodyFontSize, vm._bodyFontStyle, vm._bodyFontFamily); + + pt.x = getAlignedX(vm, bodyAlign); + + // Before Body + var fillLineOfText = function(line) { + ctx.fillText(line, pt.x + xLinePadding, pt.y); + pt.y += bodyFontSize + bodySpacing; + }; + + // Before body lines + ctx.fillStyle = vm.bodyFontColor; + helpers$1.each(vm.beforeBody, fillLineOfText); + + xLinePadding = drawColorBoxes && bodyAlign !== 'right' + ? bodyAlign === 'center' ? (bodyFontSize / 2 + 1) : (bodyFontSize + 2) + : 0; + + // Draw body lines now + helpers$1.each(body, function(bodyItem, i) { + textColor = vm.labelTextColors[i]; + ctx.fillStyle = textColor; + helpers$1.each(bodyItem.before, fillLineOfText); + + helpers$1.each(bodyItem.lines, function(line) { + // Draw Legend-like boxes if needed + if (drawColorBoxes) { + // Fill a white rect so that colours merge nicely if the opacity is < 1 + ctx.fillStyle = vm.legendColorBackground; + ctx.fillRect(colorX, pt.y, bodyFontSize, bodyFontSize); + + // Border + ctx.lineWidth = 1; + ctx.strokeStyle = labelColors[i].borderColor; + ctx.strokeRect(colorX, pt.y, bodyFontSize, bodyFontSize); + + // Inner square + ctx.fillStyle = labelColors[i].backgroundColor; + ctx.fillRect(colorX + 1, pt.y + 1, bodyFontSize - 2, bodyFontSize - 2); + ctx.fillStyle = textColor; + } + + fillLineOfText(line); + }); + + helpers$1.each(bodyItem.after, fillLineOfText); + }); + + // Reset back to 0 for after body + xLinePadding = 0; + + // After body lines + helpers$1.each(vm.afterBody, fillLineOfText); + pt.y -= bodySpacing; // Remove last body spacing + }, + + drawFooter: function(pt, vm, ctx) { + var footer = vm.footer; + + if (footer.length) { + pt.x = getAlignedX(vm, vm._footerAlign); + pt.y += vm.footerMarginTop; + + ctx.textAlign = vm._footerAlign; + ctx.textBaseline = 'top'; + + ctx.fillStyle = vm.footerFontColor; + ctx.font = helpers$1.fontString(vm.footerFontSize, vm._footerFontStyle, vm._footerFontFamily); + + helpers$1.each(footer, function(line) { + ctx.fillText(line, pt.x, pt.y); + pt.y += vm.footerFontSize + vm.footerSpacing; + }); + } + }, + + drawBackground: function(pt, vm, ctx, tooltipSize) { + ctx.fillStyle = vm.backgroundColor; + ctx.strokeStyle = vm.borderColor; + ctx.lineWidth = vm.borderWidth; + var xAlign = vm.xAlign; + var yAlign = vm.yAlign; + var x = pt.x; + var y = pt.y; + var width = tooltipSize.width; + var height = tooltipSize.height; + var radius = vm.cornerRadius; + + ctx.beginPath(); + ctx.moveTo(x + radius, y); + if (yAlign === 'top') { + this.drawCaret(pt, tooltipSize); + } + ctx.lineTo(x + width - radius, y); + ctx.quadraticCurveTo(x + width, y, x + width, y + radius); + if (yAlign === 'center' && xAlign === 'right') { + this.drawCaret(pt, tooltipSize); + } + ctx.lineTo(x + width, y + height - radius); + ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height); + if (yAlign === 'bottom') { + this.drawCaret(pt, tooltipSize); + } + ctx.lineTo(x + radius, y + height); + ctx.quadraticCurveTo(x, y + height, x, y + height - radius); + if (yAlign === 'center' && xAlign === 'left') { + this.drawCaret(pt, tooltipSize); + } + ctx.lineTo(x, y + radius); + ctx.quadraticCurveTo(x, y, x + radius, y); + ctx.closePath(); + + ctx.fill(); + + if (vm.borderWidth > 0) { + ctx.stroke(); + } + }, + + draw: function() { + var ctx = this._chart.ctx; + var vm = this._view; + + if (vm.opacity === 0) { + return; + } + + var tooltipSize = { + width: vm.width, + height: vm.height + }; + var pt = { + x: vm.x, + y: vm.y + }; + + // IE11/Edge does not like very small opacities, so snap to 0 + var opacity = Math.abs(vm.opacity < 1e-3) ? 0 : vm.opacity; + + // Truthy/falsey value for empty tooltip + var hasTooltipContent = vm.title.length || vm.beforeBody.length || vm.body.length || vm.afterBody.length || vm.footer.length; + + if (this._options.enabled && hasTooltipContent) { + ctx.save(); + ctx.globalAlpha = opacity; + + // Draw Background + this.drawBackground(pt, vm, ctx, tooltipSize); + + // Draw Title, Body, and Footer + pt.y += vm.yPadding; + + // Titles + this.drawTitle(pt, vm, ctx); + + // Body + this.drawBody(pt, vm, ctx); + + // Footer + this.drawFooter(pt, vm, ctx); + + ctx.restore(); + } + }, + + /** + * Handle an event + * @private + * @param {IEvent} event - The event to handle + * @returns {boolean} true if the tooltip changed + */ + handleEvent: function(e) { + var me = this; + var options = me._options; + var changed = false; + + me._lastActive = me._lastActive || []; + + // Find Active Elements for tooltips + if (e.type === 'mouseout') { + me._active = []; + } else { + me._active = me._chart.getElementsAtEventForMode(e, options.mode, options); + } + + // Remember Last Actives + changed = !helpers$1.arrayEquals(me._active, me._lastActive); + + // Only handle target event on tooltip change + if (changed) { + me._lastActive = me._active; + + if (options.enabled || options.custom) { + me._eventPosition = { + x: e.x, + y: e.y + }; + + me.update(true); + me.pivot(); + } + } + + return changed; + } +}); + +/** + * @namespace Chart.Tooltip.positioners + */ +var positioners_1 = positioners; + +var core_tooltip = exports$3; +core_tooltip.positioners = positioners_1; + +var valueOrDefault$8 = helpers$1.valueOrDefault; + +core_defaults._set('global', { + elements: {}, + events: [ + 'mousemove', + 'mouseout', + 'click', + 'touchstart', + 'touchmove' + ], + hover: { + onHover: null, + mode: 'nearest', + intersect: true, + animationDuration: 400 + }, + onClick: null, + maintainAspectRatio: true, + responsive: true, + responsiveAnimationDuration: 0 +}); + +/** + * Recursively merge the given config objects representing the `scales` option + * by incorporating scale defaults in `xAxes` and `yAxes` array items, then + * returns a deep copy of the result, thus doesn't alter inputs. + */ +function mergeScaleConfig(/* config objects ... */) { + return helpers$1.merge({}, [].slice.call(arguments), { + merger: function(key, target, source, options) { + if (key === 'xAxes' || key === 'yAxes') { + var slen = source[key].length; + var i, type, scale; + + if (!target[key]) { + target[key] = []; + } + + for (i = 0; i < slen; ++i) { + scale = source[key][i]; + type = valueOrDefault$8(scale.type, key === 'xAxes' ? 'category' : 'linear'); + + if (i >= target[key].length) { + target[key].push({}); + } + + if (!target[key][i].type || (scale.type && scale.type !== target[key][i].type)) { + // new/untyped scale or type changed: let's apply the new defaults + // then merge source scale to correctly overwrite the defaults. + helpers$1.merge(target[key][i], [core_scaleService.getScaleDefaults(type), scale]); + } else { + // scales type are the same + helpers$1.merge(target[key][i], scale); + } + } + } else { + helpers$1._merger(key, target, source, options); + } + } + }); +} + +/** + * Recursively merge the given config objects as the root options by handling + * default scale options for the `scales` and `scale` properties, then returns + * a deep copy of the result, thus doesn't alter inputs. + */ +function mergeConfig(/* config objects ... */) { + return helpers$1.merge({}, [].slice.call(arguments), { + merger: function(key, target, source, options) { + var tval = target[key] || {}; + var sval = source[key]; + + if (key === 'scales') { + // scale config merging is complex. Add our own function here for that + target[key] = mergeScaleConfig(tval, sval); + } else if (key === 'scale') { + // used in polar area & radar charts since there is only one scale + target[key] = helpers$1.merge(tval, [core_scaleService.getScaleDefaults(sval.type), sval]); + } else { + helpers$1._merger(key, target, source, options); + } + } + }); +} + +function initConfig(config) { + config = config || {}; + + // Do NOT use mergeConfig for the data object because this method merges arrays + // and so would change references to labels and datasets, preventing data updates. + var data = config.data = config.data || {}; + data.datasets = data.datasets || []; + data.labels = data.labels || []; + + config.options = mergeConfig( + core_defaults.global, + core_defaults[config.type], + config.options || {}); + + return config; +} + +function updateConfig(chart) { + var newOptions = chart.options; + + helpers$1.each(chart.scales, function(scale) { + core_layouts.removeBox(chart, scale); + }); + + newOptions = mergeConfig( + core_defaults.global, + core_defaults[chart.config.type], + newOptions); + + chart.options = chart.config.options = newOptions; + chart.ensureScalesHaveIDs(); + chart.buildOrUpdateScales(); + + // Tooltip + chart.tooltip._options = newOptions.tooltips; + chart.tooltip.initialize(); +} + +function positionIsHorizontal(position) { + return position === 'top' || position === 'bottom'; +} + +var Chart = function(item, config) { + this.construct(item, config); + return this; +}; + +helpers$1.extend(Chart.prototype, /** @lends Chart */ { + /** + * @private + */ + construct: function(item, config) { + var me = this; + + config = initConfig(config); + + var context = platform.acquireContext(item, config); + var canvas = context && context.canvas; + var height = canvas && canvas.height; + var width = canvas && canvas.width; + + me.id = helpers$1.uid(); + me.ctx = context; + me.canvas = canvas; + me.config = config; + me.width = width; + me.height = height; + me.aspectRatio = height ? width / height : null; + me.options = config.options; + me._bufferedRender = false; + + /** + * Provided for backward compatibility, Chart and Chart.Controller have been merged, + * the "instance" still need to be defined since it might be called from plugins. + * @prop Chart#chart + * @deprecated since version 2.6.0 + * @todo remove at version 3 + * @private + */ + me.chart = me; + me.controller = me; // chart.chart.controller #inception + + // Add the chart instance to the global namespace + Chart.instances[me.id] = me; + + // Define alias to the config data: `chart.data === chart.config.data` + Object.defineProperty(me, 'data', { + get: function() { + return me.config.data; + }, + set: function(value) { + me.config.data = value; + } + }); + + if (!context || !canvas) { + // The given item is not a compatible context2d element, let's return before finalizing + // the chart initialization but after setting basic chart / controller properties that + // can help to figure out that the chart is not valid (e.g chart.canvas !== null); + // https://github.com/chartjs/Chart.js/issues/2807 + console.error("Failed to create chart: can't acquire context from the given item"); + return; + } + + me.initialize(); + me.update(); + }, + + /** + * @private + */ + initialize: function() { + var me = this; + + // Before init plugin notification + core_plugins.notify(me, 'beforeInit'); + + helpers$1.retinaScale(me, me.options.devicePixelRatio); + + me.bindEvents(); + + if (me.options.responsive) { + // Initial resize before chart draws (must be silent to preserve initial animations). + me.resize(true); + } + + // Make sure scales have IDs and are built before we build any controllers. + me.ensureScalesHaveIDs(); + me.buildOrUpdateScales(); + me.initToolTip(); + + // After init plugin notification + core_plugins.notify(me, 'afterInit'); + + return me; + }, + + clear: function() { + helpers$1.canvas.clear(this); + return this; + }, + + stop: function() { + // Stops any current animation loop occurring + core_animations.cancelAnimation(this); + return this; + }, + + resize: function(silent) { + var me = this; + var options = me.options; + var canvas = me.canvas; + var aspectRatio = (options.maintainAspectRatio && me.aspectRatio) || null; + + // the canvas render width and height will be casted to integers so make sure that + // the canvas display style uses the same integer values to avoid blurring effect. + + // Set to 0 instead of canvas.size because the size defaults to 300x150 if the element is collapsed + var newWidth = Math.max(0, Math.floor(helpers$1.getMaximumWidth(canvas))); + var newHeight = Math.max(0, Math.floor(aspectRatio ? newWidth / aspectRatio : helpers$1.getMaximumHeight(canvas))); + + if (me.width === newWidth && me.height === newHeight) { + return; + } + + canvas.width = me.width = newWidth; + canvas.height = me.height = newHeight; + canvas.style.width = newWidth + 'px'; + canvas.style.height = newHeight + 'px'; + + helpers$1.retinaScale(me, options.devicePixelRatio); + + if (!silent) { + // Notify any plugins about the resize + var newSize = {width: newWidth, height: newHeight}; + core_plugins.notify(me, 'resize', [newSize]); + + // Notify of resize + if (options.onResize) { + options.onResize(me, newSize); + } + + me.stop(); + me.update({ + duration: options.responsiveAnimationDuration + }); + } + }, + + ensureScalesHaveIDs: function() { + var options = this.options; + var scalesOptions = options.scales || {}; + var scaleOptions = options.scale; + + helpers$1.each(scalesOptions.xAxes, function(xAxisOptions, index) { + xAxisOptions.id = xAxisOptions.id || ('x-axis-' + index); + }); + + helpers$1.each(scalesOptions.yAxes, function(yAxisOptions, index) { + yAxisOptions.id = yAxisOptions.id || ('y-axis-' + index); + }); + + if (scaleOptions) { + scaleOptions.id = scaleOptions.id || 'scale'; + } + }, + + /** + * Builds a map of scale ID to scale object for future lookup. + */ + buildOrUpdateScales: function() { + var me = this; + var options = me.options; + var scales = me.scales || {}; + var items = []; + var updated = Object.keys(scales).reduce(function(obj, id) { + obj[id] = false; + return obj; + }, {}); + + if (options.scales) { + items = items.concat( + (options.scales.xAxes || []).map(function(xAxisOptions) { + return {options: xAxisOptions, dtype: 'category', dposition: 'bottom'}; + }), + (options.scales.yAxes || []).map(function(yAxisOptions) { + return {options: yAxisOptions, dtype: 'linear', dposition: 'left'}; + }) + ); + } + + if (options.scale) { + items.push({ + options: options.scale, + dtype: 'radialLinear', + isDefault: true, + dposition: 'chartArea' + }); + } + + helpers$1.each(items, function(item) { + var scaleOptions = item.options; + var id = scaleOptions.id; + var scaleType = valueOrDefault$8(scaleOptions.type, item.dtype); + + if (positionIsHorizontal(scaleOptions.position) !== positionIsHorizontal(item.dposition)) { + scaleOptions.position = item.dposition; + } + + updated[id] = true; + var scale = null; + if (id in scales && scales[id].type === scaleType) { + scale = scales[id]; + scale.options = scaleOptions; + scale.ctx = me.ctx; + scale.chart = me; + } else { + var scaleClass = core_scaleService.getScaleConstructor(scaleType); + if (!scaleClass) { + return; + } + scale = new scaleClass({ + id: id, + type: scaleType, + options: scaleOptions, + ctx: me.ctx, + chart: me + }); + scales[scale.id] = scale; + } + + scale.mergeTicksOptions(); + + // TODO(SB): I think we should be able to remove this custom case (options.scale) + // and consider it as a regular scale part of the "scales"" map only! This would + // make the logic easier and remove some useless? custom code. + if (item.isDefault) { + me.scale = scale; + } + }); + // clear up discarded scales + helpers$1.each(updated, function(hasUpdated, id) { + if (!hasUpdated) { + delete scales[id]; + } + }); + + me.scales = scales; + + core_scaleService.addScalesToLayout(this); + }, + + buildOrUpdateControllers: function() { + var me = this; + var newControllers = []; + + helpers$1.each(me.data.datasets, function(dataset, datasetIndex) { + var meta = me.getDatasetMeta(datasetIndex); + var type = dataset.type || me.config.type; + + if (meta.type && meta.type !== type) { + me.destroyDatasetMeta(datasetIndex); + meta = me.getDatasetMeta(datasetIndex); + } + meta.type = type; + + if (meta.controller) { + meta.controller.updateIndex(datasetIndex); + meta.controller.linkScales(); + } else { + var ControllerClass = controllers[meta.type]; + if (ControllerClass === undefined) { + throw new Error('"' + meta.type + '" is not a chart type.'); + } + + meta.controller = new ControllerClass(me, datasetIndex); + newControllers.push(meta.controller); + } + }, me); + + return newControllers; + }, + + /** + * Reset the elements of all datasets + * @private + */ + resetElements: function() { + var me = this; + helpers$1.each(me.data.datasets, function(dataset, datasetIndex) { + me.getDatasetMeta(datasetIndex).controller.reset(); + }, me); + }, + + /** + * Resets the chart back to it's state before the initial animation + */ + reset: function() { + this.resetElements(); + this.tooltip.initialize(); + }, + + update: function(config) { + var me = this; + + if (!config || typeof config !== 'object') { + // backwards compatibility + config = { + duration: config, + lazy: arguments[1] + }; + } + + updateConfig(me); + + // plugins options references might have change, let's invalidate the cache + // https://github.com/chartjs/Chart.js/issues/5111#issuecomment-355934167 + core_plugins._invalidate(me); + + if (core_plugins.notify(me, 'beforeUpdate') === false) { + return; + } + + // In case the entire data object changed + me.tooltip._data = me.data; + + // Make sure dataset controllers are updated and new controllers are reset + var newControllers = me.buildOrUpdateControllers(); + + // Make sure all dataset controllers have correct meta data counts + helpers$1.each(me.data.datasets, function(dataset, datasetIndex) { + me.getDatasetMeta(datasetIndex).controller.buildOrUpdateElements(); + }, me); + + me.updateLayout(); + + // Can only reset the new controllers after the scales have been updated + if (me.options.animation && me.options.animation.duration) { + helpers$1.each(newControllers, function(controller) { + controller.reset(); + }); + } + + me.updateDatasets(); + + // Need to reset tooltip in case it is displayed with elements that are removed + // after update. + me.tooltip.initialize(); + + // Last active contains items that were previously in the tooltip. + // When we reset the tooltip, we need to clear it + me.lastActive = []; + + // Do this before render so that any plugins that need final scale updates can use it + core_plugins.notify(me, 'afterUpdate'); + + if (me._bufferedRender) { + me._bufferedRequest = { + duration: config.duration, + easing: config.easing, + lazy: config.lazy + }; + } else { + me.render(config); + } + }, + + /** + * Updates the chart layout unless a plugin returns `false` to the `beforeLayout` + * hook, in which case, plugins will not be called on `afterLayout`. + * @private + */ + updateLayout: function() { + var me = this; + + if (core_plugins.notify(me, 'beforeLayout') === false) { + return; + } + + core_layouts.update(this, this.width, this.height); + + /** + * Provided for backward compatibility, use `afterLayout` instead. + * @method IPlugin#afterScaleUpdate + * @deprecated since version 2.5.0 + * @todo remove at version 3 + * @private + */ + core_plugins.notify(me, 'afterScaleUpdate'); + core_plugins.notify(me, 'afterLayout'); + }, + + /** + * Updates all datasets unless a plugin returns `false` to the `beforeDatasetsUpdate` + * hook, in which case, plugins will not be called on `afterDatasetsUpdate`. + * @private + */ + updateDatasets: function() { + var me = this; + + if (core_plugins.notify(me, 'beforeDatasetsUpdate') === false) { + return; + } + + for (var i = 0, ilen = me.data.datasets.length; i < ilen; ++i) { + me.updateDataset(i); + } + + core_plugins.notify(me, 'afterDatasetsUpdate'); + }, + + /** + * Updates dataset at index unless a plugin returns `false` to the `beforeDatasetUpdate` + * hook, in which case, plugins will not be called on `afterDatasetUpdate`. + * @private + */ + updateDataset: function(index) { + var me = this; + var meta = me.getDatasetMeta(index); + var args = { + meta: meta, + index: index + }; + + if (core_plugins.notify(me, 'beforeDatasetUpdate', [args]) === false) { + return; + } + + meta.controller.update(); + + core_plugins.notify(me, 'afterDatasetUpdate', [args]); + }, + + render: function(config) { + var me = this; + + if (!config || typeof config !== 'object') { + // backwards compatibility + config = { + duration: config, + lazy: arguments[1] + }; + } + + var animationOptions = me.options.animation; + var duration = valueOrDefault$8(config.duration, animationOptions && animationOptions.duration); + var lazy = config.lazy; + + if (core_plugins.notify(me, 'beforeRender') === false) { + return; + } + + var onComplete = function(animation) { + core_plugins.notify(me, 'afterRender'); + helpers$1.callback(animationOptions && animationOptions.onComplete, [animation], me); + }; + + if (animationOptions && duration) { + var animation = new core_animation({ + numSteps: duration / 16.66, // 60 fps + easing: config.easing || animationOptions.easing, + + render: function(chart, animationObject) { + var easingFunction = helpers$1.easing.effects[animationObject.easing]; + var currentStep = animationObject.currentStep; + var stepDecimal = currentStep / animationObject.numSteps; + + chart.draw(easingFunction(stepDecimal), stepDecimal, currentStep); + }, + + onAnimationProgress: animationOptions.onProgress, + onAnimationComplete: onComplete + }); + + core_animations.addAnimation(me, animation, duration, lazy); + } else { + me.draw(); + + // See https://github.com/chartjs/Chart.js/issues/3781 + onComplete(new core_animation({numSteps: 0, chart: me})); + } + + return me; + }, + + draw: function(easingValue) { + var me = this; + + me.clear(); + + if (helpers$1.isNullOrUndef(easingValue)) { + easingValue = 1; + } + + me.transition(easingValue); + + if (me.width <= 0 || me.height <= 0) { + return; + } + + if (core_plugins.notify(me, 'beforeDraw', [easingValue]) === false) { + return; + } + + // Draw all the scales + helpers$1.each(me.boxes, function(box) { + box.draw(me.chartArea); + }, me); + + me.drawDatasets(easingValue); + me._drawTooltip(easingValue); + + core_plugins.notify(me, 'afterDraw', [easingValue]); + }, + + /** + * @private + */ + transition: function(easingValue) { + var me = this; + + for (var i = 0, ilen = (me.data.datasets || []).length; i < ilen; ++i) { + if (me.isDatasetVisible(i)) { + me.getDatasetMeta(i).controller.transition(easingValue); + } + } + + me.tooltip.transition(easingValue); + }, + + /** + * Draws all datasets unless a plugin returns `false` to the `beforeDatasetsDraw` + * hook, in which case, plugins will not be called on `afterDatasetsDraw`. + * @private + */ + drawDatasets: function(easingValue) { + var me = this; + + if (core_plugins.notify(me, 'beforeDatasetsDraw', [easingValue]) === false) { + return; + } + + // Draw datasets reversed to support proper line stacking + for (var i = (me.data.datasets || []).length - 1; i >= 0; --i) { + if (me.isDatasetVisible(i)) { + me.drawDataset(i, easingValue); + } + } + + core_plugins.notify(me, 'afterDatasetsDraw', [easingValue]); + }, + + /** + * Draws dataset at index unless a plugin returns `false` to the `beforeDatasetDraw` + * hook, in which case, plugins will not be called on `afterDatasetDraw`. + * @private + */ + drawDataset: function(index, easingValue) { + var me = this; + var meta = me.getDatasetMeta(index); + var args = { + meta: meta, + index: index, + easingValue: easingValue + }; + + if (core_plugins.notify(me, 'beforeDatasetDraw', [args]) === false) { + return; + } + + meta.controller.draw(easingValue); + + core_plugins.notify(me, 'afterDatasetDraw', [args]); + }, + + /** + * Draws tooltip unless a plugin returns `false` to the `beforeTooltipDraw` + * hook, in which case, plugins will not be called on `afterTooltipDraw`. + * @private + */ + _drawTooltip: function(easingValue) { + var me = this; + var tooltip = me.tooltip; + var args = { + tooltip: tooltip, + easingValue: easingValue + }; + + if (core_plugins.notify(me, 'beforeTooltipDraw', [args]) === false) { + return; + } + + tooltip.draw(); + + core_plugins.notify(me, 'afterTooltipDraw', [args]); + }, + + /** + * Get the single element that was clicked on + * @return An object containing the dataset index and element index of the matching element. Also contains the rectangle that was draw + */ + getElementAtEvent: function(e) { + return core_interaction.modes.single(this, e); + }, + + getElementsAtEvent: function(e) { + return core_interaction.modes.label(this, e, {intersect: true}); + }, + + getElementsAtXAxis: function(e) { + return core_interaction.modes['x-axis'](this, e, {intersect: true}); + }, + + getElementsAtEventForMode: function(e, mode, options) { + var method = core_interaction.modes[mode]; + if (typeof method === 'function') { + return method(this, e, options); + } + + return []; + }, + + getDatasetAtEvent: function(e) { + return core_interaction.modes.dataset(this, e, {intersect: true}); + }, + + getDatasetMeta: function(datasetIndex) { + var me = this; + var dataset = me.data.datasets[datasetIndex]; + if (!dataset._meta) { + dataset._meta = {}; + } + + var meta = dataset._meta[me.id]; + if (!meta) { + meta = dataset._meta[me.id] = { + type: null, + data: [], + dataset: null, + controller: null, + hidden: null, // See isDatasetVisible() comment + xAxisID: null, + yAxisID: null + }; + } + + return meta; + }, + + getVisibleDatasetCount: function() { + var count = 0; + for (var i = 0, ilen = this.data.datasets.length; i < ilen; ++i) { + if (this.isDatasetVisible(i)) { + count++; + } + } + return count; + }, + + isDatasetVisible: function(datasetIndex) { + var meta = this.getDatasetMeta(datasetIndex); + + // meta.hidden is a per chart dataset hidden flag override with 3 states: if true or false, + // the dataset.hidden value is ignored, else if null, the dataset hidden state is returned. + return typeof meta.hidden === 'boolean' ? !meta.hidden : !this.data.datasets[datasetIndex].hidden; + }, + + generateLegend: function() { + return this.options.legendCallback(this); + }, + + /** + * @private + */ + destroyDatasetMeta: function(datasetIndex) { + var id = this.id; + var dataset = this.data.datasets[datasetIndex]; + var meta = dataset._meta && dataset._meta[id]; + + if (meta) { + meta.controller.destroy(); + delete dataset._meta[id]; + } + }, + + destroy: function() { + var me = this; + var canvas = me.canvas; + var i, ilen; + + me.stop(); + + // dataset controllers need to cleanup associated data + for (i = 0, ilen = me.data.datasets.length; i < ilen; ++i) { + me.destroyDatasetMeta(i); + } + + if (canvas) { + me.unbindEvents(); + helpers$1.canvas.clear(me); + platform.releaseContext(me.ctx); + me.canvas = null; + me.ctx = null; + } + + core_plugins.notify(me, 'destroy'); + + delete Chart.instances[me.id]; + }, + + toBase64Image: function() { + return this.canvas.toDataURL.apply(this.canvas, arguments); + }, + + initToolTip: function() { + var me = this; + me.tooltip = new core_tooltip({ + _chart: me, + _chartInstance: me, // deprecated, backward compatibility + _data: me.data, + _options: me.options.tooltips + }, me); + }, + + /** + * @private + */ + bindEvents: function() { + var me = this; + var listeners = me._listeners = {}; + var listener = function() { + me.eventHandler.apply(me, arguments); + }; + + helpers$1.each(me.options.events, function(type) { + platform.addEventListener(me, type, listener); + listeners[type] = listener; + }); + + // Elements used to detect size change should not be injected for non responsive charts. + // See https://github.com/chartjs/Chart.js/issues/2210 + if (me.options.responsive) { + listener = function() { + me.resize(); + }; + + platform.addEventListener(me, 'resize', listener); + listeners.resize = listener; + } + }, + + /** + * @private + */ + unbindEvents: function() { + var me = this; + var listeners = me._listeners; + if (!listeners) { + return; + } + + delete me._listeners; + helpers$1.each(listeners, function(listener, type) { + platform.removeEventListener(me, type, listener); + }); + }, + + updateHoverStyle: function(elements, mode, enabled) { + var method = enabled ? 'setHoverStyle' : 'removeHoverStyle'; + var element, i, ilen; + + for (i = 0, ilen = elements.length; i < ilen; ++i) { + element = elements[i]; + if (element) { + this.getDatasetMeta(element._datasetIndex).controller[method](element); + } + } + }, + + /** + * @private + */ + eventHandler: function(e) { + var me = this; + var tooltip = me.tooltip; + + if (core_plugins.notify(me, 'beforeEvent', [e]) === false) { + return; + } + + // Buffer any update calls so that renders do not occur + me._bufferedRender = true; + me._bufferedRequest = null; + + var changed = me.handleEvent(e); + // for smooth tooltip animations issue #4989 + // the tooltip should be the source of change + // Animation check workaround: + // tooltip._start will be null when tooltip isn't animating + if (tooltip) { + changed = tooltip._start + ? tooltip.handleEvent(e) + : changed | tooltip.handleEvent(e); + } + + core_plugins.notify(me, 'afterEvent', [e]); + + var bufferedRequest = me._bufferedRequest; + if (bufferedRequest) { + // If we have an update that was triggered, we need to do a normal render + me.render(bufferedRequest); + } else if (changed && !me.animating) { + // If entering, leaving, or changing elements, animate the change via pivot + me.stop(); + + // We only need to render at this point. Updating will cause scales to be + // recomputed generating flicker & using more memory than necessary. + me.render({ + duration: me.options.hover.animationDuration, + lazy: true + }); + } + + me._bufferedRender = false; + me._bufferedRequest = null; + + return me; + }, + + /** + * Handle an event + * @private + * @param {IEvent} event the event to handle + * @return {boolean} true if the chart needs to re-render + */ + handleEvent: function(e) { + var me = this; + var options = me.options || {}; + var hoverOptions = options.hover; + var changed = false; + + me.lastActive = me.lastActive || []; + + // Find Active Elements for hover and tooltips + if (e.type === 'mouseout') { + me.active = []; + } else { + me.active = me.getElementsAtEventForMode(e, hoverOptions.mode, hoverOptions); + } + + // Invoke onHover hook + // Need to call with native event here to not break backwards compatibility + helpers$1.callback(options.onHover || options.hover.onHover, [e.native, me.active], me); + + if (e.type === 'mouseup' || e.type === 'click') { + if (options.onClick) { + // Use e.native here for backwards compatibility + options.onClick.call(me, e.native, me.active); + } + } + + // Remove styling for last active (even if it may still be active) + if (me.lastActive.length) { + me.updateHoverStyle(me.lastActive, hoverOptions.mode, false); + } + + // Built in hover styling + if (me.active.length && hoverOptions.mode) { + me.updateHoverStyle(me.active, hoverOptions.mode, true); + } + + changed = !helpers$1.arrayEquals(me.active, me.lastActive); + + // Remember Last Actives + me.lastActive = me.active; + + return changed; + } +}); + +/** + * NOTE(SB) We actually don't use this container anymore but we need to keep it + * for backward compatibility. Though, it can still be useful for plugins that + * would need to work on multiple charts?! + */ +Chart.instances = {}; + +var core_controller = Chart; + +// DEPRECATIONS + +/** + * Provided for backward compatibility, use Chart instead. + * @class Chart.Controller + * @deprecated since version 2.6 + * @todo remove at version 3 + * @private + */ +Chart.Controller = Chart; + +/** + * Provided for backward compatibility, not available anymore. + * @namespace Chart + * @deprecated since version 2.8 + * @todo remove at version 3 + * @private + */ +Chart.types = {}; + +/** + * Provided for backward compatibility, not available anymore. + * @namespace Chart.helpers.configMerge + * @deprecated since version 2.8.0 + * @todo remove at version 3 + * @private + */ +helpers$1.configMerge = mergeConfig; + +/** + * Provided for backward compatibility, not available anymore. + * @namespace Chart.helpers.scaleMerge + * @deprecated since version 2.8.0 + * @todo remove at version 3 + * @private + */ +helpers$1.scaleMerge = mergeScaleConfig; + +var core_helpers = function() { + + // -- Basic js utility methods + + helpers$1.where = function(collection, filterCallback) { + if (helpers$1.isArray(collection) && Array.prototype.filter) { + return collection.filter(filterCallback); + } + var filtered = []; + + helpers$1.each(collection, function(item) { + if (filterCallback(item)) { + filtered.push(item); + } + }); + + return filtered; + }; + helpers$1.findIndex = Array.prototype.findIndex ? + function(array, callback, scope) { + return array.findIndex(callback, scope); + } : + function(array, callback, scope) { + scope = scope === undefined ? array : scope; + for (var i = 0, ilen = array.length; i < ilen; ++i) { + if (callback.call(scope, array[i], i, array)) { + return i; + } + } + return -1; + }; + helpers$1.findNextWhere = function(arrayToSearch, filterCallback, startIndex) { + // Default to start of the array + if (helpers$1.isNullOrUndef(startIndex)) { + startIndex = -1; + } + for (var i = startIndex + 1; i < arrayToSearch.length; i++) { + var currentItem = arrayToSearch[i]; + if (filterCallback(currentItem)) { + return currentItem; + } + } + }; + helpers$1.findPreviousWhere = function(arrayToSearch, filterCallback, startIndex) { + // Default to end of the array + if (helpers$1.isNullOrUndef(startIndex)) { + startIndex = arrayToSearch.length; + } + for (var i = startIndex - 1; i >= 0; i--) { + var currentItem = arrayToSearch[i]; + if (filterCallback(currentItem)) { + return currentItem; + } + } + }; + + // -- Math methods + helpers$1.isNumber = function(n) { + return !isNaN(parseFloat(n)) && isFinite(n); + }; + helpers$1.almostEquals = function(x, y, epsilon) { + return Math.abs(x - y) < epsilon; + }; + helpers$1.almostWhole = function(x, epsilon) { + var rounded = Math.round(x); + return (((rounded - epsilon) < x) && ((rounded + epsilon) > x)); + }; + helpers$1.max = function(array) { + return array.reduce(function(max, value) { + if (!isNaN(value)) { + return Math.max(max, value); + } + return max; + }, Number.NEGATIVE_INFINITY); + }; + helpers$1.min = function(array) { + return array.reduce(function(min, value) { + if (!isNaN(value)) { + return Math.min(min, value); + } + return min; + }, Number.POSITIVE_INFINITY); + }; + helpers$1.sign = Math.sign ? + function(x) { + return Math.sign(x); + } : + function(x) { + x = +x; // convert to a number + if (x === 0 || isNaN(x)) { + return x; + } + return x > 0 ? 1 : -1; + }; + helpers$1.log10 = Math.log10 ? + function(x) { + return Math.log10(x); + } : + function(x) { + var exponent = Math.log(x) * Math.LOG10E; // Math.LOG10E = 1 / Math.LN10. + // Check for whole powers of 10, + // which due to floating point rounding error should be corrected. + var powerOf10 = Math.round(exponent); + var isPowerOf10 = x === Math.pow(10, powerOf10); + + return isPowerOf10 ? powerOf10 : exponent; + }; + helpers$1.toRadians = function(degrees) { + return degrees * (Math.PI / 180); + }; + helpers$1.toDegrees = function(radians) { + return radians * (180 / Math.PI); + }; + + /** + * Returns the number of decimal places + * i.e. the number of digits after the decimal point, of the value of this Number. + * @param {number} x - A number. + * @returns {number} The number of decimal places. + * @private + */ + helpers$1._decimalPlaces = function(x) { + if (!helpers$1.isFinite(x)) { + return; + } + var e = 1; + var p = 0; + while (Math.round(x * e) / e !== x) { + e *= 10; + p++; + } + return p; + }; + + // Gets the angle from vertical upright to the point about a centre. + helpers$1.getAngleFromPoint = function(centrePoint, anglePoint) { + var distanceFromXCenter = anglePoint.x - centrePoint.x; + var distanceFromYCenter = anglePoint.y - centrePoint.y; + var radialDistanceFromCenter = Math.sqrt(distanceFromXCenter * distanceFromXCenter + distanceFromYCenter * distanceFromYCenter); + + var angle = Math.atan2(distanceFromYCenter, distanceFromXCenter); + + if (angle < (-0.5 * Math.PI)) { + angle += 2.0 * Math.PI; // make sure the returned angle is in the range of (-PI/2, 3PI/2] + } + + return { + angle: angle, + distance: radialDistanceFromCenter + }; + }; + helpers$1.distanceBetweenPoints = function(pt1, pt2) { + return Math.sqrt(Math.pow(pt2.x - pt1.x, 2) + Math.pow(pt2.y - pt1.y, 2)); + }; + + /** + * Provided for backward compatibility, not available anymore + * @function Chart.helpers.aliasPixel + * @deprecated since version 2.8.0 + * @todo remove at version 3 + */ + helpers$1.aliasPixel = function(pixelWidth) { + return (pixelWidth % 2 === 0) ? 0 : 0.5; + }; + + /** + * Returns the aligned pixel value to avoid anti-aliasing blur + * @param {Chart} chart - The chart instance. + * @param {number} pixel - A pixel value. + * @param {number} width - The width of the element. + * @returns {number} The aligned pixel value. + * @private + */ + helpers$1._alignPixel = function(chart, pixel, width) { + var devicePixelRatio = chart.currentDevicePixelRatio; + var halfWidth = width / 2; + return Math.round((pixel - halfWidth) * devicePixelRatio) / devicePixelRatio + halfWidth; + }; + + helpers$1.splineCurve = function(firstPoint, middlePoint, afterPoint, t) { + // Props to Rob Spencer at scaled innovation for his post on splining between points + // http://scaledinnovation.com/analytics/splines/aboutSplines.html + + // This function must also respect "skipped" points + + var previous = firstPoint.skip ? middlePoint : firstPoint; + var current = middlePoint; + var next = afterPoint.skip ? middlePoint : afterPoint; + + var d01 = Math.sqrt(Math.pow(current.x - previous.x, 2) + Math.pow(current.y - previous.y, 2)); + var d12 = Math.sqrt(Math.pow(next.x - current.x, 2) + Math.pow(next.y - current.y, 2)); + + var s01 = d01 / (d01 + d12); + var s12 = d12 / (d01 + d12); + + // If all points are the same, s01 & s02 will be inf + s01 = isNaN(s01) ? 0 : s01; + s12 = isNaN(s12) ? 0 : s12; + + var fa = t * s01; // scaling factor for triangle Ta + var fb = t * s12; + + return { + previous: { + x: current.x - fa * (next.x - previous.x), + y: current.y - fa * (next.y - previous.y) + }, + next: { + x: current.x + fb * (next.x - previous.x), + y: current.y + fb * (next.y - previous.y) + } + }; + }; + helpers$1.EPSILON = Number.EPSILON || 1e-14; + helpers$1.splineCurveMonotone = function(points) { + // This function calculates Bézier control points in a similar way than |splineCurve|, + // but preserves monotonicity of the provided data and ensures no local extremums are added + // between the dataset discrete points due to the interpolation. + // See : https://en.wikipedia.org/wiki/Monotone_cubic_interpolation + + var pointsWithTangents = (points || []).map(function(point) { + return { + model: point._model, + deltaK: 0, + mK: 0 + }; + }); + + // Calculate slopes (deltaK) and initialize tangents (mK) + var pointsLen = pointsWithTangents.length; + var i, pointBefore, pointCurrent, pointAfter; + for (i = 0; i < pointsLen; ++i) { + pointCurrent = pointsWithTangents[i]; + if (pointCurrent.model.skip) { + continue; + } + + pointBefore = i > 0 ? pointsWithTangents[i - 1] : null; + pointAfter = i < pointsLen - 1 ? pointsWithTangents[i + 1] : null; + if (pointAfter && !pointAfter.model.skip) { + var slopeDeltaX = (pointAfter.model.x - pointCurrent.model.x); + + // In the case of two points that appear at the same x pixel, slopeDeltaX is 0 + pointCurrent.deltaK = slopeDeltaX !== 0 ? (pointAfter.model.y - pointCurrent.model.y) / slopeDeltaX : 0; + } + + if (!pointBefore || pointBefore.model.skip) { + pointCurrent.mK = pointCurrent.deltaK; + } else if (!pointAfter || pointAfter.model.skip) { + pointCurrent.mK = pointBefore.deltaK; + } else if (this.sign(pointBefore.deltaK) !== this.sign(pointCurrent.deltaK)) { + pointCurrent.mK = 0; + } else { + pointCurrent.mK = (pointBefore.deltaK + pointCurrent.deltaK) / 2; + } + } + + // Adjust tangents to ensure monotonic properties + var alphaK, betaK, tauK, squaredMagnitude; + for (i = 0; i < pointsLen - 1; ++i) { + pointCurrent = pointsWithTangents[i]; + pointAfter = pointsWithTangents[i + 1]; + if (pointCurrent.model.skip || pointAfter.model.skip) { + continue; + } + + if (helpers$1.almostEquals(pointCurrent.deltaK, 0, this.EPSILON)) { + pointCurrent.mK = pointAfter.mK = 0; + continue; + } + + alphaK = pointCurrent.mK / pointCurrent.deltaK; + betaK = pointAfter.mK / pointCurrent.deltaK; + squaredMagnitude = Math.pow(alphaK, 2) + Math.pow(betaK, 2); + if (squaredMagnitude <= 9) { + continue; + } + + tauK = 3 / Math.sqrt(squaredMagnitude); + pointCurrent.mK = alphaK * tauK * pointCurrent.deltaK; + pointAfter.mK = betaK * tauK * pointCurrent.deltaK; + } + + // Compute control points + var deltaX; + for (i = 0; i < pointsLen; ++i) { + pointCurrent = pointsWithTangents[i]; + if (pointCurrent.model.skip) { + continue; + } + + pointBefore = i > 0 ? pointsWithTangents[i - 1] : null; + pointAfter = i < pointsLen - 1 ? pointsWithTangents[i + 1] : null; + if (pointBefore && !pointBefore.model.skip) { + deltaX = (pointCurrent.model.x - pointBefore.model.x) / 3; + pointCurrent.model.controlPointPreviousX = pointCurrent.model.x - deltaX; + pointCurrent.model.controlPointPreviousY = pointCurrent.model.y - deltaX * pointCurrent.mK; + } + if (pointAfter && !pointAfter.model.skip) { + deltaX = (pointAfter.model.x - pointCurrent.model.x) / 3; + pointCurrent.model.controlPointNextX = pointCurrent.model.x + deltaX; + pointCurrent.model.controlPointNextY = pointCurrent.model.y + deltaX * pointCurrent.mK; + } + } + }; + helpers$1.nextItem = function(collection, index, loop) { + if (loop) { + return index >= collection.length - 1 ? collection[0] : collection[index + 1]; + } + return index >= collection.length - 1 ? collection[collection.length - 1] : collection[index + 1]; + }; + helpers$1.previousItem = function(collection, index, loop) { + if (loop) { + return index <= 0 ? collection[collection.length - 1] : collection[index - 1]; + } + return index <= 0 ? collection[0] : collection[index - 1]; + }; + // Implementation of the nice number algorithm used in determining where axis labels will go + helpers$1.niceNum = function(range, round) { + var exponent = Math.floor(helpers$1.log10(range)); + var fraction = range / Math.pow(10, exponent); + var niceFraction; + + if (round) { + if (fraction < 1.5) { + niceFraction = 1; + } else if (fraction < 3) { + niceFraction = 2; + } else if (fraction < 7) { + niceFraction = 5; + } else { + niceFraction = 10; + } + } else if (fraction <= 1.0) { + niceFraction = 1; + } else if (fraction <= 2) { + niceFraction = 2; + } else if (fraction <= 5) { + niceFraction = 5; + } else { + niceFraction = 10; + } + + return niceFraction * Math.pow(10, exponent); + }; + // Request animation polyfill - https://www.paulirish.com/2011/requestanimationframe-for-smart-animating/ + helpers$1.requestAnimFrame = (function() { + if (typeof window === 'undefined') { + return function(callback) { + callback(); + }; + } + return window.requestAnimationFrame || + window.webkitRequestAnimationFrame || + window.mozRequestAnimationFrame || + window.oRequestAnimationFrame || + window.msRequestAnimationFrame || + function(callback) { + return window.setTimeout(callback, 1000 / 60); + }; + }()); + // -- DOM methods + helpers$1.getRelativePosition = function(evt, chart) { + var mouseX, mouseY; + var e = evt.originalEvent || evt; + var canvas = evt.target || evt.srcElement; + var boundingRect = canvas.getBoundingClientRect(); + + var touches = e.touches; + if (touches && touches.length > 0) { + mouseX = touches[0].clientX; + mouseY = touches[0].clientY; + + } else { + mouseX = e.clientX; + mouseY = e.clientY; + } + + // Scale mouse coordinates into canvas coordinates + // by following the pattern laid out by 'jerryj' in the comments of + // https://www.html5canvastutorials.com/advanced/html5-canvas-mouse-coordinates/ + var paddingLeft = parseFloat(helpers$1.getStyle(canvas, 'padding-left')); + var paddingTop = parseFloat(helpers$1.getStyle(canvas, 'padding-top')); + var paddingRight = parseFloat(helpers$1.getStyle(canvas, 'padding-right')); + var paddingBottom = parseFloat(helpers$1.getStyle(canvas, 'padding-bottom')); + var width = boundingRect.right - boundingRect.left - paddingLeft - paddingRight; + var height = boundingRect.bottom - boundingRect.top - paddingTop - paddingBottom; + + // We divide by the current device pixel ratio, because the canvas is scaled up by that amount in each direction. However + // the backend model is in unscaled coordinates. Since we are going to deal with our model coordinates, we go back here + mouseX = Math.round((mouseX - boundingRect.left - paddingLeft) / (width) * canvas.width / chart.currentDevicePixelRatio); + mouseY = Math.round((mouseY - boundingRect.top - paddingTop) / (height) * canvas.height / chart.currentDevicePixelRatio); + + return { + x: mouseX, + y: mouseY + }; + + }; + + // Private helper function to convert max-width/max-height values that may be percentages into a number + function parseMaxStyle(styleValue, node, parentProperty) { + var valueInPixels; + if (typeof styleValue === 'string') { + valueInPixels = parseInt(styleValue, 10); + + if (styleValue.indexOf('%') !== -1) { + // percentage * size in dimension + valueInPixels = valueInPixels / 100 * node.parentNode[parentProperty]; + } + } else { + valueInPixels = styleValue; + } + + return valueInPixels; + } + + /** + * Returns if the given value contains an effective constraint. + * @private + */ + function isConstrainedValue(value) { + return value !== undefined && value !== null && value !== 'none'; + } + + /** + * Returns the max width or height of the given DOM node in a cross-browser compatible fashion + * @param {HTMLElement} domNode - the node to check the constraint on + * @param {string} maxStyle - the style that defines the maximum for the direction we are using ('max-width' / 'max-height') + * @param {string} percentageProperty - property of parent to use when calculating width as a percentage + * @see {@link https://www.nathanaeljones.com/blog/2013/reading-max-width-cross-browser} + */ + function getConstraintDimension(domNode, maxStyle, percentageProperty) { + var view = document.defaultView; + var parentNode = helpers$1._getParentNode(domNode); + var constrainedNode = view.getComputedStyle(domNode)[maxStyle]; + var constrainedContainer = view.getComputedStyle(parentNode)[maxStyle]; + var hasCNode = isConstrainedValue(constrainedNode); + var hasCContainer = isConstrainedValue(constrainedContainer); + var infinity = Number.POSITIVE_INFINITY; + + if (hasCNode || hasCContainer) { + return Math.min( + hasCNode ? parseMaxStyle(constrainedNode, domNode, percentageProperty) : infinity, + hasCContainer ? parseMaxStyle(constrainedContainer, parentNode, percentageProperty) : infinity); + } + + return 'none'; + } + // returns Number or undefined if no constraint + helpers$1.getConstraintWidth = function(domNode) { + return getConstraintDimension(domNode, 'max-width', 'clientWidth'); + }; + // returns Number or undefined if no constraint + helpers$1.getConstraintHeight = function(domNode) { + return getConstraintDimension(domNode, 'max-height', 'clientHeight'); + }; + /** + * @private + */ + helpers$1._calculatePadding = function(container, padding, parentDimension) { + padding = helpers$1.getStyle(container, padding); + + return padding.indexOf('%') > -1 ? parentDimension * parseInt(padding, 10) / 100 : parseInt(padding, 10); + }; + /** + * @private + */ + helpers$1._getParentNode = function(domNode) { + var parent = domNode.parentNode; + if (parent && parent.toString() === '[object ShadowRoot]') { + parent = parent.host; + } + return parent; + }; + helpers$1.getMaximumWidth = function(domNode) { + var container = helpers$1._getParentNode(domNode); + if (!container) { + return domNode.clientWidth; + } + + var clientWidth = container.clientWidth; + var paddingLeft = helpers$1._calculatePadding(container, 'padding-left', clientWidth); + var paddingRight = helpers$1._calculatePadding(container, 'padding-right', clientWidth); + + var w = clientWidth - paddingLeft - paddingRight; + var cw = helpers$1.getConstraintWidth(domNode); + return isNaN(cw) ? w : Math.min(w, cw); + }; + helpers$1.getMaximumHeight = function(domNode) { + var container = helpers$1._getParentNode(domNode); + if (!container) { + return domNode.clientHeight; + } + + var clientHeight = container.clientHeight; + var paddingTop = helpers$1._calculatePadding(container, 'padding-top', clientHeight); + var paddingBottom = helpers$1._calculatePadding(container, 'padding-bottom', clientHeight); + + var h = clientHeight - paddingTop - paddingBottom; + var ch = helpers$1.getConstraintHeight(domNode); + return isNaN(ch) ? h : Math.min(h, ch); + }; + helpers$1.getStyle = function(el, property) { + return el.currentStyle ? + el.currentStyle[property] : + document.defaultView.getComputedStyle(el, null).getPropertyValue(property); + }; + helpers$1.retinaScale = function(chart, forceRatio) { + var pixelRatio = chart.currentDevicePixelRatio = forceRatio || (typeof window !== 'undefined' && window.devicePixelRatio) || 1; + if (pixelRatio === 1) { + return; + } + + var canvas = chart.canvas; + var height = chart.height; + var width = chart.width; + + canvas.height = height * pixelRatio; + canvas.width = width * pixelRatio; + chart.ctx.scale(pixelRatio, pixelRatio); + + // If no style has been set on the canvas, the render size is used as display size, + // making the chart visually bigger, so let's enforce it to the "correct" values. + // See https://github.com/chartjs/Chart.js/issues/3575 + if (!canvas.style.height && !canvas.style.width) { + canvas.style.height = height + 'px'; + canvas.style.width = width + 'px'; + } + }; + // -- Canvas methods + helpers$1.fontString = function(pixelSize, fontStyle, fontFamily) { + return fontStyle + ' ' + pixelSize + 'px ' + fontFamily; + }; + helpers$1.longestText = function(ctx, font, arrayOfThings, cache) { + cache = cache || {}; + var data = cache.data = cache.data || {}; + var gc = cache.garbageCollect = cache.garbageCollect || []; + + if (cache.font !== font) { + data = cache.data = {}; + gc = cache.garbageCollect = []; + cache.font = font; + } + + ctx.font = font; + var longest = 0; + helpers$1.each(arrayOfThings, function(thing) { + // Undefined strings and arrays should not be measured + if (thing !== undefined && thing !== null && helpers$1.isArray(thing) !== true) { + longest = helpers$1.measureText(ctx, data, gc, longest, thing); + } else if (helpers$1.isArray(thing)) { + // if it is an array lets measure each element + // to do maybe simplify this function a bit so we can do this more recursively? + helpers$1.each(thing, function(nestedThing) { + // Undefined strings and arrays should not be measured + if (nestedThing !== undefined && nestedThing !== null && !helpers$1.isArray(nestedThing)) { + longest = helpers$1.measureText(ctx, data, gc, longest, nestedThing); + } + }); + } + }); + + var gcLen = gc.length / 2; + if (gcLen > arrayOfThings.length) { + for (var i = 0; i < gcLen; i++) { + delete data[gc[i]]; + } + gc.splice(0, gcLen); + } + return longest; + }; + helpers$1.measureText = function(ctx, data, gc, longest, string) { + var textWidth = data[string]; + if (!textWidth) { + textWidth = data[string] = ctx.measureText(string).width; + gc.push(string); + } + if (textWidth > longest) { + longest = textWidth; + } + return longest; + }; + helpers$1.numberOfLabelLines = function(arrayOfThings) { + var numberOfLines = 1; + helpers$1.each(arrayOfThings, function(thing) { + if (helpers$1.isArray(thing)) { + if (thing.length > numberOfLines) { + numberOfLines = thing.length; + } + } + }); + return numberOfLines; + }; + + helpers$1.color = !chartjsColor ? + function(value) { + console.error('Color.js not found!'); + return value; + } : + function(value) { + /* global CanvasGradient */ + if (value instanceof CanvasGradient) { + value = core_defaults.global.defaultColor; + } + + return chartjsColor(value); + }; + + helpers$1.getHoverColor = function(colorValue) { + /* global CanvasPattern */ + return (colorValue instanceof CanvasPattern || colorValue instanceof CanvasGradient) ? + colorValue : + helpers$1.color(colorValue).saturate(0.5).darken(0.1).rgbString(); + }; +}; + +function abstract() { + throw new Error( + 'This method is not implemented: either no adapter can ' + + 'be found or an incomplete integration was provided.' + ); +} + +/** + * Date adapter (current used by the time scale) + * @namespace Chart._adapters._date + * @memberof Chart._adapters + * @private + */ + +/** + * Currently supported unit string values. + * @typedef {('millisecond'|'second'|'minute'|'hour'|'day'|'week'|'month'|'quarter'|'year')} + * @memberof Chart._adapters._date + * @name Unit + */ + +/** + * @class + */ +function DateAdapter(options) { + this.options = options || {}; +} + +helpers$1.extend(DateAdapter.prototype, /** @lends DateAdapter */ { + /** + * Returns a map of time formats for the supported formatting units defined + * in Unit as well as 'datetime' representing a detailed date/time string. + * @returns {{string: string}} + */ + formats: abstract, + + /** + * Parses the given `value` and return the associated timestamp. + * @param {any} value - the value to parse (usually comes from the data) + * @param {string} [format] - the expected data format + * @returns {(number|null)} + * @function + */ + parse: abstract, + + /** + * Returns the formatted date in the specified `format` for a given `timestamp`. + * @param {number} timestamp - the timestamp to format + * @param {string} format - the date/time token + * @return {string} + * @function + */ + format: abstract, + + /** + * Adds the specified `amount` of `unit` to the given `timestamp`. + * @param {number} timestamp - the input timestamp + * @param {number} amount - the amount to add + * @param {Unit} unit - the unit as string + * @return {number} + * @function + */ + add: abstract, + + /** + * Returns the number of `unit` between the given timestamps. + * @param {number} max - the input timestamp (reference) + * @param {number} min - the timestamp to substract + * @param {Unit} unit - the unit as string + * @return {number} + * @function + */ + diff: abstract, + + /** + * Returns start of `unit` for the given `timestamp`. + * @param {number} timestamp - the input timestamp + * @param {Unit} unit - the unit as string + * @param {number} [weekday] - the ISO day of the week with 1 being Monday + * and 7 being Sunday (only needed if param *unit* is `isoWeek`). + * @function + */ + startOf: abstract, + + /** + * Returns end of `unit` for the given `timestamp`. + * @param {number} timestamp - the input timestamp + * @param {Unit} unit - the unit as string + * @function + */ + endOf: abstract, + + // DEPRECATIONS + + /** + * Provided for backward compatibility for scale.getValueForPixel(), + * this method should be overridden only by the moment adapter. + * @deprecated since version 2.8.0 + * @todo remove at version 3 + * @private + */ + _create: function(value) { + return value; + } +}); + +DateAdapter.override = function(members) { + helpers$1.extend(DateAdapter.prototype, members); +}; + +var _date = DateAdapter; + +var core_adapters = { + _date: _date +}; + +/** + * Namespace to hold static tick generation functions + * @namespace Chart.Ticks + */ +var core_ticks = { + /** + * Namespace to hold formatters for different types of ticks + * @namespace Chart.Ticks.formatters + */ + formatters: { + /** + * Formatter for value labels + * @method Chart.Ticks.formatters.values + * @param value the value to display + * @return {string|string[]} the label to display + */ + values: function(value) { + return helpers$1.isArray(value) ? value : '' + value; + }, + + /** + * Formatter for linear numeric ticks + * @method Chart.Ticks.formatters.linear + * @param tickValue {number} the value to be formatted + * @param index {number} the position of the tickValue parameter in the ticks array + * @param ticks {number[]} the list of ticks being converted + * @return {string} string representation of the tickValue parameter + */ + linear: function(tickValue, index, ticks) { + // If we have lots of ticks, don't use the ones + var delta = ticks.length > 3 ? ticks[2] - ticks[1] : ticks[1] - ticks[0]; + + // If we have a number like 2.5 as the delta, figure out how many decimal places we need + if (Math.abs(delta) > 1) { + if (tickValue !== Math.floor(tickValue)) { + // not an integer + delta = tickValue - Math.floor(tickValue); + } + } + + var logDelta = helpers$1.log10(Math.abs(delta)); + var tickString = ''; + + if (tickValue !== 0) { + var maxTick = Math.max(Math.abs(ticks[0]), Math.abs(ticks[ticks.length - 1])); + if (maxTick < 1e-4) { // all ticks are small numbers; use scientific notation + var logTick = helpers$1.log10(Math.abs(tickValue)); + tickString = tickValue.toExponential(Math.floor(logTick) - Math.floor(logDelta)); + } else { + var numDecimal = -1 * Math.floor(logDelta); + numDecimal = Math.max(Math.min(numDecimal, 20), 0); // toFixed has a max of 20 decimal places + tickString = tickValue.toFixed(numDecimal); + } + } else { + tickString = '0'; // never show decimal places for 0 + } + + return tickString; + }, + + logarithmic: function(tickValue, index, ticks) { + var remain = tickValue / (Math.pow(10, Math.floor(helpers$1.log10(tickValue)))); + + if (tickValue === 0) { + return '0'; + } else if (remain === 1 || remain === 2 || remain === 5 || index === 0 || index === ticks.length - 1) { + return tickValue.toExponential(); + } + return ''; + } + } +}; + +var valueOrDefault$9 = helpers$1.valueOrDefault; +var valueAtIndexOrDefault = helpers$1.valueAtIndexOrDefault; + +core_defaults._set('scale', { + display: true, + position: 'left', + offset: false, + + // grid line settings + gridLines: { + display: true, + color: 'rgba(0, 0, 0, 0.1)', + lineWidth: 1, + drawBorder: true, + drawOnChartArea: true, + drawTicks: true, + tickMarkLength: 10, + zeroLineWidth: 1, + zeroLineColor: 'rgba(0,0,0,0.25)', + zeroLineBorderDash: [], + zeroLineBorderDashOffset: 0.0, + offsetGridLines: false, + borderDash: [], + borderDashOffset: 0.0 + }, + + // scale label + scaleLabel: { + // display property + display: false, + + // actual label + labelString: '', + + // top/bottom padding + padding: { + top: 4, + bottom: 4 + } + }, + + // label settings + ticks: { + beginAtZero: false, + minRotation: 0, + maxRotation: 50, + mirror: false, + padding: 0, + reverse: false, + display: true, + autoSkip: true, + autoSkipPadding: 0, + labelOffset: 0, + // We pass through arrays to be rendered as multiline labels, we convert Others to strings here. + callback: core_ticks.formatters.values, + minor: {}, + major: {} + } +}); + +function labelsFromTicks(ticks) { + var labels = []; + var i, ilen; + + for (i = 0, ilen = ticks.length; i < ilen; ++i) { + labels.push(ticks[i].label); + } + + return labels; +} + +function getPixelForGridLine(scale, index, offsetGridLines) { + var lineValue = scale.getPixelForTick(index); + + if (offsetGridLines) { + if (scale.getTicks().length === 1) { + lineValue -= scale.isHorizontal() ? + Math.max(lineValue - scale.left, scale.right - lineValue) : + Math.max(lineValue - scale.top, scale.bottom - lineValue); + } else if (index === 0) { + lineValue -= (scale.getPixelForTick(1) - lineValue) / 2; + } else { + lineValue -= (lineValue - scale.getPixelForTick(index - 1)) / 2; + } + } + return lineValue; +} + +function computeTextSize(context, tick, font) { + return helpers$1.isArray(tick) ? + helpers$1.longestText(context, font, tick) : + context.measureText(tick).width; +} + +var core_scale = core_element.extend({ + /** + * Get the padding needed for the scale + * @method getPadding + * @private + * @returns {Padding} the necessary padding + */ + getPadding: function() { + var me = this; + return { + left: me.paddingLeft || 0, + top: me.paddingTop || 0, + right: me.paddingRight || 0, + bottom: me.paddingBottom || 0 + }; + }, + + /** + * Returns the scale tick objects ({label, major}) + * @since 2.7 + */ + getTicks: function() { + return this._ticks; + }, + + // These methods are ordered by lifecyle. Utilities then follow. + // Any function defined here is inherited by all scale types. + // Any function can be extended by the scale type + + mergeTicksOptions: function() { + var ticks = this.options.ticks; + if (ticks.minor === false) { + ticks.minor = { + display: false + }; + } + if (ticks.major === false) { + ticks.major = { + display: false + }; + } + for (var key in ticks) { + if (key !== 'major' && key !== 'minor') { + if (typeof ticks.minor[key] === 'undefined') { + ticks.minor[key] = ticks[key]; + } + if (typeof ticks.major[key] === 'undefined') { + ticks.major[key] = ticks[key]; + } + } + } + }, + beforeUpdate: function() { + helpers$1.callback(this.options.beforeUpdate, [this]); + }, + + update: function(maxWidth, maxHeight, margins) { + var me = this; + var i, ilen, labels, label, ticks, tick; + + // Update Lifecycle - Probably don't want to ever extend or overwrite this function ;) + me.beforeUpdate(); + + // Absorb the master measurements + me.maxWidth = maxWidth; + me.maxHeight = maxHeight; + me.margins = helpers$1.extend({ + left: 0, + right: 0, + top: 0, + bottom: 0 + }, margins); + + me._maxLabelLines = 0; + me.longestLabelWidth = 0; + me.longestTextCache = me.longestTextCache || {}; + + // Dimensions + me.beforeSetDimensions(); + me.setDimensions(); + me.afterSetDimensions(); + + // Data min/max + me.beforeDataLimits(); + me.determineDataLimits(); + me.afterDataLimits(); + + // Ticks - `this.ticks` is now DEPRECATED! + // Internal ticks are now stored as objects in the PRIVATE `this._ticks` member + // and must not be accessed directly from outside this class. `this.ticks` being + // around for long time and not marked as private, we can't change its structure + // without unexpected breaking changes. If you need to access the scale ticks, + // use scale.getTicks() instead. + + me.beforeBuildTicks(); + + // New implementations should return an array of objects but for BACKWARD COMPAT, + // we still support no return (`this.ticks` internally set by calling this method). + ticks = me.buildTicks() || []; + + // Allow modification of ticks in callback. + ticks = me.afterBuildTicks(ticks) || ticks; + + me.beforeTickToLabelConversion(); + + // New implementations should return the formatted tick labels but for BACKWARD + // COMPAT, we still support no return (`this.ticks` internally changed by calling + // this method and supposed to contain only string values). + labels = me.convertTicksToLabels(ticks) || me.ticks; + + me.afterTickToLabelConversion(); + + me.ticks = labels; // BACKWARD COMPATIBILITY + + // IMPORTANT: from this point, we consider that `this.ticks` will NEVER change! + + // BACKWARD COMPAT: synchronize `_ticks` with labels (so potentially `this.ticks`) + for (i = 0, ilen = labels.length; i < ilen; ++i) { + label = labels[i]; + tick = ticks[i]; + if (!tick) { + ticks.push(tick = { + label: label, + major: false + }); + } else { + tick.label = label; + } + } + + me._ticks = ticks; + + // Tick Rotation + me.beforeCalculateTickRotation(); + me.calculateTickRotation(); + me.afterCalculateTickRotation(); + // Fit + me.beforeFit(); + me.fit(); + me.afterFit(); + // + me.afterUpdate(); + + return me.minSize; + + }, + afterUpdate: function() { + helpers$1.callback(this.options.afterUpdate, [this]); + }, + + // + + beforeSetDimensions: function() { + helpers$1.callback(this.options.beforeSetDimensions, [this]); + }, + setDimensions: function() { + var me = this; + // Set the unconstrained dimension before label rotation + if (me.isHorizontal()) { + // Reset position before calculating rotation + me.width = me.maxWidth; + me.left = 0; + me.right = me.width; + } else { + me.height = me.maxHeight; + + // Reset position before calculating rotation + me.top = 0; + me.bottom = me.height; + } + + // Reset padding + me.paddingLeft = 0; + me.paddingTop = 0; + me.paddingRight = 0; + me.paddingBottom = 0; + }, + afterSetDimensions: function() { + helpers$1.callback(this.options.afterSetDimensions, [this]); + }, + + // Data limits + beforeDataLimits: function() { + helpers$1.callback(this.options.beforeDataLimits, [this]); + }, + determineDataLimits: helpers$1.noop, + afterDataLimits: function() { + helpers$1.callback(this.options.afterDataLimits, [this]); + }, + + // + beforeBuildTicks: function() { + helpers$1.callback(this.options.beforeBuildTicks, [this]); + }, + buildTicks: helpers$1.noop, + afterBuildTicks: function(ticks) { + var me = this; + // ticks is empty for old axis implementations here + if (helpers$1.isArray(ticks) && ticks.length) { + return helpers$1.callback(me.options.afterBuildTicks, [me, ticks]); + } + // Support old implementations (that modified `this.ticks` directly in buildTicks) + me.ticks = helpers$1.callback(me.options.afterBuildTicks, [me, me.ticks]) || me.ticks; + return ticks; + }, + + beforeTickToLabelConversion: function() { + helpers$1.callback(this.options.beforeTickToLabelConversion, [this]); + }, + convertTicksToLabels: function() { + var me = this; + // Convert ticks to strings + var tickOpts = me.options.ticks; + me.ticks = me.ticks.map(tickOpts.userCallback || tickOpts.callback, this); + }, + afterTickToLabelConversion: function() { + helpers$1.callback(this.options.afterTickToLabelConversion, [this]); + }, + + // + + beforeCalculateTickRotation: function() { + helpers$1.callback(this.options.beforeCalculateTickRotation, [this]); + }, + calculateTickRotation: function() { + var me = this; + var context = me.ctx; + var tickOpts = me.options.ticks; + var labels = labelsFromTicks(me._ticks); + + // Get the width of each grid by calculating the difference + // between x offsets between 0 and 1. + var tickFont = helpers$1.options._parseFont(tickOpts); + context.font = tickFont.string; + + var labelRotation = tickOpts.minRotation || 0; + + if (labels.length && me.options.display && me.isHorizontal()) { + var originalLabelWidth = helpers$1.longestText(context, tickFont.string, labels, me.longestTextCache); + var labelWidth = originalLabelWidth; + var cosRotation, sinRotation; + + // Allow 3 pixels x2 padding either side for label readability + var tickWidth = me.getPixelForTick(1) - me.getPixelForTick(0) - 6; + + // Max label rotation can be set or default to 90 - also act as a loop counter + while (labelWidth > tickWidth && labelRotation < tickOpts.maxRotation) { + var angleRadians = helpers$1.toRadians(labelRotation); + cosRotation = Math.cos(angleRadians); + sinRotation = Math.sin(angleRadians); + + if (sinRotation * originalLabelWidth > me.maxHeight) { + // go back one step + labelRotation--; + break; + } + + labelRotation++; + labelWidth = cosRotation * originalLabelWidth; + } + } + + me.labelRotation = labelRotation; + }, + afterCalculateTickRotation: function() { + helpers$1.callback(this.options.afterCalculateTickRotation, [this]); + }, + + // + + beforeFit: function() { + helpers$1.callback(this.options.beforeFit, [this]); + }, + fit: function() { + var me = this; + // Reset + var minSize = me.minSize = { + width: 0, + height: 0 + }; + + var labels = labelsFromTicks(me._ticks); + + var opts = me.options; + var tickOpts = opts.ticks; + var scaleLabelOpts = opts.scaleLabel; + var gridLineOpts = opts.gridLines; + var display = me._isVisible(); + var position = opts.position; + var isHorizontal = me.isHorizontal(); + + var parseFont = helpers$1.options._parseFont; + var tickFont = parseFont(tickOpts); + var tickMarkLength = opts.gridLines.tickMarkLength; + + // Width + if (isHorizontal) { + // subtract the margins to line up with the chartArea if we are a full width scale + minSize.width = me.isFullWidth() ? me.maxWidth - me.margins.left - me.margins.right : me.maxWidth; + } else { + minSize.width = display && gridLineOpts.drawTicks ? tickMarkLength : 0; + } + + // height + if (isHorizontal) { + minSize.height = display && gridLineOpts.drawTicks ? tickMarkLength : 0; + } else { + minSize.height = me.maxHeight; // fill all the height + } + + // Are we showing a title for the scale? + if (scaleLabelOpts.display && display) { + var scaleLabelFont = parseFont(scaleLabelOpts); + var scaleLabelPadding = helpers$1.options.toPadding(scaleLabelOpts.padding); + var deltaHeight = scaleLabelFont.lineHeight + scaleLabelPadding.height; + + if (isHorizontal) { + minSize.height += deltaHeight; + } else { + minSize.width += deltaHeight; + } + } + + // Don't bother fitting the ticks if we are not showing the labels + if (tickOpts.display && display) { + var largestTextWidth = helpers$1.longestText(me.ctx, tickFont.string, labels, me.longestTextCache); + var tallestLabelHeightInLines = helpers$1.numberOfLabelLines(labels); + var lineSpace = tickFont.size * 0.5; + var tickPadding = me.options.ticks.padding; + + // Store max number of lines and widest label for _autoSkip + me._maxLabelLines = tallestLabelHeightInLines; + me.longestLabelWidth = largestTextWidth; + + if (isHorizontal) { + var angleRadians = helpers$1.toRadians(me.labelRotation); + var cosRotation = Math.cos(angleRadians); + var sinRotation = Math.sin(angleRadians); + + // TODO - improve this calculation + var labelHeight = (sinRotation * largestTextWidth) + + (tickFont.lineHeight * tallestLabelHeightInLines) + + lineSpace; // padding + + minSize.height = Math.min(me.maxHeight, minSize.height + labelHeight + tickPadding); + + me.ctx.font = tickFont.string; + var firstLabelWidth = computeTextSize(me.ctx, labels[0], tickFont.string); + var lastLabelWidth = computeTextSize(me.ctx, labels[labels.length - 1], tickFont.string); + var offsetLeft = me.getPixelForTick(0) - me.left; + var offsetRight = me.right - me.getPixelForTick(labels.length - 1); + var paddingLeft, paddingRight; + + // Ensure that our ticks are always inside the canvas. When rotated, ticks are right aligned + // which means that the right padding is dominated by the font height + if (me.labelRotation !== 0) { + paddingLeft = position === 'bottom' ? (cosRotation * firstLabelWidth) : (cosRotation * lineSpace); + paddingRight = position === 'bottom' ? (cosRotation * lineSpace) : (cosRotation * lastLabelWidth); + } else { + paddingLeft = firstLabelWidth / 2; + paddingRight = lastLabelWidth / 2; + } + me.paddingLeft = Math.max(paddingLeft - offsetLeft, 0) + 3; // add 3 px to move away from canvas edges + me.paddingRight = Math.max(paddingRight - offsetRight, 0) + 3; + } else { + // A vertical axis is more constrained by the width. Labels are the + // dominant factor here, so get that length first and account for padding + if (tickOpts.mirror) { + largestTextWidth = 0; + } else { + // use lineSpace for consistency with horizontal axis + // tickPadding is not implemented for horizontal + largestTextWidth += tickPadding + lineSpace; + } + + minSize.width = Math.min(me.maxWidth, minSize.width + largestTextWidth); + + me.paddingTop = tickFont.size / 2; + me.paddingBottom = tickFont.size / 2; + } + } + + me.handleMargins(); + + me.width = minSize.width; + me.height = minSize.height; + }, + + /** + * Handle margins and padding interactions + * @private + */ + handleMargins: function() { + var me = this; + if (me.margins) { + me.paddingLeft = Math.max(me.paddingLeft - me.margins.left, 0); + me.paddingTop = Math.max(me.paddingTop - me.margins.top, 0); + me.paddingRight = Math.max(me.paddingRight - me.margins.right, 0); + me.paddingBottom = Math.max(me.paddingBottom - me.margins.bottom, 0); + } + }, + + afterFit: function() { + helpers$1.callback(this.options.afterFit, [this]); + }, + + // Shared Methods + isHorizontal: function() { + return this.options.position === 'top' || this.options.position === 'bottom'; + }, + isFullWidth: function() { + return (this.options.fullWidth); + }, + + // Get the correct value. NaN bad inputs, If the value type is object get the x or y based on whether we are horizontal or not + getRightValue: function(rawValue) { + // Null and undefined values first + if (helpers$1.isNullOrUndef(rawValue)) { + return NaN; + } + // isNaN(object) returns true, so make sure NaN is checking for a number; Discard Infinite values + if ((typeof rawValue === 'number' || rawValue instanceof Number) && !isFinite(rawValue)) { + return NaN; + } + // If it is in fact an object, dive in one more level + if (rawValue) { + if (this.isHorizontal()) { + if (rawValue.x !== undefined) { + return this.getRightValue(rawValue.x); + } + } else if (rawValue.y !== undefined) { + return this.getRightValue(rawValue.y); + } + } + + // Value is good, return it + return rawValue; + }, + + /** + * Used to get the value to display in the tooltip for the data at the given index + * @param index + * @param datasetIndex + */ + getLabelForIndex: helpers$1.noop, + + /** + * Returns the location of the given data point. Value can either be an index or a numerical value + * The coordinate (0, 0) is at the upper-left corner of the canvas + * @param value + * @param index + * @param datasetIndex + */ + getPixelForValue: helpers$1.noop, + + /** + * Used to get the data value from a given pixel. This is the inverse of getPixelForValue + * The coordinate (0, 0) is at the upper-left corner of the canvas + * @param pixel + */ + getValueForPixel: helpers$1.noop, + + /** + * Returns the location of the tick at the given index + * The coordinate (0, 0) is at the upper-left corner of the canvas + */ + getPixelForTick: function(index) { + var me = this; + var offset = me.options.offset; + if (me.isHorizontal()) { + var innerWidth = me.width - (me.paddingLeft + me.paddingRight); + var tickWidth = innerWidth / Math.max((me._ticks.length - (offset ? 0 : 1)), 1); + var pixel = (tickWidth * index) + me.paddingLeft; + + if (offset) { + pixel += tickWidth / 2; + } + + var finalVal = me.left + pixel; + finalVal += me.isFullWidth() ? me.margins.left : 0; + return finalVal; + } + var innerHeight = me.height - (me.paddingTop + me.paddingBottom); + return me.top + (index * (innerHeight / (me._ticks.length - 1))); + }, + + /** + * Utility for getting the pixel location of a percentage of scale + * The coordinate (0, 0) is at the upper-left corner of the canvas + */ + getPixelForDecimal: function(decimal) { + var me = this; + if (me.isHorizontal()) { + var innerWidth = me.width - (me.paddingLeft + me.paddingRight); + var valueOffset = (innerWidth * decimal) + me.paddingLeft; + + var finalVal = me.left + valueOffset; + finalVal += me.isFullWidth() ? me.margins.left : 0; + return finalVal; + } + return me.top + (decimal * me.height); + }, + + /** + * Returns the pixel for the minimum chart value + * The coordinate (0, 0) is at the upper-left corner of the canvas + */ + getBasePixel: function() { + return this.getPixelForValue(this.getBaseValue()); + }, + + getBaseValue: function() { + var me = this; + var min = me.min; + var max = me.max; + + return me.beginAtZero ? 0 : + min < 0 && max < 0 ? max : + min > 0 && max > 0 ? min : + 0; + }, + + /** + * Returns a subset of ticks to be plotted to avoid overlapping labels. + * @private + */ + _autoSkip: function(ticks) { + var me = this; + var isHorizontal = me.isHorizontal(); + var optionTicks = me.options.ticks.minor; + var tickCount = ticks.length; + var skipRatio = false; + var maxTicks = optionTicks.maxTicksLimit; + + // Total space needed to display all ticks. First and last ticks are + // drawn as their center at end of axis, so tickCount-1 + var ticksLength = me._tickSize() * (tickCount - 1); + + // Axis length + var axisLength = isHorizontal + ? me.width - (me.paddingLeft + me.paddingRight) + : me.height - (me.paddingTop + me.PaddingBottom); + + var result = []; + var i, tick; + + if (ticksLength > axisLength) { + skipRatio = 1 + Math.floor(ticksLength / axisLength); + } + + // if they defined a max number of optionTicks, + // increase skipRatio until that number is met + if (tickCount > maxTicks) { + skipRatio = Math.max(skipRatio, 1 + Math.floor(tickCount / maxTicks)); + } + + for (i = 0; i < tickCount; i++) { + tick = ticks[i]; + + if (skipRatio > 1 && i % skipRatio > 0) { + // leave tick in place but make sure it's not displayed (#4635) + delete tick.label; + } + result.push(tick); + } + return result; + }, + + /** + * @private + */ + _tickSize: function() { + var me = this; + var isHorizontal = me.isHorizontal(); + var optionTicks = me.options.ticks.minor; + + // Calculate space needed by label in axis direction. + var rot = helpers$1.toRadians(me.labelRotation); + var cos = Math.abs(Math.cos(rot)); + var sin = Math.abs(Math.sin(rot)); + + var padding = optionTicks.autoSkipPadding || 0; + var w = (me.longestLabelWidth + padding) || 0; + + var tickFont = helpers$1.options._parseFont(optionTicks); + var h = (me._maxLabelLines * tickFont.lineHeight + padding) || 0; + + // Calculate space needed for 1 tick in axis direction. + return isHorizontal + ? h * cos > w * sin ? w / cos : h / sin + : h * sin < w * cos ? h / cos : w / sin; + }, + + /** + * @private + */ + _isVisible: function() { + var me = this; + var chart = me.chart; + var display = me.options.display; + var i, ilen, meta; + + if (display !== 'auto') { + return !!display; + } + + // When 'auto', the scale is visible if at least one associated dataset is visible. + for (i = 0, ilen = chart.data.datasets.length; i < ilen; ++i) { + if (chart.isDatasetVisible(i)) { + meta = chart.getDatasetMeta(i); + if (meta.xAxisID === me.id || meta.yAxisID === me.id) { + return true; + } + } + } + + return false; + }, + + /** + * Actually draw the scale on the canvas + * @param {object} chartArea - the area of the chart to draw full grid lines on + */ + draw: function(chartArea) { + var me = this; + var options = me.options; + + if (!me._isVisible()) { + return; + } + + var chart = me.chart; + var context = me.ctx; + var globalDefaults = core_defaults.global; + var defaultFontColor = globalDefaults.defaultFontColor; + var optionTicks = options.ticks.minor; + var optionMajorTicks = options.ticks.major || optionTicks; + var gridLines = options.gridLines; + var scaleLabel = options.scaleLabel; + var position = options.position; + + var isRotated = me.labelRotation !== 0; + var isMirrored = optionTicks.mirror; + var isHorizontal = me.isHorizontal(); + + var parseFont = helpers$1.options._parseFont; + var ticks = optionTicks.display && optionTicks.autoSkip ? me._autoSkip(me.getTicks()) : me.getTicks(); + var tickFontColor = valueOrDefault$9(optionTicks.fontColor, defaultFontColor); + var tickFont = parseFont(optionTicks); + var lineHeight = tickFont.lineHeight; + var majorTickFontColor = valueOrDefault$9(optionMajorTicks.fontColor, defaultFontColor); + var majorTickFont = parseFont(optionMajorTicks); + var tickPadding = optionTicks.padding; + var labelOffset = optionTicks.labelOffset; + + var tl = gridLines.drawTicks ? gridLines.tickMarkLength : 0; + + var scaleLabelFontColor = valueOrDefault$9(scaleLabel.fontColor, defaultFontColor); + var scaleLabelFont = parseFont(scaleLabel); + var scaleLabelPadding = helpers$1.options.toPadding(scaleLabel.padding); + var labelRotationRadians = helpers$1.toRadians(me.labelRotation); + + var itemsToDraw = []; + + var axisWidth = gridLines.drawBorder ? valueAtIndexOrDefault(gridLines.lineWidth, 0, 0) : 0; + var alignPixel = helpers$1._alignPixel; + var borderValue, tickStart, tickEnd; + + if (position === 'top') { + borderValue = alignPixel(chart, me.bottom, axisWidth); + tickStart = me.bottom - tl; + tickEnd = borderValue - axisWidth / 2; + } else if (position === 'bottom') { + borderValue = alignPixel(chart, me.top, axisWidth); + tickStart = borderValue + axisWidth / 2; + tickEnd = me.top + tl; + } else if (position === 'left') { + borderValue = alignPixel(chart, me.right, axisWidth); + tickStart = me.right - tl; + tickEnd = borderValue - axisWidth / 2; + } else { + borderValue = alignPixel(chart, me.left, axisWidth); + tickStart = borderValue + axisWidth / 2; + tickEnd = me.left + tl; + } + + var epsilon = 0.0000001; // 0.0000001 is margin in pixels for Accumulated error. + + helpers$1.each(ticks, function(tick, index) { + // autoskipper skipped this tick (#4635) + if (helpers$1.isNullOrUndef(tick.label)) { + return; + } + + var label = tick.label; + var lineWidth, lineColor, borderDash, borderDashOffset; + if (index === me.zeroLineIndex && options.offset === gridLines.offsetGridLines) { + // Draw the first index specially + lineWidth = gridLines.zeroLineWidth; + lineColor = gridLines.zeroLineColor; + borderDash = gridLines.zeroLineBorderDash || []; + borderDashOffset = gridLines.zeroLineBorderDashOffset || 0.0; + } else { + lineWidth = valueAtIndexOrDefault(gridLines.lineWidth, index); + lineColor = valueAtIndexOrDefault(gridLines.color, index); + borderDash = gridLines.borderDash || []; + borderDashOffset = gridLines.borderDashOffset || 0.0; + } + + // Common properties + var tx1, ty1, tx2, ty2, x1, y1, x2, y2, labelX, labelY, textOffset, textAlign; + var labelCount = helpers$1.isArray(label) ? label.length : 1; + var lineValue = getPixelForGridLine(me, index, gridLines.offsetGridLines); + + if (isHorizontal) { + var labelYOffset = tl + tickPadding; + + if (lineValue < me.left - epsilon) { + lineColor = 'rgba(0,0,0,0)'; + } + + tx1 = tx2 = x1 = x2 = alignPixel(chart, lineValue, lineWidth); + ty1 = tickStart; + ty2 = tickEnd; + labelX = me.getPixelForTick(index) + labelOffset; // x values for optionTicks (need to consider offsetLabel option) + + if (position === 'top') { + y1 = alignPixel(chart, chartArea.top, axisWidth) + axisWidth / 2; + y2 = chartArea.bottom; + textOffset = ((!isRotated ? 0.5 : 1) - labelCount) * lineHeight; + textAlign = !isRotated ? 'center' : 'left'; + labelY = me.bottom - labelYOffset; + } else { + y1 = chartArea.top; + y2 = alignPixel(chart, chartArea.bottom, axisWidth) - axisWidth / 2; + textOffset = (!isRotated ? 0.5 : 0) * lineHeight; + textAlign = !isRotated ? 'center' : 'right'; + labelY = me.top + labelYOffset; + } + } else { + var labelXOffset = (isMirrored ? 0 : tl) + tickPadding; + + if (lineValue < me.top - epsilon) { + lineColor = 'rgba(0,0,0,0)'; + } + + tx1 = tickStart; + tx2 = tickEnd; + ty1 = ty2 = y1 = y2 = alignPixel(chart, lineValue, lineWidth); + labelY = me.getPixelForTick(index) + labelOffset; + textOffset = (1 - labelCount) * lineHeight / 2; + + if (position === 'left') { + x1 = alignPixel(chart, chartArea.left, axisWidth) + axisWidth / 2; + x2 = chartArea.right; + textAlign = isMirrored ? 'left' : 'right'; + labelX = me.right - labelXOffset; + } else { + x1 = chartArea.left; + x2 = alignPixel(chart, chartArea.right, axisWidth) - axisWidth / 2; + textAlign = isMirrored ? 'right' : 'left'; + labelX = me.left + labelXOffset; + } + } + + itemsToDraw.push({ + tx1: tx1, + ty1: ty1, + tx2: tx2, + ty2: ty2, + x1: x1, + y1: y1, + x2: x2, + y2: y2, + labelX: labelX, + labelY: labelY, + glWidth: lineWidth, + glColor: lineColor, + glBorderDash: borderDash, + glBorderDashOffset: borderDashOffset, + rotation: -1 * labelRotationRadians, + label: label, + major: tick.major, + textOffset: textOffset, + textAlign: textAlign + }); + }); + + // Draw all of the tick labels, tick marks, and grid lines at the correct places + helpers$1.each(itemsToDraw, function(itemToDraw) { + var glWidth = itemToDraw.glWidth; + var glColor = itemToDraw.glColor; + + if (gridLines.display && glWidth && glColor) { + context.save(); + context.lineWidth = glWidth; + context.strokeStyle = glColor; + if (context.setLineDash) { + context.setLineDash(itemToDraw.glBorderDash); + context.lineDashOffset = itemToDraw.glBorderDashOffset; + } + + context.beginPath(); + + if (gridLines.drawTicks) { + context.moveTo(itemToDraw.tx1, itemToDraw.ty1); + context.lineTo(itemToDraw.tx2, itemToDraw.ty2); + } + + if (gridLines.drawOnChartArea) { + context.moveTo(itemToDraw.x1, itemToDraw.y1); + context.lineTo(itemToDraw.x2, itemToDraw.y2); + } + + context.stroke(); + context.restore(); + } + + if (optionTicks.display) { + // Make sure we draw text in the correct color and font + context.save(); + context.translate(itemToDraw.labelX, itemToDraw.labelY); + context.rotate(itemToDraw.rotation); + context.font = itemToDraw.major ? majorTickFont.string : tickFont.string; + context.fillStyle = itemToDraw.major ? majorTickFontColor : tickFontColor; + context.textBaseline = 'middle'; + context.textAlign = itemToDraw.textAlign; + + var label = itemToDraw.label; + var y = itemToDraw.textOffset; + if (helpers$1.isArray(label)) { + for (var i = 0; i < label.length; ++i) { + // We just make sure the multiline element is a string here.. + context.fillText('' + label[i], 0, y); + y += lineHeight; + } + } else { + context.fillText(label, 0, y); + } + context.restore(); + } + }); + + if (scaleLabel.display) { + // Draw the scale label + var scaleLabelX; + var scaleLabelY; + var rotation = 0; + var halfLineHeight = scaleLabelFont.lineHeight / 2; + + if (isHorizontal) { + scaleLabelX = me.left + ((me.right - me.left) / 2); // midpoint of the width + scaleLabelY = position === 'bottom' + ? me.bottom - halfLineHeight - scaleLabelPadding.bottom + : me.top + halfLineHeight + scaleLabelPadding.top; + } else { + var isLeft = position === 'left'; + scaleLabelX = isLeft + ? me.left + halfLineHeight + scaleLabelPadding.top + : me.right - halfLineHeight - scaleLabelPadding.top; + scaleLabelY = me.top + ((me.bottom - me.top) / 2); + rotation = isLeft ? -0.5 * Math.PI : 0.5 * Math.PI; + } + + context.save(); + context.translate(scaleLabelX, scaleLabelY); + context.rotate(rotation); + context.textAlign = 'center'; + context.textBaseline = 'middle'; + context.fillStyle = scaleLabelFontColor; // render in correct colour + context.font = scaleLabelFont.string; + context.fillText(scaleLabel.labelString, 0, 0); + context.restore(); + } + + if (axisWidth) { + // Draw the line at the edge of the axis + var firstLineWidth = axisWidth; + var lastLineWidth = valueAtIndexOrDefault(gridLines.lineWidth, ticks.length - 1, 0); + var x1, x2, y1, y2; + + if (isHorizontal) { + x1 = alignPixel(chart, me.left, firstLineWidth) - firstLineWidth / 2; + x2 = alignPixel(chart, me.right, lastLineWidth) + lastLineWidth / 2; + y1 = y2 = borderValue; + } else { + y1 = alignPixel(chart, me.top, firstLineWidth) - firstLineWidth / 2; + y2 = alignPixel(chart, me.bottom, lastLineWidth) + lastLineWidth / 2; + x1 = x2 = borderValue; + } + + context.lineWidth = axisWidth; + context.strokeStyle = valueAtIndexOrDefault(gridLines.color, 0); + context.beginPath(); + context.moveTo(x1, y1); + context.lineTo(x2, y2); + context.stroke(); + } + } +}); + +var defaultConfig = { + position: 'bottom' +}; + +var scale_category = core_scale.extend({ + /** + * Internal function to get the correct labels. If data.xLabels or data.yLabels are defined, use those + * else fall back to data.labels + * @private + */ + getLabels: function() { + var data = this.chart.data; + return this.options.labels || (this.isHorizontal() ? data.xLabels : data.yLabels) || data.labels; + }, + + determineDataLimits: function() { + var me = this; + var labels = me.getLabels(); + me.minIndex = 0; + me.maxIndex = labels.length - 1; + var findIndex; + + if (me.options.ticks.min !== undefined) { + // user specified min value + findIndex = labels.indexOf(me.options.ticks.min); + me.minIndex = findIndex !== -1 ? findIndex : me.minIndex; + } + + if (me.options.ticks.max !== undefined) { + // user specified max value + findIndex = labels.indexOf(me.options.ticks.max); + me.maxIndex = findIndex !== -1 ? findIndex : me.maxIndex; + } + + me.min = labels[me.minIndex]; + me.max = labels[me.maxIndex]; + }, + + buildTicks: function() { + var me = this; + var labels = me.getLabels(); + // If we are viewing some subset of labels, slice the original array + me.ticks = (me.minIndex === 0 && me.maxIndex === labels.length - 1) ? labels : labels.slice(me.minIndex, me.maxIndex + 1); + }, + + getLabelForIndex: function(index, datasetIndex) { + var me = this; + var chart = me.chart; + + if (chart.getDatasetMeta(datasetIndex).controller._getValueScaleId() === me.id) { + return me.getRightValue(chart.data.datasets[datasetIndex].data[index]); + } + + return me.ticks[index - me.minIndex]; + }, + + // Used to get data value locations. Value can either be an index or a numerical value + getPixelForValue: function(value, index) { + var me = this; + var offset = me.options.offset; + // 1 is added because we need the length but we have the indexes + var offsetAmt = Math.max((me.maxIndex + 1 - me.minIndex - (offset ? 0 : 1)), 1); + + // If value is a data object, then index is the index in the data array, + // not the index of the scale. We need to change that. + var valueCategory; + if (value !== undefined && value !== null) { + valueCategory = me.isHorizontal() ? value.x : value.y; + } + if (valueCategory !== undefined || (value !== undefined && isNaN(index))) { + var labels = me.getLabels(); + value = valueCategory || value; + var idx = labels.indexOf(value); + index = idx !== -1 ? idx : index; + } + + if (me.isHorizontal()) { + var valueWidth = me.width / offsetAmt; + var widthOffset = (valueWidth * (index - me.minIndex)); + + if (offset) { + widthOffset += (valueWidth / 2); + } + + return me.left + widthOffset; + } + var valueHeight = me.height / offsetAmt; + var heightOffset = (valueHeight * (index - me.minIndex)); + + if (offset) { + heightOffset += (valueHeight / 2); + } + + return me.top + heightOffset; + }, + + getPixelForTick: function(index) { + return this.getPixelForValue(this.ticks[index], index + this.minIndex, null); + }, + + getValueForPixel: function(pixel) { + var me = this; + var offset = me.options.offset; + var value; + var offsetAmt = Math.max((me._ticks.length - (offset ? 0 : 1)), 1); + var horz = me.isHorizontal(); + var valueDimension = (horz ? me.width : me.height) / offsetAmt; + + pixel -= horz ? me.left : me.top; + + if (offset) { + pixel -= (valueDimension / 2); + } + + if (pixel <= 0) { + value = 0; + } else { + value = Math.round(pixel / valueDimension); + } + + return value + me.minIndex; + }, + + getBasePixel: function() { + return this.bottom; + } +}); + +// INTERNAL: static default options, registered in src/index.js +var _defaults = defaultConfig; +scale_category._defaults = _defaults; + +var noop = helpers$1.noop; +var isNullOrUndef = helpers$1.isNullOrUndef; + +/** + * Generate a set of linear ticks + * @param generationOptions the options used to generate the ticks + * @param dataRange the range of the data + * @returns {number[]} array of tick values + */ +function generateTicks(generationOptions, dataRange) { + var ticks = []; + // To get a "nice" value for the tick spacing, we will use the appropriately named + // "nice number" algorithm. See https://stackoverflow.com/questions/8506881/nice-label-algorithm-for-charts-with-minimum-ticks + // for details. + + var MIN_SPACING = 1e-14; + var stepSize = generationOptions.stepSize; + var unit = stepSize || 1; + var maxNumSpaces = generationOptions.maxTicks - 1; + var min = generationOptions.min; + var max = generationOptions.max; + var precision = generationOptions.precision; + var rmin = dataRange.min; + var rmax = dataRange.max; + var spacing = helpers$1.niceNum((rmax - rmin) / maxNumSpaces / unit) * unit; + var factor, niceMin, niceMax, numSpaces; + + // Beyond MIN_SPACING floating point numbers being to lose precision + // such that we can't do the math necessary to generate ticks + if (spacing < MIN_SPACING && isNullOrUndef(min) && isNullOrUndef(max)) { + return [rmin, rmax]; + } + + numSpaces = Math.ceil(rmax / spacing) - Math.floor(rmin / spacing); + if (numSpaces > maxNumSpaces) { + // If the calculated num of spaces exceeds maxNumSpaces, recalculate it + spacing = helpers$1.niceNum(numSpaces * spacing / maxNumSpaces / unit) * unit; + } + + if (stepSize || isNullOrUndef(precision)) { + // If a precision is not specified, calculate factor based on spacing + factor = Math.pow(10, helpers$1._decimalPlaces(spacing)); + } else { + // If the user specified a precision, round to that number of decimal places + factor = Math.pow(10, precision); + spacing = Math.ceil(spacing * factor) / factor; + } + + niceMin = Math.floor(rmin / spacing) * spacing; + niceMax = Math.ceil(rmax / spacing) * spacing; + + // If min, max and stepSize is set and they make an evenly spaced scale use it. + if (stepSize) { + // If very close to our whole number, use it. + if (!isNullOrUndef(min) && helpers$1.almostWhole(min / spacing, spacing / 1000)) { + niceMin = min; + } + if (!isNullOrUndef(max) && helpers$1.almostWhole(max / spacing, spacing / 1000)) { + niceMax = max; + } + } + + numSpaces = (niceMax - niceMin) / spacing; + // If very close to our rounded value, use it. + if (helpers$1.almostEquals(numSpaces, Math.round(numSpaces), spacing / 1000)) { + numSpaces = Math.round(numSpaces); + } else { + numSpaces = Math.ceil(numSpaces); + } + + niceMin = Math.round(niceMin * factor) / factor; + niceMax = Math.round(niceMax * factor) / factor; + ticks.push(isNullOrUndef(min) ? niceMin : min); + for (var j = 1; j < numSpaces; ++j) { + ticks.push(Math.round((niceMin + j * spacing) * factor) / factor); + } + ticks.push(isNullOrUndef(max) ? niceMax : max); + + return ticks; +} + +var scale_linearbase = core_scale.extend({ + getRightValue: function(value) { + if (typeof value === 'string') { + return +value; + } + return core_scale.prototype.getRightValue.call(this, value); + }, + + handleTickRangeOptions: function() { + var me = this; + var opts = me.options; + var tickOpts = opts.ticks; + + // If we are forcing it to begin at 0, but 0 will already be rendered on the chart, + // do nothing since that would make the chart weird. If the user really wants a weird chart + // axis, they can manually override it + if (tickOpts.beginAtZero) { + var minSign = helpers$1.sign(me.min); + var maxSign = helpers$1.sign(me.max); + + if (minSign < 0 && maxSign < 0) { + // move the top up to 0 + me.max = 0; + } else if (minSign > 0 && maxSign > 0) { + // move the bottom down to 0 + me.min = 0; + } + } + + var setMin = tickOpts.min !== undefined || tickOpts.suggestedMin !== undefined; + var setMax = tickOpts.max !== undefined || tickOpts.suggestedMax !== undefined; + + if (tickOpts.min !== undefined) { + me.min = tickOpts.min; + } else if (tickOpts.suggestedMin !== undefined) { + if (me.min === null) { + me.min = tickOpts.suggestedMin; + } else { + me.min = Math.min(me.min, tickOpts.suggestedMin); + } + } + + if (tickOpts.max !== undefined) { + me.max = tickOpts.max; + } else if (tickOpts.suggestedMax !== undefined) { + if (me.max === null) { + me.max = tickOpts.suggestedMax; + } else { + me.max = Math.max(me.max, tickOpts.suggestedMax); + } + } + + if (setMin !== setMax) { + // We set the min or the max but not both. + // So ensure that our range is good + // Inverted or 0 length range can happen when + // ticks.min is set, and no datasets are visible + if (me.min >= me.max) { + if (setMin) { + me.max = me.min + 1; + } else { + me.min = me.max - 1; + } + } + } + + if (me.min === me.max) { + me.max++; + + if (!tickOpts.beginAtZero) { + me.min--; + } + } + }, + + getTickLimit: function() { + var me = this; + var tickOpts = me.options.ticks; + var stepSize = tickOpts.stepSize; + var maxTicksLimit = tickOpts.maxTicksLimit; + var maxTicks; + + if (stepSize) { + maxTicks = Math.ceil(me.max / stepSize) - Math.floor(me.min / stepSize) + 1; + } else { + maxTicks = me._computeTickLimit(); + maxTicksLimit = maxTicksLimit || 11; + } + + if (maxTicksLimit) { + maxTicks = Math.min(maxTicksLimit, maxTicks); + } + + return maxTicks; + }, + + _computeTickLimit: function() { + return Number.POSITIVE_INFINITY; + }, + + handleDirectionalChanges: noop, + + buildTicks: function() { + var me = this; + var opts = me.options; + var tickOpts = opts.ticks; + + // Figure out what the max number of ticks we can support it is based on the size of + // the axis area. For now, we say that the minimum tick spacing in pixels must be 40 + // We also limit the maximum number of ticks to 11 which gives a nice 10 squares on + // the graph. Make sure we always have at least 2 ticks + var maxTicks = me.getTickLimit(); + maxTicks = Math.max(2, maxTicks); + + var numericGeneratorOptions = { + maxTicks: maxTicks, + min: tickOpts.min, + max: tickOpts.max, + precision: tickOpts.precision, + stepSize: helpers$1.valueOrDefault(tickOpts.fixedStepSize, tickOpts.stepSize) + }; + var ticks = me.ticks = generateTicks(numericGeneratorOptions, me); + + me.handleDirectionalChanges(); + + // At this point, we need to update our max and min given the tick values since we have expanded the + // range of the scale + me.max = helpers$1.max(ticks); + me.min = helpers$1.min(ticks); + + if (tickOpts.reverse) { + ticks.reverse(); + + me.start = me.max; + me.end = me.min; + } else { + me.start = me.min; + me.end = me.max; + } + }, + + convertTicksToLabels: function() { + var me = this; + me.ticksAsNumbers = me.ticks.slice(); + me.zeroLineIndex = me.ticks.indexOf(0); + + core_scale.prototype.convertTicksToLabels.call(me); + } +}); + +var defaultConfig$1 = { + position: 'left', + ticks: { + callback: core_ticks.formatters.linear + } +}; + +var scale_linear = scale_linearbase.extend({ + determineDataLimits: function() { + var me = this; + var opts = me.options; + var chart = me.chart; + var data = chart.data; + var datasets = data.datasets; + var isHorizontal = me.isHorizontal(); + var DEFAULT_MIN = 0; + var DEFAULT_MAX = 1; + + function IDMatches(meta) { + return isHorizontal ? meta.xAxisID === me.id : meta.yAxisID === me.id; + } + + // First Calculate the range + me.min = null; + me.max = null; + + var hasStacks = opts.stacked; + if (hasStacks === undefined) { + helpers$1.each(datasets, function(dataset, datasetIndex) { + if (hasStacks) { + return; + } + + var meta = chart.getDatasetMeta(datasetIndex); + if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta) && + meta.stack !== undefined) { + hasStacks = true; + } + }); + } + + if (opts.stacked || hasStacks) { + var valuesPerStack = {}; + + helpers$1.each(datasets, function(dataset, datasetIndex) { + var meta = chart.getDatasetMeta(datasetIndex); + var key = [ + meta.type, + // we have a separate stack for stack=undefined datasets when the opts.stacked is undefined + ((opts.stacked === undefined && meta.stack === undefined) ? datasetIndex : ''), + meta.stack + ].join('.'); + + if (valuesPerStack[key] === undefined) { + valuesPerStack[key] = { + positiveValues: [], + negativeValues: [] + }; + } + + // Store these per type + var positiveValues = valuesPerStack[key].positiveValues; + var negativeValues = valuesPerStack[key].negativeValues; + + if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta)) { + helpers$1.each(dataset.data, function(rawValue, index) { + var value = +me.getRightValue(rawValue); + if (isNaN(value) || meta.data[index].hidden) { + return; + } + + positiveValues[index] = positiveValues[index] || 0; + negativeValues[index] = negativeValues[index] || 0; + + if (opts.relativePoints) { + positiveValues[index] = 100; + } else if (value < 0) { + negativeValues[index] += value; + } else { + positiveValues[index] += value; + } + }); + } + }); + + helpers$1.each(valuesPerStack, function(valuesForType) { + var values = valuesForType.positiveValues.concat(valuesForType.negativeValues); + var minVal = helpers$1.min(values); + var maxVal = helpers$1.max(values); + me.min = me.min === null ? minVal : Math.min(me.min, minVal); + me.max = me.max === null ? maxVal : Math.max(me.max, maxVal); + }); + + } else { + helpers$1.each(datasets, function(dataset, datasetIndex) { + var meta = chart.getDatasetMeta(datasetIndex); + if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta)) { + helpers$1.each(dataset.data, function(rawValue, index) { + var value = +me.getRightValue(rawValue); + if (isNaN(value) || meta.data[index].hidden) { + return; + } + + if (me.min === null) { + me.min = value; + } else if (value < me.min) { + me.min = value; + } + + if (me.max === null) { + me.max = value; + } else if (value > me.max) { + me.max = value; + } + }); + } + }); + } + + me.min = isFinite(me.min) && !isNaN(me.min) ? me.min : DEFAULT_MIN; + me.max = isFinite(me.max) && !isNaN(me.max) ? me.max : DEFAULT_MAX; + + // Common base implementation to handle ticks.min, ticks.max, ticks.beginAtZero + this.handleTickRangeOptions(); + }, + + // Returns the maximum number of ticks based on the scale dimension + _computeTickLimit: function() { + var me = this; + var tickFont; + + if (me.isHorizontal()) { + return Math.ceil(me.width / 40); + } + tickFont = helpers$1.options._parseFont(me.options.ticks); + return Math.ceil(me.height / tickFont.lineHeight); + }, + + // Called after the ticks are built. We need + handleDirectionalChanges: function() { + if (!this.isHorizontal()) { + // We are in a vertical orientation. The top value is the highest. So reverse the array + this.ticks.reverse(); + } + }, + + getLabelForIndex: function(index, datasetIndex) { + return +this.getRightValue(this.chart.data.datasets[datasetIndex].data[index]); + }, + + // Utils + getPixelForValue: function(value) { + // This must be called after fit has been run so that + // this.left, this.top, this.right, and this.bottom have been defined + var me = this; + var start = me.start; + + var rightValue = +me.getRightValue(value); + var pixel; + var range = me.end - start; + + if (me.isHorizontal()) { + pixel = me.left + (me.width / range * (rightValue - start)); + } else { + pixel = me.bottom - (me.height / range * (rightValue - start)); + } + return pixel; + }, + + getValueForPixel: function(pixel) { + var me = this; + var isHorizontal = me.isHorizontal(); + var innerDimension = isHorizontal ? me.width : me.height; + var offset = (isHorizontal ? pixel - me.left : me.bottom - pixel) / innerDimension; + return me.start + ((me.end - me.start) * offset); + }, + + getPixelForTick: function(index) { + return this.getPixelForValue(this.ticksAsNumbers[index]); + } +}); + +// INTERNAL: static default options, registered in src/index.js +var _defaults$1 = defaultConfig$1; +scale_linear._defaults = _defaults$1; + +var valueOrDefault$a = helpers$1.valueOrDefault; + +/** + * Generate a set of logarithmic ticks + * @param generationOptions the options used to generate the ticks + * @param dataRange the range of the data + * @returns {number[]} array of tick values + */ +function generateTicks$1(generationOptions, dataRange) { + var ticks = []; + + var tickVal = valueOrDefault$a(generationOptions.min, Math.pow(10, Math.floor(helpers$1.log10(dataRange.min)))); + + var endExp = Math.floor(helpers$1.log10(dataRange.max)); + var endSignificand = Math.ceil(dataRange.max / Math.pow(10, endExp)); + var exp, significand; + + if (tickVal === 0) { + exp = Math.floor(helpers$1.log10(dataRange.minNotZero)); + significand = Math.floor(dataRange.minNotZero / Math.pow(10, exp)); + + ticks.push(tickVal); + tickVal = significand * Math.pow(10, exp); + } else { + exp = Math.floor(helpers$1.log10(tickVal)); + significand = Math.floor(tickVal / Math.pow(10, exp)); + } + var precision = exp < 0 ? Math.pow(10, Math.abs(exp)) : 1; + + do { + ticks.push(tickVal); + + ++significand; + if (significand === 10) { + significand = 1; + ++exp; + precision = exp >= 0 ? 1 : precision; + } + + tickVal = Math.round(significand * Math.pow(10, exp) * precision) / precision; + } while (exp < endExp || (exp === endExp && significand < endSignificand)); + + var lastTick = valueOrDefault$a(generationOptions.max, tickVal); + ticks.push(lastTick); + + return ticks; +} + +var defaultConfig$2 = { + position: 'left', + + // label settings + ticks: { + callback: core_ticks.formatters.logarithmic + } +}; + +// TODO(v3): change this to positiveOrDefault +function nonNegativeOrDefault(value, defaultValue) { + return helpers$1.isFinite(value) && value >= 0 ? value : defaultValue; +} + +var scale_logarithmic = core_scale.extend({ + determineDataLimits: function() { + var me = this; + var opts = me.options; + var chart = me.chart; + var data = chart.data; + var datasets = data.datasets; + var isHorizontal = me.isHorizontal(); + function IDMatches(meta) { + return isHorizontal ? meta.xAxisID === me.id : meta.yAxisID === me.id; + } + + // Calculate Range + me.min = null; + me.max = null; + me.minNotZero = null; + + var hasStacks = opts.stacked; + if (hasStacks === undefined) { + helpers$1.each(datasets, function(dataset, datasetIndex) { + if (hasStacks) { + return; + } + + var meta = chart.getDatasetMeta(datasetIndex); + if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta) && + meta.stack !== undefined) { + hasStacks = true; + } + }); + } + + if (opts.stacked || hasStacks) { + var valuesPerStack = {}; + + helpers$1.each(datasets, function(dataset, datasetIndex) { + var meta = chart.getDatasetMeta(datasetIndex); + var key = [ + meta.type, + // we have a separate stack for stack=undefined datasets when the opts.stacked is undefined + ((opts.stacked === undefined && meta.stack === undefined) ? datasetIndex : ''), + meta.stack + ].join('.'); + + if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta)) { + if (valuesPerStack[key] === undefined) { + valuesPerStack[key] = []; + } + + helpers$1.each(dataset.data, function(rawValue, index) { + var values = valuesPerStack[key]; + var value = +me.getRightValue(rawValue); + // invalid, hidden and negative values are ignored + if (isNaN(value) || meta.data[index].hidden || value < 0) { + return; + } + values[index] = values[index] || 0; + values[index] += value; + }); + } + }); + + helpers$1.each(valuesPerStack, function(valuesForType) { + if (valuesForType.length > 0) { + var minVal = helpers$1.min(valuesForType); + var maxVal = helpers$1.max(valuesForType); + me.min = me.min === null ? minVal : Math.min(me.min, minVal); + me.max = me.max === null ? maxVal : Math.max(me.max, maxVal); + } + }); + + } else { + helpers$1.each(datasets, function(dataset, datasetIndex) { + var meta = chart.getDatasetMeta(datasetIndex); + if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta)) { + helpers$1.each(dataset.data, function(rawValue, index) { + var value = +me.getRightValue(rawValue); + // invalid, hidden and negative values are ignored + if (isNaN(value) || meta.data[index].hidden || value < 0) { + return; + } + + if (me.min === null) { + me.min = value; + } else if (value < me.min) { + me.min = value; + } + + if (me.max === null) { + me.max = value; + } else if (value > me.max) { + me.max = value; + } + + if (value !== 0 && (me.minNotZero === null || value < me.minNotZero)) { + me.minNotZero = value; + } + }); + } + }); + } + + // Common base implementation to handle ticks.min, ticks.max + this.handleTickRangeOptions(); + }, + + handleTickRangeOptions: function() { + var me = this; + var tickOpts = me.options.ticks; + var DEFAULT_MIN = 1; + var DEFAULT_MAX = 10; + + me.min = nonNegativeOrDefault(tickOpts.min, me.min); + me.max = nonNegativeOrDefault(tickOpts.max, me.max); + + if (me.min === me.max) { + if (me.min !== 0 && me.min !== null) { + me.min = Math.pow(10, Math.floor(helpers$1.log10(me.min)) - 1); + me.max = Math.pow(10, Math.floor(helpers$1.log10(me.max)) + 1); + } else { + me.min = DEFAULT_MIN; + me.max = DEFAULT_MAX; + } + } + if (me.min === null) { + me.min = Math.pow(10, Math.floor(helpers$1.log10(me.max)) - 1); + } + if (me.max === null) { + me.max = me.min !== 0 + ? Math.pow(10, Math.floor(helpers$1.log10(me.min)) + 1) + : DEFAULT_MAX; + } + if (me.minNotZero === null) { + if (me.min > 0) { + me.minNotZero = me.min; + } else if (me.max < 1) { + me.minNotZero = Math.pow(10, Math.floor(helpers$1.log10(me.max))); + } else { + me.minNotZero = DEFAULT_MIN; + } + } + }, + + buildTicks: function() { + var me = this; + var tickOpts = me.options.ticks; + var reverse = !me.isHorizontal(); + + var generationOptions = { + min: nonNegativeOrDefault(tickOpts.min), + max: nonNegativeOrDefault(tickOpts.max) + }; + var ticks = me.ticks = generateTicks$1(generationOptions, me); + + // At this point, we need to update our max and min given the tick values since we have expanded the + // range of the scale + me.max = helpers$1.max(ticks); + me.min = helpers$1.min(ticks); + + if (tickOpts.reverse) { + reverse = !reverse; + me.start = me.max; + me.end = me.min; + } else { + me.start = me.min; + me.end = me.max; + } + if (reverse) { + ticks.reverse(); + } + }, + + convertTicksToLabels: function() { + this.tickValues = this.ticks.slice(); + + core_scale.prototype.convertTicksToLabels.call(this); + }, + + // Get the correct tooltip label + getLabelForIndex: function(index, datasetIndex) { + return +this.getRightValue(this.chart.data.datasets[datasetIndex].data[index]); + }, + + getPixelForTick: function(index) { + return this.getPixelForValue(this.tickValues[index]); + }, + + /** + * Returns the value of the first tick. + * @param {number} value - The minimum not zero value. + * @return {number} The first tick value. + * @private + */ + _getFirstTickValue: function(value) { + var exp = Math.floor(helpers$1.log10(value)); + var significand = Math.floor(value / Math.pow(10, exp)); + + return significand * Math.pow(10, exp); + }, + + getPixelForValue: function(value) { + var me = this; + var tickOpts = me.options.ticks; + var reverse = tickOpts.reverse; + var log10 = helpers$1.log10; + var firstTickValue = me._getFirstTickValue(me.minNotZero); + var offset = 0; + var innerDimension, pixel, start, end, sign; + + value = +me.getRightValue(value); + if (reverse) { + start = me.end; + end = me.start; + sign = -1; + } else { + start = me.start; + end = me.end; + sign = 1; + } + if (me.isHorizontal()) { + innerDimension = me.width; + pixel = reverse ? me.right : me.left; + } else { + innerDimension = me.height; + sign *= -1; // invert, since the upper-left corner of the canvas is at pixel (0, 0) + pixel = reverse ? me.top : me.bottom; + } + if (value !== start) { + if (start === 0) { // include zero tick + offset = valueOrDefault$a(tickOpts.fontSize, core_defaults.global.defaultFontSize); + innerDimension -= offset; + start = firstTickValue; + } + if (value !== 0) { + offset += innerDimension / (log10(end) - log10(start)) * (log10(value) - log10(start)); + } + pixel += sign * offset; + } + return pixel; + }, + + getValueForPixel: function(pixel) { + var me = this; + var tickOpts = me.options.ticks; + var reverse = tickOpts.reverse; + var log10 = helpers$1.log10; + var firstTickValue = me._getFirstTickValue(me.minNotZero); + var innerDimension, start, end, value; + + if (reverse) { + start = me.end; + end = me.start; + } else { + start = me.start; + end = me.end; + } + if (me.isHorizontal()) { + innerDimension = me.width; + value = reverse ? me.right - pixel : pixel - me.left; + } else { + innerDimension = me.height; + value = reverse ? pixel - me.top : me.bottom - pixel; + } + if (value !== start) { + if (start === 0) { // include zero tick + var offset = valueOrDefault$a(tickOpts.fontSize, core_defaults.global.defaultFontSize); + value -= offset; + innerDimension -= offset; + start = firstTickValue; + } + value *= log10(end) - log10(start); + value /= innerDimension; + value = Math.pow(10, log10(start) + value); + } + return value; + } +}); + +// INTERNAL: static default options, registered in src/index.js +var _defaults$2 = defaultConfig$2; +scale_logarithmic._defaults = _defaults$2; + +var valueOrDefault$b = helpers$1.valueOrDefault; +var valueAtIndexOrDefault$1 = helpers$1.valueAtIndexOrDefault; +var resolve$7 = helpers$1.options.resolve; + +var defaultConfig$3 = { + display: true, + + // Boolean - Whether to animate scaling the chart from the centre + animate: true, + position: 'chartArea', + + angleLines: { + display: true, + color: 'rgba(0, 0, 0, 0.1)', + lineWidth: 1, + borderDash: [], + borderDashOffset: 0.0 + }, + + gridLines: { + circular: false + }, + + // label settings + ticks: { + // Boolean - Show a backdrop to the scale label + showLabelBackdrop: true, + + // String - The colour of the label backdrop + backdropColor: 'rgba(255,255,255,0.75)', + + // Number - The backdrop padding above & below the label in pixels + backdropPaddingY: 2, + + // Number - The backdrop padding to the side of the label in pixels + backdropPaddingX: 2, + + callback: core_ticks.formatters.linear + }, + + pointLabels: { + // Boolean - if true, show point labels + display: true, + + // Number - Point label font size in pixels + fontSize: 10, + + // Function - Used to convert point labels + callback: function(label) { + return label; + } + } +}; + +function getValueCount(scale) { + var opts = scale.options; + return opts.angleLines.display || opts.pointLabels.display ? scale.chart.data.labels.length : 0; +} + +function getTickBackdropHeight(opts) { + var tickOpts = opts.ticks; + + if (tickOpts.display && opts.display) { + return valueOrDefault$b(tickOpts.fontSize, core_defaults.global.defaultFontSize) + tickOpts.backdropPaddingY * 2; + } + return 0; +} + +function measureLabelSize(ctx, lineHeight, label) { + if (helpers$1.isArray(label)) { + return { + w: helpers$1.longestText(ctx, ctx.font, label), + h: label.length * lineHeight + }; + } + + return { + w: ctx.measureText(label).width, + h: lineHeight + }; +} + +function determineLimits(angle, pos, size, min, max) { + if (angle === min || angle === max) { + return { + start: pos - (size / 2), + end: pos + (size / 2) + }; + } else if (angle < min || angle > max) { + return { + start: pos - size, + end: pos + }; + } + + return { + start: pos, + end: pos + size + }; +} + +/** + * Helper function to fit a radial linear scale with point labels + */ +function fitWithPointLabels(scale) { + + // Right, this is really confusing and there is a lot of maths going on here + // The gist of the problem is here: https://gist.github.com/nnnick/696cc9c55f4b0beb8fe9 + // + // Reaction: https://dl.dropboxusercontent.com/u/34601363/toomuchscience.gif + // + // Solution: + // + // We assume the radius of the polygon is half the size of the canvas at first + // at each index we check if the text overlaps. + // + // Where it does, we store that angle and that index. + // + // After finding the largest index and angle we calculate how much we need to remove + // from the shape radius to move the point inwards by that x. + // + // We average the left and right distances to get the maximum shape radius that can fit in the box + // along with labels. + // + // Once we have that, we can find the centre point for the chart, by taking the x text protrusion + // on each side, removing that from the size, halving it and adding the left x protrusion width. + // + // This will mean we have a shape fitted to the canvas, as large as it can be with the labels + // and position it in the most space efficient manner + // + // https://dl.dropboxusercontent.com/u/34601363/yeahscience.gif + + var plFont = helpers$1.options._parseFont(scale.options.pointLabels); + + // Get maximum radius of the polygon. Either half the height (minus the text width) or half the width. + // Use this to calculate the offset + change. - Make sure L/R protrusion is at least 0 to stop issues with centre points + var furthestLimits = { + l: 0, + r: scale.width, + t: 0, + b: scale.height - scale.paddingTop + }; + var furthestAngles = {}; + var i, textSize, pointPosition; + + scale.ctx.font = plFont.string; + scale._pointLabelSizes = []; + + var valueCount = getValueCount(scale); + for (i = 0; i < valueCount; i++) { + pointPosition = scale.getPointPosition(i, scale.drawingArea + 5); + textSize = measureLabelSize(scale.ctx, plFont.lineHeight, scale.pointLabels[i] || ''); + scale._pointLabelSizes[i] = textSize; + + // Add quarter circle to make degree 0 mean top of circle + var angleRadians = scale.getIndexAngle(i); + var angle = helpers$1.toDegrees(angleRadians) % 360; + var hLimits = determineLimits(angle, pointPosition.x, textSize.w, 0, 180); + var vLimits = determineLimits(angle, pointPosition.y, textSize.h, 90, 270); + + if (hLimits.start < furthestLimits.l) { + furthestLimits.l = hLimits.start; + furthestAngles.l = angleRadians; + } + + if (hLimits.end > furthestLimits.r) { + furthestLimits.r = hLimits.end; + furthestAngles.r = angleRadians; + } + + if (vLimits.start < furthestLimits.t) { + furthestLimits.t = vLimits.start; + furthestAngles.t = angleRadians; + } + + if (vLimits.end > furthestLimits.b) { + furthestLimits.b = vLimits.end; + furthestAngles.b = angleRadians; + } + } + + scale.setReductions(scale.drawingArea, furthestLimits, furthestAngles); +} + +function getTextAlignForAngle(angle) { + if (angle === 0 || angle === 180) { + return 'center'; + } else if (angle < 180) { + return 'left'; + } + + return 'right'; +} + +function fillText(ctx, text, position, lineHeight) { + var y = position.y + lineHeight / 2; + var i, ilen; + + if (helpers$1.isArray(text)) { + for (i = 0, ilen = text.length; i < ilen; ++i) { + ctx.fillText(text[i], position.x, y); + y += lineHeight; + } + } else { + ctx.fillText(text, position.x, y); + } +} + +function adjustPointPositionForLabelHeight(angle, textSize, position) { + if (angle === 90 || angle === 270) { + position.y -= (textSize.h / 2); + } else if (angle > 270 || angle < 90) { + position.y -= textSize.h; + } +} + +function drawPointLabels(scale) { + var ctx = scale.ctx; + var opts = scale.options; + var angleLineOpts = opts.angleLines; + var gridLineOpts = opts.gridLines; + var pointLabelOpts = opts.pointLabels; + var lineWidth = valueOrDefault$b(angleLineOpts.lineWidth, gridLineOpts.lineWidth); + var lineColor = valueOrDefault$b(angleLineOpts.color, gridLineOpts.color); + var tickBackdropHeight = getTickBackdropHeight(opts); + + ctx.save(); + ctx.lineWidth = lineWidth; + ctx.strokeStyle = lineColor; + if (ctx.setLineDash) { + ctx.setLineDash(resolve$7([angleLineOpts.borderDash, gridLineOpts.borderDash, []])); + ctx.lineDashOffset = resolve$7([angleLineOpts.borderDashOffset, gridLineOpts.borderDashOffset, 0.0]); + } + + var outerDistance = scale.getDistanceFromCenterForValue(opts.ticks.reverse ? scale.min : scale.max); + + // Point Label Font + var plFont = helpers$1.options._parseFont(pointLabelOpts); + + ctx.font = plFont.string; + ctx.textBaseline = 'middle'; + + for (var i = getValueCount(scale) - 1; i >= 0; i--) { + if (angleLineOpts.display && lineWidth && lineColor) { + var outerPosition = scale.getPointPosition(i, outerDistance); + ctx.beginPath(); + ctx.moveTo(scale.xCenter, scale.yCenter); + ctx.lineTo(outerPosition.x, outerPosition.y); + ctx.stroke(); + } + + if (pointLabelOpts.display) { + // Extra pixels out for some label spacing + var extra = (i === 0 ? tickBackdropHeight / 2 : 0); + var pointLabelPosition = scale.getPointPosition(i, outerDistance + extra + 5); + + // Keep this in loop since we may support array properties here + var pointLabelFontColor = valueAtIndexOrDefault$1(pointLabelOpts.fontColor, i, core_defaults.global.defaultFontColor); + ctx.fillStyle = pointLabelFontColor; + + var angleRadians = scale.getIndexAngle(i); + var angle = helpers$1.toDegrees(angleRadians); + ctx.textAlign = getTextAlignForAngle(angle); + adjustPointPositionForLabelHeight(angle, scale._pointLabelSizes[i], pointLabelPosition); + fillText(ctx, scale.pointLabels[i] || '', pointLabelPosition, plFont.lineHeight); + } + } + ctx.restore(); +} + +function drawRadiusLine(scale, gridLineOpts, radius, index) { + var ctx = scale.ctx; + var circular = gridLineOpts.circular; + var valueCount = getValueCount(scale); + var lineColor = valueAtIndexOrDefault$1(gridLineOpts.color, index - 1); + var lineWidth = valueAtIndexOrDefault$1(gridLineOpts.lineWidth, index - 1); + var pointPosition; + + if ((!circular && !valueCount) || !lineColor || !lineWidth) { + return; + } + + ctx.save(); + ctx.strokeStyle = lineColor; + ctx.lineWidth = lineWidth; + if (ctx.setLineDash) { + ctx.setLineDash(gridLineOpts.borderDash || []); + ctx.lineDashOffset = gridLineOpts.borderDashOffset || 0.0; + } + + ctx.beginPath(); + if (circular) { + // Draw circular arcs between the points + ctx.arc(scale.xCenter, scale.yCenter, radius, 0, Math.PI * 2); + } else { + // Draw straight lines connecting each index + pointPosition = scale.getPointPosition(0, radius); + ctx.moveTo(pointPosition.x, pointPosition.y); + + for (var i = 1; i < valueCount; i++) { + pointPosition = scale.getPointPosition(i, radius); + ctx.lineTo(pointPosition.x, pointPosition.y); + } + } + ctx.closePath(); + ctx.stroke(); + ctx.restore(); +} + +function numberOrZero(param) { + return helpers$1.isNumber(param) ? param : 0; +} + +var scale_radialLinear = scale_linearbase.extend({ + setDimensions: function() { + var me = this; + + // Set the unconstrained dimension before label rotation + me.width = me.maxWidth; + me.height = me.maxHeight; + me.paddingTop = getTickBackdropHeight(me.options) / 2; + me.xCenter = Math.floor(me.width / 2); + me.yCenter = Math.floor((me.height - me.paddingTop) / 2); + me.drawingArea = Math.min(me.height - me.paddingTop, me.width) / 2; + }, + + determineDataLimits: function() { + var me = this; + var chart = me.chart; + var min = Number.POSITIVE_INFINITY; + var max = Number.NEGATIVE_INFINITY; + + helpers$1.each(chart.data.datasets, function(dataset, datasetIndex) { + if (chart.isDatasetVisible(datasetIndex)) { + var meta = chart.getDatasetMeta(datasetIndex); + + helpers$1.each(dataset.data, function(rawValue, index) { + var value = +me.getRightValue(rawValue); + if (isNaN(value) || meta.data[index].hidden) { + return; + } + + min = Math.min(value, min); + max = Math.max(value, max); + }); + } + }); + + me.min = (min === Number.POSITIVE_INFINITY ? 0 : min); + me.max = (max === Number.NEGATIVE_INFINITY ? 0 : max); + + // Common base implementation to handle ticks.min, ticks.max, ticks.beginAtZero + me.handleTickRangeOptions(); + }, + + // Returns the maximum number of ticks based on the scale dimension + _computeTickLimit: function() { + return Math.ceil(this.drawingArea / getTickBackdropHeight(this.options)); + }, + + convertTicksToLabels: function() { + var me = this; + + scale_linearbase.prototype.convertTicksToLabels.call(me); + + // Point labels + me.pointLabels = me.chart.data.labels.map(me.options.pointLabels.callback, me); + }, + + getLabelForIndex: function(index, datasetIndex) { + return +this.getRightValue(this.chart.data.datasets[datasetIndex].data[index]); + }, + + fit: function() { + var me = this; + var opts = me.options; + + if (opts.display && opts.pointLabels.display) { + fitWithPointLabels(me); + } else { + me.setCenterPoint(0, 0, 0, 0); + } + }, + + /** + * Set radius reductions and determine new radius and center point + * @private + */ + setReductions: function(largestPossibleRadius, furthestLimits, furthestAngles) { + var me = this; + var radiusReductionLeft = furthestLimits.l / Math.sin(furthestAngles.l); + var radiusReductionRight = Math.max(furthestLimits.r - me.width, 0) / Math.sin(furthestAngles.r); + var radiusReductionTop = -furthestLimits.t / Math.cos(furthestAngles.t); + var radiusReductionBottom = -Math.max(furthestLimits.b - (me.height - me.paddingTop), 0) / Math.cos(furthestAngles.b); + + radiusReductionLeft = numberOrZero(radiusReductionLeft); + radiusReductionRight = numberOrZero(radiusReductionRight); + radiusReductionTop = numberOrZero(radiusReductionTop); + radiusReductionBottom = numberOrZero(radiusReductionBottom); + + me.drawingArea = Math.min( + Math.floor(largestPossibleRadius - (radiusReductionLeft + radiusReductionRight) / 2), + Math.floor(largestPossibleRadius - (radiusReductionTop + radiusReductionBottom) / 2)); + me.setCenterPoint(radiusReductionLeft, radiusReductionRight, radiusReductionTop, radiusReductionBottom); + }, + + setCenterPoint: function(leftMovement, rightMovement, topMovement, bottomMovement) { + var me = this; + var maxRight = me.width - rightMovement - me.drawingArea; + var maxLeft = leftMovement + me.drawingArea; + var maxTop = topMovement + me.drawingArea; + var maxBottom = (me.height - me.paddingTop) - bottomMovement - me.drawingArea; + + me.xCenter = Math.floor(((maxLeft + maxRight) / 2) + me.left); + me.yCenter = Math.floor(((maxTop + maxBottom) / 2) + me.top + me.paddingTop); + }, + + getIndexAngle: function(index) { + var angleMultiplier = (Math.PI * 2) / getValueCount(this); + var startAngle = this.chart.options && this.chart.options.startAngle ? + this.chart.options.startAngle : + 0; + + var startAngleRadians = startAngle * Math.PI * 2 / 360; + + // Start from the top instead of right, so remove a quarter of the circle + return index * angleMultiplier + startAngleRadians; + }, + + getDistanceFromCenterForValue: function(value) { + var me = this; + + if (value === null) { + return 0; // null always in center + } + + // Take into account half font size + the yPadding of the top value + var scalingFactor = me.drawingArea / (me.max - me.min); + if (me.options.ticks.reverse) { + return (me.max - value) * scalingFactor; + } + return (value - me.min) * scalingFactor; + }, + + getPointPosition: function(index, distanceFromCenter) { + var me = this; + var thisAngle = me.getIndexAngle(index) - (Math.PI / 2); + return { + x: Math.cos(thisAngle) * distanceFromCenter + me.xCenter, + y: Math.sin(thisAngle) * distanceFromCenter + me.yCenter + }; + }, + + getPointPositionForValue: function(index, value) { + return this.getPointPosition(index, this.getDistanceFromCenterForValue(value)); + }, + + getBasePosition: function() { + var me = this; + var min = me.min; + var max = me.max; + + return me.getPointPositionForValue(0, + me.beginAtZero ? 0 : + min < 0 && max < 0 ? max : + min > 0 && max > 0 ? min : + 0); + }, + + draw: function() { + var me = this; + var opts = me.options; + var gridLineOpts = opts.gridLines; + var tickOpts = opts.ticks; + + if (opts.display) { + var ctx = me.ctx; + var startAngle = this.getIndexAngle(0); + var tickFont = helpers$1.options._parseFont(tickOpts); + + if (opts.angleLines.display || opts.pointLabels.display) { + drawPointLabels(me); + } + + helpers$1.each(me.ticks, function(label, index) { + // Don't draw a centre value (if it is minimum) + if (index > 0 || tickOpts.reverse) { + var yCenterOffset = me.getDistanceFromCenterForValue(me.ticksAsNumbers[index]); + + // Draw circular lines around the scale + if (gridLineOpts.display && index !== 0) { + drawRadiusLine(me, gridLineOpts, yCenterOffset, index); + } + + if (tickOpts.display) { + var tickFontColor = valueOrDefault$b(tickOpts.fontColor, core_defaults.global.defaultFontColor); + ctx.font = tickFont.string; + + ctx.save(); + ctx.translate(me.xCenter, me.yCenter); + ctx.rotate(startAngle); + + if (tickOpts.showLabelBackdrop) { + var labelWidth = ctx.measureText(label).width; + ctx.fillStyle = tickOpts.backdropColor; + ctx.fillRect( + -labelWidth / 2 - tickOpts.backdropPaddingX, + -yCenterOffset - tickFont.size / 2 - tickOpts.backdropPaddingY, + labelWidth + tickOpts.backdropPaddingX * 2, + tickFont.size + tickOpts.backdropPaddingY * 2 + ); + } + + ctx.textAlign = 'center'; + ctx.textBaseline = 'middle'; + ctx.fillStyle = tickFontColor; + ctx.fillText(label, 0, -yCenterOffset); + ctx.restore(); + } + } + }); + } + } +}); + +// INTERNAL: static default options, registered in src/index.js +var _defaults$3 = defaultConfig$3; +scale_radialLinear._defaults = _defaults$3; + +var valueOrDefault$c = helpers$1.valueOrDefault; + +// Integer constants are from the ES6 spec. +var MIN_INTEGER = Number.MIN_SAFE_INTEGER || -9007199254740991; +var MAX_INTEGER = Number.MAX_SAFE_INTEGER || 9007199254740991; + +var INTERVALS = { + millisecond: { + common: true, + size: 1, + steps: [1, 2, 5, 10, 20, 50, 100, 250, 500] + }, + second: { + common: true, + size: 1000, + steps: [1, 2, 5, 10, 15, 30] + }, + minute: { + common: true, + size: 60000, + steps: [1, 2, 5, 10, 15, 30] + }, + hour: { + common: true, + size: 3600000, + steps: [1, 2, 3, 6, 12] + }, + day: { + common: true, + size: 86400000, + steps: [1, 2, 5] + }, + week: { + common: false, + size: 604800000, + steps: [1, 2, 3, 4] + }, + month: { + common: true, + size: 2.628e9, + steps: [1, 2, 3] + }, + quarter: { + common: false, + size: 7.884e9, + steps: [1, 2, 3, 4] + }, + year: { + common: true, + size: 3.154e10 + } +}; + +var UNITS = Object.keys(INTERVALS); + +function sorter(a, b) { + return a - b; +} + +function arrayUnique(items) { + var hash = {}; + var out = []; + var i, ilen, item; + + for (i = 0, ilen = items.length; i < ilen; ++i) { + item = items[i]; + if (!hash[item]) { + hash[item] = true; + out.push(item); + } + } + + return out; +} + +/** + * Returns an array of {time, pos} objects used to interpolate a specific `time` or position + * (`pos`) on the scale, by searching entries before and after the requested value. `pos` is + * a decimal between 0 and 1: 0 being the start of the scale (left or top) and 1 the other + * extremity (left + width or top + height). Note that it would be more optimized to directly + * store pre-computed pixels, but the scale dimensions are not guaranteed at the time we need + * to create the lookup table. The table ALWAYS contains at least two items: min and max. + * + * @param {number[]} timestamps - timestamps sorted from lowest to highest. + * @param {string} distribution - If 'linear', timestamps will be spread linearly along the min + * and max range, so basically, the table will contains only two items: {min, 0} and {max, 1}. + * If 'series', timestamps will be positioned at the same distance from each other. In this + * case, only timestamps that break the time linearity are registered, meaning that in the + * best case, all timestamps are linear, the table contains only min and max. + */ +function buildLookupTable(timestamps, min, max, distribution) { + if (distribution === 'linear' || !timestamps.length) { + return [ + {time: min, pos: 0}, + {time: max, pos: 1} + ]; + } + + var table = []; + var items = [min]; + var i, ilen, prev, curr, next; + + for (i = 0, ilen = timestamps.length; i < ilen; ++i) { + curr = timestamps[i]; + if (curr > min && curr < max) { + items.push(curr); + } + } + + items.push(max); + + for (i = 0, ilen = items.length; i < ilen; ++i) { + next = items[i + 1]; + prev = items[i - 1]; + curr = items[i]; + + // only add points that breaks the scale linearity + if (prev === undefined || next === undefined || Math.round((next + prev) / 2) !== curr) { + table.push({time: curr, pos: i / (ilen - 1)}); + } + } + + return table; +} + +// @see adapted from https://www.anujgakhar.com/2014/03/01/binary-search-in-javascript/ +function lookup(table, key, value) { + var lo = 0; + var hi = table.length - 1; + var mid, i0, i1; + + while (lo >= 0 && lo <= hi) { + mid = (lo + hi) >> 1; + i0 = table[mid - 1] || null; + i1 = table[mid]; + + if (!i0) { + // given value is outside table (before first item) + return {lo: null, hi: i1}; + } else if (i1[key] < value) { + lo = mid + 1; + } else if (i0[key] > value) { + hi = mid - 1; + } else { + return {lo: i0, hi: i1}; + } + } + + // given value is outside table (after last item) + return {lo: i1, hi: null}; +} + +/** + * Linearly interpolates the given source `value` using the table items `skey` values and + * returns the associated `tkey` value. For example, interpolate(table, 'time', 42, 'pos') + * returns the position for a timestamp equal to 42. If value is out of bounds, values at + * index [0, 1] or [n - 1, n] are used for the interpolation. + */ +function interpolate$1(table, skey, sval, tkey) { + var range = lookup(table, skey, sval); + + // Note: the lookup table ALWAYS contains at least 2 items (min and max) + var prev = !range.lo ? table[0] : !range.hi ? table[table.length - 2] : range.lo; + var next = !range.lo ? table[1] : !range.hi ? table[table.length - 1] : range.hi; + + var span = next[skey] - prev[skey]; + var ratio = span ? (sval - prev[skey]) / span : 0; + var offset = (next[tkey] - prev[tkey]) * ratio; + + return prev[tkey] + offset; +} + +function toTimestamp(scale, input) { + var adapter = scale._adapter; + var options = scale.options.time; + var parser = options.parser; + var format = parser || options.format; + var value = input; + + if (typeof parser === 'function') { + value = parser(value); + } + + // Only parse if its not a timestamp already + if (!helpers$1.isFinite(value)) { + value = typeof format === 'string' + ? adapter.parse(value, format) + : adapter.parse(value); + } + + if (value !== null) { + return +value; + } + + // Labels are in an incompatible format and no `parser` has been provided. + // The user might still use the deprecated `format` option for parsing. + if (!parser && typeof format === 'function') { + value = format(input); + + // `format` could return something else than a timestamp, if so, parse it + if (!helpers$1.isFinite(value)) { + value = adapter.parse(value); + } + } + + return value; +} + +function parse(scale, input) { + if (helpers$1.isNullOrUndef(input)) { + return null; + } + + var options = scale.options.time; + var value = toTimestamp(scale, scale.getRightValue(input)); + if (value === null) { + return value; + } + + if (options.round) { + value = +scale._adapter.startOf(value, options.round); + } + + return value; +} + +/** + * Returns the number of unit to skip to be able to display up to `capacity` number of ticks + * in `unit` for the given `min` / `max` range and respecting the interval steps constraints. + */ +function determineStepSize(min, max, unit, capacity) { + var range = max - min; + var interval = INTERVALS[unit]; + var milliseconds = interval.size; + var steps = interval.steps; + var i, ilen, factor; + + if (!steps) { + return Math.ceil(range / (capacity * milliseconds)); + } + + for (i = 0, ilen = steps.length; i < ilen; ++i) { + factor = steps[i]; + if (Math.ceil(range / (milliseconds * factor)) <= capacity) { + break; + } + } + + return factor; +} + +/** + * Figures out what unit results in an appropriate number of auto-generated ticks + */ +function determineUnitForAutoTicks(minUnit, min, max, capacity) { + var ilen = UNITS.length; + var i, interval, factor; + + for (i = UNITS.indexOf(minUnit); i < ilen - 1; ++i) { + interval = INTERVALS[UNITS[i]]; + factor = interval.steps ? interval.steps[interval.steps.length - 1] : MAX_INTEGER; + + if (interval.common && Math.ceil((max - min) / (factor * interval.size)) <= capacity) { + return UNITS[i]; + } + } + + return UNITS[ilen - 1]; +} + +/** + * Figures out what unit to format a set of ticks with + */ +function determineUnitForFormatting(scale, ticks, minUnit, min, max) { + var ilen = UNITS.length; + var i, unit; + + for (i = ilen - 1; i >= UNITS.indexOf(minUnit); i--) { + unit = UNITS[i]; + if (INTERVALS[unit].common && scale._adapter.diff(max, min, unit) >= ticks.length) { + return unit; + } + } + + return UNITS[minUnit ? UNITS.indexOf(minUnit) : 0]; +} + +function determineMajorUnit(unit) { + for (var i = UNITS.indexOf(unit) + 1, ilen = UNITS.length; i < ilen; ++i) { + if (INTERVALS[UNITS[i]].common) { + return UNITS[i]; + } + } +} + +/** + * Generates a maximum of `capacity` timestamps between min and max, rounded to the + * `minor` unit, aligned on the `major` unit and using the given scale time `options`. + * Important: this method can return ticks outside the min and max range, it's the + * responsibility of the calling code to clamp values if needed. + */ +function generate(scale, min, max, capacity) { + var adapter = scale._adapter; + var options = scale.options; + var timeOpts = options.time; + var minor = timeOpts.unit || determineUnitForAutoTicks(timeOpts.minUnit, min, max, capacity); + var major = determineMajorUnit(minor); + var stepSize = valueOrDefault$c(timeOpts.stepSize, timeOpts.unitStepSize); + var weekday = minor === 'week' ? timeOpts.isoWeekday : false; + var majorTicksEnabled = options.ticks.major.enabled; + var interval = INTERVALS[minor]; + var first = min; + var last = max; + var ticks = []; + var time; + + if (!stepSize) { + stepSize = determineStepSize(min, max, minor, capacity); + } + + // For 'week' unit, handle the first day of week option + if (weekday) { + first = +adapter.startOf(first, 'isoWeek', weekday); + last = +adapter.startOf(last, 'isoWeek', weekday); + } + + // Align first/last ticks on unit + first = +adapter.startOf(first, weekday ? 'day' : minor); + last = +adapter.startOf(last, weekday ? 'day' : minor); + + // Make sure that the last tick include max + if (last < max) { + last = +adapter.add(last, 1, minor); + } + + time = first; + + if (majorTicksEnabled && major && !weekday && !timeOpts.round) { + // Align the first tick on the previous `minor` unit aligned on the `major` unit: + // we first aligned time on the previous `major` unit then add the number of full + // stepSize there is between first and the previous major time. + time = +adapter.startOf(time, major); + time = +adapter.add(time, ~~((first - time) / (interval.size * stepSize)) * stepSize, minor); + } + + for (; time < last; time = +adapter.add(time, stepSize, minor)) { + ticks.push(+time); + } + + ticks.push(+time); + + return ticks; +} + +/** + * Returns the start and end offsets from edges in the form of {start, end} + * where each value is a relative width to the scale and ranges between 0 and 1. + * They add extra margins on the both sides by scaling down the original scale. + * Offsets are added when the `offset` option is true. + */ +function computeOffsets(table, ticks, min, max, options) { + var start = 0; + var end = 0; + var first, last; + + if (options.offset && ticks.length) { + if (!options.time.min) { + first = interpolate$1(table, 'time', ticks[0], 'pos'); + if (ticks.length === 1) { + start = 1 - first; + } else { + start = (interpolate$1(table, 'time', ticks[1], 'pos') - first) / 2; + } + } + if (!options.time.max) { + last = interpolate$1(table, 'time', ticks[ticks.length - 1], 'pos'); + if (ticks.length === 1) { + end = last; + } else { + end = (last - interpolate$1(table, 'time', ticks[ticks.length - 2], 'pos')) / 2; + } + } + } + + return {start: start, end: end}; +} + +function ticksFromTimestamps(scale, values, majorUnit) { + var ticks = []; + var i, ilen, value, major; + + for (i = 0, ilen = values.length; i < ilen; ++i) { + value = values[i]; + major = majorUnit ? value === +scale._adapter.startOf(value, majorUnit) : false; + + ticks.push({ + value: value, + major: major + }); + } + + return ticks; +} + +var defaultConfig$4 = { + position: 'bottom', + + /** + * Data distribution along the scale: + * - 'linear': data are spread according to their time (distances can vary), + * - 'series': data are spread at the same distance from each other. + * @see https://github.com/chartjs/Chart.js/pull/4507 + * @since 2.7.0 + */ + distribution: 'linear', + + /** + * Scale boundary strategy (bypassed by min/max time options) + * - `data`: make sure data are fully visible, ticks outside are removed + * - `ticks`: make sure ticks are fully visible, data outside are truncated + * @see https://github.com/chartjs/Chart.js/pull/4556 + * @since 2.7.0 + */ + bounds: 'data', + + adapters: {}, + time: { + parser: false, // false == a pattern string from https://momentjs.com/docs/#/parsing/string-format/ or a custom callback that converts its argument to a moment + format: false, // DEPRECATED false == date objects, moment object, callback or a pattern string from https://momentjs.com/docs/#/parsing/string-format/ + unit: false, // false == automatic or override with week, month, year, etc. + round: false, // none, or override with week, month, year, etc. + displayFormat: false, // DEPRECATED + isoWeekday: false, // override week start day - see https://momentjs.com/docs/#/get-set/iso-weekday/ + minUnit: 'millisecond', + displayFormats: {} + }, + ticks: { + autoSkip: false, + + /** + * Ticks generation input values: + * - 'auto': generates "optimal" ticks based on scale size and time options. + * - 'data': generates ticks from data (including labels from data {t|x|y} objects). + * - 'labels': generates ticks from user given `data.labels` values ONLY. + * @see https://github.com/chartjs/Chart.js/pull/4507 + * @since 2.7.0 + */ + source: 'auto', + + major: { + enabled: false + } + } +}; + +var scale_time = core_scale.extend({ + initialize: function() { + this.mergeTicksOptions(); + core_scale.prototype.initialize.call(this); + }, + + update: function() { + var me = this; + var options = me.options; + var time = options.time || (options.time = {}); + var adapter = me._adapter = new core_adapters._date(options.adapters.date); + + // DEPRECATIONS: output a message only one time per update + if (time.format) { + console.warn('options.time.format is deprecated and replaced by options.time.parser.'); + } + + // Backward compatibility: before introducing adapter, `displayFormats` was + // supposed to contain *all* unit/string pairs but this can't be resolved + // when loading the scale (adapters are loaded afterward), so let's populate + // missing formats on update + helpers$1.mergeIf(time.displayFormats, adapter.formats()); + + return core_scale.prototype.update.apply(me, arguments); + }, + + /** + * Allows data to be referenced via 't' attribute + */ + getRightValue: function(rawValue) { + if (rawValue && rawValue.t !== undefined) { + rawValue = rawValue.t; + } + return core_scale.prototype.getRightValue.call(this, rawValue); + }, + + determineDataLimits: function() { + var me = this; + var chart = me.chart; + var adapter = me._adapter; + var timeOpts = me.options.time; + var unit = timeOpts.unit || 'day'; + var min = MAX_INTEGER; + var max = MIN_INTEGER; + var timestamps = []; + var datasets = []; + var labels = []; + var i, j, ilen, jlen, data, timestamp; + var dataLabels = chart.data.labels || []; + + // Convert labels to timestamps + for (i = 0, ilen = dataLabels.length; i < ilen; ++i) { + labels.push(parse(me, dataLabels[i])); + } + + // Convert data to timestamps + for (i = 0, ilen = (chart.data.datasets || []).length; i < ilen; ++i) { + if (chart.isDatasetVisible(i)) { + data = chart.data.datasets[i].data; + + // Let's consider that all data have the same format. + if (helpers$1.isObject(data[0])) { + datasets[i] = []; + + for (j = 0, jlen = data.length; j < jlen; ++j) { + timestamp = parse(me, data[j]); + timestamps.push(timestamp); + datasets[i][j] = timestamp; + } + } else { + for (j = 0, jlen = labels.length; j < jlen; ++j) { + timestamps.push(labels[j]); + } + datasets[i] = labels.slice(0); + } + } else { + datasets[i] = []; + } + } + + if (labels.length) { + // Sort labels **after** data have been converted + labels = arrayUnique(labels).sort(sorter); + min = Math.min(min, labels[0]); + max = Math.max(max, labels[labels.length - 1]); + } + + if (timestamps.length) { + timestamps = arrayUnique(timestamps).sort(sorter); + min = Math.min(min, timestamps[0]); + max = Math.max(max, timestamps[timestamps.length - 1]); + } + + min = parse(me, timeOpts.min) || min; + max = parse(me, timeOpts.max) || max; + + // In case there is no valid min/max, set limits based on unit time option + min = min === MAX_INTEGER ? +adapter.startOf(Date.now(), unit) : min; + max = max === MIN_INTEGER ? +adapter.endOf(Date.now(), unit) + 1 : max; + + // Make sure that max is strictly higher than min (required by the lookup table) + me.min = Math.min(min, max); + me.max = Math.max(min + 1, max); + + // PRIVATE + me._horizontal = me.isHorizontal(); + me._table = []; + me._timestamps = { + data: timestamps, + datasets: datasets, + labels: labels + }; + }, + + buildTicks: function() { + var me = this; + var min = me.min; + var max = me.max; + var options = me.options; + var timeOpts = options.time; + var timestamps = []; + var ticks = []; + var i, ilen, timestamp; + + switch (options.ticks.source) { + case 'data': + timestamps = me._timestamps.data; + break; + case 'labels': + timestamps = me._timestamps.labels; + break; + case 'auto': + default: + timestamps = generate(me, min, max, me.getLabelCapacity(min), options); + } + + if (options.bounds === 'ticks' && timestamps.length) { + min = timestamps[0]; + max = timestamps[timestamps.length - 1]; + } + + // Enforce limits with user min/max options + min = parse(me, timeOpts.min) || min; + max = parse(me, timeOpts.max) || max; + + // Remove ticks outside the min/max range + for (i = 0, ilen = timestamps.length; i < ilen; ++i) { + timestamp = timestamps[i]; + if (timestamp >= min && timestamp <= max) { + ticks.push(timestamp); + } + } + + me.min = min; + me.max = max; + + // PRIVATE + me._unit = timeOpts.unit || determineUnitForFormatting(me, ticks, timeOpts.minUnit, me.min, me.max); + me._majorUnit = determineMajorUnit(me._unit); + me._table = buildLookupTable(me._timestamps.data, min, max, options.distribution); + me._offsets = computeOffsets(me._table, ticks, min, max, options); + + if (options.ticks.reverse) { + ticks.reverse(); + } + + return ticksFromTimestamps(me, ticks, me._majorUnit); + }, + + getLabelForIndex: function(index, datasetIndex) { + var me = this; + var adapter = me._adapter; + var data = me.chart.data; + var timeOpts = me.options.time; + var label = data.labels && index < data.labels.length ? data.labels[index] : ''; + var value = data.datasets[datasetIndex].data[index]; + + if (helpers$1.isObject(value)) { + label = me.getRightValue(value); + } + if (timeOpts.tooltipFormat) { + return adapter.format(toTimestamp(me, label), timeOpts.tooltipFormat); + } + if (typeof label === 'string') { + return label; + } + return adapter.format(toTimestamp(me, label), timeOpts.displayFormats.datetime); + }, + + /** + * Function to format an individual tick mark + * @private + */ + tickFormatFunction: function(time, index, ticks, format) { + var me = this; + var adapter = me._adapter; + var options = me.options; + var formats = options.time.displayFormats; + var minorFormat = formats[me._unit]; + var majorUnit = me._majorUnit; + var majorFormat = formats[majorUnit]; + var majorTime = +adapter.startOf(time, majorUnit); + var majorTickOpts = options.ticks.major; + var major = majorTickOpts.enabled && majorUnit && majorFormat && time === majorTime; + var label = adapter.format(time, format ? format : major ? majorFormat : minorFormat); + var tickOpts = major ? majorTickOpts : options.ticks.minor; + var formatter = valueOrDefault$c(tickOpts.callback, tickOpts.userCallback); + + return formatter ? formatter(label, index, ticks) : label; + }, + + convertTicksToLabels: function(ticks) { + var labels = []; + var i, ilen; + + for (i = 0, ilen = ticks.length; i < ilen; ++i) { + labels.push(this.tickFormatFunction(ticks[i].value, i, ticks)); + } + + return labels; + }, + + /** + * @private + */ + getPixelForOffset: function(time) { + var me = this; + var isReverse = me.options.ticks.reverse; + var size = me._horizontal ? me.width : me.height; + var start = me._horizontal ? isReverse ? me.right : me.left : isReverse ? me.bottom : me.top; + var pos = interpolate$1(me._table, 'time', time, 'pos'); + var offset = size * (me._offsets.start + pos) / (me._offsets.start + 1 + me._offsets.end); + + return isReverse ? start - offset : start + offset; + }, + + getPixelForValue: function(value, index, datasetIndex) { + var me = this; + var time = null; + + if (index !== undefined && datasetIndex !== undefined) { + time = me._timestamps.datasets[datasetIndex][index]; + } + + if (time === null) { + time = parse(me, value); + } + + if (time !== null) { + return me.getPixelForOffset(time); + } + }, + + getPixelForTick: function(index) { + var ticks = this.getTicks(); + return index >= 0 && index < ticks.length ? + this.getPixelForOffset(ticks[index].value) : + null; + }, + + getValueForPixel: function(pixel) { + var me = this; + var size = me._horizontal ? me.width : me.height; + var start = me._horizontal ? me.left : me.top; + var pos = (size ? (pixel - start) / size : 0) * (me._offsets.start + 1 + me._offsets.start) - me._offsets.end; + var time = interpolate$1(me._table, 'pos', pos, 'time'); + + // DEPRECATION, we should return time directly + return me._adapter._create(time); + }, + + /** + * Crude approximation of what the label width might be + * @private + */ + getLabelWidth: function(label) { + var me = this; + var ticksOpts = me.options.ticks; + var tickLabelWidth = me.ctx.measureText(label).width; + var angle = helpers$1.toRadians(ticksOpts.maxRotation); + var cosRotation = Math.cos(angle); + var sinRotation = Math.sin(angle); + var tickFontSize = valueOrDefault$c(ticksOpts.fontSize, core_defaults.global.defaultFontSize); + + return (tickLabelWidth * cosRotation) + (tickFontSize * sinRotation); + }, + + /** + * @private + */ + getLabelCapacity: function(exampleTime) { + var me = this; + + // pick the longest format (milliseconds) for guestimation + var format = me.options.time.displayFormats.millisecond; + var exampleLabel = me.tickFormatFunction(exampleTime, 0, [], format); + var tickLabelWidth = me.getLabelWidth(exampleLabel); + var innerWidth = me.isHorizontal() ? me.width : me.height; + var capacity = Math.floor(innerWidth / tickLabelWidth); + + return capacity > 0 ? capacity : 1; + } +}); + +// INTERNAL: static default options, registered in src/index.js +var _defaults$4 = defaultConfig$4; +scale_time._defaults = _defaults$4; + +var scales = { + category: scale_category, + linear: scale_linear, + logarithmic: scale_logarithmic, + radialLinear: scale_radialLinear, + time: scale_time +}; + +var moment = createCommonjsModule(function (module, exports) { +(function (global, factory) { + module.exports = factory(); +}(commonjsGlobal, (function () { + var hookCallback; + + function hooks () { + return hookCallback.apply(null, arguments); + } + + // This is done to register the method called with moment() + // without creating circular dependencies. + function setHookCallback (callback) { + hookCallback = callback; + } + + function isArray(input) { + return input instanceof Array || Object.prototype.toString.call(input) === '[object Array]'; + } + + function isObject(input) { + // IE8 will treat undefined and null as object if it wasn't for + // input != null + return input != null && Object.prototype.toString.call(input) === '[object Object]'; + } + + function isObjectEmpty(obj) { + if (Object.getOwnPropertyNames) { + return (Object.getOwnPropertyNames(obj).length === 0); + } else { + var k; + for (k in obj) { + if (obj.hasOwnProperty(k)) { + return false; + } + } + return true; + } + } + + function isUndefined(input) { + return input === void 0; + } + + function isNumber(input) { + return typeof input === 'number' || Object.prototype.toString.call(input) === '[object Number]'; + } + + function isDate(input) { + return input instanceof Date || Object.prototype.toString.call(input) === '[object Date]'; + } + + function map(arr, fn) { + var res = [], i; + for (i = 0; i < arr.length; ++i) { + res.push(fn(arr[i], i)); + } + return res; + } + + function hasOwnProp(a, b) { + return Object.prototype.hasOwnProperty.call(a, b); + } + + function extend(a, b) { + for (var i in b) { + if (hasOwnProp(b, i)) { + a[i] = b[i]; + } + } + + if (hasOwnProp(b, 'toString')) { + a.toString = b.toString; + } + + if (hasOwnProp(b, 'valueOf')) { + a.valueOf = b.valueOf; + } + + return a; + } + + function createUTC (input, format, locale, strict) { + return createLocalOrUTC(input, format, locale, strict, true).utc(); + } + + function defaultParsingFlags() { + // We need to deep clone this object. + return { + empty : false, + unusedTokens : [], + unusedInput : [], + overflow : -2, + charsLeftOver : 0, + nullInput : false, + invalidMonth : null, + invalidFormat : false, + userInvalidated : false, + iso : false, + parsedDateParts : [], + meridiem : null, + rfc2822 : false, + weekdayMismatch : false + }; + } + + function getParsingFlags(m) { + if (m._pf == null) { + m._pf = defaultParsingFlags(); + } + return m._pf; + } + + var some; + if (Array.prototype.some) { + some = Array.prototype.some; + } else { + some = function (fun) { + var t = Object(this); + var len = t.length >>> 0; + + for (var i = 0; i < len; i++) { + if (i in t && fun.call(this, t[i], i, t)) { + return true; + } + } + + return false; + }; + } + + function isValid(m) { + if (m._isValid == null) { + var flags = getParsingFlags(m); + var parsedParts = some.call(flags.parsedDateParts, function (i) { + return i != null; + }); + var isNowValid = !isNaN(m._d.getTime()) && + flags.overflow < 0 && + !flags.empty && + !flags.invalidMonth && + !flags.invalidWeekday && + !flags.weekdayMismatch && + !flags.nullInput && + !flags.invalidFormat && + !flags.userInvalidated && + (!flags.meridiem || (flags.meridiem && parsedParts)); + + if (m._strict) { + isNowValid = isNowValid && + flags.charsLeftOver === 0 && + flags.unusedTokens.length === 0 && + flags.bigHour === undefined; + } + + if (Object.isFrozen == null || !Object.isFrozen(m)) { + m._isValid = isNowValid; + } + else { + return isNowValid; + } + } + return m._isValid; + } + + function createInvalid (flags) { + var m = createUTC(NaN); + if (flags != null) { + extend(getParsingFlags(m), flags); + } + else { + getParsingFlags(m).userInvalidated = true; + } + + return m; + } + + // Plugins that add properties should also add the key here (null value), + // so we can properly clone ourselves. + var momentProperties = hooks.momentProperties = []; + + function copyConfig(to, from) { + var i, prop, val; + + if (!isUndefined(from._isAMomentObject)) { + to._isAMomentObject = from._isAMomentObject; + } + if (!isUndefined(from._i)) { + to._i = from._i; + } + if (!isUndefined(from._f)) { + to._f = from._f; + } + if (!isUndefined(from._l)) { + to._l = from._l; + } + if (!isUndefined(from._strict)) { + to._strict = from._strict; + } + if (!isUndefined(from._tzm)) { + to._tzm = from._tzm; + } + if (!isUndefined(from._isUTC)) { + to._isUTC = from._isUTC; + } + if (!isUndefined(from._offset)) { + to._offset = from._offset; + } + if (!isUndefined(from._pf)) { + to._pf = getParsingFlags(from); + } + if (!isUndefined(from._locale)) { + to._locale = from._locale; + } + + if (momentProperties.length > 0) { + for (i = 0; i < momentProperties.length; i++) { + prop = momentProperties[i]; + val = from[prop]; + if (!isUndefined(val)) { + to[prop] = val; + } + } + } + + return to; + } + + var updateInProgress = false; + + // Moment prototype object + function Moment(config) { + copyConfig(this, config); + this._d = new Date(config._d != null ? config._d.getTime() : NaN); + if (!this.isValid()) { + this._d = new Date(NaN); + } + // Prevent infinite loop in case updateOffset creates new moment + // objects. + if (updateInProgress === false) { + updateInProgress = true; + hooks.updateOffset(this); + updateInProgress = false; + } + } + + function isMoment (obj) { + return obj instanceof Moment || (obj != null && obj._isAMomentObject != null); + } + + function absFloor (number) { + if (number < 0) { + // -0 -> 0 + return Math.ceil(number) || 0; + } else { + return Math.floor(number); + } + } + + function toInt(argumentForCoercion) { + var coercedNumber = +argumentForCoercion, + value = 0; + + if (coercedNumber !== 0 && isFinite(coercedNumber)) { + value = absFloor(coercedNumber); + } + + return value; + } + + // compare two arrays, return the number of differences + function compareArrays(array1, array2, dontConvert) { + var len = Math.min(array1.length, array2.length), + lengthDiff = Math.abs(array1.length - array2.length), + diffs = 0, + i; + for (i = 0; i < len; i++) { + if ((dontConvert && array1[i] !== array2[i]) || + (!dontConvert && toInt(array1[i]) !== toInt(array2[i]))) { + diffs++; + } + } + return diffs + lengthDiff; + } + + function warn(msg) { + if (hooks.suppressDeprecationWarnings === false && + (typeof console !== 'undefined') && console.warn) { + console.warn('Deprecation warning: ' + msg); + } + } + + function deprecate(msg, fn) { + var firstTime = true; + + return extend(function () { + if (hooks.deprecationHandler != null) { + hooks.deprecationHandler(null, msg); + } + if (firstTime) { + var args = []; + var arg; + for (var i = 0; i < arguments.length; i++) { + arg = ''; + if (typeof arguments[i] === 'object') { + arg += '\n[' + i + '] '; + for (var key in arguments[0]) { + arg += key + ': ' + arguments[0][key] + ', '; + } + arg = arg.slice(0, -2); // Remove trailing comma and space + } else { + arg = arguments[i]; + } + args.push(arg); + } + warn(msg + '\nArguments: ' + Array.prototype.slice.call(args).join('') + '\n' + (new Error()).stack); + firstTime = false; + } + return fn.apply(this, arguments); + }, fn); + } + + var deprecations = {}; + + function deprecateSimple(name, msg) { + if (hooks.deprecationHandler != null) { + hooks.deprecationHandler(name, msg); + } + if (!deprecations[name]) { + warn(msg); + deprecations[name] = true; + } + } + + hooks.suppressDeprecationWarnings = false; + hooks.deprecationHandler = null; + + function isFunction(input) { + return input instanceof Function || Object.prototype.toString.call(input) === '[object Function]'; + } + + function set (config) { + var prop, i; + for (i in config) { + prop = config[i]; + if (isFunction(prop)) { + this[i] = prop; + } else { + this['_' + i] = prop; + } + } + this._config = config; + // Lenient ordinal parsing accepts just a number in addition to + // number + (possibly) stuff coming from _dayOfMonthOrdinalParse. + // TODO: Remove "ordinalParse" fallback in next major release. + this._dayOfMonthOrdinalParseLenient = new RegExp( + (this._dayOfMonthOrdinalParse.source || this._ordinalParse.source) + + '|' + (/\d{1,2}/).source); + } + + function mergeConfigs(parentConfig, childConfig) { + var res = extend({}, parentConfig), prop; + for (prop in childConfig) { + if (hasOwnProp(childConfig, prop)) { + if (isObject(parentConfig[prop]) && isObject(childConfig[prop])) { + res[prop] = {}; + extend(res[prop], parentConfig[prop]); + extend(res[prop], childConfig[prop]); + } else if (childConfig[prop] != null) { + res[prop] = childConfig[prop]; + } else { + delete res[prop]; + } + } + } + for (prop in parentConfig) { + if (hasOwnProp(parentConfig, prop) && + !hasOwnProp(childConfig, prop) && + isObject(parentConfig[prop])) { + // make sure changes to properties don't modify parent config + res[prop] = extend({}, res[prop]); + } + } + return res; + } + + function Locale(config) { + if (config != null) { + this.set(config); + } + } + + var keys; + + if (Object.keys) { + keys = Object.keys; + } else { + keys = function (obj) { + var i, res = []; + for (i in obj) { + if (hasOwnProp(obj, i)) { + res.push(i); + } + } + return res; + }; + } + + var defaultCalendar = { + sameDay : '[Today at] LT', + nextDay : '[Tomorrow at] LT', + nextWeek : 'dddd [at] LT', + lastDay : '[Yesterday at] LT', + lastWeek : '[Last] dddd [at] LT', + sameElse : 'L' + }; + + function calendar (key, mom, now) { + var output = this._calendar[key] || this._calendar['sameElse']; + return isFunction(output) ? output.call(mom, now) : output; + } + + var defaultLongDateFormat = { + LTS : 'h:mm:ss A', + LT : 'h:mm A', + L : 'MM/DD/YYYY', + LL : 'MMMM D, YYYY', + LLL : 'MMMM D, YYYY h:mm A', + LLLL : 'dddd, MMMM D, YYYY h:mm A' + }; + + function longDateFormat (key) { + var format = this._longDateFormat[key], + formatUpper = this._longDateFormat[key.toUpperCase()]; + + if (format || !formatUpper) { + return format; + } + + this._longDateFormat[key] = formatUpper.replace(/MMMM|MM|DD|dddd/g, function (val) { + return val.slice(1); + }); + + return this._longDateFormat[key]; + } + + var defaultInvalidDate = 'Invalid date'; + + function invalidDate () { + return this._invalidDate; + } + + var defaultOrdinal = '%d'; + var defaultDayOfMonthOrdinalParse = /\d{1,2}/; + + function ordinal (number) { + return this._ordinal.replace('%d', number); + } + + var defaultRelativeTime = { + future : 'in %s', + past : '%s ago', + s : 'a few seconds', + ss : '%d seconds', + m : 'a minute', + mm : '%d minutes', + h : 'an hour', + hh : '%d hours', + d : 'a day', + dd : '%d days', + M : 'a month', + MM : '%d months', + y : 'a year', + yy : '%d years' + }; + + function relativeTime (number, withoutSuffix, string, isFuture) { + var output = this._relativeTime[string]; + return (isFunction(output)) ? + output(number, withoutSuffix, string, isFuture) : + output.replace(/%d/i, number); + } + + function pastFuture (diff, output) { + var format = this._relativeTime[diff > 0 ? 'future' : 'past']; + return isFunction(format) ? format(output) : format.replace(/%s/i, output); + } + + var aliases = {}; + + function addUnitAlias (unit, shorthand) { + var lowerCase = unit.toLowerCase(); + aliases[lowerCase] = aliases[lowerCase + 's'] = aliases[shorthand] = unit; + } + + function normalizeUnits(units) { + return typeof units === 'string' ? aliases[units] || aliases[units.toLowerCase()] : undefined; + } + + function normalizeObjectUnits(inputObject) { + var normalizedInput = {}, + normalizedProp, + prop; + + for (prop in inputObject) { + if (hasOwnProp(inputObject, prop)) { + normalizedProp = normalizeUnits(prop); + if (normalizedProp) { + normalizedInput[normalizedProp] = inputObject[prop]; + } + } + } + + return normalizedInput; + } + + var priorities = {}; + + function addUnitPriority(unit, priority) { + priorities[unit] = priority; + } + + function getPrioritizedUnits(unitsObj) { + var units = []; + for (var u in unitsObj) { + units.push({unit: u, priority: priorities[u]}); + } + units.sort(function (a, b) { + return a.priority - b.priority; + }); + return units; + } + + function zeroFill(number, targetLength, forceSign) { + var absNumber = '' + Math.abs(number), + zerosToFill = targetLength - absNumber.length, + sign = number >= 0; + return (sign ? (forceSign ? '+' : '') : '-') + + Math.pow(10, Math.max(0, zerosToFill)).toString().substr(1) + absNumber; + } + + var formattingTokens = /(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g; + + var localFormattingTokens = /(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g; + + var formatFunctions = {}; + + var formatTokenFunctions = {}; + + // token: 'M' + // padded: ['MM', 2] + // ordinal: 'Mo' + // callback: function () { this.month() + 1 } + function addFormatToken (token, padded, ordinal, callback) { + var func = callback; + if (typeof callback === 'string') { + func = function () { + return this[callback](); + }; + } + if (token) { + formatTokenFunctions[token] = func; + } + if (padded) { + formatTokenFunctions[padded[0]] = function () { + return zeroFill(func.apply(this, arguments), padded[1], padded[2]); + }; + } + if (ordinal) { + formatTokenFunctions[ordinal] = function () { + return this.localeData().ordinal(func.apply(this, arguments), token); + }; + } + } + + function removeFormattingTokens(input) { + if (input.match(/\[[\s\S]/)) { + return input.replace(/^\[|\]$/g, ''); + } + return input.replace(/\\/g, ''); + } + + function makeFormatFunction(format) { + var array = format.match(formattingTokens), i, length; + + for (i = 0, length = array.length; i < length; i++) { + if (formatTokenFunctions[array[i]]) { + array[i] = formatTokenFunctions[array[i]]; + } else { + array[i] = removeFormattingTokens(array[i]); + } + } + + return function (mom) { + var output = '', i; + for (i = 0; i < length; i++) { + output += isFunction(array[i]) ? array[i].call(mom, format) : array[i]; + } + return output; + }; + } + + // format date using native date object + function formatMoment(m, format) { + if (!m.isValid()) { + return m.localeData().invalidDate(); + } + + format = expandFormat(format, m.localeData()); + formatFunctions[format] = formatFunctions[format] || makeFormatFunction(format); + + return formatFunctions[format](m); + } + + function expandFormat(format, locale) { + var i = 5; + + function replaceLongDateFormatTokens(input) { + return locale.longDateFormat(input) || input; + } + + localFormattingTokens.lastIndex = 0; + while (i >= 0 && localFormattingTokens.test(format)) { + format = format.replace(localFormattingTokens, replaceLongDateFormatTokens); + localFormattingTokens.lastIndex = 0; + i -= 1; + } + + return format; + } + + var match1 = /\d/; // 0 - 9 + var match2 = /\d\d/; // 00 - 99 + var match3 = /\d{3}/; // 000 - 999 + var match4 = /\d{4}/; // 0000 - 9999 + var match6 = /[+-]?\d{6}/; // -999999 - 999999 + var match1to2 = /\d\d?/; // 0 - 99 + var match3to4 = /\d\d\d\d?/; // 999 - 9999 + var match5to6 = /\d\d\d\d\d\d?/; // 99999 - 999999 + var match1to3 = /\d{1,3}/; // 0 - 999 + var match1to4 = /\d{1,4}/; // 0 - 9999 + var match1to6 = /[+-]?\d{1,6}/; // -999999 - 999999 + + var matchUnsigned = /\d+/; // 0 - inf + var matchSigned = /[+-]?\d+/; // -inf - inf + + var matchOffset = /Z|[+-]\d\d:?\d\d/gi; // +00:00 -00:00 +0000 -0000 or Z + var matchShortOffset = /Z|[+-]\d\d(?::?\d\d)?/gi; // +00 -00 +00:00 -00:00 +0000 -0000 or Z + + var matchTimestamp = /[+-]?\d+(\.\d{1,3})?/; // 123456789 123456789.123 + + // any word (or two) characters or numbers including two/three word month in arabic. + // includes scottish gaelic two word and hyphenated months + var matchWord = /[0-9]{0,256}['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFF07\uFF10-\uFFEF]{1,256}|[\u0600-\u06FF\/]{1,256}(\s*?[\u0600-\u06FF]{1,256}){1,2}/i; + + var regexes = {}; + + function addRegexToken (token, regex, strictRegex) { + regexes[token] = isFunction(regex) ? regex : function (isStrict, localeData) { + return (isStrict && strictRegex) ? strictRegex : regex; + }; + } + + function getParseRegexForToken (token, config) { + if (!hasOwnProp(regexes, token)) { + return new RegExp(unescapeFormat(token)); + } + + return regexes[token](config._strict, config._locale); + } + + // Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript + function unescapeFormat(s) { + return regexEscape(s.replace('\\', '').replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function (matched, p1, p2, p3, p4) { + return p1 || p2 || p3 || p4; + })); + } + + function regexEscape(s) { + return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'); + } + + var tokens = {}; + + function addParseToken (token, callback) { + var i, func = callback; + if (typeof token === 'string') { + token = [token]; + } + if (isNumber(callback)) { + func = function (input, array) { + array[callback] = toInt(input); + }; + } + for (i = 0; i < token.length; i++) { + tokens[token[i]] = func; + } + } + + function addWeekParseToken (token, callback) { + addParseToken(token, function (input, array, config, token) { + config._w = config._w || {}; + callback(input, config._w, config, token); + }); + } + + function addTimeToArrayFromToken(token, input, config) { + if (input != null && hasOwnProp(tokens, token)) { + tokens[token](input, config._a, config, token); + } + } + + var YEAR = 0; + var MONTH = 1; + var DATE = 2; + var HOUR = 3; + var MINUTE = 4; + var SECOND = 5; + var MILLISECOND = 6; + var WEEK = 7; + var WEEKDAY = 8; + + // FORMATTING + + addFormatToken('Y', 0, 0, function () { + var y = this.year(); + return y <= 9999 ? '' + y : '+' + y; + }); + + addFormatToken(0, ['YY', 2], 0, function () { + return this.year() % 100; + }); + + addFormatToken(0, ['YYYY', 4], 0, 'year'); + addFormatToken(0, ['YYYYY', 5], 0, 'year'); + addFormatToken(0, ['YYYYYY', 6, true], 0, 'year'); + + // ALIASES + + addUnitAlias('year', 'y'); + + // PRIORITIES + + addUnitPriority('year', 1); + + // PARSING + + addRegexToken('Y', matchSigned); + addRegexToken('YY', match1to2, match2); + addRegexToken('YYYY', match1to4, match4); + addRegexToken('YYYYY', match1to6, match6); + addRegexToken('YYYYYY', match1to6, match6); + + addParseToken(['YYYYY', 'YYYYYY'], YEAR); + addParseToken('YYYY', function (input, array) { + array[YEAR] = input.length === 2 ? hooks.parseTwoDigitYear(input) : toInt(input); + }); + addParseToken('YY', function (input, array) { + array[YEAR] = hooks.parseTwoDigitYear(input); + }); + addParseToken('Y', function (input, array) { + array[YEAR] = parseInt(input, 10); + }); + + // HELPERS + + function daysInYear(year) { + return isLeapYear(year) ? 366 : 365; + } + + function isLeapYear(year) { + return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0; + } + + // HOOKS + + hooks.parseTwoDigitYear = function (input) { + return toInt(input) + (toInt(input) > 68 ? 1900 : 2000); + }; + + // MOMENTS + + var getSetYear = makeGetSet('FullYear', true); + + function getIsLeapYear () { + return isLeapYear(this.year()); + } + + function makeGetSet (unit, keepTime) { + return function (value) { + if (value != null) { + set$1(this, unit, value); + hooks.updateOffset(this, keepTime); + return this; + } else { + return get(this, unit); + } + }; + } + + function get (mom, unit) { + return mom.isValid() ? + mom._d['get' + (mom._isUTC ? 'UTC' : '') + unit]() : NaN; + } + + function set$1 (mom, unit, value) { + if (mom.isValid() && !isNaN(value)) { + if (unit === 'FullYear' && isLeapYear(mom.year()) && mom.month() === 1 && mom.date() === 29) { + mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value, mom.month(), daysInMonth(value, mom.month())); + } + else { + mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value); + } + } + } + + // MOMENTS + + function stringGet (units) { + units = normalizeUnits(units); + if (isFunction(this[units])) { + return this[units](); + } + return this; + } + + + function stringSet (units, value) { + if (typeof units === 'object') { + units = normalizeObjectUnits(units); + var prioritized = getPrioritizedUnits(units); + for (var i = 0; i < prioritized.length; i++) { + this[prioritized[i].unit](units[prioritized[i].unit]); + } + } else { + units = normalizeUnits(units); + if (isFunction(this[units])) { + return this[units](value); + } + } + return this; + } + + function mod(n, x) { + return ((n % x) + x) % x; + } + + var indexOf; + + if (Array.prototype.indexOf) { + indexOf = Array.prototype.indexOf; + } else { + indexOf = function (o) { + // I know + var i; + for (i = 0; i < this.length; ++i) { + if (this[i] === o) { + return i; + } + } + return -1; + }; + } + + function daysInMonth(year, month) { + if (isNaN(year) || isNaN(month)) { + return NaN; + } + var modMonth = mod(month, 12); + year += (month - modMonth) / 12; + return modMonth === 1 ? (isLeapYear(year) ? 29 : 28) : (31 - modMonth % 7 % 2); + } + + // FORMATTING + + addFormatToken('M', ['MM', 2], 'Mo', function () { + return this.month() + 1; + }); + + addFormatToken('MMM', 0, 0, function (format) { + return this.localeData().monthsShort(this, format); + }); + + addFormatToken('MMMM', 0, 0, function (format) { + return this.localeData().months(this, format); + }); + + // ALIASES + + addUnitAlias('month', 'M'); + + // PRIORITY + + addUnitPriority('month', 8); + + // PARSING + + addRegexToken('M', match1to2); + addRegexToken('MM', match1to2, match2); + addRegexToken('MMM', function (isStrict, locale) { + return locale.monthsShortRegex(isStrict); + }); + addRegexToken('MMMM', function (isStrict, locale) { + return locale.monthsRegex(isStrict); + }); + + addParseToken(['M', 'MM'], function (input, array) { + array[MONTH] = toInt(input) - 1; + }); + + addParseToken(['MMM', 'MMMM'], function (input, array, config, token) { + var month = config._locale.monthsParse(input, token, config._strict); + // if we didn't find a month name, mark the date as invalid. + if (month != null) { + array[MONTH] = month; + } else { + getParsingFlags(config).invalidMonth = input; + } + }); + + // LOCALES + + var MONTHS_IN_FORMAT = /D[oD]?(\[[^\[\]]*\]|\s)+MMMM?/; + var defaultLocaleMonths = 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'); + function localeMonths (m, format) { + if (!m) { + return isArray(this._months) ? this._months : + this._months['standalone']; + } + return isArray(this._months) ? this._months[m.month()] : + this._months[(this._months.isFormat || MONTHS_IN_FORMAT).test(format) ? 'format' : 'standalone'][m.month()]; + } + + var defaultLocaleMonthsShort = 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'); + function localeMonthsShort (m, format) { + if (!m) { + return isArray(this._monthsShort) ? this._monthsShort : + this._monthsShort['standalone']; + } + return isArray(this._monthsShort) ? this._monthsShort[m.month()] : + this._monthsShort[MONTHS_IN_FORMAT.test(format) ? 'format' : 'standalone'][m.month()]; + } + + function handleStrictParse(monthName, format, strict) { + var i, ii, mom, llc = monthName.toLocaleLowerCase(); + if (!this._monthsParse) { + // this is not used + this._monthsParse = []; + this._longMonthsParse = []; + this._shortMonthsParse = []; + for (i = 0; i < 12; ++i) { + mom = createUTC([2000, i]); + this._shortMonthsParse[i] = this.monthsShort(mom, '').toLocaleLowerCase(); + this._longMonthsParse[i] = this.months(mom, '').toLocaleLowerCase(); + } + } + + if (strict) { + if (format === 'MMM') { + ii = indexOf.call(this._shortMonthsParse, llc); + return ii !== -1 ? ii : null; + } else { + ii = indexOf.call(this._longMonthsParse, llc); + return ii !== -1 ? ii : null; + } + } else { + if (format === 'MMM') { + ii = indexOf.call(this._shortMonthsParse, llc); + if (ii !== -1) { + return ii; + } + ii = indexOf.call(this._longMonthsParse, llc); + return ii !== -1 ? ii : null; + } else { + ii = indexOf.call(this._longMonthsParse, llc); + if (ii !== -1) { + return ii; + } + ii = indexOf.call(this._shortMonthsParse, llc); + return ii !== -1 ? ii : null; + } + } + } + + function localeMonthsParse (monthName, format, strict) { + var i, mom, regex; + + if (this._monthsParseExact) { + return handleStrictParse.call(this, monthName, format, strict); + } + + if (!this._monthsParse) { + this._monthsParse = []; + this._longMonthsParse = []; + this._shortMonthsParse = []; + } + + // TODO: add sorting + // Sorting makes sure if one month (or abbr) is a prefix of another + // see sorting in computeMonthsParse + for (i = 0; i < 12; i++) { + // make the regex if we don't have it already + mom = createUTC([2000, i]); + if (strict && !this._longMonthsParse[i]) { + this._longMonthsParse[i] = new RegExp('^' + this.months(mom, '').replace('.', '') + '$', 'i'); + this._shortMonthsParse[i] = new RegExp('^' + this.monthsShort(mom, '').replace('.', '') + '$', 'i'); + } + if (!strict && !this._monthsParse[i]) { + regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, ''); + this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i'); + } + // test the regex + if (strict && format === 'MMMM' && this._longMonthsParse[i].test(monthName)) { + return i; + } else if (strict && format === 'MMM' && this._shortMonthsParse[i].test(monthName)) { + return i; + } else if (!strict && this._monthsParse[i].test(monthName)) { + return i; + } + } + } + + // MOMENTS + + function setMonth (mom, value) { + var dayOfMonth; + + if (!mom.isValid()) { + // No op + return mom; + } + + if (typeof value === 'string') { + if (/^\d+$/.test(value)) { + value = toInt(value); + } else { + value = mom.localeData().monthsParse(value); + // TODO: Another silent failure? + if (!isNumber(value)) { + return mom; + } + } + } + + dayOfMonth = Math.min(mom.date(), daysInMonth(mom.year(), value)); + mom._d['set' + (mom._isUTC ? 'UTC' : '') + 'Month'](value, dayOfMonth); + return mom; + } + + function getSetMonth (value) { + if (value != null) { + setMonth(this, value); + hooks.updateOffset(this, true); + return this; + } else { + return get(this, 'Month'); + } + } + + function getDaysInMonth () { + return daysInMonth(this.year(), this.month()); + } + + var defaultMonthsShortRegex = matchWord; + function monthsShortRegex (isStrict) { + if (this._monthsParseExact) { + if (!hasOwnProp(this, '_monthsRegex')) { + computeMonthsParse.call(this); + } + if (isStrict) { + return this._monthsShortStrictRegex; + } else { + return this._monthsShortRegex; + } + } else { + if (!hasOwnProp(this, '_monthsShortRegex')) { + this._monthsShortRegex = defaultMonthsShortRegex; + } + return this._monthsShortStrictRegex && isStrict ? + this._monthsShortStrictRegex : this._monthsShortRegex; + } + } + + var defaultMonthsRegex = matchWord; + function monthsRegex (isStrict) { + if (this._monthsParseExact) { + if (!hasOwnProp(this, '_monthsRegex')) { + computeMonthsParse.call(this); + } + if (isStrict) { + return this._monthsStrictRegex; + } else { + return this._monthsRegex; + } + } else { + if (!hasOwnProp(this, '_monthsRegex')) { + this._monthsRegex = defaultMonthsRegex; + } + return this._monthsStrictRegex && isStrict ? + this._monthsStrictRegex : this._monthsRegex; + } + } + + function computeMonthsParse () { + function cmpLenRev(a, b) { + return b.length - a.length; + } + + var shortPieces = [], longPieces = [], mixedPieces = [], + i, mom; + for (i = 0; i < 12; i++) { + // make the regex if we don't have it already + mom = createUTC([2000, i]); + shortPieces.push(this.monthsShort(mom, '')); + longPieces.push(this.months(mom, '')); + mixedPieces.push(this.months(mom, '')); + mixedPieces.push(this.monthsShort(mom, '')); + } + // Sorting makes sure if one month (or abbr) is a prefix of another it + // will match the longer piece. + shortPieces.sort(cmpLenRev); + longPieces.sort(cmpLenRev); + mixedPieces.sort(cmpLenRev); + for (i = 0; i < 12; i++) { + shortPieces[i] = regexEscape(shortPieces[i]); + longPieces[i] = regexEscape(longPieces[i]); + } + for (i = 0; i < 24; i++) { + mixedPieces[i] = regexEscape(mixedPieces[i]); + } + + this._monthsRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i'); + this._monthsShortRegex = this._monthsRegex; + this._monthsStrictRegex = new RegExp('^(' + longPieces.join('|') + ')', 'i'); + this._monthsShortStrictRegex = new RegExp('^(' + shortPieces.join('|') + ')', 'i'); + } + + function createDate (y, m, d, h, M, s, ms) { + // can't just apply() to create a date: + // https://stackoverflow.com/q/181348 + var date; + // the date constructor remaps years 0-99 to 1900-1999 + if (y < 100 && y >= 0) { + // preserve leap years using a full 400 year cycle, then reset + date = new Date(y + 400, m, d, h, M, s, ms); + if (isFinite(date.getFullYear())) { + date.setFullYear(y); + } + } else { + date = new Date(y, m, d, h, M, s, ms); + } + + return date; + } + + function createUTCDate (y) { + var date; + // the Date.UTC function remaps years 0-99 to 1900-1999 + if (y < 100 && y >= 0) { + var args = Array.prototype.slice.call(arguments); + // preserve leap years using a full 400 year cycle, then reset + args[0] = y + 400; + date = new Date(Date.UTC.apply(null, args)); + if (isFinite(date.getUTCFullYear())) { + date.setUTCFullYear(y); + } + } else { + date = new Date(Date.UTC.apply(null, arguments)); + } + + return date; + } + + // start-of-first-week - start-of-year + function firstWeekOffset(year, dow, doy) { + var // first-week day -- which january is always in the first week (4 for iso, 1 for other) + fwd = 7 + dow - doy, + // first-week day local weekday -- which local weekday is fwd + fwdlw = (7 + createUTCDate(year, 0, fwd).getUTCDay() - dow) % 7; + + return -fwdlw + fwd - 1; + } + + // https://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday + function dayOfYearFromWeeks(year, week, weekday, dow, doy) { + var localWeekday = (7 + weekday - dow) % 7, + weekOffset = firstWeekOffset(year, dow, doy), + dayOfYear = 1 + 7 * (week - 1) + localWeekday + weekOffset, + resYear, resDayOfYear; + + if (dayOfYear <= 0) { + resYear = year - 1; + resDayOfYear = daysInYear(resYear) + dayOfYear; + } else if (dayOfYear > daysInYear(year)) { + resYear = year + 1; + resDayOfYear = dayOfYear - daysInYear(year); + } else { + resYear = year; + resDayOfYear = dayOfYear; + } + + return { + year: resYear, + dayOfYear: resDayOfYear + }; + } + + function weekOfYear(mom, dow, doy) { + var weekOffset = firstWeekOffset(mom.year(), dow, doy), + week = Math.floor((mom.dayOfYear() - weekOffset - 1) / 7) + 1, + resWeek, resYear; + + if (week < 1) { + resYear = mom.year() - 1; + resWeek = week + weeksInYear(resYear, dow, doy); + } else if (week > weeksInYear(mom.year(), dow, doy)) { + resWeek = week - weeksInYear(mom.year(), dow, doy); + resYear = mom.year() + 1; + } else { + resYear = mom.year(); + resWeek = week; + } + + return { + week: resWeek, + year: resYear + }; + } + + function weeksInYear(year, dow, doy) { + var weekOffset = firstWeekOffset(year, dow, doy), + weekOffsetNext = firstWeekOffset(year + 1, dow, doy); + return (daysInYear(year) - weekOffset + weekOffsetNext) / 7; + } + + // FORMATTING + + addFormatToken('w', ['ww', 2], 'wo', 'week'); + addFormatToken('W', ['WW', 2], 'Wo', 'isoWeek'); + + // ALIASES + + addUnitAlias('week', 'w'); + addUnitAlias('isoWeek', 'W'); + + // PRIORITIES + + addUnitPriority('week', 5); + addUnitPriority('isoWeek', 5); + + // PARSING + + addRegexToken('w', match1to2); + addRegexToken('ww', match1to2, match2); + addRegexToken('W', match1to2); + addRegexToken('WW', match1to2, match2); + + addWeekParseToken(['w', 'ww', 'W', 'WW'], function (input, week, config, token) { + week[token.substr(0, 1)] = toInt(input); + }); + + // HELPERS + + // LOCALES + + function localeWeek (mom) { + return weekOfYear(mom, this._week.dow, this._week.doy).week; + } + + var defaultLocaleWeek = { + dow : 0, // Sunday is the first day of the week. + doy : 6 // The week that contains Jan 6th is the first week of the year. + }; + + function localeFirstDayOfWeek () { + return this._week.dow; + } + + function localeFirstDayOfYear () { + return this._week.doy; + } + + // MOMENTS + + function getSetWeek (input) { + var week = this.localeData().week(this); + return input == null ? week : this.add((input - week) * 7, 'd'); + } + + function getSetISOWeek (input) { + var week = weekOfYear(this, 1, 4).week; + return input == null ? week : this.add((input - week) * 7, 'd'); + } + + // FORMATTING + + addFormatToken('d', 0, 'do', 'day'); + + addFormatToken('dd', 0, 0, function (format) { + return this.localeData().weekdaysMin(this, format); + }); + + addFormatToken('ddd', 0, 0, function (format) { + return this.localeData().weekdaysShort(this, format); + }); + + addFormatToken('dddd', 0, 0, function (format) { + return this.localeData().weekdays(this, format); + }); + + addFormatToken('e', 0, 0, 'weekday'); + addFormatToken('E', 0, 0, 'isoWeekday'); + + // ALIASES + + addUnitAlias('day', 'd'); + addUnitAlias('weekday', 'e'); + addUnitAlias('isoWeekday', 'E'); + + // PRIORITY + addUnitPriority('day', 11); + addUnitPriority('weekday', 11); + addUnitPriority('isoWeekday', 11); + + // PARSING + + addRegexToken('d', match1to2); + addRegexToken('e', match1to2); + addRegexToken('E', match1to2); + addRegexToken('dd', function (isStrict, locale) { + return locale.weekdaysMinRegex(isStrict); + }); + addRegexToken('ddd', function (isStrict, locale) { + return locale.weekdaysShortRegex(isStrict); + }); + addRegexToken('dddd', function (isStrict, locale) { + return locale.weekdaysRegex(isStrict); + }); + + addWeekParseToken(['dd', 'ddd', 'dddd'], function (input, week, config, token) { + var weekday = config._locale.weekdaysParse(input, token, config._strict); + // if we didn't get a weekday name, mark the date as invalid + if (weekday != null) { + week.d = weekday; + } else { + getParsingFlags(config).invalidWeekday = input; + } + }); + + addWeekParseToken(['d', 'e', 'E'], function (input, week, config, token) { + week[token] = toInt(input); + }); + + // HELPERS + + function parseWeekday(input, locale) { + if (typeof input !== 'string') { + return input; + } + + if (!isNaN(input)) { + return parseInt(input, 10); + } + + input = locale.weekdaysParse(input); + if (typeof input === 'number') { + return input; + } + + return null; + } + + function parseIsoWeekday(input, locale) { + if (typeof input === 'string') { + return locale.weekdaysParse(input) % 7 || 7; + } + return isNaN(input) ? null : input; + } + + // LOCALES + function shiftWeekdays (ws, n) { + return ws.slice(n, 7).concat(ws.slice(0, n)); + } + + var defaultLocaleWeekdays = 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'); + function localeWeekdays (m, format) { + var weekdays = isArray(this._weekdays) ? this._weekdays : + this._weekdays[(m && m !== true && this._weekdays.isFormat.test(format)) ? 'format' : 'standalone']; + return (m === true) ? shiftWeekdays(weekdays, this._week.dow) + : (m) ? weekdays[m.day()] : weekdays; + } + + var defaultLocaleWeekdaysShort = 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'); + function localeWeekdaysShort (m) { + return (m === true) ? shiftWeekdays(this._weekdaysShort, this._week.dow) + : (m) ? this._weekdaysShort[m.day()] : this._weekdaysShort; + } + + var defaultLocaleWeekdaysMin = 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'); + function localeWeekdaysMin (m) { + return (m === true) ? shiftWeekdays(this._weekdaysMin, this._week.dow) + : (m) ? this._weekdaysMin[m.day()] : this._weekdaysMin; + } + + function handleStrictParse$1(weekdayName, format, strict) { + var i, ii, mom, llc = weekdayName.toLocaleLowerCase(); + if (!this._weekdaysParse) { + this._weekdaysParse = []; + this._shortWeekdaysParse = []; + this._minWeekdaysParse = []; + + for (i = 0; i < 7; ++i) { + mom = createUTC([2000, 1]).day(i); + this._minWeekdaysParse[i] = this.weekdaysMin(mom, '').toLocaleLowerCase(); + this._shortWeekdaysParse[i] = this.weekdaysShort(mom, '').toLocaleLowerCase(); + this._weekdaysParse[i] = this.weekdays(mom, '').toLocaleLowerCase(); + } + } + + if (strict) { + if (format === 'dddd') { + ii = indexOf.call(this._weekdaysParse, llc); + return ii !== -1 ? ii : null; + } else if (format === 'ddd') { + ii = indexOf.call(this._shortWeekdaysParse, llc); + return ii !== -1 ? ii : null; + } else { + ii = indexOf.call(this._minWeekdaysParse, llc); + return ii !== -1 ? ii : null; + } + } else { + if (format === 'dddd') { + ii = indexOf.call(this._weekdaysParse, llc); + if (ii !== -1) { + return ii; + } + ii = indexOf.call(this._shortWeekdaysParse, llc); + if (ii !== -1) { + return ii; + } + ii = indexOf.call(this._minWeekdaysParse, llc); + return ii !== -1 ? ii : null; + } else if (format === 'ddd') { + ii = indexOf.call(this._shortWeekdaysParse, llc); + if (ii !== -1) { + return ii; + } + ii = indexOf.call(this._weekdaysParse, llc); + if (ii !== -1) { + return ii; + } + ii = indexOf.call(this._minWeekdaysParse, llc); + return ii !== -1 ? ii : null; + } else { + ii = indexOf.call(this._minWeekdaysParse, llc); + if (ii !== -1) { + return ii; + } + ii = indexOf.call(this._weekdaysParse, llc); + if (ii !== -1) { + return ii; + } + ii = indexOf.call(this._shortWeekdaysParse, llc); + return ii !== -1 ? ii : null; + } + } + } + + function localeWeekdaysParse (weekdayName, format, strict) { + var i, mom, regex; + + if (this._weekdaysParseExact) { + return handleStrictParse$1.call(this, weekdayName, format, strict); + } + + if (!this._weekdaysParse) { + this._weekdaysParse = []; + this._minWeekdaysParse = []; + this._shortWeekdaysParse = []; + this._fullWeekdaysParse = []; + } + + for (i = 0; i < 7; i++) { + // make the regex if we don't have it already + + mom = createUTC([2000, 1]).day(i); + if (strict && !this._fullWeekdaysParse[i]) { + this._fullWeekdaysParse[i] = new RegExp('^' + this.weekdays(mom, '').replace('.', '\\.?') + '$', 'i'); + this._shortWeekdaysParse[i] = new RegExp('^' + this.weekdaysShort(mom, '').replace('.', '\\.?') + '$', 'i'); + this._minWeekdaysParse[i] = new RegExp('^' + this.weekdaysMin(mom, '').replace('.', '\\.?') + '$', 'i'); + } + if (!this._weekdaysParse[i]) { + regex = '^' + this.weekdays(mom, '') + '|^' + this.weekdaysShort(mom, '') + '|^' + this.weekdaysMin(mom, ''); + this._weekdaysParse[i] = new RegExp(regex.replace('.', ''), 'i'); + } + // test the regex + if (strict && format === 'dddd' && this._fullWeekdaysParse[i].test(weekdayName)) { + return i; + } else if (strict && format === 'ddd' && this._shortWeekdaysParse[i].test(weekdayName)) { + return i; + } else if (strict && format === 'dd' && this._minWeekdaysParse[i].test(weekdayName)) { + return i; + } else if (!strict && this._weekdaysParse[i].test(weekdayName)) { + return i; + } + } + } + + // MOMENTS + + function getSetDayOfWeek (input) { + if (!this.isValid()) { + return input != null ? this : NaN; + } + var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay(); + if (input != null) { + input = parseWeekday(input, this.localeData()); + return this.add(input - day, 'd'); + } else { + return day; + } + } + + function getSetLocaleDayOfWeek (input) { + if (!this.isValid()) { + return input != null ? this : NaN; + } + var weekday = (this.day() + 7 - this.localeData()._week.dow) % 7; + return input == null ? weekday : this.add(input - weekday, 'd'); + } + + function getSetISODayOfWeek (input) { + if (!this.isValid()) { + return input != null ? this : NaN; + } + + // behaves the same as moment#day except + // as a getter, returns 7 instead of 0 (1-7 range instead of 0-6) + // as a setter, sunday should belong to the previous week. + + if (input != null) { + var weekday = parseIsoWeekday(input, this.localeData()); + return this.day(this.day() % 7 ? weekday : weekday - 7); + } else { + return this.day() || 7; + } + } + + var defaultWeekdaysRegex = matchWord; + function weekdaysRegex (isStrict) { + if (this._weekdaysParseExact) { + if (!hasOwnProp(this, '_weekdaysRegex')) { + computeWeekdaysParse.call(this); + } + if (isStrict) { + return this._weekdaysStrictRegex; + } else { + return this._weekdaysRegex; + } + } else { + if (!hasOwnProp(this, '_weekdaysRegex')) { + this._weekdaysRegex = defaultWeekdaysRegex; + } + return this._weekdaysStrictRegex && isStrict ? + this._weekdaysStrictRegex : this._weekdaysRegex; + } + } + + var defaultWeekdaysShortRegex = matchWord; + function weekdaysShortRegex (isStrict) { + if (this._weekdaysParseExact) { + if (!hasOwnProp(this, '_weekdaysRegex')) { + computeWeekdaysParse.call(this); + } + if (isStrict) { + return this._weekdaysShortStrictRegex; + } else { + return this._weekdaysShortRegex; + } + } else { + if (!hasOwnProp(this, '_weekdaysShortRegex')) { + this._weekdaysShortRegex = defaultWeekdaysShortRegex; + } + return this._weekdaysShortStrictRegex && isStrict ? + this._weekdaysShortStrictRegex : this._weekdaysShortRegex; + } + } + + var defaultWeekdaysMinRegex = matchWord; + function weekdaysMinRegex (isStrict) { + if (this._weekdaysParseExact) { + if (!hasOwnProp(this, '_weekdaysRegex')) { + computeWeekdaysParse.call(this); + } + if (isStrict) { + return this._weekdaysMinStrictRegex; + } else { + return this._weekdaysMinRegex; + } + } else { + if (!hasOwnProp(this, '_weekdaysMinRegex')) { + this._weekdaysMinRegex = defaultWeekdaysMinRegex; + } + return this._weekdaysMinStrictRegex && isStrict ? + this._weekdaysMinStrictRegex : this._weekdaysMinRegex; + } + } + + + function computeWeekdaysParse () { + function cmpLenRev(a, b) { + return b.length - a.length; + } + + var minPieces = [], shortPieces = [], longPieces = [], mixedPieces = [], + i, mom, minp, shortp, longp; + for (i = 0; i < 7; i++) { + // make the regex if we don't have it already + mom = createUTC([2000, 1]).day(i); + minp = this.weekdaysMin(mom, ''); + shortp = this.weekdaysShort(mom, ''); + longp = this.weekdays(mom, ''); + minPieces.push(minp); + shortPieces.push(shortp); + longPieces.push(longp); + mixedPieces.push(minp); + mixedPieces.push(shortp); + mixedPieces.push(longp); + } + // Sorting makes sure if one weekday (or abbr) is a prefix of another it + // will match the longer piece. + minPieces.sort(cmpLenRev); + shortPieces.sort(cmpLenRev); + longPieces.sort(cmpLenRev); + mixedPieces.sort(cmpLenRev); + for (i = 0; i < 7; i++) { + shortPieces[i] = regexEscape(shortPieces[i]); + longPieces[i] = regexEscape(longPieces[i]); + mixedPieces[i] = regexEscape(mixedPieces[i]); + } + + this._weekdaysRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i'); + this._weekdaysShortRegex = this._weekdaysRegex; + this._weekdaysMinRegex = this._weekdaysRegex; + + this._weekdaysStrictRegex = new RegExp('^(' + longPieces.join('|') + ')', 'i'); + this._weekdaysShortStrictRegex = new RegExp('^(' + shortPieces.join('|') + ')', 'i'); + this._weekdaysMinStrictRegex = new RegExp('^(' + minPieces.join('|') + ')', 'i'); + } + + // FORMATTING + + function hFormat() { + return this.hours() % 12 || 12; + } + + function kFormat() { + return this.hours() || 24; + } + + addFormatToken('H', ['HH', 2], 0, 'hour'); + addFormatToken('h', ['hh', 2], 0, hFormat); + addFormatToken('k', ['kk', 2], 0, kFormat); + + addFormatToken('hmm', 0, 0, function () { + return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2); + }); + + addFormatToken('hmmss', 0, 0, function () { + return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2) + + zeroFill(this.seconds(), 2); + }); + + addFormatToken('Hmm', 0, 0, function () { + return '' + this.hours() + zeroFill(this.minutes(), 2); + }); + + addFormatToken('Hmmss', 0, 0, function () { + return '' + this.hours() + zeroFill(this.minutes(), 2) + + zeroFill(this.seconds(), 2); + }); + + function meridiem (token, lowercase) { + addFormatToken(token, 0, 0, function () { + return this.localeData().meridiem(this.hours(), this.minutes(), lowercase); + }); + } + + meridiem('a', true); + meridiem('A', false); + + // ALIASES + + addUnitAlias('hour', 'h'); + + // PRIORITY + addUnitPriority('hour', 13); + + // PARSING + + function matchMeridiem (isStrict, locale) { + return locale._meridiemParse; + } + + addRegexToken('a', matchMeridiem); + addRegexToken('A', matchMeridiem); + addRegexToken('H', match1to2); + addRegexToken('h', match1to2); + addRegexToken('k', match1to2); + addRegexToken('HH', match1to2, match2); + addRegexToken('hh', match1to2, match2); + addRegexToken('kk', match1to2, match2); + + addRegexToken('hmm', match3to4); + addRegexToken('hmmss', match5to6); + addRegexToken('Hmm', match3to4); + addRegexToken('Hmmss', match5to6); + + addParseToken(['H', 'HH'], HOUR); + addParseToken(['k', 'kk'], function (input, array, config) { + var kInput = toInt(input); + array[HOUR] = kInput === 24 ? 0 : kInput; + }); + addParseToken(['a', 'A'], function (input, array, config) { + config._isPm = config._locale.isPM(input); + config._meridiem = input; + }); + addParseToken(['h', 'hh'], function (input, array, config) { + array[HOUR] = toInt(input); + getParsingFlags(config).bigHour = true; + }); + addParseToken('hmm', function (input, array, config) { + var pos = input.length - 2; + array[HOUR] = toInt(input.substr(0, pos)); + array[MINUTE] = toInt(input.substr(pos)); + getParsingFlags(config).bigHour = true; + }); + addParseToken('hmmss', function (input, array, config) { + var pos1 = input.length - 4; + var pos2 = input.length - 2; + array[HOUR] = toInt(input.substr(0, pos1)); + array[MINUTE] = toInt(input.substr(pos1, 2)); + array[SECOND] = toInt(input.substr(pos2)); + getParsingFlags(config).bigHour = true; + }); + addParseToken('Hmm', function (input, array, config) { + var pos = input.length - 2; + array[HOUR] = toInt(input.substr(0, pos)); + array[MINUTE] = toInt(input.substr(pos)); + }); + addParseToken('Hmmss', function (input, array, config) { + var pos1 = input.length - 4; + var pos2 = input.length - 2; + array[HOUR] = toInt(input.substr(0, pos1)); + array[MINUTE] = toInt(input.substr(pos1, 2)); + array[SECOND] = toInt(input.substr(pos2)); + }); + + // LOCALES + + function localeIsPM (input) { + // IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays + // Using charAt should be more compatible. + return ((input + '').toLowerCase().charAt(0) === 'p'); + } + + var defaultLocaleMeridiemParse = /[ap]\.?m?\.?/i; + function localeMeridiem (hours, minutes, isLower) { + if (hours > 11) { + return isLower ? 'pm' : 'PM'; + } else { + return isLower ? 'am' : 'AM'; + } + } + + + // MOMENTS + + // Setting the hour should keep the time, because the user explicitly + // specified which hour they want. So trying to maintain the same hour (in + // a new timezone) makes sense. Adding/subtracting hours does not follow + // this rule. + var getSetHour = makeGetSet('Hours', true); + + var baseConfig = { + calendar: defaultCalendar, + longDateFormat: defaultLongDateFormat, + invalidDate: defaultInvalidDate, + ordinal: defaultOrdinal, + dayOfMonthOrdinalParse: defaultDayOfMonthOrdinalParse, + relativeTime: defaultRelativeTime, + + months: defaultLocaleMonths, + monthsShort: defaultLocaleMonthsShort, + + week: defaultLocaleWeek, + + weekdays: defaultLocaleWeekdays, + weekdaysMin: defaultLocaleWeekdaysMin, + weekdaysShort: defaultLocaleWeekdaysShort, + + meridiemParse: defaultLocaleMeridiemParse + }; + + // internal storage for locale config files + var locales = {}; + var localeFamilies = {}; + var globalLocale; + + function normalizeLocale(key) { + return key ? key.toLowerCase().replace('_', '-') : key; + } + + // pick the locale from the array + // try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each + // substring from most specific to least, but move to the next array item if it's a more specific variant than the current root + function chooseLocale(names) { + var i = 0, j, next, locale, split; + + while (i < names.length) { + split = normalizeLocale(names[i]).split('-'); + j = split.length; + next = normalizeLocale(names[i + 1]); + next = next ? next.split('-') : null; + while (j > 0) { + locale = loadLocale(split.slice(0, j).join('-')); + if (locale) { + return locale; + } + if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) { + //the next array item is better than a shallower substring of this one + break; + } + j--; + } + i++; + } + return globalLocale; + } + + function loadLocale(name) { + var oldLocale = null; + // TODO: Find a better way to register and load all the locales in Node + if (!locales[name] && ('object' !== 'undefined') && + module && module.exports) { + try { + oldLocale = globalLocale._abbr; + var aliasedRequire = commonjsRequire; + aliasedRequire('./locale/' + name); + getSetGlobalLocale(oldLocale); + } catch (e) {} + } + return locales[name]; + } + + // This function will load locale and then set the global locale. If + // no arguments are passed in, it will simply return the current global + // locale key. + function getSetGlobalLocale (key, values) { + var data; + if (key) { + if (isUndefined(values)) { + data = getLocale(key); + } + else { + data = defineLocale(key, values); + } + + if (data) { + // moment.duration._locale = moment._locale = data; + globalLocale = data; + } + else { + if ((typeof console !== 'undefined') && console.warn) { + //warn user if arguments are passed but the locale could not be set + console.warn('Locale ' + key + ' not found. Did you forget to load it?'); + } + } + } + + return globalLocale._abbr; + } + + function defineLocale (name, config) { + if (config !== null) { + var locale, parentConfig = baseConfig; + config.abbr = name; + if (locales[name] != null) { + deprecateSimple('defineLocaleOverride', + 'use moment.updateLocale(localeName, config) to change ' + + 'an existing locale. moment.defineLocale(localeName, ' + + 'config) should only be used for creating a new locale ' + + 'See http://momentjs.com/guides/#/warnings/define-locale/ for more info.'); + parentConfig = locales[name]._config; + } else if (config.parentLocale != null) { + if (locales[config.parentLocale] != null) { + parentConfig = locales[config.parentLocale]._config; + } else { + locale = loadLocale(config.parentLocale); + if (locale != null) { + parentConfig = locale._config; + } else { + if (!localeFamilies[config.parentLocale]) { + localeFamilies[config.parentLocale] = []; + } + localeFamilies[config.parentLocale].push({ + name: name, + config: config + }); + return null; + } + } + } + locales[name] = new Locale(mergeConfigs(parentConfig, config)); + + if (localeFamilies[name]) { + localeFamilies[name].forEach(function (x) { + defineLocale(x.name, x.config); + }); + } + + // backwards compat for now: also set the locale + // make sure we set the locale AFTER all child locales have been + // created, so we won't end up with the child locale set. + getSetGlobalLocale(name); + + + return locales[name]; + } else { + // useful for testing + delete locales[name]; + return null; + } + } + + function updateLocale(name, config) { + if (config != null) { + var locale, tmpLocale, parentConfig = baseConfig; + // MERGE + tmpLocale = loadLocale(name); + if (tmpLocale != null) { + parentConfig = tmpLocale._config; + } + config = mergeConfigs(parentConfig, config); + locale = new Locale(config); + locale.parentLocale = locales[name]; + locales[name] = locale; + + // backwards compat for now: also set the locale + getSetGlobalLocale(name); + } else { + // pass null for config to unupdate, useful for tests + if (locales[name] != null) { + if (locales[name].parentLocale != null) { + locales[name] = locales[name].parentLocale; + } else if (locales[name] != null) { + delete locales[name]; + } + } + } + return locales[name]; + } + + // returns locale data + function getLocale (key) { + var locale; + + if (key && key._locale && key._locale._abbr) { + key = key._locale._abbr; + } + + if (!key) { + return globalLocale; + } + + if (!isArray(key)) { + //short-circuit everything else + locale = loadLocale(key); + if (locale) { + return locale; + } + key = [key]; + } + + return chooseLocale(key); + } + + function listLocales() { + return keys(locales); + } + + function checkOverflow (m) { + var overflow; + var a = m._a; + + if (a && getParsingFlags(m).overflow === -2) { + overflow = + a[MONTH] < 0 || a[MONTH] > 11 ? MONTH : + a[DATE] < 1 || a[DATE] > daysInMonth(a[YEAR], a[MONTH]) ? DATE : + a[HOUR] < 0 || a[HOUR] > 24 || (a[HOUR] === 24 && (a[MINUTE] !== 0 || a[SECOND] !== 0 || a[MILLISECOND] !== 0)) ? HOUR : + a[MINUTE] < 0 || a[MINUTE] > 59 ? MINUTE : + a[SECOND] < 0 || a[SECOND] > 59 ? SECOND : + a[MILLISECOND] < 0 || a[MILLISECOND] > 999 ? MILLISECOND : + -1; + + if (getParsingFlags(m)._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) { + overflow = DATE; + } + if (getParsingFlags(m)._overflowWeeks && overflow === -1) { + overflow = WEEK; + } + if (getParsingFlags(m)._overflowWeekday && overflow === -1) { + overflow = WEEKDAY; + } + + getParsingFlags(m).overflow = overflow; + } + + return m; + } + + // Pick the first defined of two or three arguments. + function defaults(a, b, c) { + if (a != null) { + return a; + } + if (b != null) { + return b; + } + return c; + } + + function currentDateArray(config) { + // hooks is actually the exported moment object + var nowValue = new Date(hooks.now()); + if (config._useUTC) { + return [nowValue.getUTCFullYear(), nowValue.getUTCMonth(), nowValue.getUTCDate()]; + } + return [nowValue.getFullYear(), nowValue.getMonth(), nowValue.getDate()]; + } + + // convert an array to a date. + // the array should mirror the parameters below + // note: all values past the year are optional and will default to the lowest possible value. + // [year, month, day , hour, minute, second, millisecond] + function configFromArray (config) { + var i, date, input = [], currentDate, expectedWeekday, yearToUse; + + if (config._d) { + return; + } + + currentDate = currentDateArray(config); + + //compute day of the year from weeks and weekdays + if (config._w && config._a[DATE] == null && config._a[MONTH] == null) { + dayOfYearFromWeekInfo(config); + } + + //if the day of the year is set, figure out what it is + if (config._dayOfYear != null) { + yearToUse = defaults(config._a[YEAR], currentDate[YEAR]); + + if (config._dayOfYear > daysInYear(yearToUse) || config._dayOfYear === 0) { + getParsingFlags(config)._overflowDayOfYear = true; + } + + date = createUTCDate(yearToUse, 0, config._dayOfYear); + config._a[MONTH] = date.getUTCMonth(); + config._a[DATE] = date.getUTCDate(); + } + + // Default to current date. + // * if no year, month, day of month are given, default to today + // * if day of month is given, default month and year + // * if month is given, default only year + // * if year is given, don't default anything + for (i = 0; i < 3 && config._a[i] == null; ++i) { + config._a[i] = input[i] = currentDate[i]; + } + + // Zero out whatever was not defaulted, including time + for (; i < 7; i++) { + config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i]; + } + + // Check for 24:00:00.000 + if (config._a[HOUR] === 24 && + config._a[MINUTE] === 0 && + config._a[SECOND] === 0 && + config._a[MILLISECOND] === 0) { + config._nextDay = true; + config._a[HOUR] = 0; + } + + config._d = (config._useUTC ? createUTCDate : createDate).apply(null, input); + expectedWeekday = config._useUTC ? config._d.getUTCDay() : config._d.getDay(); + + // Apply timezone offset from input. The actual utcOffset can be changed + // with parseZone. + if (config._tzm != null) { + config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm); + } + + if (config._nextDay) { + config._a[HOUR] = 24; + } + + // check for mismatching day of week + if (config._w && typeof config._w.d !== 'undefined' && config._w.d !== expectedWeekday) { + getParsingFlags(config).weekdayMismatch = true; + } + } + + function dayOfYearFromWeekInfo(config) { + var w, weekYear, week, weekday, dow, doy, temp, weekdayOverflow; + + w = config._w; + if (w.GG != null || w.W != null || w.E != null) { + dow = 1; + doy = 4; + + // TODO: We need to take the current isoWeekYear, but that depends on + // how we interpret now (local, utc, fixed offset). So create + // a now version of current config (take local/utc/offset flags, and + // create now). + weekYear = defaults(w.GG, config._a[YEAR], weekOfYear(createLocal(), 1, 4).year); + week = defaults(w.W, 1); + weekday = defaults(w.E, 1); + if (weekday < 1 || weekday > 7) { + weekdayOverflow = true; + } + } else { + dow = config._locale._week.dow; + doy = config._locale._week.doy; + + var curWeek = weekOfYear(createLocal(), dow, doy); + + weekYear = defaults(w.gg, config._a[YEAR], curWeek.year); + + // Default to current week. + week = defaults(w.w, curWeek.week); + + if (w.d != null) { + // weekday -- low day numbers are considered next week + weekday = w.d; + if (weekday < 0 || weekday > 6) { + weekdayOverflow = true; + } + } else if (w.e != null) { + // local weekday -- counting starts from beginning of week + weekday = w.e + dow; + if (w.e < 0 || w.e > 6) { + weekdayOverflow = true; + } + } else { + // default to beginning of week + weekday = dow; + } + } + if (week < 1 || week > weeksInYear(weekYear, dow, doy)) { + getParsingFlags(config)._overflowWeeks = true; + } else if (weekdayOverflow != null) { + getParsingFlags(config)._overflowWeekday = true; + } else { + temp = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy); + config._a[YEAR] = temp.year; + config._dayOfYear = temp.dayOfYear; + } + } + + // iso 8601 regex + // 0000-00-00 0000-W00 or 0000-W00-0 + T + 00 or 00:00 or 00:00:00 or 00:00:00.000 + +00:00 or +0000 or +00) + var extendedIsoRegex = /^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/; + var basicIsoRegex = /^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/; + + var tzRegex = /Z|[+-]\d\d(?::?\d\d)?/; + + var isoDates = [ + ['YYYYYY-MM-DD', /[+-]\d{6}-\d\d-\d\d/], + ['YYYY-MM-DD', /\d{4}-\d\d-\d\d/], + ['GGGG-[W]WW-E', /\d{4}-W\d\d-\d/], + ['GGGG-[W]WW', /\d{4}-W\d\d/, false], + ['YYYY-DDD', /\d{4}-\d{3}/], + ['YYYY-MM', /\d{4}-\d\d/, false], + ['YYYYYYMMDD', /[+-]\d{10}/], + ['YYYYMMDD', /\d{8}/], + // YYYYMM is NOT allowed by the standard + ['GGGG[W]WWE', /\d{4}W\d{3}/], + ['GGGG[W]WW', /\d{4}W\d{2}/, false], + ['YYYYDDD', /\d{7}/] + ]; + + // iso time formats and regexes + var isoTimes = [ + ['HH:mm:ss.SSSS', /\d\d:\d\d:\d\d\.\d+/], + ['HH:mm:ss,SSSS', /\d\d:\d\d:\d\d,\d+/], + ['HH:mm:ss', /\d\d:\d\d:\d\d/], + ['HH:mm', /\d\d:\d\d/], + ['HHmmss.SSSS', /\d\d\d\d\d\d\.\d+/], + ['HHmmss,SSSS', /\d\d\d\d\d\d,\d+/], + ['HHmmss', /\d\d\d\d\d\d/], + ['HHmm', /\d\d\d\d/], + ['HH', /\d\d/] + ]; + + var aspNetJsonRegex = /^\/?Date\((\-?\d+)/i; + + // date from iso format + function configFromISO(config) { + var i, l, + string = config._i, + match = extendedIsoRegex.exec(string) || basicIsoRegex.exec(string), + allowTime, dateFormat, timeFormat, tzFormat; + + if (match) { + getParsingFlags(config).iso = true; + + for (i = 0, l = isoDates.length; i < l; i++) { + if (isoDates[i][1].exec(match[1])) { + dateFormat = isoDates[i][0]; + allowTime = isoDates[i][2] !== false; + break; + } + } + if (dateFormat == null) { + config._isValid = false; + return; + } + if (match[3]) { + for (i = 0, l = isoTimes.length; i < l; i++) { + if (isoTimes[i][1].exec(match[3])) { + // match[2] should be 'T' or space + timeFormat = (match[2] || ' ') + isoTimes[i][0]; + break; + } + } + if (timeFormat == null) { + config._isValid = false; + return; + } + } + if (!allowTime && timeFormat != null) { + config._isValid = false; + return; + } + if (match[4]) { + if (tzRegex.exec(match[4])) { + tzFormat = 'Z'; + } else { + config._isValid = false; + return; + } + } + config._f = dateFormat + (timeFormat || '') + (tzFormat || ''); + configFromStringAndFormat(config); + } else { + config._isValid = false; + } + } + + // RFC 2822 regex: For details see https://tools.ietf.org/html/rfc2822#section-3.3 + var rfc2822 = /^(?:(Mon|Tue|Wed|Thu|Fri|Sat|Sun),?\s)?(\d{1,2})\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(\d{2,4})\s(\d\d):(\d\d)(?::(\d\d))?\s(?:(UT|GMT|[ECMP][SD]T)|([Zz])|([+-]\d{4}))$/; + + function extractFromRFC2822Strings(yearStr, monthStr, dayStr, hourStr, minuteStr, secondStr) { + var result = [ + untruncateYear(yearStr), + defaultLocaleMonthsShort.indexOf(monthStr), + parseInt(dayStr, 10), + parseInt(hourStr, 10), + parseInt(minuteStr, 10) + ]; + + if (secondStr) { + result.push(parseInt(secondStr, 10)); + } + + return result; + } + + function untruncateYear(yearStr) { + var year = parseInt(yearStr, 10); + if (year <= 49) { + return 2000 + year; + } else if (year <= 999) { + return 1900 + year; + } + return year; + } + + function preprocessRFC2822(s) { + // Remove comments and folding whitespace and replace multiple-spaces with a single space + return s.replace(/\([^)]*\)|[\n\t]/g, ' ').replace(/(\s\s+)/g, ' ').replace(/^\s\s*/, '').replace(/\s\s*$/, ''); + } + + function checkWeekday(weekdayStr, parsedInput, config) { + if (weekdayStr) { + // TODO: Replace the vanilla JS Date object with an indepentent day-of-week check. + var weekdayProvided = defaultLocaleWeekdaysShort.indexOf(weekdayStr), + weekdayActual = new Date(parsedInput[0], parsedInput[1], parsedInput[2]).getDay(); + if (weekdayProvided !== weekdayActual) { + getParsingFlags(config).weekdayMismatch = true; + config._isValid = false; + return false; + } + } + return true; + } + + var obsOffsets = { + UT: 0, + GMT: 0, + EDT: -4 * 60, + EST: -5 * 60, + CDT: -5 * 60, + CST: -6 * 60, + MDT: -6 * 60, + MST: -7 * 60, + PDT: -7 * 60, + PST: -8 * 60 + }; + + function calculateOffset(obsOffset, militaryOffset, numOffset) { + if (obsOffset) { + return obsOffsets[obsOffset]; + } else if (militaryOffset) { + // the only allowed military tz is Z + return 0; + } else { + var hm = parseInt(numOffset, 10); + var m = hm % 100, h = (hm - m) / 100; + return h * 60 + m; + } + } + + // date and time from ref 2822 format + function configFromRFC2822(config) { + var match = rfc2822.exec(preprocessRFC2822(config._i)); + if (match) { + var parsedArray = extractFromRFC2822Strings(match[4], match[3], match[2], match[5], match[6], match[7]); + if (!checkWeekday(match[1], parsedArray, config)) { + return; + } + + config._a = parsedArray; + config._tzm = calculateOffset(match[8], match[9], match[10]); + + config._d = createUTCDate.apply(null, config._a); + config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm); + + getParsingFlags(config).rfc2822 = true; + } else { + config._isValid = false; + } + } + + // date from iso format or fallback + function configFromString(config) { + var matched = aspNetJsonRegex.exec(config._i); + + if (matched !== null) { + config._d = new Date(+matched[1]); + return; + } + + configFromISO(config); + if (config._isValid === false) { + delete config._isValid; + } else { + return; + } + + configFromRFC2822(config); + if (config._isValid === false) { + delete config._isValid; + } else { + return; + } + + // Final attempt, use Input Fallback + hooks.createFromInputFallback(config); + } + + hooks.createFromInputFallback = deprecate( + 'value provided is not in a recognized RFC2822 or ISO format. moment construction falls back to js Date(), ' + + 'which is not reliable across all browsers and versions. Non RFC2822/ISO date formats are ' + + 'discouraged and will be removed in an upcoming major release. Please refer to ' + + 'http://momentjs.com/guides/#/warnings/js-date/ for more info.', + function (config) { + config._d = new Date(config._i + (config._useUTC ? ' UTC' : '')); + } + ); + + // constant that refers to the ISO standard + hooks.ISO_8601 = function () {}; + + // constant that refers to the RFC 2822 form + hooks.RFC_2822 = function () {}; + + // date from string and format string + function configFromStringAndFormat(config) { + // TODO: Move this to another part of the creation flow to prevent circular deps + if (config._f === hooks.ISO_8601) { + configFromISO(config); + return; + } + if (config._f === hooks.RFC_2822) { + configFromRFC2822(config); + return; + } + config._a = []; + getParsingFlags(config).empty = true; + + // This array is used to make a Date, either with `new Date` or `Date.UTC` + var string = '' + config._i, + i, parsedInput, tokens, token, skipped, + stringLength = string.length, + totalParsedInputLength = 0; + + tokens = expandFormat(config._f, config._locale).match(formattingTokens) || []; + + for (i = 0; i < tokens.length; i++) { + token = tokens[i]; + parsedInput = (string.match(getParseRegexForToken(token, config)) || [])[0]; + // 'regex', getParseRegexForToken(token, config)); + if (parsedInput) { + skipped = string.substr(0, string.indexOf(parsedInput)); + if (skipped.length > 0) { + getParsingFlags(config).unusedInput.push(skipped); + } + string = string.slice(string.indexOf(parsedInput) + parsedInput.length); + totalParsedInputLength += parsedInput.length; + } + // don't parse if it's not a known token + if (formatTokenFunctions[token]) { + if (parsedInput) { + getParsingFlags(config).empty = false; + } + else { + getParsingFlags(config).unusedTokens.push(token); + } + addTimeToArrayFromToken(token, parsedInput, config); + } + else if (config._strict && !parsedInput) { + getParsingFlags(config).unusedTokens.push(token); + } + } + + // add remaining unparsed input length to the string + getParsingFlags(config).charsLeftOver = stringLength - totalParsedInputLength; + if (string.length > 0) { + getParsingFlags(config).unusedInput.push(string); + } + + // clear _12h flag if hour is <= 12 + if (config._a[HOUR] <= 12 && + getParsingFlags(config).bigHour === true && + config._a[HOUR] > 0) { + getParsingFlags(config).bigHour = undefined; + } + + getParsingFlags(config).parsedDateParts = config._a.slice(0); + getParsingFlags(config).meridiem = config._meridiem; + // handle meridiem + config._a[HOUR] = meridiemFixWrap(config._locale, config._a[HOUR], config._meridiem); + + configFromArray(config); + checkOverflow(config); + } + + + function meridiemFixWrap (locale, hour, meridiem) { + var isPm; + + if (meridiem == null) { + // nothing to do + return hour; + } + if (locale.meridiemHour != null) { + return locale.meridiemHour(hour, meridiem); + } else if (locale.isPM != null) { + // Fallback + isPm = locale.isPM(meridiem); + if (isPm && hour < 12) { + hour += 12; + } + if (!isPm && hour === 12) { + hour = 0; + } + return hour; + } else { + // this is not supposed to happen + return hour; + } + } + + // date from string and array of format strings + function configFromStringAndArray(config) { + var tempConfig, + bestMoment, + + scoreToBeat, + i, + currentScore; + + if (config._f.length === 0) { + getParsingFlags(config).invalidFormat = true; + config._d = new Date(NaN); + return; + } + + for (i = 0; i < config._f.length; i++) { + currentScore = 0; + tempConfig = copyConfig({}, config); + if (config._useUTC != null) { + tempConfig._useUTC = config._useUTC; + } + tempConfig._f = config._f[i]; + configFromStringAndFormat(tempConfig); + + if (!isValid(tempConfig)) { + continue; + } + + // if there is any input that was not parsed add a penalty for that format + currentScore += getParsingFlags(tempConfig).charsLeftOver; + + //or tokens + currentScore += getParsingFlags(tempConfig).unusedTokens.length * 10; + + getParsingFlags(tempConfig).score = currentScore; + + if (scoreToBeat == null || currentScore < scoreToBeat) { + scoreToBeat = currentScore; + bestMoment = tempConfig; + } + } + + extend(config, bestMoment || tempConfig); + } + + function configFromObject(config) { + if (config._d) { + return; + } + + var i = normalizeObjectUnits(config._i); + config._a = map([i.year, i.month, i.day || i.date, i.hour, i.minute, i.second, i.millisecond], function (obj) { + return obj && parseInt(obj, 10); + }); + + configFromArray(config); + } + + function createFromConfig (config) { + var res = new Moment(checkOverflow(prepareConfig(config))); + if (res._nextDay) { + // Adding is smart enough around DST + res.add(1, 'd'); + res._nextDay = undefined; + } + + return res; + } + + function prepareConfig (config) { + var input = config._i, + format = config._f; + + config._locale = config._locale || getLocale(config._l); + + if (input === null || (format === undefined && input === '')) { + return createInvalid({nullInput: true}); + } + + if (typeof input === 'string') { + config._i = input = config._locale.preparse(input); + } + + if (isMoment(input)) { + return new Moment(checkOverflow(input)); + } else if (isDate(input)) { + config._d = input; + } else if (isArray(format)) { + configFromStringAndArray(config); + } else if (format) { + configFromStringAndFormat(config); + } else { + configFromInput(config); + } + + if (!isValid(config)) { + config._d = null; + } + + return config; + } + + function configFromInput(config) { + var input = config._i; + if (isUndefined(input)) { + config._d = new Date(hooks.now()); + } else if (isDate(input)) { + config._d = new Date(input.valueOf()); + } else if (typeof input === 'string') { + configFromString(config); + } else if (isArray(input)) { + config._a = map(input.slice(0), function (obj) { + return parseInt(obj, 10); + }); + configFromArray(config); + } else if (isObject(input)) { + configFromObject(config); + } else if (isNumber(input)) { + // from milliseconds + config._d = new Date(input); + } else { + hooks.createFromInputFallback(config); + } + } + + function createLocalOrUTC (input, format, locale, strict, isUTC) { + var c = {}; + + if (locale === true || locale === false) { + strict = locale; + locale = undefined; + } + + if ((isObject(input) && isObjectEmpty(input)) || + (isArray(input) && input.length === 0)) { + input = undefined; + } + // object construction must be done this way. + // https://github.com/moment/moment/issues/1423 + c._isAMomentObject = true; + c._useUTC = c._isUTC = isUTC; + c._l = locale; + c._i = input; + c._f = format; + c._strict = strict; + + return createFromConfig(c); + } + + function createLocal (input, format, locale, strict) { + return createLocalOrUTC(input, format, locale, strict, false); + } + + var prototypeMin = deprecate( + 'moment().min is deprecated, use moment.max instead. http://momentjs.com/guides/#/warnings/min-max/', + function () { + var other = createLocal.apply(null, arguments); + if (this.isValid() && other.isValid()) { + return other < this ? this : other; + } else { + return createInvalid(); + } + } + ); + + var prototypeMax = deprecate( + 'moment().max is deprecated, use moment.min instead. http://momentjs.com/guides/#/warnings/min-max/', + function () { + var other = createLocal.apply(null, arguments); + if (this.isValid() && other.isValid()) { + return other > this ? this : other; + } else { + return createInvalid(); + } + } + ); + + // Pick a moment m from moments so that m[fn](other) is true for all + // other. This relies on the function fn to be transitive. + // + // moments should either be an array of moment objects or an array, whose + // first element is an array of moment objects. + function pickBy(fn, moments) { + var res, i; + if (moments.length === 1 && isArray(moments[0])) { + moments = moments[0]; + } + if (!moments.length) { + return createLocal(); + } + res = moments[0]; + for (i = 1; i < moments.length; ++i) { + if (!moments[i].isValid() || moments[i][fn](res)) { + res = moments[i]; + } + } + return res; + } + + // TODO: Use [].sort instead? + function min () { + var args = [].slice.call(arguments, 0); + + return pickBy('isBefore', args); + } + + function max () { + var args = [].slice.call(arguments, 0); + + return pickBy('isAfter', args); + } + + var now = function () { + return Date.now ? Date.now() : +(new Date()); + }; + + var ordering = ['year', 'quarter', 'month', 'week', 'day', 'hour', 'minute', 'second', 'millisecond']; + + function isDurationValid(m) { + for (var key in m) { + if (!(indexOf.call(ordering, key) !== -1 && (m[key] == null || !isNaN(m[key])))) { + return false; + } + } + + var unitHasDecimal = false; + for (var i = 0; i < ordering.length; ++i) { + if (m[ordering[i]]) { + if (unitHasDecimal) { + return false; // only allow non-integers for smallest unit + } + if (parseFloat(m[ordering[i]]) !== toInt(m[ordering[i]])) { + unitHasDecimal = true; + } + } + } + + return true; + } + + function isValid$1() { + return this._isValid; + } + + function createInvalid$1() { + return createDuration(NaN); + } + + function Duration (duration) { + var normalizedInput = normalizeObjectUnits(duration), + years = normalizedInput.year || 0, + quarters = normalizedInput.quarter || 0, + months = normalizedInput.month || 0, + weeks = normalizedInput.week || normalizedInput.isoWeek || 0, + days = normalizedInput.day || 0, + hours = normalizedInput.hour || 0, + minutes = normalizedInput.minute || 0, + seconds = normalizedInput.second || 0, + milliseconds = normalizedInput.millisecond || 0; + + this._isValid = isDurationValid(normalizedInput); + + // representation for dateAddRemove + this._milliseconds = +milliseconds + + seconds * 1e3 + // 1000 + minutes * 6e4 + // 1000 * 60 + hours * 1000 * 60 * 60; //using 1000 * 60 * 60 instead of 36e5 to avoid floating point rounding errors https://github.com/moment/moment/issues/2978 + // Because of dateAddRemove treats 24 hours as different from a + // day when working around DST, we need to store them separately + this._days = +days + + weeks * 7; + // It is impossible to translate months into days without knowing + // which months you are are talking about, so we have to store + // it separately. + this._months = +months + + quarters * 3 + + years * 12; + + this._data = {}; + + this._locale = getLocale(); + + this._bubble(); + } + + function isDuration (obj) { + return obj instanceof Duration; + } + + function absRound (number) { + if (number < 0) { + return Math.round(-1 * number) * -1; + } else { + return Math.round(number); + } + } + + // FORMATTING + + function offset (token, separator) { + addFormatToken(token, 0, 0, function () { + var offset = this.utcOffset(); + var sign = '+'; + if (offset < 0) { + offset = -offset; + sign = '-'; + } + return sign + zeroFill(~~(offset / 60), 2) + separator + zeroFill(~~(offset) % 60, 2); + }); + } + + offset('Z', ':'); + offset('ZZ', ''); + + // PARSING + + addRegexToken('Z', matchShortOffset); + addRegexToken('ZZ', matchShortOffset); + addParseToken(['Z', 'ZZ'], function (input, array, config) { + config._useUTC = true; + config._tzm = offsetFromString(matchShortOffset, input); + }); + + // HELPERS + + // timezone chunker + // '+10:00' > ['10', '00'] + // '-1530' > ['-15', '30'] + var chunkOffset = /([\+\-]|\d\d)/gi; + + function offsetFromString(matcher, string) { + var matches = (string || '').match(matcher); + + if (matches === null) { + return null; + } + + var chunk = matches[matches.length - 1] || []; + var parts = (chunk + '').match(chunkOffset) || ['-', 0, 0]; + var minutes = +(parts[1] * 60) + toInt(parts[2]); + + return minutes === 0 ? + 0 : + parts[0] === '+' ? minutes : -minutes; + } + + // Return a moment from input, that is local/utc/zone equivalent to model. + function cloneWithOffset(input, model) { + var res, diff; + if (model._isUTC) { + res = model.clone(); + diff = (isMoment(input) || isDate(input) ? input.valueOf() : createLocal(input).valueOf()) - res.valueOf(); + // Use low-level api, because this fn is low-level api. + res._d.setTime(res._d.valueOf() + diff); + hooks.updateOffset(res, false); + return res; + } else { + return createLocal(input).local(); + } + } + + function getDateOffset (m) { + // On Firefox.24 Date#getTimezoneOffset returns a floating point. + // https://github.com/moment/moment/pull/1871 + return -Math.round(m._d.getTimezoneOffset() / 15) * 15; + } + + // HOOKS + + // This function will be called whenever a moment is mutated. + // It is intended to keep the offset in sync with the timezone. + hooks.updateOffset = function () {}; + + // MOMENTS + + // keepLocalTime = true means only change the timezone, without + // affecting the local hour. So 5:31:26 +0300 --[utcOffset(2, true)]--> + // 5:31:26 +0200 It is possible that 5:31:26 doesn't exist with offset + // +0200, so we adjust the time as needed, to be valid. + // + // Keeping the time actually adds/subtracts (one hour) + // from the actual represented time. That is why we call updateOffset + // a second time. In case it wants us to change the offset again + // _changeInProgress == true case, then we have to adjust, because + // there is no such time in the given timezone. + function getSetOffset (input, keepLocalTime, keepMinutes) { + var offset = this._offset || 0, + localAdjust; + if (!this.isValid()) { + return input != null ? this : NaN; + } + if (input != null) { + if (typeof input === 'string') { + input = offsetFromString(matchShortOffset, input); + if (input === null) { + return this; + } + } else if (Math.abs(input) < 16 && !keepMinutes) { + input = input * 60; + } + if (!this._isUTC && keepLocalTime) { + localAdjust = getDateOffset(this); + } + this._offset = input; + this._isUTC = true; + if (localAdjust != null) { + this.add(localAdjust, 'm'); + } + if (offset !== input) { + if (!keepLocalTime || this._changeInProgress) { + addSubtract(this, createDuration(input - offset, 'm'), 1, false); + } else if (!this._changeInProgress) { + this._changeInProgress = true; + hooks.updateOffset(this, true); + this._changeInProgress = null; + } + } + return this; + } else { + return this._isUTC ? offset : getDateOffset(this); + } + } + + function getSetZone (input, keepLocalTime) { + if (input != null) { + if (typeof input !== 'string') { + input = -input; + } + + this.utcOffset(input, keepLocalTime); + + return this; + } else { + return -this.utcOffset(); + } + } + + function setOffsetToUTC (keepLocalTime) { + return this.utcOffset(0, keepLocalTime); + } + + function setOffsetToLocal (keepLocalTime) { + if (this._isUTC) { + this.utcOffset(0, keepLocalTime); + this._isUTC = false; + + if (keepLocalTime) { + this.subtract(getDateOffset(this), 'm'); + } + } + return this; + } + + function setOffsetToParsedOffset () { + if (this._tzm != null) { + this.utcOffset(this._tzm, false, true); + } else if (typeof this._i === 'string') { + var tZone = offsetFromString(matchOffset, this._i); + if (tZone != null) { + this.utcOffset(tZone); + } + else { + this.utcOffset(0, true); + } + } + return this; + } + + function hasAlignedHourOffset (input) { + if (!this.isValid()) { + return false; + } + input = input ? createLocal(input).utcOffset() : 0; + + return (this.utcOffset() - input) % 60 === 0; + } + + function isDaylightSavingTime () { + return ( + this.utcOffset() > this.clone().month(0).utcOffset() || + this.utcOffset() > this.clone().month(5).utcOffset() + ); + } + + function isDaylightSavingTimeShifted () { + if (!isUndefined(this._isDSTShifted)) { + return this._isDSTShifted; + } + + var c = {}; + + copyConfig(c, this); + c = prepareConfig(c); + + if (c._a) { + var other = c._isUTC ? createUTC(c._a) : createLocal(c._a); + this._isDSTShifted = this.isValid() && + compareArrays(c._a, other.toArray()) > 0; + } else { + this._isDSTShifted = false; + } + + return this._isDSTShifted; + } + + function isLocal () { + return this.isValid() ? !this._isUTC : false; + } + + function isUtcOffset () { + return this.isValid() ? this._isUTC : false; + } + + function isUtc () { + return this.isValid() ? this._isUTC && this._offset === 0 : false; + } + + // ASP.NET json date format regex + var aspNetRegex = /^(\-|\+)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)(\.\d*)?)?$/; + + // from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html + // somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere + // and further modified to allow for strings containing both week and day + var isoRegex = /^(-|\+)?P(?:([-+]?[0-9,.]*)Y)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)W)?(?:([-+]?[0-9,.]*)D)?(?:T(?:([-+]?[0-9,.]*)H)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)S)?)?$/; + + function createDuration (input, key) { + var duration = input, + // matching against regexp is expensive, do it on demand + match = null, + sign, + ret, + diffRes; + + if (isDuration(input)) { + duration = { + ms : input._milliseconds, + d : input._days, + M : input._months + }; + } else if (isNumber(input)) { + duration = {}; + if (key) { + duration[key] = input; + } else { + duration.milliseconds = input; + } + } else if (!!(match = aspNetRegex.exec(input))) { + sign = (match[1] === '-') ? -1 : 1; + duration = { + y : 0, + d : toInt(match[DATE]) * sign, + h : toInt(match[HOUR]) * sign, + m : toInt(match[MINUTE]) * sign, + s : toInt(match[SECOND]) * sign, + ms : toInt(absRound(match[MILLISECOND] * 1000)) * sign // the millisecond decimal point is included in the match + }; + } else if (!!(match = isoRegex.exec(input))) { + sign = (match[1] === '-') ? -1 : 1; + duration = { + y : parseIso(match[2], sign), + M : parseIso(match[3], sign), + w : parseIso(match[4], sign), + d : parseIso(match[5], sign), + h : parseIso(match[6], sign), + m : parseIso(match[7], sign), + s : parseIso(match[8], sign) + }; + } else if (duration == null) {// checks for null or undefined + duration = {}; + } else if (typeof duration === 'object' && ('from' in duration || 'to' in duration)) { + diffRes = momentsDifference(createLocal(duration.from), createLocal(duration.to)); + + duration = {}; + duration.ms = diffRes.milliseconds; + duration.M = diffRes.months; + } + + ret = new Duration(duration); + + if (isDuration(input) && hasOwnProp(input, '_locale')) { + ret._locale = input._locale; + } + + return ret; + } + + createDuration.fn = Duration.prototype; + createDuration.invalid = createInvalid$1; + + function parseIso (inp, sign) { + // We'd normally use ~~inp for this, but unfortunately it also + // converts floats to ints. + // inp may be undefined, so careful calling replace on it. + var res = inp && parseFloat(inp.replace(',', '.')); + // apply sign while we're at it + return (isNaN(res) ? 0 : res) * sign; + } + + function positiveMomentsDifference(base, other) { + var res = {}; + + res.months = other.month() - base.month() + + (other.year() - base.year()) * 12; + if (base.clone().add(res.months, 'M').isAfter(other)) { + --res.months; + } + + res.milliseconds = +other - +(base.clone().add(res.months, 'M')); + + return res; + } + + function momentsDifference(base, other) { + var res; + if (!(base.isValid() && other.isValid())) { + return {milliseconds: 0, months: 0}; + } + + other = cloneWithOffset(other, base); + if (base.isBefore(other)) { + res = positiveMomentsDifference(base, other); + } else { + res = positiveMomentsDifference(other, base); + res.milliseconds = -res.milliseconds; + res.months = -res.months; + } + + return res; + } + + // TODO: remove 'name' arg after deprecation is removed + function createAdder(direction, name) { + return function (val, period) { + var dur, tmp; + //invert the arguments, but complain about it + if (period !== null && !isNaN(+period)) { + deprecateSimple(name, 'moment().' + name + '(period, number) is deprecated. Please use moment().' + name + '(number, period). ' + + 'See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info.'); + tmp = val; val = period; period = tmp; + } + + val = typeof val === 'string' ? +val : val; + dur = createDuration(val, period); + addSubtract(this, dur, direction); + return this; + }; + } + + function addSubtract (mom, duration, isAdding, updateOffset) { + var milliseconds = duration._milliseconds, + days = absRound(duration._days), + months = absRound(duration._months); + + if (!mom.isValid()) { + // No op + return; + } + + updateOffset = updateOffset == null ? true : updateOffset; + + if (months) { + setMonth(mom, get(mom, 'Month') + months * isAdding); + } + if (days) { + set$1(mom, 'Date', get(mom, 'Date') + days * isAdding); + } + if (milliseconds) { + mom._d.setTime(mom._d.valueOf() + milliseconds * isAdding); + } + if (updateOffset) { + hooks.updateOffset(mom, days || months); + } + } + + var add = createAdder(1, 'add'); + var subtract = createAdder(-1, 'subtract'); + + function getCalendarFormat(myMoment, now) { + var diff = myMoment.diff(now, 'days', true); + return diff < -6 ? 'sameElse' : + diff < -1 ? 'lastWeek' : + diff < 0 ? 'lastDay' : + diff < 1 ? 'sameDay' : + diff < 2 ? 'nextDay' : + diff < 7 ? 'nextWeek' : 'sameElse'; + } + + function calendar$1 (time, formats) { + // We want to compare the start of today, vs this. + // Getting start-of-today depends on whether we're local/utc/offset or not. + var now = time || createLocal(), + sod = cloneWithOffset(now, this).startOf('day'), + format = hooks.calendarFormat(this, sod) || 'sameElse'; + + var output = formats && (isFunction(formats[format]) ? formats[format].call(this, now) : formats[format]); + + return this.format(output || this.localeData().calendar(format, this, createLocal(now))); + } + + function clone () { + return new Moment(this); + } + + function isAfter (input, units) { + var localInput = isMoment(input) ? input : createLocal(input); + if (!(this.isValid() && localInput.isValid())) { + return false; + } + units = normalizeUnits(units) || 'millisecond'; + if (units === 'millisecond') { + return this.valueOf() > localInput.valueOf(); + } else { + return localInput.valueOf() < this.clone().startOf(units).valueOf(); + } + } + + function isBefore (input, units) { + var localInput = isMoment(input) ? input : createLocal(input); + if (!(this.isValid() && localInput.isValid())) { + return false; + } + units = normalizeUnits(units) || 'millisecond'; + if (units === 'millisecond') { + return this.valueOf() < localInput.valueOf(); + } else { + return this.clone().endOf(units).valueOf() < localInput.valueOf(); + } + } + + function isBetween (from, to, units, inclusivity) { + var localFrom = isMoment(from) ? from : createLocal(from), + localTo = isMoment(to) ? to : createLocal(to); + if (!(this.isValid() && localFrom.isValid() && localTo.isValid())) { + return false; + } + inclusivity = inclusivity || '()'; + return (inclusivity[0] === '(' ? this.isAfter(localFrom, units) : !this.isBefore(localFrom, units)) && + (inclusivity[1] === ')' ? this.isBefore(localTo, units) : !this.isAfter(localTo, units)); + } + + function isSame (input, units) { + var localInput = isMoment(input) ? input : createLocal(input), + inputMs; + if (!(this.isValid() && localInput.isValid())) { + return false; + } + units = normalizeUnits(units) || 'millisecond'; + if (units === 'millisecond') { + return this.valueOf() === localInput.valueOf(); + } else { + inputMs = localInput.valueOf(); + return this.clone().startOf(units).valueOf() <= inputMs && inputMs <= this.clone().endOf(units).valueOf(); + } + } + + function isSameOrAfter (input, units) { + return this.isSame(input, units) || this.isAfter(input, units); + } + + function isSameOrBefore (input, units) { + return this.isSame(input, units) || this.isBefore(input, units); + } + + function diff (input, units, asFloat) { + var that, + zoneDelta, + output; + + if (!this.isValid()) { + return NaN; + } + + that = cloneWithOffset(input, this); + + if (!that.isValid()) { + return NaN; + } + + zoneDelta = (that.utcOffset() - this.utcOffset()) * 6e4; + + units = normalizeUnits(units); + + switch (units) { + case 'year': output = monthDiff(this, that) / 12; break; + case 'month': output = monthDiff(this, that); break; + case 'quarter': output = monthDiff(this, that) / 3; break; + case 'second': output = (this - that) / 1e3; break; // 1000 + case 'minute': output = (this - that) / 6e4; break; // 1000 * 60 + case 'hour': output = (this - that) / 36e5; break; // 1000 * 60 * 60 + case 'day': output = (this - that - zoneDelta) / 864e5; break; // 1000 * 60 * 60 * 24, negate dst + case 'week': output = (this - that - zoneDelta) / 6048e5; break; // 1000 * 60 * 60 * 24 * 7, negate dst + default: output = this - that; + } + + return asFloat ? output : absFloor(output); + } + + function monthDiff (a, b) { + // difference in months + var wholeMonthDiff = ((b.year() - a.year()) * 12) + (b.month() - a.month()), + // b is in (anchor - 1 month, anchor + 1 month) + anchor = a.clone().add(wholeMonthDiff, 'months'), + anchor2, adjust; + + if (b - anchor < 0) { + anchor2 = a.clone().add(wholeMonthDiff - 1, 'months'); + // linear across the month + adjust = (b - anchor) / (anchor - anchor2); + } else { + anchor2 = a.clone().add(wholeMonthDiff + 1, 'months'); + // linear across the month + adjust = (b - anchor) / (anchor2 - anchor); + } + + //check for negative zero, return zero if negative zero + return -(wholeMonthDiff + adjust) || 0; + } + + hooks.defaultFormat = 'YYYY-MM-DDTHH:mm:ssZ'; + hooks.defaultFormatUtc = 'YYYY-MM-DDTHH:mm:ss[Z]'; + + function toString () { + return this.clone().locale('en').format('ddd MMM DD YYYY HH:mm:ss [GMT]ZZ'); + } + + function toISOString(keepOffset) { + if (!this.isValid()) { + return null; + } + var utc = keepOffset !== true; + var m = utc ? this.clone().utc() : this; + if (m.year() < 0 || m.year() > 9999) { + return formatMoment(m, utc ? 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]' : 'YYYYYY-MM-DD[T]HH:mm:ss.SSSZ'); + } + if (isFunction(Date.prototype.toISOString)) { + // native implementation is ~50x faster, use it when we can + if (utc) { + return this.toDate().toISOString(); + } else { + return new Date(this.valueOf() + this.utcOffset() * 60 * 1000).toISOString().replace('Z', formatMoment(m, 'Z')); + } + } + return formatMoment(m, utc ? 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]' : 'YYYY-MM-DD[T]HH:mm:ss.SSSZ'); + } + + /** + * Return a human readable representation of a moment that can + * also be evaluated to get a new moment which is the same + * + * @link https://nodejs.org/dist/latest/docs/api/util.html#util_custom_inspect_function_on_objects + */ + function inspect () { + if (!this.isValid()) { + return 'moment.invalid(/* ' + this._i + ' */)'; + } + var func = 'moment'; + var zone = ''; + if (!this.isLocal()) { + func = this.utcOffset() === 0 ? 'moment.utc' : 'moment.parseZone'; + zone = 'Z'; + } + var prefix = '[' + func + '("]'; + var year = (0 <= this.year() && this.year() <= 9999) ? 'YYYY' : 'YYYYYY'; + var datetime = '-MM-DD[T]HH:mm:ss.SSS'; + var suffix = zone + '[")]'; + + return this.format(prefix + year + datetime + suffix); + } + + function format (inputString) { + if (!inputString) { + inputString = this.isUtc() ? hooks.defaultFormatUtc : hooks.defaultFormat; + } + var output = formatMoment(this, inputString); + return this.localeData().postformat(output); + } + + function from (time, withoutSuffix) { + if (this.isValid() && + ((isMoment(time) && time.isValid()) || + createLocal(time).isValid())) { + return createDuration({to: this, from: time}).locale(this.locale()).humanize(!withoutSuffix); + } else { + return this.localeData().invalidDate(); + } + } + + function fromNow (withoutSuffix) { + return this.from(createLocal(), withoutSuffix); + } + + function to (time, withoutSuffix) { + if (this.isValid() && + ((isMoment(time) && time.isValid()) || + createLocal(time).isValid())) { + return createDuration({from: this, to: time}).locale(this.locale()).humanize(!withoutSuffix); + } else { + return this.localeData().invalidDate(); + } + } + + function toNow (withoutSuffix) { + return this.to(createLocal(), withoutSuffix); + } + + // If passed a locale key, it will set the locale for this + // instance. Otherwise, it will return the locale configuration + // variables for this instance. + function locale (key) { + var newLocaleData; + + if (key === undefined) { + return this._locale._abbr; + } else { + newLocaleData = getLocale(key); + if (newLocaleData != null) { + this._locale = newLocaleData; + } + return this; + } + } + + var lang = deprecate( + 'moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.', + function (key) { + if (key === undefined) { + return this.localeData(); + } else { + return this.locale(key); + } + } + ); + + function localeData () { + return this._locale; + } + + var MS_PER_SECOND = 1000; + var MS_PER_MINUTE = 60 * MS_PER_SECOND; + var MS_PER_HOUR = 60 * MS_PER_MINUTE; + var MS_PER_400_YEARS = (365 * 400 + 97) * 24 * MS_PER_HOUR; + + // actual modulo - handles negative numbers (for dates before 1970): + function mod$1(dividend, divisor) { + return (dividend % divisor + divisor) % divisor; + } + + function localStartOfDate(y, m, d) { + // the date constructor remaps years 0-99 to 1900-1999 + if (y < 100 && y >= 0) { + // preserve leap years using a full 400 year cycle, then reset + return new Date(y + 400, m, d) - MS_PER_400_YEARS; + } else { + return new Date(y, m, d).valueOf(); + } + } + + function utcStartOfDate(y, m, d) { + // Date.UTC remaps years 0-99 to 1900-1999 + if (y < 100 && y >= 0) { + // preserve leap years using a full 400 year cycle, then reset + return Date.UTC(y + 400, m, d) - MS_PER_400_YEARS; + } else { + return Date.UTC(y, m, d); + } + } + + function startOf (units) { + var time; + units = normalizeUnits(units); + if (units === undefined || units === 'millisecond' || !this.isValid()) { + return this; + } + + var startOfDate = this._isUTC ? utcStartOfDate : localStartOfDate; + + switch (units) { + case 'year': + time = startOfDate(this.year(), 0, 1); + break; + case 'quarter': + time = startOfDate(this.year(), this.month() - this.month() % 3, 1); + break; + case 'month': + time = startOfDate(this.year(), this.month(), 1); + break; + case 'week': + time = startOfDate(this.year(), this.month(), this.date() - this.weekday()); + break; + case 'isoWeek': + time = startOfDate(this.year(), this.month(), this.date() - (this.isoWeekday() - 1)); + break; + case 'day': + case 'date': + time = startOfDate(this.year(), this.month(), this.date()); + break; + case 'hour': + time = this._d.valueOf(); + time -= mod$1(time + (this._isUTC ? 0 : this.utcOffset() * MS_PER_MINUTE), MS_PER_HOUR); + break; + case 'minute': + time = this._d.valueOf(); + time -= mod$1(time, MS_PER_MINUTE); + break; + case 'second': + time = this._d.valueOf(); + time -= mod$1(time, MS_PER_SECOND); + break; + } + + this._d.setTime(time); + hooks.updateOffset(this, true); + return this; + } + + function endOf (units) { + var time; + units = normalizeUnits(units); + if (units === undefined || units === 'millisecond' || !this.isValid()) { + return this; + } + + var startOfDate = this._isUTC ? utcStartOfDate : localStartOfDate; + + switch (units) { + case 'year': + time = startOfDate(this.year() + 1, 0, 1) - 1; + break; + case 'quarter': + time = startOfDate(this.year(), this.month() - this.month() % 3 + 3, 1) - 1; + break; + case 'month': + time = startOfDate(this.year(), this.month() + 1, 1) - 1; + break; + case 'week': + time = startOfDate(this.year(), this.month(), this.date() - this.weekday() + 7) - 1; + break; + case 'isoWeek': + time = startOfDate(this.year(), this.month(), this.date() - (this.isoWeekday() - 1) + 7) - 1; + break; + case 'day': + case 'date': + time = startOfDate(this.year(), this.month(), this.date() + 1) - 1; + break; + case 'hour': + time = this._d.valueOf(); + time += MS_PER_HOUR - mod$1(time + (this._isUTC ? 0 : this.utcOffset() * MS_PER_MINUTE), MS_PER_HOUR) - 1; + break; + case 'minute': + time = this._d.valueOf(); + time += MS_PER_MINUTE - mod$1(time, MS_PER_MINUTE) - 1; + break; + case 'second': + time = this._d.valueOf(); + time += MS_PER_SECOND - mod$1(time, MS_PER_SECOND) - 1; + break; + } + + this._d.setTime(time); + hooks.updateOffset(this, true); + return this; + } + + function valueOf () { + return this._d.valueOf() - ((this._offset || 0) * 60000); + } + + function unix () { + return Math.floor(this.valueOf() / 1000); + } + + function toDate () { + return new Date(this.valueOf()); + } + + function toArray () { + var m = this; + return [m.year(), m.month(), m.date(), m.hour(), m.minute(), m.second(), m.millisecond()]; + } + + function toObject () { + var m = this; + return { + years: m.year(), + months: m.month(), + date: m.date(), + hours: m.hours(), + minutes: m.minutes(), + seconds: m.seconds(), + milliseconds: m.milliseconds() + }; + } + + function toJSON () { + // new Date(NaN).toJSON() === null + return this.isValid() ? this.toISOString() : null; + } + + function isValid$2 () { + return isValid(this); + } + + function parsingFlags () { + return extend({}, getParsingFlags(this)); + } + + function invalidAt () { + return getParsingFlags(this).overflow; + } + + function creationData() { + return { + input: this._i, + format: this._f, + locale: this._locale, + isUTC: this._isUTC, + strict: this._strict + }; + } + + // FORMATTING + + addFormatToken(0, ['gg', 2], 0, function () { + return this.weekYear() % 100; + }); + + addFormatToken(0, ['GG', 2], 0, function () { + return this.isoWeekYear() % 100; + }); + + function addWeekYearFormatToken (token, getter) { + addFormatToken(0, [token, token.length], 0, getter); + } + + addWeekYearFormatToken('gggg', 'weekYear'); + addWeekYearFormatToken('ggggg', 'weekYear'); + addWeekYearFormatToken('GGGG', 'isoWeekYear'); + addWeekYearFormatToken('GGGGG', 'isoWeekYear'); + + // ALIASES + + addUnitAlias('weekYear', 'gg'); + addUnitAlias('isoWeekYear', 'GG'); + + // PRIORITY + + addUnitPriority('weekYear', 1); + addUnitPriority('isoWeekYear', 1); + + + // PARSING + + addRegexToken('G', matchSigned); + addRegexToken('g', matchSigned); + addRegexToken('GG', match1to2, match2); + addRegexToken('gg', match1to2, match2); + addRegexToken('GGGG', match1to4, match4); + addRegexToken('gggg', match1to4, match4); + addRegexToken('GGGGG', match1to6, match6); + addRegexToken('ggggg', match1to6, match6); + + addWeekParseToken(['gggg', 'ggggg', 'GGGG', 'GGGGG'], function (input, week, config, token) { + week[token.substr(0, 2)] = toInt(input); + }); + + addWeekParseToken(['gg', 'GG'], function (input, week, config, token) { + week[token] = hooks.parseTwoDigitYear(input); + }); + + // MOMENTS + + function getSetWeekYear (input) { + return getSetWeekYearHelper.call(this, + input, + this.week(), + this.weekday(), + this.localeData()._week.dow, + this.localeData()._week.doy); + } + + function getSetISOWeekYear (input) { + return getSetWeekYearHelper.call(this, + input, this.isoWeek(), this.isoWeekday(), 1, 4); + } + + function getISOWeeksInYear () { + return weeksInYear(this.year(), 1, 4); + } + + function getWeeksInYear () { + var weekInfo = this.localeData()._week; + return weeksInYear(this.year(), weekInfo.dow, weekInfo.doy); + } + + function getSetWeekYearHelper(input, week, weekday, dow, doy) { + var weeksTarget; + if (input == null) { + return weekOfYear(this, dow, doy).year; + } else { + weeksTarget = weeksInYear(input, dow, doy); + if (week > weeksTarget) { + week = weeksTarget; + } + return setWeekAll.call(this, input, week, weekday, dow, doy); + } + } + + function setWeekAll(weekYear, week, weekday, dow, doy) { + var dayOfYearData = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy), + date = createUTCDate(dayOfYearData.year, 0, dayOfYearData.dayOfYear); + + this.year(date.getUTCFullYear()); + this.month(date.getUTCMonth()); + this.date(date.getUTCDate()); + return this; + } + + // FORMATTING + + addFormatToken('Q', 0, 'Qo', 'quarter'); + + // ALIASES + + addUnitAlias('quarter', 'Q'); + + // PRIORITY + + addUnitPriority('quarter', 7); + + // PARSING + + addRegexToken('Q', match1); + addParseToken('Q', function (input, array) { + array[MONTH] = (toInt(input) - 1) * 3; + }); + + // MOMENTS + + function getSetQuarter (input) { + return input == null ? Math.ceil((this.month() + 1) / 3) : this.month((input - 1) * 3 + this.month() % 3); + } + + // FORMATTING + + addFormatToken('D', ['DD', 2], 'Do', 'date'); + + // ALIASES + + addUnitAlias('date', 'D'); + + // PRIORITY + addUnitPriority('date', 9); + + // PARSING + + addRegexToken('D', match1to2); + addRegexToken('DD', match1to2, match2); + addRegexToken('Do', function (isStrict, locale) { + // TODO: Remove "ordinalParse" fallback in next major release. + return isStrict ? + (locale._dayOfMonthOrdinalParse || locale._ordinalParse) : + locale._dayOfMonthOrdinalParseLenient; + }); + + addParseToken(['D', 'DD'], DATE); + addParseToken('Do', function (input, array) { + array[DATE] = toInt(input.match(match1to2)[0]); + }); + + // MOMENTS + + var getSetDayOfMonth = makeGetSet('Date', true); + + // FORMATTING + + addFormatToken('DDD', ['DDDD', 3], 'DDDo', 'dayOfYear'); + + // ALIASES + + addUnitAlias('dayOfYear', 'DDD'); + + // PRIORITY + addUnitPriority('dayOfYear', 4); + + // PARSING + + addRegexToken('DDD', match1to3); + addRegexToken('DDDD', match3); + addParseToken(['DDD', 'DDDD'], function (input, array, config) { + config._dayOfYear = toInt(input); + }); + + // HELPERS + + // MOMENTS + + function getSetDayOfYear (input) { + var dayOfYear = Math.round((this.clone().startOf('day') - this.clone().startOf('year')) / 864e5) + 1; + return input == null ? dayOfYear : this.add((input - dayOfYear), 'd'); + } + + // FORMATTING + + addFormatToken('m', ['mm', 2], 0, 'minute'); + + // ALIASES + + addUnitAlias('minute', 'm'); + + // PRIORITY + + addUnitPriority('minute', 14); + + // PARSING + + addRegexToken('m', match1to2); + addRegexToken('mm', match1to2, match2); + addParseToken(['m', 'mm'], MINUTE); + + // MOMENTS + + var getSetMinute = makeGetSet('Minutes', false); + + // FORMATTING + + addFormatToken('s', ['ss', 2], 0, 'second'); + + // ALIASES + + addUnitAlias('second', 's'); + + // PRIORITY + + addUnitPriority('second', 15); + + // PARSING + + addRegexToken('s', match1to2); + addRegexToken('ss', match1to2, match2); + addParseToken(['s', 'ss'], SECOND); + + // MOMENTS + + var getSetSecond = makeGetSet('Seconds', false); + + // FORMATTING + + addFormatToken('S', 0, 0, function () { + return ~~(this.millisecond() / 100); + }); + + addFormatToken(0, ['SS', 2], 0, function () { + return ~~(this.millisecond() / 10); + }); + + addFormatToken(0, ['SSS', 3], 0, 'millisecond'); + addFormatToken(0, ['SSSS', 4], 0, function () { + return this.millisecond() * 10; + }); + addFormatToken(0, ['SSSSS', 5], 0, function () { + return this.millisecond() * 100; + }); + addFormatToken(0, ['SSSSSS', 6], 0, function () { + return this.millisecond() * 1000; + }); + addFormatToken(0, ['SSSSSSS', 7], 0, function () { + return this.millisecond() * 10000; + }); + addFormatToken(0, ['SSSSSSSS', 8], 0, function () { + return this.millisecond() * 100000; + }); + addFormatToken(0, ['SSSSSSSSS', 9], 0, function () { + return this.millisecond() * 1000000; + }); + + + // ALIASES + + addUnitAlias('millisecond', 'ms'); + + // PRIORITY + + addUnitPriority('millisecond', 16); + + // PARSING + + addRegexToken('S', match1to3, match1); + addRegexToken('SS', match1to3, match2); + addRegexToken('SSS', match1to3, match3); + + var token; + for (token = 'SSSS'; token.length <= 9; token += 'S') { + addRegexToken(token, matchUnsigned); + } + + function parseMs(input, array) { + array[MILLISECOND] = toInt(('0.' + input) * 1000); + } + + for (token = 'S'; token.length <= 9; token += 'S') { + addParseToken(token, parseMs); + } + // MOMENTS + + var getSetMillisecond = makeGetSet('Milliseconds', false); + + // FORMATTING + + addFormatToken('z', 0, 0, 'zoneAbbr'); + addFormatToken('zz', 0, 0, 'zoneName'); + + // MOMENTS + + function getZoneAbbr () { + return this._isUTC ? 'UTC' : ''; + } + + function getZoneName () { + return this._isUTC ? 'Coordinated Universal Time' : ''; + } + + var proto = Moment.prototype; + + proto.add = add; + proto.calendar = calendar$1; + proto.clone = clone; + proto.diff = diff; + proto.endOf = endOf; + proto.format = format; + proto.from = from; + proto.fromNow = fromNow; + proto.to = to; + proto.toNow = toNow; + proto.get = stringGet; + proto.invalidAt = invalidAt; + proto.isAfter = isAfter; + proto.isBefore = isBefore; + proto.isBetween = isBetween; + proto.isSame = isSame; + proto.isSameOrAfter = isSameOrAfter; + proto.isSameOrBefore = isSameOrBefore; + proto.isValid = isValid$2; + proto.lang = lang; + proto.locale = locale; + proto.localeData = localeData; + proto.max = prototypeMax; + proto.min = prototypeMin; + proto.parsingFlags = parsingFlags; + proto.set = stringSet; + proto.startOf = startOf; + proto.subtract = subtract; + proto.toArray = toArray; + proto.toObject = toObject; + proto.toDate = toDate; + proto.toISOString = toISOString; + proto.inspect = inspect; + proto.toJSON = toJSON; + proto.toString = toString; + proto.unix = unix; + proto.valueOf = valueOf; + proto.creationData = creationData; + proto.year = getSetYear; + proto.isLeapYear = getIsLeapYear; + proto.weekYear = getSetWeekYear; + proto.isoWeekYear = getSetISOWeekYear; + proto.quarter = proto.quarters = getSetQuarter; + proto.month = getSetMonth; + proto.daysInMonth = getDaysInMonth; + proto.week = proto.weeks = getSetWeek; + proto.isoWeek = proto.isoWeeks = getSetISOWeek; + proto.weeksInYear = getWeeksInYear; + proto.isoWeeksInYear = getISOWeeksInYear; + proto.date = getSetDayOfMonth; + proto.day = proto.days = getSetDayOfWeek; + proto.weekday = getSetLocaleDayOfWeek; + proto.isoWeekday = getSetISODayOfWeek; + proto.dayOfYear = getSetDayOfYear; + proto.hour = proto.hours = getSetHour; + proto.minute = proto.minutes = getSetMinute; + proto.second = proto.seconds = getSetSecond; + proto.millisecond = proto.milliseconds = getSetMillisecond; + proto.utcOffset = getSetOffset; + proto.utc = setOffsetToUTC; + proto.local = setOffsetToLocal; + proto.parseZone = setOffsetToParsedOffset; + proto.hasAlignedHourOffset = hasAlignedHourOffset; + proto.isDST = isDaylightSavingTime; + proto.isLocal = isLocal; + proto.isUtcOffset = isUtcOffset; + proto.isUtc = isUtc; + proto.isUTC = isUtc; + proto.zoneAbbr = getZoneAbbr; + proto.zoneName = getZoneName; + proto.dates = deprecate('dates accessor is deprecated. Use date instead.', getSetDayOfMonth); + proto.months = deprecate('months accessor is deprecated. Use month instead', getSetMonth); + proto.years = deprecate('years accessor is deprecated. Use year instead', getSetYear); + proto.zone = deprecate('moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/', getSetZone); + proto.isDSTShifted = deprecate('isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information', isDaylightSavingTimeShifted); + + function createUnix (input) { + return createLocal(input * 1000); + } + + function createInZone () { + return createLocal.apply(null, arguments).parseZone(); + } + + function preParsePostFormat (string) { + return string; + } + + var proto$1 = Locale.prototype; + + proto$1.calendar = calendar; + proto$1.longDateFormat = longDateFormat; + proto$1.invalidDate = invalidDate; + proto$1.ordinal = ordinal; + proto$1.preparse = preParsePostFormat; + proto$1.postformat = preParsePostFormat; + proto$1.relativeTime = relativeTime; + proto$1.pastFuture = pastFuture; + proto$1.set = set; + + proto$1.months = localeMonths; + proto$1.monthsShort = localeMonthsShort; + proto$1.monthsParse = localeMonthsParse; + proto$1.monthsRegex = monthsRegex; + proto$1.monthsShortRegex = monthsShortRegex; + proto$1.week = localeWeek; + proto$1.firstDayOfYear = localeFirstDayOfYear; + proto$1.firstDayOfWeek = localeFirstDayOfWeek; + + proto$1.weekdays = localeWeekdays; + proto$1.weekdaysMin = localeWeekdaysMin; + proto$1.weekdaysShort = localeWeekdaysShort; + proto$1.weekdaysParse = localeWeekdaysParse; + + proto$1.weekdaysRegex = weekdaysRegex; + proto$1.weekdaysShortRegex = weekdaysShortRegex; + proto$1.weekdaysMinRegex = weekdaysMinRegex; + + proto$1.isPM = localeIsPM; + proto$1.meridiem = localeMeridiem; + + function get$1 (format, index, field, setter) { + var locale = getLocale(); + var utc = createUTC().set(setter, index); + return locale[field](utc, format); + } + + function listMonthsImpl (format, index, field) { + if (isNumber(format)) { + index = format; + format = undefined; + } + + format = format || ''; + + if (index != null) { + return get$1(format, index, field, 'month'); + } + + var i; + var out = []; + for (i = 0; i < 12; i++) { + out[i] = get$1(format, i, field, 'month'); + } + return out; + } + + // () + // (5) + // (fmt, 5) + // (fmt) + // (true) + // (true, 5) + // (true, fmt, 5) + // (true, fmt) + function listWeekdaysImpl (localeSorted, format, index, field) { + if (typeof localeSorted === 'boolean') { + if (isNumber(format)) { + index = format; + format = undefined; + } + + format = format || ''; + } else { + format = localeSorted; + index = format; + localeSorted = false; + + if (isNumber(format)) { + index = format; + format = undefined; + } + + format = format || ''; + } + + var locale = getLocale(), + shift = localeSorted ? locale._week.dow : 0; + + if (index != null) { + return get$1(format, (index + shift) % 7, field, 'day'); + } + + var i; + var out = []; + for (i = 0; i < 7; i++) { + out[i] = get$1(format, (i + shift) % 7, field, 'day'); + } + return out; + } + + function listMonths (format, index) { + return listMonthsImpl(format, index, 'months'); + } + + function listMonthsShort (format, index) { + return listMonthsImpl(format, index, 'monthsShort'); + } + + function listWeekdays (localeSorted, format, index) { + return listWeekdaysImpl(localeSorted, format, index, 'weekdays'); + } + + function listWeekdaysShort (localeSorted, format, index) { + return listWeekdaysImpl(localeSorted, format, index, 'weekdaysShort'); + } + + function listWeekdaysMin (localeSorted, format, index) { + return listWeekdaysImpl(localeSorted, format, index, 'weekdaysMin'); + } + + getSetGlobalLocale('en', { + dayOfMonthOrdinalParse: /\d{1,2}(th|st|nd|rd)/, + ordinal : function (number) { + var b = number % 10, + output = (toInt(number % 100 / 10) === 1) ? 'th' : + (b === 1) ? 'st' : + (b === 2) ? 'nd' : + (b === 3) ? 'rd' : 'th'; + return number + output; + } + }); + + // Side effect imports + + hooks.lang = deprecate('moment.lang is deprecated. Use moment.locale instead.', getSetGlobalLocale); + hooks.langData = deprecate('moment.langData is deprecated. Use moment.localeData instead.', getLocale); + + var mathAbs = Math.abs; + + function abs () { + var data = this._data; + + this._milliseconds = mathAbs(this._milliseconds); + this._days = mathAbs(this._days); + this._months = mathAbs(this._months); + + data.milliseconds = mathAbs(data.milliseconds); + data.seconds = mathAbs(data.seconds); + data.minutes = mathAbs(data.minutes); + data.hours = mathAbs(data.hours); + data.months = mathAbs(data.months); + data.years = mathAbs(data.years); + + return this; + } + + function addSubtract$1 (duration, input, value, direction) { + var other = createDuration(input, value); + + duration._milliseconds += direction * other._milliseconds; + duration._days += direction * other._days; + duration._months += direction * other._months; + + return duration._bubble(); + } + + // supports only 2.0-style add(1, 's') or add(duration) + function add$1 (input, value) { + return addSubtract$1(this, input, value, 1); + } + + // supports only 2.0-style subtract(1, 's') or subtract(duration) + function subtract$1 (input, value) { + return addSubtract$1(this, input, value, -1); + } + + function absCeil (number) { + if (number < 0) { + return Math.floor(number); + } else { + return Math.ceil(number); + } + } + + function bubble () { + var milliseconds = this._milliseconds; + var days = this._days; + var months = this._months; + var data = this._data; + var seconds, minutes, hours, years, monthsFromDays; + + // if we have a mix of positive and negative values, bubble down first + // check: https://github.com/moment/moment/issues/2166 + if (!((milliseconds >= 0 && days >= 0 && months >= 0) || + (milliseconds <= 0 && days <= 0 && months <= 0))) { + milliseconds += absCeil(monthsToDays(months) + days) * 864e5; + days = 0; + months = 0; + } + + // The following code bubbles up values, see the tests for + // examples of what that means. + data.milliseconds = milliseconds % 1000; + + seconds = absFloor(milliseconds / 1000); + data.seconds = seconds % 60; + + minutes = absFloor(seconds / 60); + data.minutes = minutes % 60; + + hours = absFloor(minutes / 60); + data.hours = hours % 24; + + days += absFloor(hours / 24); + + // convert days to months + monthsFromDays = absFloor(daysToMonths(days)); + months += monthsFromDays; + days -= absCeil(monthsToDays(monthsFromDays)); + + // 12 months -> 1 year + years = absFloor(months / 12); + months %= 12; + + data.days = days; + data.months = months; + data.years = years; + + return this; + } + + function daysToMonths (days) { + // 400 years have 146097 days (taking into account leap year rules) + // 400 years have 12 months === 4800 + return days * 4800 / 146097; + } + + function monthsToDays (months) { + // the reverse of daysToMonths + return months * 146097 / 4800; + } + + function as (units) { + if (!this.isValid()) { + return NaN; + } + var days; + var months; + var milliseconds = this._milliseconds; + + units = normalizeUnits(units); + + if (units === 'month' || units === 'quarter' || units === 'year') { + days = this._days + milliseconds / 864e5; + months = this._months + daysToMonths(days); + switch (units) { + case 'month': return months; + case 'quarter': return months / 3; + case 'year': return months / 12; + } + } else { + // handle milliseconds separately because of floating point math errors (issue #1867) + days = this._days + Math.round(monthsToDays(this._months)); + switch (units) { + case 'week' : return days / 7 + milliseconds / 6048e5; + case 'day' : return days + milliseconds / 864e5; + case 'hour' : return days * 24 + milliseconds / 36e5; + case 'minute' : return days * 1440 + milliseconds / 6e4; + case 'second' : return days * 86400 + milliseconds / 1000; + // Math.floor prevents floating point math errors here + case 'millisecond': return Math.floor(days * 864e5) + milliseconds; + default: throw new Error('Unknown unit ' + units); + } + } + } + + // TODO: Use this.as('ms')? + function valueOf$1 () { + if (!this.isValid()) { + return NaN; + } + return ( + this._milliseconds + + this._days * 864e5 + + (this._months % 12) * 2592e6 + + toInt(this._months / 12) * 31536e6 + ); + } + + function makeAs (alias) { + return function () { + return this.as(alias); + }; + } + + var asMilliseconds = makeAs('ms'); + var asSeconds = makeAs('s'); + var asMinutes = makeAs('m'); + var asHours = makeAs('h'); + var asDays = makeAs('d'); + var asWeeks = makeAs('w'); + var asMonths = makeAs('M'); + var asQuarters = makeAs('Q'); + var asYears = makeAs('y'); + + function clone$1 () { + return createDuration(this); + } + + function get$2 (units) { + units = normalizeUnits(units); + return this.isValid() ? this[units + 's']() : NaN; + } + + function makeGetter(name) { + return function () { + return this.isValid() ? this._data[name] : NaN; + }; + } + + var milliseconds = makeGetter('milliseconds'); + var seconds = makeGetter('seconds'); + var minutes = makeGetter('minutes'); + var hours = makeGetter('hours'); + var days = makeGetter('days'); + var months = makeGetter('months'); + var years = makeGetter('years'); + + function weeks () { + return absFloor(this.days() / 7); + } + + var round = Math.round; + var thresholds = { + ss: 44, // a few seconds to seconds + s : 45, // seconds to minute + m : 45, // minutes to hour + h : 22, // hours to day + d : 26, // days to month + M : 11 // months to year + }; + + // helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize + function substituteTimeAgo(string, number, withoutSuffix, isFuture, locale) { + return locale.relativeTime(number || 1, !!withoutSuffix, string, isFuture); + } + + function relativeTime$1 (posNegDuration, withoutSuffix, locale) { + var duration = createDuration(posNegDuration).abs(); + var seconds = round(duration.as('s')); + var minutes = round(duration.as('m')); + var hours = round(duration.as('h')); + var days = round(duration.as('d')); + var months = round(duration.as('M')); + var years = round(duration.as('y')); + + var a = seconds <= thresholds.ss && ['s', seconds] || + seconds < thresholds.s && ['ss', seconds] || + minutes <= 1 && ['m'] || + minutes < thresholds.m && ['mm', minutes] || + hours <= 1 && ['h'] || + hours < thresholds.h && ['hh', hours] || + days <= 1 && ['d'] || + days < thresholds.d && ['dd', days] || + months <= 1 && ['M'] || + months < thresholds.M && ['MM', months] || + years <= 1 && ['y'] || ['yy', years]; + + a[2] = withoutSuffix; + a[3] = +posNegDuration > 0; + a[4] = locale; + return substituteTimeAgo.apply(null, a); + } + + // This function allows you to set the rounding function for relative time strings + function getSetRelativeTimeRounding (roundingFunction) { + if (roundingFunction === undefined) { + return round; + } + if (typeof(roundingFunction) === 'function') { + round = roundingFunction; + return true; + } + return false; + } + + // This function allows you to set a threshold for relative time strings + function getSetRelativeTimeThreshold (threshold, limit) { + if (thresholds[threshold] === undefined) { + return false; + } + if (limit === undefined) { + return thresholds[threshold]; + } + thresholds[threshold] = limit; + if (threshold === 's') { + thresholds.ss = limit - 1; + } + return true; + } + + function humanize (withSuffix) { + if (!this.isValid()) { + return this.localeData().invalidDate(); + } + + var locale = this.localeData(); + var output = relativeTime$1(this, !withSuffix, locale); + + if (withSuffix) { + output = locale.pastFuture(+this, output); + } + + return locale.postformat(output); + } + + var abs$1 = Math.abs; + + function sign(x) { + return ((x > 0) - (x < 0)) || +x; + } + + function toISOString$1() { + // for ISO strings we do not use the normal bubbling rules: + // * milliseconds bubble up until they become hours + // * days do not bubble at all + // * months bubble up until they become years + // This is because there is no context-free conversion between hours and days + // (think of clock changes) + // and also not between days and months (28-31 days per month) + if (!this.isValid()) { + return this.localeData().invalidDate(); + } + + var seconds = abs$1(this._milliseconds) / 1000; + var days = abs$1(this._days); + var months = abs$1(this._months); + var minutes, hours, years; + + // 3600 seconds -> 60 minutes -> 1 hour + minutes = absFloor(seconds / 60); + hours = absFloor(minutes / 60); + seconds %= 60; + minutes %= 60; + + // 12 months -> 1 year + years = absFloor(months / 12); + months %= 12; + + + // inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js + var Y = years; + var M = months; + var D = days; + var h = hours; + var m = minutes; + var s = seconds ? seconds.toFixed(3).replace(/\.?0+$/, '') : ''; + var total = this.asSeconds(); + + if (!total) { + // this is the same as C#'s (Noda) and python (isodate)... + // but not other JS (goog.date) + return 'P0D'; + } + + var totalSign = total < 0 ? '-' : ''; + var ymSign = sign(this._months) !== sign(total) ? '-' : ''; + var daysSign = sign(this._days) !== sign(total) ? '-' : ''; + var hmsSign = sign(this._milliseconds) !== sign(total) ? '-' : ''; + + return totalSign + 'P' + + (Y ? ymSign + Y + 'Y' : '') + + (M ? ymSign + M + 'M' : '') + + (D ? daysSign + D + 'D' : '') + + ((h || m || s) ? 'T' : '') + + (h ? hmsSign + h + 'H' : '') + + (m ? hmsSign + m + 'M' : '') + + (s ? hmsSign + s + 'S' : ''); + } + + var proto$2 = Duration.prototype; + + proto$2.isValid = isValid$1; + proto$2.abs = abs; + proto$2.add = add$1; + proto$2.subtract = subtract$1; + proto$2.as = as; + proto$2.asMilliseconds = asMilliseconds; + proto$2.asSeconds = asSeconds; + proto$2.asMinutes = asMinutes; + proto$2.asHours = asHours; + proto$2.asDays = asDays; + proto$2.asWeeks = asWeeks; + proto$2.asMonths = asMonths; + proto$2.asQuarters = asQuarters; + proto$2.asYears = asYears; + proto$2.valueOf = valueOf$1; + proto$2._bubble = bubble; + proto$2.clone = clone$1; + proto$2.get = get$2; + proto$2.milliseconds = milliseconds; + proto$2.seconds = seconds; + proto$2.minutes = minutes; + proto$2.hours = hours; + proto$2.days = days; + proto$2.weeks = weeks; + proto$2.months = months; + proto$2.years = years; + proto$2.humanize = humanize; + proto$2.toISOString = toISOString$1; + proto$2.toString = toISOString$1; + proto$2.toJSON = toISOString$1; + proto$2.locale = locale; + proto$2.localeData = localeData; + + proto$2.toIsoString = deprecate('toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)', toISOString$1); + proto$2.lang = lang; + + // Side effect imports + + // FORMATTING + + addFormatToken('X', 0, 0, 'unix'); + addFormatToken('x', 0, 0, 'valueOf'); + + // PARSING + + addRegexToken('x', matchSigned); + addRegexToken('X', matchTimestamp); + addParseToken('X', function (input, array, config) { + config._d = new Date(parseFloat(input, 10) * 1000); + }); + addParseToken('x', function (input, array, config) { + config._d = new Date(toInt(input)); + }); + + // Side effect imports + + + hooks.version = '2.24.0'; + + setHookCallback(createLocal); + + hooks.fn = proto; + hooks.min = min; + hooks.max = max; + hooks.now = now; + hooks.utc = createUTC; + hooks.unix = createUnix; + hooks.months = listMonths; + hooks.isDate = isDate; + hooks.locale = getSetGlobalLocale; + hooks.invalid = createInvalid; + hooks.duration = createDuration; + hooks.isMoment = isMoment; + hooks.weekdays = listWeekdays; + hooks.parseZone = createInZone; + hooks.localeData = getLocale; + hooks.isDuration = isDuration; + hooks.monthsShort = listMonthsShort; + hooks.weekdaysMin = listWeekdaysMin; + hooks.defineLocale = defineLocale; + hooks.updateLocale = updateLocale; + hooks.locales = listLocales; + hooks.weekdaysShort = listWeekdaysShort; + hooks.normalizeUnits = normalizeUnits; + hooks.relativeTimeRounding = getSetRelativeTimeRounding; + hooks.relativeTimeThreshold = getSetRelativeTimeThreshold; + hooks.calendarFormat = getCalendarFormat; + hooks.prototype = proto; + + // currently HTML5 input type only supports 24-hour formats + hooks.HTML5_FMT = { + DATETIME_LOCAL: 'YYYY-MM-DDTHH:mm', // + DATETIME_LOCAL_SECONDS: 'YYYY-MM-DDTHH:mm:ss', // + DATETIME_LOCAL_MS: 'YYYY-MM-DDTHH:mm:ss.SSS', // + DATE: 'YYYY-MM-DD', // + TIME: 'HH:mm', // + TIME_SECONDS: 'HH:mm:ss', // + TIME_MS: 'HH:mm:ss.SSS', // + WEEK: 'GGGG-[W]WW', // + MONTH: 'YYYY-MM' // + }; + + return hooks; + +}))); +}); + +var FORMATS = { + datetime: 'MMM D, YYYY, h:mm:ss a', + millisecond: 'h:mm:ss.SSS a', + second: 'h:mm:ss a', + minute: 'h:mm a', + hour: 'hA', + day: 'MMM D', + week: 'll', + month: 'MMM YYYY', + quarter: '[Q]Q - YYYY', + year: 'YYYY' +}; + +core_adapters._date.override(typeof moment === 'function' ? { + _id: 'moment', // DEBUG ONLY + + formats: function() { + return FORMATS; + }, + + parse: function(value, format) { + if (typeof value === 'string' && typeof format === 'string') { + value = moment(value, format); + } else if (!(value instanceof moment)) { + value = moment(value); + } + return value.isValid() ? value.valueOf() : null; + }, + + format: function(time, format) { + return moment(time).format(format); + }, + + add: function(time, amount, unit) { + return moment(time).add(amount, unit).valueOf(); + }, + + diff: function(max, min, unit) { + return moment.duration(moment(max).diff(moment(min))).as(unit); + }, + + startOf: function(time, unit, weekday) { + time = moment(time); + if (unit === 'isoWeek') { + return time.isoWeekday(weekday).valueOf(); + } + return time.startOf(unit).valueOf(); + }, + + endOf: function(time, unit) { + return moment(time).endOf(unit).valueOf(); + }, + + // DEPRECATIONS + + /** + * Provided for backward compatibility with scale.getValueForPixel(). + * @deprecated since version 2.8.0 + * @todo remove at version 3 + * @private + */ + _create: function(time) { + return moment(time); + }, +} : {}); + +core_defaults._set('global', { + plugins: { + filler: { + propagate: true + } + } +}); + +var mappers = { + dataset: function(source) { + var index = source.fill; + var chart = source.chart; + var meta = chart.getDatasetMeta(index); + var visible = meta && chart.isDatasetVisible(index); + var points = (visible && meta.dataset._children) || []; + var length = points.length || 0; + + return !length ? null : function(point, i) { + return (i < length && points[i]._view) || null; + }; + }, + + boundary: function(source) { + var boundary = source.boundary; + var x = boundary ? boundary.x : null; + var y = boundary ? boundary.y : null; + + return function(point) { + return { + x: x === null ? point.x : x, + y: y === null ? point.y : y, + }; + }; + } +}; + +// @todo if (fill[0] === '#') +function decodeFill(el, index, count) { + var model = el._model || {}; + var fill = model.fill; + var target; + + if (fill === undefined) { + fill = !!model.backgroundColor; + } + + if (fill === false || fill === null) { + return false; + } + + if (fill === true) { + return 'origin'; + } + + target = parseFloat(fill, 10); + if (isFinite(target) && Math.floor(target) === target) { + if (fill[0] === '-' || fill[0] === '+') { + target = index + target; + } + + if (target === index || target < 0 || target >= count) { + return false; + } + + return target; + } + + switch (fill) { + // compatibility + case 'bottom': + return 'start'; + case 'top': + return 'end'; + case 'zero': + return 'origin'; + // supported boundaries + case 'origin': + case 'start': + case 'end': + return fill; + // invalid fill values + default: + return false; + } +} + +function computeBoundary(source) { + var model = source.el._model || {}; + var scale = source.el._scale || {}; + var fill = source.fill; + var target = null; + var horizontal; + + if (isFinite(fill)) { + return null; + } + + // Backward compatibility: until v3, we still need to support boundary values set on + // the model (scaleTop, scaleBottom and scaleZero) because some external plugins and + // controllers might still use it (e.g. the Smith chart). + + if (fill === 'start') { + target = model.scaleBottom === undefined ? scale.bottom : model.scaleBottom; + } else if (fill === 'end') { + target = model.scaleTop === undefined ? scale.top : model.scaleTop; + } else if (model.scaleZero !== undefined) { + target = model.scaleZero; + } else if (scale.getBasePosition) { + target = scale.getBasePosition(); + } else if (scale.getBasePixel) { + target = scale.getBasePixel(); + } + + if (target !== undefined && target !== null) { + if (target.x !== undefined && target.y !== undefined) { + return target; + } + + if (helpers$1.isFinite(target)) { + horizontal = scale.isHorizontal(); + return { + x: horizontal ? target : null, + y: horizontal ? null : target + }; + } + } + + return null; +} + +function resolveTarget(sources, index, propagate) { + var source = sources[index]; + var fill = source.fill; + var visited = [index]; + var target; + + if (!propagate) { + return fill; + } + + while (fill !== false && visited.indexOf(fill) === -1) { + if (!isFinite(fill)) { + return fill; + } + + target = sources[fill]; + if (!target) { + return false; + } + + if (target.visible) { + return fill; + } + + visited.push(fill); + fill = target.fill; + } + + return false; +} + +function createMapper(source) { + var fill = source.fill; + var type = 'dataset'; + + if (fill === false) { + return null; + } + + if (!isFinite(fill)) { + type = 'boundary'; + } + + return mappers[type](source); +} + +function isDrawable(point) { + return point && !point.skip; +} + +function drawArea(ctx, curve0, curve1, len0, len1) { + var i; + + if (!len0 || !len1) { + return; + } + + // building first area curve (normal) + ctx.moveTo(curve0[0].x, curve0[0].y); + for (i = 1; i < len0; ++i) { + helpers$1.canvas.lineTo(ctx, curve0[i - 1], curve0[i]); + } + + // joining the two area curves + ctx.lineTo(curve1[len1 - 1].x, curve1[len1 - 1].y); + + // building opposite area curve (reverse) + for (i = len1 - 1; i > 0; --i) { + helpers$1.canvas.lineTo(ctx, curve1[i], curve1[i - 1], true); + } +} + +function doFill(ctx, points, mapper, view, color, loop) { + var count = points.length; + var span = view.spanGaps; + var curve0 = []; + var curve1 = []; + var len0 = 0; + var len1 = 0; + var i, ilen, index, p0, p1, d0, d1; + + ctx.beginPath(); + + for (i = 0, ilen = (count + !!loop); i < ilen; ++i) { + index = i % count; + p0 = points[index]._view; + p1 = mapper(p0, index, view); + d0 = isDrawable(p0); + d1 = isDrawable(p1); + + if (d0 && d1) { + len0 = curve0.push(p0); + len1 = curve1.push(p1); + } else if (len0 && len1) { + if (!span) { + drawArea(ctx, curve0, curve1, len0, len1); + len0 = len1 = 0; + curve0 = []; + curve1 = []; + } else { + if (d0) { + curve0.push(p0); + } + if (d1) { + curve1.push(p1); + } + } + } + } + + drawArea(ctx, curve0, curve1, len0, len1); + + ctx.closePath(); + ctx.fillStyle = color; + ctx.fill(); +} + +var plugin_filler = { + id: 'filler', + + afterDatasetsUpdate: function(chart, options) { + var count = (chart.data.datasets || []).length; + var propagate = options.propagate; + var sources = []; + var meta, i, el, source; + + for (i = 0; i < count; ++i) { + meta = chart.getDatasetMeta(i); + el = meta.dataset; + source = null; + + if (el && el._model && el instanceof elements.Line) { + source = { + visible: chart.isDatasetVisible(i), + fill: decodeFill(el, i, count), + chart: chart, + el: el + }; + } + + meta.$filler = source; + sources.push(source); + } + + for (i = 0; i < count; ++i) { + source = sources[i]; + if (!source) { + continue; + } + + source.fill = resolveTarget(sources, i, propagate); + source.boundary = computeBoundary(source); + source.mapper = createMapper(source); + } + }, + + beforeDatasetDraw: function(chart, args) { + var meta = args.meta.$filler; + if (!meta) { + return; + } + + var ctx = chart.ctx; + var el = meta.el; + var view = el._view; + var points = el._children || []; + var mapper = meta.mapper; + var color = view.backgroundColor || core_defaults.global.defaultColor; + + if (mapper && color && points.length) { + helpers$1.canvas.clipArea(ctx, chart.chartArea); + doFill(ctx, points, mapper, view, color, el._loop); + helpers$1.canvas.unclipArea(ctx); + } + } +}; + +var noop$1 = helpers$1.noop; +var valueOrDefault$d = helpers$1.valueOrDefault; + +core_defaults._set('global', { + legend: { + display: true, + position: 'top', + fullWidth: true, + reverse: false, + weight: 1000, + + // a callback that will handle + onClick: function(e, legendItem) { + var index = legendItem.datasetIndex; + var ci = this.chart; + var meta = ci.getDatasetMeta(index); + + // See controller.isDatasetVisible comment + meta.hidden = meta.hidden === null ? !ci.data.datasets[index].hidden : null; + + // We hid a dataset ... rerender the chart + ci.update(); + }, + + onHover: null, + onLeave: null, + + labels: { + boxWidth: 40, + padding: 10, + // Generates labels shown in the legend + // Valid properties to return: + // text : text to display + // fillStyle : fill of coloured box + // strokeStyle: stroke of coloured box + // hidden : if this legend item refers to a hidden item + // lineCap : cap style for line + // lineDash + // lineDashOffset : + // lineJoin : + // lineWidth : + generateLabels: function(chart) { + var data = chart.data; + return helpers$1.isArray(data.datasets) ? data.datasets.map(function(dataset, i) { + return { + text: dataset.label, + fillStyle: (!helpers$1.isArray(dataset.backgroundColor) ? dataset.backgroundColor : dataset.backgroundColor[0]), + hidden: !chart.isDatasetVisible(i), + lineCap: dataset.borderCapStyle, + lineDash: dataset.borderDash, + lineDashOffset: dataset.borderDashOffset, + lineJoin: dataset.borderJoinStyle, + lineWidth: dataset.borderWidth, + strokeStyle: dataset.borderColor, + pointStyle: dataset.pointStyle, + + // Below is extra data used for toggling the datasets + datasetIndex: i + }; + }, this) : []; + } + } + }, + + legendCallback: function(chart) { + var text = []; + text.push('
    '); + for (var i = 0; i < chart.data.datasets.length; i++) { + text.push('
  • '); + if (chart.data.datasets[i].label) { + text.push(chart.data.datasets[i].label); + } + text.push('
  • '); + } + text.push('
'); + return text.join(''); + } +}); + +/** + * Helper function to get the box width based on the usePointStyle option + * @param {object} labelopts - the label options on the legend + * @param {number} fontSize - the label font size + * @return {number} width of the color box area + */ +function getBoxWidth(labelOpts, fontSize) { + return labelOpts.usePointStyle && labelOpts.boxWidth > fontSize ? + fontSize : + labelOpts.boxWidth; +} + +/** + * IMPORTANT: this class is exposed publicly as Chart.Legend, backward compatibility required! + */ +var Legend = core_element.extend({ + + initialize: function(config) { + helpers$1.extend(this, config); + + // Contains hit boxes for each dataset (in dataset order) + this.legendHitBoxes = []; + + /** + * @private + */ + this._hoveredItem = null; + + // Are we in doughnut mode which has a different data type + this.doughnutMode = false; + }, + + // These methods are ordered by lifecycle. Utilities then follow. + // Any function defined here is inherited by all legend types. + // Any function can be extended by the legend type + + beforeUpdate: noop$1, + update: function(maxWidth, maxHeight, margins) { + var me = this; + + // Update Lifecycle - Probably don't want to ever extend or overwrite this function ;) + me.beforeUpdate(); + + // Absorb the master measurements + me.maxWidth = maxWidth; + me.maxHeight = maxHeight; + me.margins = margins; + + // Dimensions + me.beforeSetDimensions(); + me.setDimensions(); + me.afterSetDimensions(); + // Labels + me.beforeBuildLabels(); + me.buildLabels(); + me.afterBuildLabels(); + + // Fit + me.beforeFit(); + me.fit(); + me.afterFit(); + // + me.afterUpdate(); + + return me.minSize; + }, + afterUpdate: noop$1, + + // + + beforeSetDimensions: noop$1, + setDimensions: function() { + var me = this; + // Set the unconstrained dimension before label rotation + if (me.isHorizontal()) { + // Reset position before calculating rotation + me.width = me.maxWidth; + me.left = 0; + me.right = me.width; + } else { + me.height = me.maxHeight; + + // Reset position before calculating rotation + me.top = 0; + me.bottom = me.height; + } + + // Reset padding + me.paddingLeft = 0; + me.paddingTop = 0; + me.paddingRight = 0; + me.paddingBottom = 0; + + // Reset minSize + me.minSize = { + width: 0, + height: 0 + }; + }, + afterSetDimensions: noop$1, + + // + + beforeBuildLabels: noop$1, + buildLabels: function() { + var me = this; + var labelOpts = me.options.labels || {}; + var legendItems = helpers$1.callback(labelOpts.generateLabels, [me.chart], me) || []; + + if (labelOpts.filter) { + legendItems = legendItems.filter(function(item) { + return labelOpts.filter(item, me.chart.data); + }); + } + + if (me.options.reverse) { + legendItems.reverse(); + } + + me.legendItems = legendItems; + }, + afterBuildLabels: noop$1, + + // + + beforeFit: noop$1, + fit: function() { + var me = this; + var opts = me.options; + var labelOpts = opts.labels; + var display = opts.display; + + var ctx = me.ctx; + + var labelFont = helpers$1.options._parseFont(labelOpts); + var fontSize = labelFont.size; + + // Reset hit boxes + var hitboxes = me.legendHitBoxes = []; + + var minSize = me.minSize; + var isHorizontal = me.isHorizontal(); + + if (isHorizontal) { + minSize.width = me.maxWidth; // fill all the width + minSize.height = display ? 10 : 0; + } else { + minSize.width = display ? 10 : 0; + minSize.height = me.maxHeight; // fill all the height + } + + // Increase sizes here + if (display) { + ctx.font = labelFont.string; + + if (isHorizontal) { + // Labels + + // Width of each line of legend boxes. Labels wrap onto multiple lines when there are too many to fit on one + var lineWidths = me.lineWidths = [0]; + var totalHeight = 0; + + ctx.textAlign = 'left'; + ctx.textBaseline = 'top'; + + helpers$1.each(me.legendItems, function(legendItem, i) { + var boxWidth = getBoxWidth(labelOpts, fontSize); + var width = boxWidth + (fontSize / 2) + ctx.measureText(legendItem.text).width; + + if (i === 0 || lineWidths[lineWidths.length - 1] + width + labelOpts.padding > minSize.width) { + totalHeight += fontSize + labelOpts.padding; + lineWidths[lineWidths.length - (i > 0 ? 0 : 1)] = labelOpts.padding; + } + + // Store the hitbox width and height here. Final position will be updated in `draw` + hitboxes[i] = { + left: 0, + top: 0, + width: width, + height: fontSize + }; + + lineWidths[lineWidths.length - 1] += width + labelOpts.padding; + }); + + minSize.height += totalHeight; + + } else { + var vPadding = labelOpts.padding; + var columnWidths = me.columnWidths = []; + var totalWidth = labelOpts.padding; + var currentColWidth = 0; + var currentColHeight = 0; + var itemHeight = fontSize + vPadding; + + helpers$1.each(me.legendItems, function(legendItem, i) { + var boxWidth = getBoxWidth(labelOpts, fontSize); + var itemWidth = boxWidth + (fontSize / 2) + ctx.measureText(legendItem.text).width; + + // If too tall, go to new column + if (i > 0 && currentColHeight + itemHeight > minSize.height - vPadding) { + totalWidth += currentColWidth + labelOpts.padding; + columnWidths.push(currentColWidth); // previous column width + + currentColWidth = 0; + currentColHeight = 0; + } + + // Get max width + currentColWidth = Math.max(currentColWidth, itemWidth); + currentColHeight += itemHeight; + + // Store the hitbox width and height here. Final position will be updated in `draw` + hitboxes[i] = { + left: 0, + top: 0, + width: itemWidth, + height: fontSize + }; + }); + + totalWidth += currentColWidth; + columnWidths.push(currentColWidth); + minSize.width += totalWidth; + } + } + + me.width = minSize.width; + me.height = minSize.height; + }, + afterFit: noop$1, + + // Shared Methods + isHorizontal: function() { + return this.options.position === 'top' || this.options.position === 'bottom'; + }, + + // Actually draw the legend on the canvas + draw: function() { + var me = this; + var opts = me.options; + var labelOpts = opts.labels; + var globalDefaults = core_defaults.global; + var defaultColor = globalDefaults.defaultColor; + var lineDefault = globalDefaults.elements.line; + var legendWidth = me.width; + var lineWidths = me.lineWidths; + + if (opts.display) { + var ctx = me.ctx; + var fontColor = valueOrDefault$d(labelOpts.fontColor, globalDefaults.defaultFontColor); + var labelFont = helpers$1.options._parseFont(labelOpts); + var fontSize = labelFont.size; + var cursor; + + // Canvas setup + ctx.textAlign = 'left'; + ctx.textBaseline = 'middle'; + ctx.lineWidth = 0.5; + ctx.strokeStyle = fontColor; // for strikethrough effect + ctx.fillStyle = fontColor; // render in correct colour + ctx.font = labelFont.string; + + var boxWidth = getBoxWidth(labelOpts, fontSize); + var hitboxes = me.legendHitBoxes; + + // current position + var drawLegendBox = function(x, y, legendItem) { + if (isNaN(boxWidth) || boxWidth <= 0) { + return; + } + + // Set the ctx for the box + ctx.save(); + + var lineWidth = valueOrDefault$d(legendItem.lineWidth, lineDefault.borderWidth); + ctx.fillStyle = valueOrDefault$d(legendItem.fillStyle, defaultColor); + ctx.lineCap = valueOrDefault$d(legendItem.lineCap, lineDefault.borderCapStyle); + ctx.lineDashOffset = valueOrDefault$d(legendItem.lineDashOffset, lineDefault.borderDashOffset); + ctx.lineJoin = valueOrDefault$d(legendItem.lineJoin, lineDefault.borderJoinStyle); + ctx.lineWidth = lineWidth; + ctx.strokeStyle = valueOrDefault$d(legendItem.strokeStyle, defaultColor); + + if (ctx.setLineDash) { + // IE 9 and 10 do not support line dash + ctx.setLineDash(valueOrDefault$d(legendItem.lineDash, lineDefault.borderDash)); + } + + if (opts.labels && opts.labels.usePointStyle) { + // Recalculate x and y for drawPoint() because its expecting + // x and y to be center of figure (instead of top left) + var radius = boxWidth * Math.SQRT2 / 2; + var centerX = x + boxWidth / 2; + var centerY = y + fontSize / 2; + + // Draw pointStyle as legend symbol + helpers$1.canvas.drawPoint(ctx, legendItem.pointStyle, radius, centerX, centerY); + } else { + // Draw box as legend symbol + if (lineWidth !== 0) { + ctx.strokeRect(x, y, boxWidth, fontSize); + } + ctx.fillRect(x, y, boxWidth, fontSize); + } + + ctx.restore(); + }; + var fillText = function(x, y, legendItem, textWidth) { + var halfFontSize = fontSize / 2; + var xLeft = boxWidth + halfFontSize + x; + var yMiddle = y + halfFontSize; + + ctx.fillText(legendItem.text, xLeft, yMiddle); + + if (legendItem.hidden) { + // Strikethrough the text if hidden + ctx.beginPath(); + ctx.lineWidth = 2; + ctx.moveTo(xLeft, yMiddle); + ctx.lineTo(xLeft + textWidth, yMiddle); + ctx.stroke(); + } + }; + + // Horizontal + var isHorizontal = me.isHorizontal(); + if (isHorizontal) { + cursor = { + x: me.left + ((legendWidth - lineWidths[0]) / 2) + labelOpts.padding, + y: me.top + labelOpts.padding, + line: 0 + }; + } else { + cursor = { + x: me.left + labelOpts.padding, + y: me.top + labelOpts.padding, + line: 0 + }; + } + + var itemHeight = fontSize + labelOpts.padding; + helpers$1.each(me.legendItems, function(legendItem, i) { + var textWidth = ctx.measureText(legendItem.text).width; + var width = boxWidth + (fontSize / 2) + textWidth; + var x = cursor.x; + var y = cursor.y; + + // Use (me.left + me.minSize.width) and (me.top + me.minSize.height) + // instead of me.right and me.bottom because me.width and me.height + // may have been changed since me.minSize was calculated + if (isHorizontal) { + if (i > 0 && x + width + labelOpts.padding > me.left + me.minSize.width) { + y = cursor.y += itemHeight; + cursor.line++; + x = cursor.x = me.left + ((legendWidth - lineWidths[cursor.line]) / 2) + labelOpts.padding; + } + } else if (i > 0 && y + itemHeight > me.top + me.minSize.height) { + x = cursor.x = x + me.columnWidths[cursor.line] + labelOpts.padding; + y = cursor.y = me.top + labelOpts.padding; + cursor.line++; + } + + drawLegendBox(x, y, legendItem); + + hitboxes[i].left = x; + hitboxes[i].top = y; + + // Fill the actual label + fillText(x, y, legendItem, textWidth); + + if (isHorizontal) { + cursor.x += width + labelOpts.padding; + } else { + cursor.y += itemHeight; + } + + }); + } + }, + + /** + * @private + */ + _getLegendItemAt: function(x, y) { + var me = this; + var i, hitBox, lh; + + if (x >= me.left && x <= me.right && y >= me.top && y <= me.bottom) { + // See if we are touching one of the dataset boxes + lh = me.legendHitBoxes; + for (i = 0; i < lh.length; ++i) { + hitBox = lh[i]; + + if (x >= hitBox.left && x <= hitBox.left + hitBox.width && y >= hitBox.top && y <= hitBox.top + hitBox.height) { + // Touching an element + return me.legendItems[i]; + } + } + } + + return null; + }, + + /** + * Handle an event + * @private + * @param {IEvent} event - The event to handle + */ + handleEvent: function(e) { + var me = this; + var opts = me.options; + var type = e.type === 'mouseup' ? 'click' : e.type; + var hoveredItem; + + if (type === 'mousemove') { + if (!opts.onHover && !opts.onLeave) { + return; + } + } else if (type === 'click') { + if (!opts.onClick) { + return; + } + } else { + return; + } + + // Chart event already has relative position in it + hoveredItem = me._getLegendItemAt(e.x, e.y); + + if (type === 'click') { + if (hoveredItem && opts.onClick) { + // use e.native for backwards compatibility + opts.onClick.call(me, e.native, hoveredItem); + } + } else { + if (opts.onLeave && hoveredItem !== me._hoveredItem) { + if (me._hoveredItem) { + opts.onLeave.call(me, e.native, me._hoveredItem); + } + me._hoveredItem = hoveredItem; + } + + if (opts.onHover && hoveredItem) { + // use e.native for backwards compatibility + opts.onHover.call(me, e.native, hoveredItem); + } + } + } +}); + +function createNewLegendAndAttach(chart, legendOpts) { + var legend = new Legend({ + ctx: chart.ctx, + options: legendOpts, + chart: chart + }); + + core_layouts.configure(chart, legend, legendOpts); + core_layouts.addBox(chart, legend); + chart.legend = legend; +} + +var plugin_legend = { + id: 'legend', + + /** + * Backward compatibility: since 2.1.5, the legend is registered as a plugin, making + * Chart.Legend obsolete. To avoid a breaking change, we export the Legend as part of + * the plugin, which one will be re-exposed in the chart.js file. + * https://github.com/chartjs/Chart.js/pull/2640 + * @private + */ + _element: Legend, + + beforeInit: function(chart) { + var legendOpts = chart.options.legend; + + if (legendOpts) { + createNewLegendAndAttach(chart, legendOpts); + } + }, + + beforeUpdate: function(chart) { + var legendOpts = chart.options.legend; + var legend = chart.legend; + + if (legendOpts) { + helpers$1.mergeIf(legendOpts, core_defaults.global.legend); + + if (legend) { + core_layouts.configure(chart, legend, legendOpts); + legend.options = legendOpts; + } else { + createNewLegendAndAttach(chart, legendOpts); + } + } else if (legend) { + core_layouts.removeBox(chart, legend); + delete chart.legend; + } + }, + + afterEvent: function(chart, e) { + var legend = chart.legend; + if (legend) { + legend.handleEvent(e); + } + } +}; + +var noop$2 = helpers$1.noop; + +core_defaults._set('global', { + title: { + display: false, + fontStyle: 'bold', + fullWidth: true, + padding: 10, + position: 'top', + text: '', + weight: 2000 // by default greater than legend (1000) to be above + } +}); + +/** + * IMPORTANT: this class is exposed publicly as Chart.Legend, backward compatibility required! + */ +var Title = core_element.extend({ + initialize: function(config) { + var me = this; + helpers$1.extend(me, config); + + // Contains hit boxes for each dataset (in dataset order) + me.legendHitBoxes = []; + }, + + // These methods are ordered by lifecycle. Utilities then follow. + + beforeUpdate: noop$2, + update: function(maxWidth, maxHeight, margins) { + var me = this; + + // Update Lifecycle - Probably don't want to ever extend or overwrite this function ;) + me.beforeUpdate(); + + // Absorb the master measurements + me.maxWidth = maxWidth; + me.maxHeight = maxHeight; + me.margins = margins; + + // Dimensions + me.beforeSetDimensions(); + me.setDimensions(); + me.afterSetDimensions(); + // Labels + me.beforeBuildLabels(); + me.buildLabels(); + me.afterBuildLabels(); + + // Fit + me.beforeFit(); + me.fit(); + me.afterFit(); + // + me.afterUpdate(); + + return me.minSize; + + }, + afterUpdate: noop$2, + + // + + beforeSetDimensions: noop$2, + setDimensions: function() { + var me = this; + // Set the unconstrained dimension before label rotation + if (me.isHorizontal()) { + // Reset position before calculating rotation + me.width = me.maxWidth; + me.left = 0; + me.right = me.width; + } else { + me.height = me.maxHeight; + + // Reset position before calculating rotation + me.top = 0; + me.bottom = me.height; + } + + // Reset padding + me.paddingLeft = 0; + me.paddingTop = 0; + me.paddingRight = 0; + me.paddingBottom = 0; + + // Reset minSize + me.minSize = { + width: 0, + height: 0 + }; + }, + afterSetDimensions: noop$2, + + // + + beforeBuildLabels: noop$2, + buildLabels: noop$2, + afterBuildLabels: noop$2, + + // + + beforeFit: noop$2, + fit: function() { + var me = this; + var opts = me.options; + var display = opts.display; + var minSize = me.minSize; + var lineCount = helpers$1.isArray(opts.text) ? opts.text.length : 1; + var fontOpts = helpers$1.options._parseFont(opts); + var textSize = display ? (lineCount * fontOpts.lineHeight) + (opts.padding * 2) : 0; + + if (me.isHorizontal()) { + minSize.width = me.maxWidth; // fill all the width + minSize.height = textSize; + } else { + minSize.width = textSize; + minSize.height = me.maxHeight; // fill all the height + } + + me.width = minSize.width; + me.height = minSize.height; + + }, + afterFit: noop$2, + + // Shared Methods + isHorizontal: function() { + var pos = this.options.position; + return pos === 'top' || pos === 'bottom'; + }, + + // Actually draw the title block on the canvas + draw: function() { + var me = this; + var ctx = me.ctx; + var opts = me.options; + + if (opts.display) { + var fontOpts = helpers$1.options._parseFont(opts); + var lineHeight = fontOpts.lineHeight; + var offset = lineHeight / 2 + opts.padding; + var rotation = 0; + var top = me.top; + var left = me.left; + var bottom = me.bottom; + var right = me.right; + var maxWidth, titleX, titleY; + + ctx.fillStyle = helpers$1.valueOrDefault(opts.fontColor, core_defaults.global.defaultFontColor); // render in correct colour + ctx.font = fontOpts.string; + + // Horizontal + if (me.isHorizontal()) { + titleX = left + ((right - left) / 2); // midpoint of the width + titleY = top + offset; + maxWidth = right - left; + } else { + titleX = opts.position === 'left' ? left + offset : right - offset; + titleY = top + ((bottom - top) / 2); + maxWidth = bottom - top; + rotation = Math.PI * (opts.position === 'left' ? -0.5 : 0.5); + } + + ctx.save(); + ctx.translate(titleX, titleY); + ctx.rotate(rotation); + ctx.textAlign = 'center'; + ctx.textBaseline = 'middle'; + + var text = opts.text; + if (helpers$1.isArray(text)) { + var y = 0; + for (var i = 0; i < text.length; ++i) { + ctx.fillText(text[i], 0, y, maxWidth); + y += lineHeight; + } + } else { + ctx.fillText(text, 0, 0, maxWidth); + } + + ctx.restore(); + } + } +}); + +function createNewTitleBlockAndAttach(chart, titleOpts) { + var title = new Title({ + ctx: chart.ctx, + options: titleOpts, + chart: chart + }); + + core_layouts.configure(chart, title, titleOpts); + core_layouts.addBox(chart, title); + chart.titleBlock = title; +} + +var plugin_title = { + id: 'title', + + /** + * Backward compatibility: since 2.1.5, the title is registered as a plugin, making + * Chart.Title obsolete. To avoid a breaking change, we export the Title as part of + * the plugin, which one will be re-exposed in the chart.js file. + * https://github.com/chartjs/Chart.js/pull/2640 + * @private + */ + _element: Title, + + beforeInit: function(chart) { + var titleOpts = chart.options.title; + + if (titleOpts) { + createNewTitleBlockAndAttach(chart, titleOpts); + } + }, + + beforeUpdate: function(chart) { + var titleOpts = chart.options.title; + var titleBlock = chart.titleBlock; + + if (titleOpts) { + helpers$1.mergeIf(titleOpts, core_defaults.global.title); + + if (titleBlock) { + core_layouts.configure(chart, titleBlock, titleOpts); + titleBlock.options = titleOpts; + } else { + createNewTitleBlockAndAttach(chart, titleOpts); + } + } else if (titleBlock) { + core_layouts.removeBox(chart, titleBlock); + delete chart.titleBlock; + } + } +}; + +var plugins = {}; +var filler = plugin_filler; +var legend = plugin_legend; +var title = plugin_title; +plugins.filler = filler; +plugins.legend = legend; +plugins.title = title; + +/** + * @namespace Chart + */ + + +core_controller.helpers = helpers$1; + +// @todo dispatch these helpers into appropriated helpers/helpers.* file and write unit tests! +core_helpers(core_controller); + +core_controller._adapters = core_adapters; +core_controller.Animation = core_animation; +core_controller.animationService = core_animations; +core_controller.controllers = controllers; +core_controller.DatasetController = core_datasetController; +core_controller.defaults = core_defaults; +core_controller.Element = core_element; +core_controller.elements = elements; +core_controller.Interaction = core_interaction; +core_controller.layouts = core_layouts; +core_controller.platform = platform; +core_controller.plugins = core_plugins; +core_controller.Scale = core_scale; +core_controller.scaleService = core_scaleService; +core_controller.Ticks = core_ticks; +core_controller.Tooltip = core_tooltip; + +// Register built-in scales + +core_controller.helpers.each(scales, function(scale, type) { + core_controller.scaleService.registerScaleType(type, scale, scale._defaults); +}); + +// Load to register built-in adapters (as side effects) + + +// Loading built-in plugins + +for (var k in plugins) { + if (plugins.hasOwnProperty(k)) { + core_controller.plugins.register(plugins[k]); + } +} + +core_controller.platform.initialize(); + +var src = core_controller; +if (typeof window !== 'undefined') { + window.Chart = core_controller; +} + +// DEPRECATIONS + +/** + * Provided for backward compatibility, not available anymore + * @namespace Chart.Chart + * @deprecated since version 2.8.0 + * @todo remove at version 3 + * @private + */ +core_controller.Chart = core_controller; + +/** + * Provided for backward compatibility, not available anymore + * @namespace Chart.Legend + * @deprecated since version 2.1.5 + * @todo remove at version 3 + * @private + */ +core_controller.Legend = plugins.legend._element; + +/** + * Provided for backward compatibility, not available anymore + * @namespace Chart.Title + * @deprecated since version 2.1.5 + * @todo remove at version 3 + * @private + */ +core_controller.Title = plugins.title._element; + +/** + * Provided for backward compatibility, use Chart.plugins instead + * @namespace Chart.pluginService + * @deprecated since version 2.1.5 + * @todo remove at version 3 + * @private + */ +core_controller.pluginService = core_controller.plugins; + +/** + * Provided for backward compatibility, inheriting from Chart.PlugingBase has no + * effect, instead simply create/register plugins via plain JavaScript objects. + * @interface Chart.PluginBase + * @deprecated since version 2.5.0 + * @todo remove at version 3 + * @private + */ +core_controller.PluginBase = core_controller.Element.extend({}); + +/** + * Provided for backward compatibility, use Chart.helpers.canvas instead. + * @namespace Chart.canvasHelpers + * @deprecated since version 2.6.0 + * @todo remove at version 3 + * @private + */ +core_controller.canvasHelpers = core_controller.helpers.canvas; + +/** + * Provided for backward compatibility, use Chart.layouts instead. + * @namespace Chart.layoutService + * @deprecated since version 2.7.3 + * @todo remove at version 3 + * @private + */ +core_controller.layoutService = core_controller.layouts; + +/** + * Provided for backward compatibility, not available anymore. + * @namespace Chart.LinearScaleBase + * @deprecated since version 2.8 + * @todo remove at version 3 + * @private + */ +core_controller.LinearScaleBase = scale_linearbase; + +/** + * Provided for backward compatibility, instead we should create a new Chart + * by setting the type in the config (`new Chart(id, {type: '{chart-type}'}`). + * @deprecated since version 2.8.0 + * @todo remove at version 3 + */ +core_controller.helpers.each( + [ + 'Bar', + 'Bubble', + 'Doughnut', + 'Line', + 'PolarArea', + 'Radar', + 'Scatter' + ], + function(klass) { + core_controller[klass] = function(ctx, cfg) { + return new core_controller(ctx, core_controller.helpers.merge(cfg || {}, { + type: klass.charAt(0).toLowerCase() + klass.slice(1) + })); + }; + } +); + +return src; + +}))); \ No newline at end of file diff --git a/packers_and_movers_management/static/src/js/website_page.js b/packers_and_movers_management/static/src/js/website_page.js new file mode 100644 index 000000000..01cc4d6b0 --- /dev/null +++ b/packers_and_movers_management/static/src/js/website_page.js @@ -0,0 +1,57 @@ +odoo.define('packers_and_movers_management.website_page', function (require) { + 'use strict'; + var publicWidget = require('web.public.widget'); + var ajax = require('web.ajax'); + var Dialog = require('web.Dialog'); + publicWidget.registry.PackersAndMoversWidget = publicWidget.Widget.extend({ + //Extends the publicWidget.Widget class to hide and show the button and calculate the distance between locations. + selector: '.packers-and-movers-widget', + events: { + 'click #check': '_onCheckClick', + 'click #next': '_onNextClick', + 'click #country_id': '_onCountryClick', + }, + _onCheckClick: function(ev) {//Click function to fetch from and to location value and calculate the distance. + var self = this + var from_location = this.el.querySelector('#from').value + var to_location = this.el.querySelector('#to').value + if (from_location!='' && to_location!='') + { + this.el.querySelector('#loader').classList.remove("d-none"); + ajax.jsonRpc('/geo/' + from_location + '/' + to_location, 'call', { + }).then(function (data) { // success callback + self.$('#distance').val(data); + self.el.querySelector('#loader').classList.add("d-none"); + self.el.querySelector('#details').classList.remove("d-none"); + }).catch(function (data) { + self.el.querySelector('#loader').classList.add("d-none"); + Dialog.alert(this, "Please enter valid city"); + return false; + }); + } + else + { + Dialog.alert(this, "Add Pickup city and drop City"); + return false; + } + }, + _onNextClick: function (ev) {//Function to show the customer details form view + this.el.querySelector('#customer').classList.remove("d-none"); + }, + _onCountryClick: function(ev){ //Function to show the states of selected country only + var self = this; + var countryId = this.$('#country_id').val(); + ajax.jsonRpc('/get_states/' + countryId, 'call', {}) + .then(function (data) { + var stateSelect = self.$('#state_id'); + stateSelect.empty(); // Clear existing options + // Add new options based on the received data + data.forEach(function (state) { + var option = $('

{D=i7)LVkvdlEt8+!NSbE2*=tLTNx8O7+IbSR@i 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 T#l`aAW&bN9_LB#B0ABewZd}MJ literal 0 HcmV?d00001 diff --git a/packers_and_movers_management/static/src/img/order_track.jpg b/packers_and_movers_management/static/src/img/order_track.jpg new file mode 100644 index 0000000000000000000000000000000000000000..fe23454443daa938bf6791c44d035ac4c91bf4a9 GIT binary patch literal 91031 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 S{WP4uxG1vw(<|WX@c#j=UjQor literal 0 HcmV?d00001 diff --git a/packers_and_movers_management/static/src/js/dashboard_action.js b/packers_and_movers_management/static/src/js/dashboard_action.js new file mode 100644 index 000000000..2875a2da6 --- /dev/null +++ b/packers_and_movers_management/static/src/js/dashboard_action.js @@ -0,0 +1,798 @@ +/** @odoo-module */ +import { loadBundle } from "@web/core/assets"; +var AbstractAction = require('web.AbstractAction'); +var ajax = require('web.ajax'); +var core = require('web.core'); +var QWeb = core.qweb; +var rpc = require('web.rpc'); +var CustomDashBoard = AbstractAction.extend({ +// Extended abstract class to create dashboard + template: 'CustomDashBoard', + events: { + 'change #stock_selection': function(e) { + e.stopPropagation(); + var value = $(e.target).val(); + if (value=="year"){ + this.onclick_this_year(value); + }else if (value=="day"){ + this.onclick_this_day(value); + }else if (value=="month"){ + this.onclick_this_month(value); + }else if (value=="week"){ + this.onclick_this_week(value); + } + }, + }, + init: function(parent, context) { + //Function to Initializes all the values while loading the file + this._super(parent, context); + this.dashboards_templates = ['DashboardTruckBooking']; + this.booking_count = [] + this.distance_count = [] + this.total_invoice = [] + this.total_amount = [] + }, + willStart: function() {// Returns the function fetch_data when page load. + var self = this; + return Promise.all([ajax.loadLibs(this), this._super()]).then(function() { + return self.fetch_data(); + }); + }, + start: function() { + //Fetch data and return render_dashboards and render_graph function + self = this; + this.set("title", 'Dashboard'); + return this._super().then(function() { + self.render_dashboards(); + self.render_graph(); + }); + }, + render_dashboards: function() {//Return value to show in tile. + self = this; + _.each(this.dashboards_templates, function(template) { + self.$('.o_pj_dashboard').append(QWeb.render(template, {widget: self})); + }); + }, + fetch_data: function() { + //Function to call rpc query to fetch data fom python + self = this; + var def1 = this._rpc({ + model: 'truck.booking', + method: 'get_total_booking' + }).then(function(result) + { + self.booking_count = result.total_booking, + self.distance_count = result.total_distance_count, + self.total_invoice = result.total_invoice + self.total_amount = result.total_amount + }); + var def2 = this._rpc({ + model: 'truck.booking', + method: 'get_top_truck' + }).then(function(result) + { + self.truck = result['truck'] + self.customer = result['customer'] + self.upcoming = result['upcoming'] + }); + return $.when(def1,def2); + }, + render_graph: function(){//Add function to load in dashboard. + this.render_booking(); + this.render_truck(); + this.render_distance(); + this.render_weight(); + }, + render_booking:function(){ + //Function to add booking chart on the basis of customer + rpc.query({ + model: "truck.booking", + method: "get_booking_analysis", + }).then(function (result) { + new Chart(self.$("#booking"), { + type: 'bar', + data: { + labels: result.name, + datasets: [{ + label: 'Count', + data: result.count, + backgroundColor: [ + "#003f5c", + "#2f4b7c", + "#f95d6a", + "#665191", + "#d45087", + "#ff7c43", + "#ffa600", + "#a05195", + "#6d5c16", + "#CCCCFF" + + ], + borderColor: [ + "#003f5c", + "#2f4b7c", + "#f95d6a", + "#665191", + "#d45087", + "#ff7c43", + "#ffa600", + "#a05195", + "#6d5c16", + "#CCCCFF" + ], + barPercentage: 0.5, + barThickness: 6, + maxBarThickness: 8, + minBarLength: 0, + borderWidth: 1, + type: 'bar', + fill: false + }] + }, + options: { + scales: { + y: { + beginAtZero: true + }, + }, + } + }); + }); + }, + render_truck:function(){ + //Function to add booking chart on the basis of truck + rpc.query({ + model: "truck.booking", + method: "get_truck_analysis", + }).then(function (result) { + new Chart(self.$("#truck"), { + type: 'doughnut', + data: { + labels: result.name, + datasets: [{ + label: 'Count', + data: result.count, + backgroundColor: [ + "#665191", + "#ff7c43", + "#ffa600", + "#d45087", + "#a05195", + "#6d5c16", + "#CCCCFF", + "#003f5c", + "#2f4b7c", + "#f95d6a", + + ], + borderColor: [ + "#003f5c", + "#2f4b7c", + "#f95d6a", + "#665191", + "#d45087", + "#ff7c43", + "#ffa600", + "#a05195", + "#6d5c16", + "#CCCCFF" + ], + barPercentage: 0.5, + barThickness: 6, + maxBarThickness: 8, + minBarLength: 0, + borderWidth: 1, + type: 'pie', + fill: false + }] + }, + options: { + scales: { + y: { + beginAtZero: true + }, + }, + } + }); + }); + }, + render_distance:function(){ + //Function to add total distance chart on the basis of customer and truck + rpc.query({ + model: "truck.booking", + method: "get_distance", + }).then(function (result) { + new Chart(self.$("#cust_distance"), { + type: 'doughnut', + data: { + labels: result.cust, + datasets: [{ + label: 'Count', + data: result.cust_sum, + backgroundColor: [ + "#665191", + "#ff7c43", + "#ffa600", + "#d45087", + "#a05195", + "#6d5c16", + "#CCCCFF", + "#003f5c", + "#2f4b7c", + "#f95d6a", + + ], + borderColor: [ + "#003f5c", + "#2f4b7c", + "#f95d6a", + "#665191", + "#d45087", + "#ff7c43", + "#ffa600", + "#a05195", + "#6d5c16", + "#CCCCFF" + ], + barPercentage: 0.5, + barThickness: 6, + maxBarThickness: 8, + minBarLength: 0, + borderWidth: 1, + type: 'pie', + fill: false + }] + }, + options: { + scales: { + y: { + beginAtZero: true + }, + }, + } + }); + new Chart(self.$("#truck_distance"), { + type: 'line', + data: { + labels: result.truck_name,//x axis + datasets: [{ + label: 'count', // Name the series + data: result.truck_sum, + backgroundColor: '#003f5c', + borderColor: '#003f5c', + barPercentage: 0.5, + barThickness: 6, + maxBarThickness: 8, + minBarLength: 0, + borderWidth: 1, // Specify bar border width + type: 'line', // Set this data to a line chart + fill: false + }] + }, + options: { + scales: { + y: { + beginAtZero: true + }, + }, + } + }); + }); + }, + render_weight:function(){ + //Function to add total goods weight chart on the basis of customer and truck + rpc.query({ + model: "truck.booking", + method: "get_weight", + }).then(function (result) { + new Chart(self.$("#cust_weight"), { + type: 'line', + data: { + labels: result.cust,//x axis + datasets: [{ + label: 'count', // Name the series + data: result.cust_sum, + backgroundColor: '#003f5c', + borderColor: '#003f5c', + barPercentage: 0.5, + barThickness: 6, + maxBarThickness: 8, + minBarLength: 0, + borderWidth: 1, // Specify bar border width + type: 'line', // Set this data to a line chart + fill: false + }] + }, + options: { + scales: { + y: { + beginAtZero: true + }, + }, + } + }); + new Chart(self.$("#truck_weight"), { + type: 'bar', + data: { + labels: result.truck_name, + datasets: [{ + label: 'Count', + data: result.truck_sum, + backgroundColor: [ + "#003f5c", + "#2f4b7c", + "#f95d6a", + "#665191", + "#d45087", + "#ff7c43", + "#ffa600", + "#a05195", + "#6d5c16", + "#CCCCFF" + + ], + borderColor: [ + "#003f5c", + "#2f4b7c", + "#f95d6a", + "#665191", + "#d45087", + "#ff7c43", + "#ffa600", + "#a05195", + "#6d5c16", + "#CCCCFF" + ], + barPercentage: 0.5, + barThickness: 6, + maxBarThickness: 8, + minBarLength: 0, + borderWidth: 1, + type: 'bar', + fill: false + }] + }, + options: { + scales: { + y: { + beginAtZero: true + }, + }, + } + }); + + }); + }, + onclick_this_year: function (ev) {//Function shows a year filtered dashboard + self = this; + rpc.query({ + model: 'truck.booking', + method: 'get_select_filter', + args: [ev], + }) + .then(function (result) { + self.$('#booking_this_day').hide(); + self.$('#distance_this_day').hide(); + self.$('#amount_this_day').hide(); + self.$('#invoice_this_day').hide(); + self.$('#booking_this_month').hide(); + self.$('#distance_this_month').hide(); + self.$('#amount_this_month').hide(); + self.$('#invoice_this_month').hide(); + self.$('#booking_this_week').hide(); + self.$('#distance_this_week').hide(); + self.$('#amount_this_week').hide(); + self.$('#invoice_this_week').hide(); + self.$('.total').hide(); + self.$('#booking_this_year').show(); + self.$('#distance_this_year').show(); + self.$('#amount_this_year').show(); + self.$('#invoice_this_year').show(); + self.$('#booking_this_year').empty(); + self.$('#distance_this_year').empty(); + self.$('#amount_this_year').empty(); + self.$('#invoice_this_year').empty(); + self.$('#booking_this_year').append('' + result['booking'][0]['count'] + ''); + self.$('#distance_this_year').append('' + result['distance'][0]['sum'] + ''); + self.$('#amount_this_year').append('' + result['amount'][0]['sum'] + ''); + self.$('#invoice_this_year').append('' + result['invoice'][0]['sum'] + ''); + self.get_cust_invoice(result); + self.get_truck_invoice(result); + self.get_cust_distance(result); + self.get_truc_distance(result); + self.get_cust_weight(result); + self.get_truck_weight(result); + }) + }, + onclick_this_day: function (ev) {//Function shows day filtered dashboard. + self = this; + rpc.query({ + model: 'truck.booking', + method: 'get_select_filter', + args: [ev], + }) + .then(function (result) { + self.$('.total').hide(); + self.$('#booking_this_month').hide(); + self.$('#distance_this_month').hide(); + self.$('#amount_this_month').hide(); + self.$('#invoice_this_month').hide(); + self.$('#booking_this_week').hide(); + self.$('#distance_this_week').hide(); + self.$('#amount_this_week').hide(); + self.$('#invoice_this_week').hide(); + self.$('#booking_this_year').hide(); + self.$('#distance_this_year').hide(); + self.$('#amount_this_year').hide(); + self.$('#invoice_this_year').hide(); + self.$('#booking_this_day').show(); + self.$('#distance_this_day').show(); + self.$('#amount_this_day').show(); + self.$('#invoice_this_day').show(); + self.$('#booking_this_day').empty(); + self.$('#distance_this_day').empty(); + self.$('#amount_this_day').empty(); + self.$('#invoice_this_day').empty(); + self.$('#booking_this_day').append('' + result['booking'][0]['count'] + ''); + self.$('#distance_this_day').append('' + result['distance'][0]['sum'] + ''); + self.$('#amount_this_day').append('' + result['amount'][0]['sum'] + ''); + self.$('#invoice_this_day').append('' + result['invoice'][0]['sum'] + ''); + self.get_cust_invoice(result); + self.get_truck_invoice(result); + self.get_cust_distance(result); + self.get_truc_distance(result); + self.get_cust_weight(result); + self.get_truck_weight(result); + }) + }, + onclick_this_week: function (ev) {//Function shows week filtered dashboard. + self = this; + rpc.query({ + model: 'truck.booking', + method: 'get_select_filter', + args: [ev], + }) + .then(function (result) { + + self.$('.total').hide(); + self.$('#booking_this_month').hide(); + self.$('#distance_this_month').hide(); + self.$('#amount_this_month').hide(); + self.$('#invoice_this_month').hide(); + self.$('#booking_this_year').hide(); + self.$('#distance_this_year').hide(); + self.$('#amount_this_year').hide(); + self.$('#invoice_this_year').hide(); + self.$('#booking_this_day').hide(); + self.$('#distance_this_day').hide(); + self.$('#amount_this_day').hide(); + self.$('#invoice_this_day').hide(); + + self.$('#booking_this_week').show(); + self.$('#distance_this_week').show(); + self.$('#amount_this_week').show(); + self.$('#invoice_this_week').show(); + + self.$('#booking_this_week').empty(); + self.$('#distance_this_week').empty(); + self.$('#amount_this_week').empty(); + self.$('#invoice_this_week').empty(); + + self.$('#booking_this_week').append('' + result['booking'][0]['count'] + ''); + self.$('#distance_this_week').append('' + result['distance'][0]['sum'] + ''); + self.$('#amount_this_week').append('' + result['amount'][0]['sum'] + ''); + self.$('#invoice_this_week').append('' + result['invoice'][0]['sum'] + ''); + self.get_cust_invoice(result); + self.get_truck_invoice(result); + self.get_cust_distance(result); + self.get_truc_distance(result); + self.get_cust_weight(result); + self.get_truck_weight(result); + }) + }, + onclick_this_month: function (ev) {//Function shows month filtered dashboard. + self = this; + rpc.query({ + model: 'truck.booking', + method: 'get_select_filter', + args: [ev], + }) + .then(function (result) { + self.$('.total').hide(); + self.$('#booking_this_year').hide(); + self.$('#distance_this_year').hide(); + self.$('#amount_this_year').hide(); + self.$('#invoice_this_year').hide(); + self.$('#booking_this_day').hide(); + self.$('#distance_this_day').hide(); + self.$('#amount_this_day').hide(); + self.$('#invoice_this_day').hide(); + self.$('#booking_this_week').hide(); + self.$('#distance_this_week').hide(); + self.$('#amount_this_week').hide(); + self.$('#invoice_this_week').hide(); + self.$('#booking_this_month').show(); + self.$('#distance_this_month').show(); + self.$('#amount_this_month').show(); + self.$('#invoice_this_month').show(); + self.$('#booking_this_month').empty(); + self.$('#distance_this_month').empty(); + self.$('#amount_this_month').empty(); + self.$('#invoice_this_month').empty(); + self.$('#booking_this_month').append('' + result['booking'][0]['count'] + ''); + self.$('#distance_this_month').append('' + result['distance'][0]['sum'] + ''); + self.$('#amount_this_month').append('' + result['amount'][0]['sum'] + ''); + self.$('#invoice_this_month').append('' + result['invoice'][0]['sum'] + ''); + self.get_cust_invoice(result); + self.get_truck_invoice(result); + self.get_cust_distance(result); + self.get_truc_distance(result); + self.get_cust_weight(result); + self.get_truck_weight(result); + }) + }, + get_cust_invoice: function (result) { + //Function to create a chart which shows the total invoice according to the customer + new Chart(self.$("#booking"), { + type: 'bar', + data: { + labels: result.cust_invoice_name, + datasets: [{ + label: 'Count', + data: result.cust_invoice_sum, + backgroundColor: [ + "#003f5c", + "#2f4b7c", + "#f95d6a", + "#665191", + "#d45087", + "#ff7c43", + "#ffa600", + "#a05195", + "#6d5c16", + "#CCCCFF" + + ], + borderColor: [ + "#003f5c", + "#2f4b7c", + "#f95d6a", + "#665191", + "#d45087", + "#ff7c43", + "#ffa600", + "#a05195", + "#6d5c16", + "#CCCCFF" + ], + barPercentage: 0.5, + barThickness: 6, + maxBarThickness: 8, + minBarLength: 0, + borderWidth: 1, + type: 'bar', + fill: false + }] + }, + options: { + scales: { + y: { + beginAtZero: true + }, + }, + } + }); + }, + get_truck_invoice: function (result){//Function to create a chart which shows the total invoice according to the truck. + new Chart(self.$("#truck"), { + type: 'doughnut', + data: { + labels: result.truck_invoice_name, + datasets: [{ + label: 'Count', + data: result.truck_invoice_count, + backgroundColor: [ + "#665191", + "#ff7c43", + "#ffa600", + "#d45087", + "#a05195", + "#6d5c16", + "#CCCCFF", + "#003f5c", + "#2f4b7c", + "#f95d6a", + + ], + borderColor: [ + "#003f5c", + "#2f4b7c", + "#f95d6a", + "#665191", + "#d45087", + "#ff7c43", + "#ffa600", + "#a05195", + "#6d5c16", + "#CCCCFF" + ], + barPercentage: 0.5, + barThickness: 6, + maxBarThickness: 8, + minBarLength: 0, + borderWidth: 1, + type: 'pie', + fill: false + }] + }, + options: { + scales: { + y: { + beginAtZero: true + }, + }, + } + }); + }, + get_cust_distance: function (result){//Function to create a graph which shows the distance according to the customer + new Chart(self.$("#cust_distance"), { + type: 'doughnut', + data: { + labels: result.cust_distance_name, + datasets: [{ + label: 'Count', + data: result.cust_distance_count, + backgroundColor: [ + "#665191", + "#ff7c43", + "#ffa600", + "#d45087", + "#a05195", + "#6d5c16", + "#CCCCFF", + "#003f5c", + "#2f4b7c", + "#f95d6a", + + ], + borderColor: [ + "#003f5c", + "#2f4b7c", + "#f95d6a", + "#665191", + "#d45087", + "#ff7c43", + "#ffa600", + "#a05195", + "#6d5c16", + "#CCCCFF" + ], + barPercentage: 0.5, + barThickness: 6, + maxBarThickness: 8, + minBarLength: 0, + borderWidth: 1, + type: 'pie', + fill: false + }] + }, + options: { + scales: { + y: { + beginAtZero: true + }, + }, + } + }); + }, + get_truc_distance: function (result){//Function to create a graph which shows the distance according to the truck + new Chart(self.$("#truck_distance"), { + type: 'line', + data: { + labels: result.truck_distance_name,//x axis + datasets: [{ + label: 'count', // Name the series + data: result.truck_distance_count, // Specify the data values array + backgroundColor: '#003f5c', + borderColor: '#003f5c', + barPercentage: 0.5, + barThickness: 6, + maxBarThickness: 8, + minBarLength: 0, + borderWidth: 1, // Specify bar border width + type: 'line', // Set this data to a line chart + fill: false + }] + }, + options: { + scales: { + y: { + beginAtZero: true + }, + }, + } + }); + }, + get_cust_weight: function (result){//Function to create a chart which shows the total goods weight according to the customer + new Chart(self.$("#cust_weight"), { + type: 'line', + data: { + labels: result.cust_weight_name,//x axis + datasets: [{ + label: 'count', // Name the series + data: result.cust_weight_count, // Specify the data values array + backgroundColor: '#003f5c', + borderColor: '#003f5c', + barPercentage: 0.5, + barThickness: 6, + maxBarThickness: 8, + minBarLength: 0, + borderWidth: 1, // Specify bar border width + type: 'line', // Set this data to a line chart + fill: false + }] + }, + options: { + scales: { + y: { + beginAtZero: true + }, + }, + } + }); + }, + get_truck_weight: function (result){//Function to create a chart which shows the total goods weight according to the truck + new Chart(self.$("#truck_weight"), { + type: 'bar', + data: { + labels: result.truck_weight_name, + datasets: [{ + label: 'Count', + data: result.truck_weight_count, + backgroundColor: [ + "#003f5c", + "#2f4b7c", + "#f95d6a", + "#665191", + "#d45087", + "#ff7c43", + "#ffa600", + "#a05195", + "#6d5c16", + "#CCCCFF" + + ], + borderColor: [ + "#003f5c", + "#2f4b7c", + "#f95d6a", + "#665191", + "#d45087", + "#ff7c43", + "#ffa600", + "#a05195", + "#6d5c16", + "#CCCCFF" + ], + barPercentage: 0.5, + barThickness: 6, + maxBarThickness: 8, + minBarLength: 0, + borderWidth: 1, + type: 'bar', + fill: false + }] + }, + options: { + scales: { + y: { + beginAtZero: true + }, + }, + } + }); + }, +}) +core.action_registry.add('dashboard_tags', CustomDashBoard); +return CustomDashBoard; diff --git a/packers_and_movers_management/static/src/js/lib/chart_bundle.js b/packers_and_movers_management/static/src/js/lib/chart_bundle.js new file mode 100644 index 000000000..3633f095a --- /dev/null +++ b/packers_and_movers_management/static/src/js/lib/chart_bundle.js @@ -0,0 +1,19287 @@ +/*! + * Chart.js v2.8.0 + * https://www.chartjs.org + * (c) 2019 Chart.js Contributors + * Released under the MIT License + */ +(function (global, factory) { +typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : +typeof define === 'function' && define.amd ? define(factory) : +(global.Chart = factory()); +}(this, (function () { 'use strict'; + +/* MIT license */ + +var conversions = { + rgb2hsl: rgb2hsl, + rgb2hsv: rgb2hsv, + rgb2hwb: rgb2hwb, + rgb2cmyk: rgb2cmyk, + rgb2keyword: rgb2keyword, + rgb2xyz: rgb2xyz, + rgb2lab: rgb2lab, + rgb2lch: rgb2lch, + + hsl2rgb: hsl2rgb, + hsl2hsv: hsl2hsv, + hsl2hwb: hsl2hwb, + hsl2cmyk: hsl2cmyk, + hsl2keyword: hsl2keyword, + + hsv2rgb: hsv2rgb, + hsv2hsl: hsv2hsl, + hsv2hwb: hsv2hwb, + hsv2cmyk: hsv2cmyk, + hsv2keyword: hsv2keyword, + + hwb2rgb: hwb2rgb, + hwb2hsl: hwb2hsl, + hwb2hsv: hwb2hsv, + hwb2cmyk: hwb2cmyk, + hwb2keyword: hwb2keyword, + + cmyk2rgb: cmyk2rgb, + cmyk2hsl: cmyk2hsl, + cmyk2hsv: cmyk2hsv, + cmyk2hwb: cmyk2hwb, + cmyk2keyword: cmyk2keyword, + + keyword2rgb: keyword2rgb, + keyword2hsl: keyword2hsl, + keyword2hsv: keyword2hsv, + keyword2hwb: keyword2hwb, + keyword2cmyk: keyword2cmyk, + keyword2lab: keyword2lab, + keyword2xyz: keyword2xyz, + + xyz2rgb: xyz2rgb, + xyz2lab: xyz2lab, + xyz2lch: xyz2lch, + + lab2xyz: lab2xyz, + lab2rgb: lab2rgb, + lab2lch: lab2lch, + + lch2lab: lch2lab, + lch2xyz: lch2xyz, + lch2rgb: lch2rgb +}; + + +function rgb2hsl(rgb) { + var r = rgb[0]/255, + g = rgb[1]/255, + b = rgb[2]/255, + min = Math.min(r, g, b), + max = Math.max(r, g, b), + delta = max - min, + h, s, l; + + if (max == min) + h = 0; + else if (r == max) + h = (g - b) / delta; + else if (g == max) + h = 2 + (b - r) / delta; + else if (b == max) + h = 4 + (r - g)/ delta; + + h = Math.min(h * 60, 360); + + if (h < 0) + h += 360; + + l = (min + max) / 2; + + if (max == min) + s = 0; + else if (l <= 0.5) + s = delta / (max + min); + else + s = delta / (2 - max - min); + + return [h, s * 100, l * 100]; +} + +function rgb2hsv(rgb) { + var r = rgb[0], + g = rgb[1], + b = rgb[2], + min = Math.min(r, g, b), + max = Math.max(r, g, b), + delta = max - min, + h, s, v; + + if (max == 0) + s = 0; + else + s = (delta/max * 1000)/10; + + if (max == min) + h = 0; + else if (r == max) + h = (g - b) / delta; + else if (g == max) + h = 2 + (b - r) / delta; + else if (b == max) + h = 4 + (r - g) / delta; + + h = Math.min(h * 60, 360); + + if (h < 0) + h += 360; + + v = ((max / 255) * 1000) / 10; + + return [h, s, v]; +} + +function rgb2hwb(rgb) { + var r = rgb[0], + g = rgb[1], + b = rgb[2], + h = rgb2hsl(rgb)[0], + w = 1/255 * Math.min(r, Math.min(g, b)), + b = 1 - 1/255 * Math.max(r, Math.max(g, b)); + + return [h, w * 100, b * 100]; +} + +function rgb2cmyk(rgb) { + var r = rgb[0] / 255, + g = rgb[1] / 255, + b = rgb[2] / 255, + c, m, y, k; + + k = Math.min(1 - r, 1 - g, 1 - b); + c = (1 - r - k) / (1 - k) || 0; + m = (1 - g - k) / (1 - k) || 0; + y = (1 - b - k) / (1 - k) || 0; + return [c * 100, m * 100, y * 100, k * 100]; +} + +function rgb2keyword(rgb) { + return reverseKeywords[JSON.stringify(rgb)]; +} + +function rgb2xyz(rgb) { + var r = rgb[0] / 255, + g = rgb[1] / 255, + b = rgb[2] / 255; + + // assume sRGB + r = r > 0.04045 ? Math.pow(((r + 0.055) / 1.055), 2.4) : (r / 12.92); + g = g > 0.04045 ? Math.pow(((g + 0.055) / 1.055), 2.4) : (g / 12.92); + b = b > 0.04045 ? Math.pow(((b + 0.055) / 1.055), 2.4) : (b / 12.92); + + var x = (r * 0.4124) + (g * 0.3576) + (b * 0.1805); + var y = (r * 0.2126) + (g * 0.7152) + (b * 0.0722); + var z = (r * 0.0193) + (g * 0.1192) + (b * 0.9505); + + return [x * 100, y *100, z * 100]; +} + +function rgb2lab(rgb) { + var xyz = rgb2xyz(rgb), + x = xyz[0], + y = xyz[1], + z = xyz[2], + l, a, b; + + x /= 95.047; + y /= 100; + z /= 108.883; + + x = x > 0.008856 ? Math.pow(x, 1/3) : (7.787 * x) + (16 / 116); + y = y > 0.008856 ? Math.pow(y, 1/3) : (7.787 * y) + (16 / 116); + z = z > 0.008856 ? Math.pow(z, 1/3) : (7.787 * z) + (16 / 116); + + l = (116 * y) - 16; + a = 500 * (x - y); + b = 200 * (y - z); + + return [l, a, b]; +} + +function rgb2lch(args) { + return lab2lch(rgb2lab(args)); +} + +function hsl2rgb(hsl) { + var h = hsl[0] / 360, + s = hsl[1] / 100, + l = hsl[2] / 100, + t1, t2, t3, rgb, val; + + if (s == 0) { + val = l * 255; + return [val, val, val]; + } + + if (l < 0.5) + t2 = l * (1 + s); + else + t2 = l + s - l * s; + t1 = 2 * l - t2; + + rgb = [0, 0, 0]; + for (var i = 0; i < 3; i++) { + t3 = h + 1 / 3 * - (i - 1); + t3 < 0 && t3++; + t3 > 1 && t3--; + + if (6 * t3 < 1) + val = t1 + (t2 - t1) * 6 * t3; + else if (2 * t3 < 1) + val = t2; + else if (3 * t3 < 2) + val = t1 + (t2 - t1) * (2 / 3 - t3) * 6; + else + val = t1; + + rgb[i] = val * 255; + } + + return rgb; +} + +function hsl2hsv(hsl) { + var h = hsl[0], + s = hsl[1] / 100, + l = hsl[2] / 100, + sv, v; + + if(l === 0) { + // no need to do calc on black + // also avoids divide by 0 error + return [0, 0, 0]; + } + + l *= 2; + s *= (l <= 1) ? l : 2 - l; + v = (l + s) / 2; + sv = (2 * s) / (l + s); + return [h, sv * 100, v * 100]; +} + +function hsl2hwb(args) { + return rgb2hwb(hsl2rgb(args)); +} + +function hsl2cmyk(args) { + return rgb2cmyk(hsl2rgb(args)); +} + +function hsl2keyword(args) { + return rgb2keyword(hsl2rgb(args)); +} + + +function hsv2rgb(hsv) { + var h = hsv[0] / 60, + s = hsv[1] / 100, + v = hsv[2] / 100, + hi = Math.floor(h) % 6; + + var f = h - Math.floor(h), + p = 255 * v * (1 - s), + q = 255 * v * (1 - (s * f)), + t = 255 * v * (1 - (s * (1 - f))), + v = 255 * v; + + switch(hi) { + case 0: + return [v, t, p]; + case 1: + return [q, v, p]; + case 2: + return [p, v, t]; + case 3: + return [p, q, v]; + case 4: + return [t, p, v]; + case 5: + return [v, p, q]; + } +} + +function hsv2hsl(hsv) { + var h = hsv[0], + s = hsv[1] / 100, + v = hsv[2] / 100, + sl, l; + + l = (2 - s) * v; + sl = s * v; + sl /= (l <= 1) ? l : 2 - l; + sl = sl || 0; + l /= 2; + return [h, sl * 100, l * 100]; +} + +function hsv2hwb(args) { + return rgb2hwb(hsv2rgb(args)) +} + +function hsv2cmyk(args) { + return rgb2cmyk(hsv2rgb(args)); +} + +function hsv2keyword(args) { + return rgb2keyword(hsv2rgb(args)); +} + +// http://dev.w3.org/csswg/css-color/#hwb-to-rgb +function hwb2rgb(hwb) { + var h = hwb[0] / 360, + wh = hwb[1] / 100, + bl = hwb[2] / 100, + ratio = wh + bl, + i, v, f, n; + + // wh + bl cant be > 1 + if (ratio > 1) { + wh /= ratio; + bl /= ratio; + } + + i = Math.floor(6 * h); + v = 1 - bl; + f = 6 * h - i; + if ((i & 0x01) != 0) { + f = 1 - f; + } + n = wh + f * (v - wh); // linear interpolation + + switch (i) { + default: + case 6: + case 0: r = v; g = n; b = wh; break; + case 1: r = n; g = v; b = wh; break; + case 2: r = wh; g = v; b = n; break; + case 3: r = wh; g = n; b = v; break; + case 4: r = n; g = wh; b = v; break; + case 5: r = v; g = wh; b = n; break; + } + + return [r * 255, g * 255, b * 255]; +} + +function hwb2hsl(args) { + return rgb2hsl(hwb2rgb(args)); +} + +function hwb2hsv(args) { + return rgb2hsv(hwb2rgb(args)); +} + +function hwb2cmyk(args) { + return rgb2cmyk(hwb2rgb(args)); +} + +function hwb2keyword(args) { + return rgb2keyword(hwb2rgb(args)); +} + +function cmyk2rgb(cmyk) { + var c = cmyk[0] / 100, + m = cmyk[1] / 100, + y = cmyk[2] / 100, + k = cmyk[3] / 100, + r, g, b; + + r = 1 - Math.min(1, c * (1 - k) + k); + g = 1 - Math.min(1, m * (1 - k) + k); + b = 1 - Math.min(1, y * (1 - k) + k); + return [r * 255, g * 255, b * 255]; +} + +function cmyk2hsl(args) { + return rgb2hsl(cmyk2rgb(args)); +} + +function cmyk2hsv(args) { + return rgb2hsv(cmyk2rgb(args)); +} + +function cmyk2hwb(args) { + return rgb2hwb(cmyk2rgb(args)); +} + +function cmyk2keyword(args) { + return rgb2keyword(cmyk2rgb(args)); +} + + +function xyz2rgb(xyz) { + var x = xyz[0] / 100, + y = xyz[1] / 100, + z = xyz[2] / 100, + r, g, b; + + r = (x * 3.2406) + (y * -1.5372) + (z * -0.4986); + g = (x * -0.9689) + (y * 1.8758) + (z * 0.0415); + b = (x * 0.0557) + (y * -0.2040) + (z * 1.0570); + + // assume sRGB + r = r > 0.0031308 ? ((1.055 * Math.pow(r, 1.0 / 2.4)) - 0.055) + : r = (r * 12.92); + + g = g > 0.0031308 ? ((1.055 * Math.pow(g, 1.0 / 2.4)) - 0.055) + : g = (g * 12.92); + + b = b > 0.0031308 ? ((1.055 * Math.pow(b, 1.0 / 2.4)) - 0.055) + : b = (b * 12.92); + + r = Math.min(Math.max(0, r), 1); + g = Math.min(Math.max(0, g), 1); + b = Math.min(Math.max(0, b), 1); + + return [r * 255, g * 255, b * 255]; +} + +function xyz2lab(xyz) { + var x = xyz[0], + y = xyz[1], + z = xyz[2], + l, a, b; + + x /= 95.047; + y /= 100; + z /= 108.883; + + x = x > 0.008856 ? Math.pow(x, 1/3) : (7.787 * x) + (16 / 116); + y = y > 0.008856 ? Math.pow(y, 1/3) : (7.787 * y) + (16 / 116); + z = z > 0.008856 ? Math.pow(z, 1/3) : (7.787 * z) + (16 / 116); + + l = (116 * y) - 16; + a = 500 * (x - y); + b = 200 * (y - z); + + return [l, a, b]; +} + +function xyz2lch(args) { + return lab2lch(xyz2lab(args)); +} + +function lab2xyz(lab) { + var l = lab[0], + a = lab[1], + b = lab[2], + x, y, z, y2; + + if (l <= 8) { + y = (l * 100) / 903.3; + y2 = (7.787 * (y / 100)) + (16 / 116); + } else { + y = 100 * Math.pow((l + 16) / 116, 3); + y2 = Math.pow(y / 100, 1/3); + } + + x = x / 95.047 <= 0.008856 ? x = (95.047 * ((a / 500) + y2 - (16 / 116))) / 7.787 : 95.047 * Math.pow((a / 500) + y2, 3); + + z = z / 108.883 <= 0.008859 ? z = (108.883 * (y2 - (b / 200) - (16 / 116))) / 7.787 : 108.883 * Math.pow(y2 - (b / 200), 3); + + return [x, y, z]; +} + +function lab2lch(lab) { + var l = lab[0], + a = lab[1], + b = lab[2], + hr, h, c; + + hr = Math.atan2(b, a); + h = hr * 360 / 2 / Math.PI; + if (h < 0) { + h += 360; + } + c = Math.sqrt(a * a + b * b); + return [l, c, h]; +} + +function lab2rgb(args) { + return xyz2rgb(lab2xyz(args)); +} + +function lch2lab(lch) { + var l = lch[0], + c = lch[1], + h = lch[2], + a, b, hr; + + hr = h / 360 * 2 * Math.PI; + a = c * Math.cos(hr); + b = c * Math.sin(hr); + return [l, a, b]; +} + +function lch2xyz(args) { + return lab2xyz(lch2lab(args)); +} + +function lch2rgb(args) { + return lab2rgb(lch2lab(args)); +} + +function keyword2rgb(keyword) { + return cssKeywords[keyword]; +} + +function keyword2hsl(args) { + return rgb2hsl(keyword2rgb(args)); +} + +function keyword2hsv(args) { + return rgb2hsv(keyword2rgb(args)); +} + +function keyword2hwb(args) { + return rgb2hwb(keyword2rgb(args)); +} + +function keyword2cmyk(args) { + return rgb2cmyk(keyword2rgb(args)); +} + +function keyword2lab(args) { + return rgb2lab(keyword2rgb(args)); +} + +function keyword2xyz(args) { + return rgb2xyz(keyword2rgb(args)); +} + +var cssKeywords = { + aliceblue: [240,248,255], + antiquewhite: [250,235,215], + aqua: [0,255,255], + aquamarine: [127,255,212], + azure: [240,255,255], + beige: [245,245,220], + bisque: [255,228,196], + black: [0,0,0], + blanchedalmond: [255,235,205], + blue: [0,0,255], + blueviolet: [138,43,226], + brown: [165,42,42], + burlywood: [222,184,135], + cadetblue: [95,158,160], + chartreuse: [127,255,0], + chocolate: [210,105,30], + coral: [255,127,80], + cornflowerblue: [100,149,237], + cornsilk: [255,248,220], + crimson: [220,20,60], + cyan: [0,255,255], + darkblue: [0,0,139], + darkcyan: [0,139,139], + darkgoldenrod: [184,134,11], + darkgray: [169,169,169], + darkgreen: [0,100,0], + darkgrey: [169,169,169], + darkkhaki: [189,183,107], + darkmagenta: [139,0,139], + darkolivegreen: [85,107,47], + darkorange: [255,140,0], + darkorchid: [153,50,204], + darkred: [139,0,0], + darksalmon: [233,150,122], + darkseagreen: [143,188,143], + darkslateblue: [72,61,139], + darkslategray: [47,79,79], + darkslategrey: [47,79,79], + darkturquoise: [0,206,209], + darkviolet: [148,0,211], + deeppink: [255,20,147], + deepskyblue: [0,191,255], + dimgray: [105,105,105], + dimgrey: [105,105,105], + dodgerblue: [30,144,255], + firebrick: [178,34,34], + floralwhite: [255,250,240], + forestgreen: [34,139,34], + fuchsia: [255,0,255], + gainsboro: [220,220,220], + ghostwhite: [248,248,255], + gold: [255,215,0], + goldenrod: [218,165,32], + gray: [128,128,128], + green: [0,128,0], + greenyellow: [173,255,47], + grey: [128,128,128], + honeydew: [240,255,240], + hotpink: [255,105,180], + indianred: [205,92,92], + indigo: [75,0,130], + ivory: [255,255,240], + khaki: [240,230,140], + lavender: [230,230,250], + lavenderblush: [255,240,245], + lawngreen: [124,252,0], + lemonchiffon: [255,250,205], + lightblue: [173,216,230], + lightcoral: [240,128,128], + lightcyan: [224,255,255], + lightgoldenrodyellow: [250,250,210], + lightgray: [211,211,211], + lightgreen: [144,238,144], + lightgrey: [211,211,211], + lightpink: [255,182,193], + lightsalmon: [255,160,122], + lightseagreen: [32,178,170], + lightskyblue: [135,206,250], + lightslategray: [119,136,153], + lightslategrey: [119,136,153], + lightsteelblue: [176,196,222], + lightyellow: [255,255,224], + lime: [0,255,0], + limegreen: [50,205,50], + linen: [250,240,230], + magenta: [255,0,255], + maroon: [128,0,0], + mediumaquamarine: [102,205,170], + mediumblue: [0,0,205], + mediumorchid: [186,85,211], + mediumpurple: [147,112,219], + mediumseagreen: [60,179,113], + mediumslateblue: [123,104,238], + mediumspringgreen: [0,250,154], + mediumturquoise: [72,209,204], + mediumvioletred: [199,21,133], + midnightblue: [25,25,112], + mintcream: [245,255,250], + mistyrose: [255,228,225], + moccasin: [255,228,181], + navajowhite: [255,222,173], + navy: [0,0,128], + oldlace: [253,245,230], + olive: [128,128,0], + olivedrab: [107,142,35], + orange: [255,165,0], + orangered: [255,69,0], + orchid: [218,112,214], + palegoldenrod: [238,232,170], + palegreen: [152,251,152], + paleturquoise: [175,238,238], + palevioletred: [219,112,147], + papayawhip: [255,239,213], + peachpuff: [255,218,185], + peru: [205,133,63], + pink: [255,192,203], + plum: [221,160,221], + powderblue: [176,224,230], + purple: [128,0,128], + rebeccapurple: [102, 51, 153], + red: [255,0,0], + rosybrown: [188,143,143], + royalblue: [65,105,225], + saddlebrown: [139,69,19], + salmon: [250,128,114], + sandybrown: [244,164,96], + seagreen: [46,139,87], + seashell: [255,245,238], + sienna: [160,82,45], + silver: [192,192,192], + skyblue: [135,206,235], + slateblue: [106,90,205], + slategray: [112,128,144], + slategrey: [112,128,144], + snow: [255,250,250], + springgreen: [0,255,127], + steelblue: [70,130,180], + tan: [210,180,140], + teal: [0,128,128], + thistle: [216,191,216], + tomato: [255,99,71], + turquoise: [64,224,208], + violet: [238,130,238], + wheat: [245,222,179], + white: [255,255,255], + whitesmoke: [245,245,245], + yellow: [255,255,0], + yellowgreen: [154,205,50] +}; + +var reverseKeywords = {}; +for (var key in cssKeywords) { + reverseKeywords[JSON.stringify(cssKeywords[key])] = key; +} + +var convert = function() { + return new Converter(); +}; + +for (var func in conversions) { + // export Raw versions + convert[func + "Raw"] = (function(func) { + // accept array or plain args + return function(arg) { + if (typeof arg == "number") + arg = Array.prototype.slice.call(arguments); + return conversions[func](arg); + } + })(func); + + var pair = /(\w+)2(\w+)/.exec(func), + from = pair[1], + to = pair[2]; + + // export rgb2hsl and ["rgb"]["hsl"] + convert[from] = convert[from] || {}; + + convert[from][to] = convert[func] = (function(func) { + return function(arg) { + if (typeof arg == "number") + arg = Array.prototype.slice.call(arguments); + + var val = conversions[func](arg); + if (typeof val == "string" || val === undefined) + return val; // keyword + + for (var i = 0; i < val.length; i++) + val[i] = Math.round(val[i]); + return val; + } + })(func); +} + + +/* Converter does lazy conversion and caching */ +var Converter = function() { + this.convs = {}; +}; + +/* Either get the values for a space or + set the values for a space, depending on args */ +Converter.prototype.routeSpace = function(space, args) { + var values = args[0]; + if (values === undefined) { + // color.rgb() + return this.getValues(space); + } + // color.rgb(10, 10, 10) + if (typeof values == "number") { + values = Array.prototype.slice.call(args); + } + + return this.setValues(space, values); +}; + +/* Set the values for a space, invalidating cache */ +Converter.prototype.setValues = function(space, values) { + this.space = space; + this.convs = {}; + this.convs[space] = values; + return this; +}; + +/* Get the values for a space. If there's already + a conversion for the space, fetch it, otherwise + compute it */ +Converter.prototype.getValues = function(space) { + var vals = this.convs[space]; + if (!vals) { + var fspace = this.space, + from = this.convs[fspace]; + vals = convert[fspace][space](from); + + this.convs[space] = vals; + } + return vals; +}; + +["rgb", "hsl", "hsv", "cmyk", "keyword"].forEach(function(space) { + Converter.prototype[space] = function(vals) { + return this.routeSpace(space, arguments); + }; +}); + +var colorConvert = convert; + +var colorName = { + "aliceblue": [240, 248, 255], + "antiquewhite": [250, 235, 215], + "aqua": [0, 255, 255], + "aquamarine": [127, 255, 212], + "azure": [240, 255, 255], + "beige": [245, 245, 220], + "bisque": [255, 228, 196], + "black": [0, 0, 0], + "blanchedalmond": [255, 235, 205], + "blue": [0, 0, 255], + "blueviolet": [138, 43, 226], + "brown": [165, 42, 42], + "burlywood": [222, 184, 135], + "cadetblue": [95, 158, 160], + "chartreuse": [127, 255, 0], + "chocolate": [210, 105, 30], + "coral": [255, 127, 80], + "cornflowerblue": [100, 149, 237], + "cornsilk": [255, 248, 220], + "crimson": [220, 20, 60], + "cyan": [0, 255, 255], + "darkblue": [0, 0, 139], + "darkcyan": [0, 139, 139], + "darkgoldenrod": [184, 134, 11], + "darkgray": [169, 169, 169], + "darkgreen": [0, 100, 0], + "darkgrey": [169, 169, 169], + "darkkhaki": [189, 183, 107], + "darkmagenta": [139, 0, 139], + "darkolivegreen": [85, 107, 47], + "darkorange": [255, 140, 0], + "darkorchid": [153, 50, 204], + "darkred": [139, 0, 0], + "darksalmon": [233, 150, 122], + "darkseagreen": [143, 188, 143], + "darkslateblue": [72, 61, 139], + "darkslategray": [47, 79, 79], + "darkslategrey": [47, 79, 79], + "darkturquoise": [0, 206, 209], + "darkviolet": [148, 0, 211], + "deeppink": [255, 20, 147], + "deepskyblue": [0, 191, 255], + "dimgray": [105, 105, 105], + "dimgrey": [105, 105, 105], + "dodgerblue": [30, 144, 255], + "firebrick": [178, 34, 34], + "floralwhite": [255, 250, 240], + "forestgreen": [34, 139, 34], + "fuchsia": [255, 0, 255], + "gainsboro": [220, 220, 220], + "ghostwhite": [248, 248, 255], + "gold": [255, 215, 0], + "goldenrod": [218, 165, 32], + "gray": [128, 128, 128], + "green": [0, 128, 0], + "greenyellow": [173, 255, 47], + "grey": [128, 128, 128], + "honeydew": [240, 255, 240], + "hotpink": [255, 105, 180], + "indianred": [205, 92, 92], + "indigo": [75, 0, 130], + "ivory": [255, 255, 240], + "khaki": [240, 230, 140], + "lavender": [230, 230, 250], + "lavenderblush": [255, 240, 245], + "lawngreen": [124, 252, 0], + "lemonchiffon": [255, 250, 205], + "lightblue": [173, 216, 230], + "lightcoral": [240, 128, 128], + "lightcyan": [224, 255, 255], + "lightgoldenrodyellow": [250, 250, 210], + "lightgray": [211, 211, 211], + "lightgreen": [144, 238, 144], + "lightgrey": [211, 211, 211], + "lightpink": [255, 182, 193], + "lightsalmon": [255, 160, 122], + "lightseagreen": [32, 178, 170], + "lightskyblue": [135, 206, 250], + "lightslategray": [119, 136, 153], + "lightslategrey": [119, 136, 153], + "lightsteelblue": [176, 196, 222], + "lightyellow": [255, 255, 224], + "lime": [0, 255, 0], + "limegreen": [50, 205, 50], + "linen": [250, 240, 230], + "magenta": [255, 0, 255], + "maroon": [128, 0, 0], + "mediumaquamarine": [102, 205, 170], + "mediumblue": [0, 0, 205], + "mediumorchid": [186, 85, 211], + "mediumpurple": [147, 112, 219], + "mediumseagreen": [60, 179, 113], + "mediumslateblue": [123, 104, 238], + "mediumspringgreen": [0, 250, 154], + "mediumturquoise": [72, 209, 204], + "mediumvioletred": [199, 21, 133], + "midnightblue": [25, 25, 112], + "mintcream": [245, 255, 250], + "mistyrose": [255, 228, 225], + "moccasin": [255, 228, 181], + "navajowhite": [255, 222, 173], + "navy": [0, 0, 128], + "oldlace": [253, 245, 230], + "olive": [128, 128, 0], + "olivedrab": [107, 142, 35], + "orange": [255, 165, 0], + "orangered": [255, 69, 0], + "orchid": [218, 112, 214], + "palegoldenrod": [238, 232, 170], + "palegreen": [152, 251, 152], + "paleturquoise": [175, 238, 238], + "palevioletred": [219, 112, 147], + "papayawhip": [255, 239, 213], + "peachpuff": [255, 218, 185], + "peru": [205, 133, 63], + "pink": [255, 192, 203], + "plum": [221, 160, 221], + "powderblue": [176, 224, 230], + "purple": [128, 0, 128], + "rebeccapurple": [102, 51, 153], + "red": [255, 0, 0], + "rosybrown": [188, 143, 143], + "royalblue": [65, 105, 225], + "saddlebrown": [139, 69, 19], + "salmon": [250, 128, 114], + "sandybrown": [244, 164, 96], + "seagreen": [46, 139, 87], + "seashell": [255, 245, 238], + "sienna": [160, 82, 45], + "silver": [192, 192, 192], + "skyblue": [135, 206, 235], + "slateblue": [106, 90, 205], + "slategray": [112, 128, 144], + "slategrey": [112, 128, 144], + "snow": [255, 250, 250], + "springgreen": [0, 255, 127], + "steelblue": [70, 130, 180], + "tan": [210, 180, 140], + "teal": [0, 128, 128], + "thistle": [216, 191, 216], + "tomato": [255, 99, 71], + "turquoise": [64, 224, 208], + "violet": [238, 130, 238], + "wheat": [245, 222, 179], + "white": [255, 255, 255], + "whitesmoke": [245, 245, 245], + "yellow": [255, 255, 0], + "yellowgreen": [154, 205, 50] +}; + +/* MIT license */ + + +var colorString = { + getRgba: getRgba, + getHsla: getHsla, + getRgb: getRgb, + getHsl: getHsl, + getHwb: getHwb, + getAlpha: getAlpha, + + hexString: hexString, + rgbString: rgbString, + rgbaString: rgbaString, + percentString: percentString, + percentaString: percentaString, + hslString: hslString, + hslaString: hslaString, + hwbString: hwbString, + keyword: keyword +}; + +function getRgba(string) { + if (!string) { + return; + } + var abbr = /^#([a-fA-F0-9]{3,4})$/i, + hex = /^#([a-fA-F0-9]{6}([a-fA-F0-9]{2})?)$/i, + rgba = /^rgba?\(\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/i, + per = /^rgba?\(\s*([+-]?[\d\.]+)\%\s*,\s*([+-]?[\d\.]+)\%\s*,\s*([+-]?[\d\.]+)\%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/i, + keyword = /(\w+)/; + + var rgb = [0, 0, 0], + a = 1, + match = string.match(abbr), + hexAlpha = ""; + if (match) { + match = match[1]; + hexAlpha = match[3]; + for (var i = 0; i < rgb.length; i++) { + rgb[i] = parseInt(match[i] + match[i], 16); + } + if (hexAlpha) { + a = Math.round((parseInt(hexAlpha + hexAlpha, 16) / 255) * 100) / 100; + } + } + else if (match = string.match(hex)) { + hexAlpha = match[2]; + match = match[1]; + for (var i = 0; i < rgb.length; i++) { + rgb[i] = parseInt(match.slice(i * 2, i * 2 + 2), 16); + } + if (hexAlpha) { + a = Math.round((parseInt(hexAlpha, 16) / 255) * 100) / 100; + } + } + else if (match = string.match(rgba)) { + for (var i = 0; i < rgb.length; i++) { + rgb[i] = parseInt(match[i + 1]); + } + a = parseFloat(match[4]); + } + else if (match = string.match(per)) { + for (var i = 0; i < rgb.length; i++) { + rgb[i] = Math.round(parseFloat(match[i + 1]) * 2.55); + } + a = parseFloat(match[4]); + } + else if (match = string.match(keyword)) { + if (match[1] == "transparent") { + return [0, 0, 0, 0]; + } + rgb = colorName[match[1]]; + if (!rgb) { + return; + } + } + + for (var i = 0; i < rgb.length; i++) { + rgb[i] = scale(rgb[i], 0, 255); + } + if (!a && a != 0) { + a = 1; + } + else { + a = scale(a, 0, 1); + } + rgb[3] = a; + return rgb; +} + +function getHsla(string) { + if (!string) { + return; + } + var hsl = /^hsla?\(\s*([+-]?\d+)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)/; + var match = string.match(hsl); + if (match) { + var alpha = parseFloat(match[4]); + var h = scale(parseInt(match[1]), 0, 360), + s = scale(parseFloat(match[2]), 0, 100), + l = scale(parseFloat(match[3]), 0, 100), + a = scale(isNaN(alpha) ? 1 : alpha, 0, 1); + return [h, s, l, a]; + } +} + +function getHwb(string) { + if (!string) { + return; + } + var hwb = /^hwb\(\s*([+-]?\d+)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)/; + var match = string.match(hwb); + if (match) { + var alpha = parseFloat(match[4]); + var h = scale(parseInt(match[1]), 0, 360), + w = scale(parseFloat(match[2]), 0, 100), + b = scale(parseFloat(match[3]), 0, 100), + a = scale(isNaN(alpha) ? 1 : alpha, 0, 1); + return [h, w, b, a]; + } +} + +function getRgb(string) { + var rgba = getRgba(string); + return rgba && rgba.slice(0, 3); +} + +function getHsl(string) { + var hsla = getHsla(string); + return hsla && hsla.slice(0, 3); +} + +function getAlpha(string) { + var vals = getRgba(string); + if (vals) { + return vals[3]; + } + else if (vals = getHsla(string)) { + return vals[3]; + } + else if (vals = getHwb(string)) { + return vals[3]; + } +} + +// generators +function hexString(rgba, a) { + var a = (a !== undefined && rgba.length === 3) ? a : rgba[3]; + return "#" + hexDouble(rgba[0]) + + hexDouble(rgba[1]) + + hexDouble(rgba[2]) + + ( + (a >= 0 && a < 1) + ? hexDouble(Math.round(a * 255)) + : "" + ); +} + +function rgbString(rgba, alpha) { + if (alpha < 1 || (rgba[3] && rgba[3] < 1)) { + return rgbaString(rgba, alpha); + } + return "rgb(" + rgba[0] + ", " + rgba[1] + ", " + rgba[2] + ")"; +} + +function rgbaString(rgba, alpha) { + if (alpha === undefined) { + alpha = (rgba[3] !== undefined ? rgba[3] : 1); + } + return "rgba(" + rgba[0] + ", " + rgba[1] + ", " + rgba[2] + + ", " + alpha + ")"; +} + +function percentString(rgba, alpha) { + if (alpha < 1 || (rgba[3] && rgba[3] < 1)) { + return percentaString(rgba, alpha); + } + var r = Math.round(rgba[0]/255 * 100), + g = Math.round(rgba[1]/255 * 100), + b = Math.round(rgba[2]/255 * 100); + + return "rgb(" + r + "%, " + g + "%, " + b + "%)"; +} + +function percentaString(rgba, alpha) { + var r = Math.round(rgba[0]/255 * 100), + g = Math.round(rgba[1]/255 * 100), + b = Math.round(rgba[2]/255 * 100); + return "rgba(" + r + "%, " + g + "%, " + b + "%, " + (alpha || rgba[3] || 1) + ")"; +} + +function hslString(hsla, alpha) { + if (alpha < 1 || (hsla[3] && hsla[3] < 1)) { + return hslaString(hsla, alpha); + } + return "hsl(" + hsla[0] + ", " + hsla[1] + "%, " + hsla[2] + "%)"; +} + +function hslaString(hsla, alpha) { + if (alpha === undefined) { + alpha = (hsla[3] !== undefined ? hsla[3] : 1); + } + return "hsla(" + hsla[0] + ", " + hsla[1] + "%, " + hsla[2] + "%, " + + alpha + ")"; +} + +// hwb is a bit different than rgb(a) & hsl(a) since there is no alpha specific syntax +// (hwb have alpha optional & 1 is default value) +function hwbString(hwb, alpha) { + if (alpha === undefined) { + alpha = (hwb[3] !== undefined ? hwb[3] : 1); + } + return "hwb(" + hwb[0] + ", " + hwb[1] + "%, " + hwb[2] + "%" + + (alpha !== undefined && alpha !== 1 ? ", " + alpha : "") + ")"; +} + +function keyword(rgb) { + return reverseNames[rgb.slice(0, 3)]; +} + +// helpers +function scale(num, min, max) { + return Math.min(Math.max(min, num), max); +} + +function hexDouble(num) { + var str = num.toString(16).toUpperCase(); + return (str.length < 2) ? "0" + str : str; +} + + +//create a list of reverse color names +var reverseNames = {}; +for (var name in colorName) { + reverseNames[colorName[name]] = name; +} + +/* MIT license */ + + + +var Color = function (obj) { + if (obj instanceof Color) { + return obj; + } + if (!(this instanceof Color)) { + return new Color(obj); + } + + this.valid = false; + this.values = { + rgb: [0, 0, 0], + hsl: [0, 0, 0], + hsv: [0, 0, 0], + hwb: [0, 0, 0], + cmyk: [0, 0, 0, 0], + alpha: 1 + }; + + // parse Color() argument + var vals; + if (typeof obj === 'string') { + vals = colorString.getRgba(obj); + if (vals) { + this.setValues('rgb', vals); + } else if (vals = colorString.getHsla(obj)) { + this.setValues('hsl', vals); + } else if (vals = colorString.getHwb(obj)) { + this.setValues('hwb', vals); + } + } else if (typeof obj === 'object') { + vals = obj; + if (vals.r !== undefined || vals.red !== undefined) { + this.setValues('rgb', vals); + } else if (vals.l !== undefined || vals.lightness !== undefined) { + this.setValues('hsl', vals); + } else if (vals.v !== undefined || vals.value !== undefined) { + this.setValues('hsv', vals); + } else if (vals.w !== undefined || vals.whiteness !== undefined) { + this.setValues('hwb', vals); + } else if (vals.c !== undefined || vals.cyan !== undefined) { + this.setValues('cmyk', vals); + } + } +}; + +Color.prototype = { + isValid: function () { + return this.valid; + }, + rgb: function () { + return this.setSpace('rgb', arguments); + }, + hsl: function () { + return this.setSpace('hsl', arguments); + }, + hsv: function () { + return this.setSpace('hsv', arguments); + }, + hwb: function () { + return this.setSpace('hwb', arguments); + }, + cmyk: function () { + return this.setSpace('cmyk', arguments); + }, + + rgbArray: function () { + return this.values.rgb; + }, + hslArray: function () { + return this.values.hsl; + }, + hsvArray: function () { + return this.values.hsv; + }, + hwbArray: function () { + var values = this.values; + if (values.alpha !== 1) { + return values.hwb.concat([values.alpha]); + } + return values.hwb; + }, + cmykArray: function () { + return this.values.cmyk; + }, + rgbaArray: function () { + var values = this.values; + return values.rgb.concat([values.alpha]); + }, + hslaArray: function () { + var values = this.values; + return values.hsl.concat([values.alpha]); + }, + alpha: function (val) { + if (val === undefined) { + return this.values.alpha; + } + this.setValues('alpha', val); + return this; + }, + + red: function (val) { + return this.setChannel('rgb', 0, val); + }, + green: function (val) { + return this.setChannel('rgb', 1, val); + }, + blue: function (val) { + return this.setChannel('rgb', 2, val); + }, + hue: function (val) { + if (val) { + val %= 360; + val = val < 0 ? 360 + val : val; + } + return this.setChannel('hsl', 0, val); + }, + saturation: function (val) { + return this.setChannel('hsl', 1, val); + }, + lightness: function (val) { + return this.setChannel('hsl', 2, val); + }, + saturationv: function (val) { + return this.setChannel('hsv', 1, val); + }, + whiteness: function (val) { + return this.setChannel('hwb', 1, val); + }, + blackness: function (val) { + return this.setChannel('hwb', 2, val); + }, + value: function (val) { + return this.setChannel('hsv', 2, val); + }, + cyan: function (val) { + return this.setChannel('cmyk', 0, val); + }, + magenta: function (val) { + return this.setChannel('cmyk', 1, val); + }, + yellow: function (val) { + return this.setChannel('cmyk', 2, val); + }, + black: function (val) { + return this.setChannel('cmyk', 3, val); + }, + + hexString: function () { + return colorString.hexString(this.values.rgb); + }, + rgbString: function () { + return colorString.rgbString(this.values.rgb, this.values.alpha); + }, + rgbaString: function () { + return colorString.rgbaString(this.values.rgb, this.values.alpha); + }, + percentString: function () { + return colorString.percentString(this.values.rgb, this.values.alpha); + }, + hslString: function () { + return colorString.hslString(this.values.hsl, this.values.alpha); + }, + hslaString: function () { + return colorString.hslaString(this.values.hsl, this.values.alpha); + }, + hwbString: function () { + return colorString.hwbString(this.values.hwb, this.values.alpha); + }, + keyword: function () { + return colorString.keyword(this.values.rgb, this.values.alpha); + }, + + rgbNumber: function () { + var rgb = this.values.rgb; + return (rgb[0] << 16) | (rgb[1] << 8) | rgb[2]; + }, + + luminosity: function () { + // http://www.w3.org/TR/WCAG20/#relativeluminancedef + var rgb = this.values.rgb; + var lum = []; + for (var i = 0; i < rgb.length; i++) { + var chan = rgb[i] / 255; + lum[i] = (chan <= 0.03928) ? chan / 12.92 : Math.pow(((chan + 0.055) / 1.055), 2.4); + } + return 0.2126 * lum[0] + 0.7152 * lum[1] + 0.0722 * lum[2]; + }, + + contrast: function (color2) { + // http://www.w3.org/TR/WCAG20/#contrast-ratiodef + var lum1 = this.luminosity(); + var lum2 = color2.luminosity(); + if (lum1 > lum2) { + return (lum1 + 0.05) / (lum2 + 0.05); + } + return (lum2 + 0.05) / (lum1 + 0.05); + }, + + level: function (color2) { + var contrastRatio = this.contrast(color2); + if (contrastRatio >= 7.1) { + return 'AAA'; + } + + return (contrastRatio >= 4.5) ? 'AA' : ''; + }, + + dark: function () { + // YIQ equation from http://24ways.org/2010/calculating-color-contrast + var rgb = this.values.rgb; + var yiq = (rgb[0] * 299 + rgb[1] * 587 + rgb[2] * 114) / 1000; + return yiq < 128; + }, + + light: function () { + return !this.dark(); + }, + + negate: function () { + var rgb = []; + for (var i = 0; i < 3; i++) { + rgb[i] = 255 - this.values.rgb[i]; + } + this.setValues('rgb', rgb); + return this; + }, + + lighten: function (ratio) { + var hsl = this.values.hsl; + hsl[2] += hsl[2] * ratio; + this.setValues('hsl', hsl); + return this; + }, + + darken: function (ratio) { + var hsl = this.values.hsl; + hsl[2] -= hsl[2] * ratio; + this.setValues('hsl', hsl); + return this; + }, + + saturate: function (ratio) { + var hsl = this.values.hsl; + hsl[1] += hsl[1] * ratio; + this.setValues('hsl', hsl); + return this; + }, + + desaturate: function (ratio) { + var hsl = this.values.hsl; + hsl[1] -= hsl[1] * ratio; + this.setValues('hsl', hsl); + return this; + }, + + whiten: function (ratio) { + var hwb = this.values.hwb; + hwb[1] += hwb[1] * ratio; + this.setValues('hwb', hwb); + return this; + }, + + blacken: function (ratio) { + var hwb = this.values.hwb; + hwb[2] += hwb[2] * ratio; + this.setValues('hwb', hwb); + return this; + }, + + greyscale: function () { + var rgb = this.values.rgb; + // http://en.wikipedia.org/wiki/Grayscale#Converting_color_to_grayscale + var val = rgb[0] * 0.3 + rgb[1] * 0.59 + rgb[2] * 0.11; + this.setValues('rgb', [val, val, val]); + return this; + }, + + clearer: function (ratio) { + var alpha = this.values.alpha; + this.setValues('alpha', alpha - (alpha * ratio)); + return this; + }, + + opaquer: function (ratio) { + var alpha = this.values.alpha; + this.setValues('alpha', alpha + (alpha * ratio)); + return this; + }, + + rotate: function (degrees) { + var hsl = this.values.hsl; + var hue = (hsl[0] + degrees) % 360; + hsl[0] = hue < 0 ? 360 + hue : hue; + this.setValues('hsl', hsl); + return this; + }, + + /** + * Ported from sass implementation in C + * https://github.com/sass/libsass/blob/0e6b4a2850092356aa3ece07c6b249f0221caced/functions.cpp#L209 + */ + mix: function (mixinColor, weight) { + var color1 = this; + var color2 = mixinColor; + var p = weight === undefined ? 0.5 : weight; + + var w = 2 * p - 1; + var a = color1.alpha() - color2.alpha(); + + var w1 = (((w * a === -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; + var w2 = 1 - w1; + + return this + .rgb( + w1 * color1.red() + w2 * color2.red(), + w1 * color1.green() + w2 * color2.green(), + w1 * color1.blue() + w2 * color2.blue() + ) + .alpha(color1.alpha() * p + color2.alpha() * (1 - p)); + }, + + toJSON: function () { + return this.rgb(); + }, + + clone: function () { + // NOTE(SB): using node-clone creates a dependency to Buffer when using browserify, + // making the final build way to big to embed in Chart.js. So let's do it manually, + // assuming that values to clone are 1 dimension arrays containing only numbers, + // except 'alpha' which is a number. + var result = new Color(); + var source = this.values; + var target = result.values; + var value, type; + + for (var prop in source) { + if (source.hasOwnProperty(prop)) { + value = source[prop]; + type = ({}).toString.call(value); + if (type === '[object Array]') { + target[prop] = value.slice(0); + } else if (type === '[object Number]') { + target[prop] = value; + } else { + console.error('unexpected color value:', value); + } + } + } + + return result; + } +}; + +Color.prototype.spaces = { + rgb: ['red', 'green', 'blue'], + hsl: ['hue', 'saturation', 'lightness'], + hsv: ['hue', 'saturation', 'value'], + hwb: ['hue', 'whiteness', 'blackness'], + cmyk: ['cyan', 'magenta', 'yellow', 'black'] +}; + +Color.prototype.maxes = { + rgb: [255, 255, 255], + hsl: [360, 100, 100], + hsv: [360, 100, 100], + hwb: [360, 100, 100], + cmyk: [100, 100, 100, 100] +}; + +Color.prototype.getValues = function (space) { + var values = this.values; + var vals = {}; + + for (var i = 0; i < space.length; i++) { + vals[space.charAt(i)] = values[space][i]; + } + + if (values.alpha !== 1) { + vals.a = values.alpha; + } + + // {r: 255, g: 255, b: 255, a: 0.4} + return vals; +}; + +Color.prototype.setValues = function (space, vals) { + var values = this.values; + var spaces = this.spaces; + var maxes = this.maxes; + var alpha = 1; + var i; + + this.valid = true; + + if (space === 'alpha') { + alpha = vals; + } else if (vals.length) { + // [10, 10, 10] + values[space] = vals.slice(0, space.length); + alpha = vals[space.length]; + } else if (vals[space.charAt(0)] !== undefined) { + // {r: 10, g: 10, b: 10} + for (i = 0; i < space.length; i++) { + values[space][i] = vals[space.charAt(i)]; + } + + alpha = vals.a; + } else if (vals[spaces[space][0]] !== undefined) { + // {red: 10, green: 10, blue: 10} + var chans = spaces[space]; + + for (i = 0; i < space.length; i++) { + values[space][i] = vals[chans[i]]; + } + + alpha = vals.alpha; + } + + values.alpha = Math.max(0, Math.min(1, (alpha === undefined ? values.alpha : alpha))); + + if (space === 'alpha') { + return false; + } + + var capped; + + // cap values of the space prior converting all values + for (i = 0; i < space.length; i++) { + capped = Math.max(0, Math.min(maxes[space][i], values[space][i])); + values[space][i] = Math.round(capped); + } + + // convert to all the other color spaces + for (var sname in spaces) { + if (sname !== space) { + values[sname] = colorConvert[space][sname](values[space]); + } + } + + return true; +}; + +Color.prototype.setSpace = function (space, args) { + var vals = args[0]; + + if (vals === undefined) { + // color.rgb() + return this.getValues(space); + } + + // color.rgb(10, 10, 10) + if (typeof vals === 'number') { + vals = Array.prototype.slice.call(args); + } + + this.setValues(space, vals); + return this; +}; + +Color.prototype.setChannel = function (space, index, val) { + var svalues = this.values[space]; + if (val === undefined) { + // color.red() + return svalues[index]; + } else if (val === svalues[index]) { + // color.red(color.red()) + return this; + } + + // color.red(100) + svalues[index] = val; + this.setValues(space, svalues); + + return this; +}; + +if (typeof window !== 'undefined') { + window.Color = Color; +} + +var chartjsColor = Color; + +/** + * @namespace Chart.helpers + */ +var helpers = { + /** + * An empty function that can be used, for example, for optional callback. + */ + noop: function() {}, + + /** + * Returns a unique id, sequentially generated from a global variable. + * @returns {number} + * @function + */ + uid: (function() { + var id = 0; + return function() { + return id++; + }; + }()), + + /** + * Returns true if `value` is neither null nor undefined, else returns false. + * @param {*} value - The value to test. + * @returns {boolean} + * @since 2.7.0 + */ + isNullOrUndef: function(value) { + return value === null || typeof value === 'undefined'; + }, + + /** + * Returns true if `value` is an array (including typed arrays), else returns false. + * @param {*} value - The value to test. + * @returns {boolean} + * @function + */ + isArray: function(value) { + if (Array.isArray && Array.isArray(value)) { + return true; + } + var type = Object.prototype.toString.call(value); + if (type.substr(0, 7) === '[object' && type.substr(-6) === 'Array]') { + return true; + } + return false; + }, + + /** + * Returns true if `value` is an object (excluding null), else returns false. + * @param {*} value - The value to test. + * @returns {boolean} + * @since 2.7.0 + */ + isObject: function(value) { + return value !== null && Object.prototype.toString.call(value) === '[object Object]'; + }, + + /** + * Returns true if `value` is a finite number, else returns false + * @param {*} value - The value to test. + * @returns {boolean} + */ + isFinite: function(value) { + return (typeof value === 'number' || value instanceof Number) && isFinite(value); + }, + + /** + * Returns `value` if defined, else returns `defaultValue`. + * @param {*} value - The value to return if defined. + * @param {*} defaultValue - The value to return if `value` is undefined. + * @returns {*} + */ + valueOrDefault: function(value, defaultValue) { + return typeof value === 'undefined' ? defaultValue : value; + }, + + /** + * Returns value at the given `index` in array if defined, else returns `defaultValue`. + * @param {Array} value - The array to lookup for value at `index`. + * @param {number} index - The index in `value` to lookup for value. + * @param {*} defaultValue - The value to return if `value[index]` is undefined. + * @returns {*} + */ + valueAtIndexOrDefault: function(value, index, defaultValue) { + return helpers.valueOrDefault(helpers.isArray(value) ? value[index] : value, defaultValue); + }, + + /** + * Calls `fn` with the given `args` in the scope defined by `thisArg` and returns the + * value returned by `fn`. If `fn` is not a function, this method returns undefined. + * @param {function} fn - The function to call. + * @param {Array|undefined|null} args - The arguments with which `fn` should be called. + * @param {object} [thisArg] - The value of `this` provided for the call to `fn`. + * @returns {*} + */ + callback: function(fn, args, thisArg) { + if (fn && typeof fn.call === 'function') { + return fn.apply(thisArg, args); + } + }, + + /** + * Note(SB) for performance sake, this method should only be used when loopable type + * is unknown or in none intensive code (not called often and small loopable). Else + * it's preferable to use a regular for() loop and save extra function calls. + * @param {object|Array} loopable - The object or array to be iterated. + * @param {function} fn - The function to call for each item. + * @param {object} [thisArg] - The value of `this` provided for the call to `fn`. + * @param {boolean} [reverse] - If true, iterates backward on the loopable. + */ + each: function(loopable, fn, thisArg, reverse) { + var i, len, keys; + if (helpers.isArray(loopable)) { + len = loopable.length; + if (reverse) { + for (i = len - 1; i >= 0; i--) { + fn.call(thisArg, loopable[i], i); + } + } else { + for (i = 0; i < len; i++) { + fn.call(thisArg, loopable[i], i); + } + } + } else if (helpers.isObject(loopable)) { + keys = Object.keys(loopable); + len = keys.length; + for (i = 0; i < len; i++) { + fn.call(thisArg, loopable[keys[i]], keys[i]); + } + } + }, + + /** + * Returns true if the `a0` and `a1` arrays have the same content, else returns false. + * @see https://stackoverflow.com/a/14853974 + * @param {Array} a0 - The array to compare + * @param {Array} a1 - The array to compare + * @returns {boolean} + */ + arrayEquals: function(a0, a1) { + var i, ilen, v0, v1; + + if (!a0 || !a1 || a0.length !== a1.length) { + return false; + } + + for (i = 0, ilen = a0.length; i < ilen; ++i) { + v0 = a0[i]; + v1 = a1[i]; + + if (v0 instanceof Array && v1 instanceof Array) { + if (!helpers.arrayEquals(v0, v1)) { + return false; + } + } else if (v0 !== v1) { + // NOTE: two different object instances will never be equal: {x:20} != {x:20} + return false; + } + } + + return true; + }, + + /** + * Returns a deep copy of `source` without keeping references on objects and arrays. + * @param {*} source - The value to clone. + * @returns {*} + */ + clone: function(source) { + if (helpers.isArray(source)) { + return source.map(helpers.clone); + } + + if (helpers.isObject(source)) { + var target = {}; + var keys = Object.keys(source); + var klen = keys.length; + var k = 0; + + for (; k < klen; ++k) { + target[keys[k]] = helpers.clone(source[keys[k]]); + } + + return target; + } + + return source; + }, + + /** + * The default merger when Chart.helpers.merge is called without merger option. + * Note(SB): also used by mergeConfig and mergeScaleConfig as fallback. + * @private + */ + _merger: function(key, target, source, options) { + var tval = target[key]; + var sval = source[key]; + + if (helpers.isObject(tval) && helpers.isObject(sval)) { + helpers.merge(tval, sval, options); + } else { + target[key] = helpers.clone(sval); + } + }, + + /** + * Merges source[key] in target[key] only if target[key] is undefined. + * @private + */ + _mergerIf: function(key, target, source) { + var tval = target[key]; + var sval = source[key]; + + if (helpers.isObject(tval) && helpers.isObject(sval)) { + helpers.mergeIf(tval, sval); + } else if (!target.hasOwnProperty(key)) { + target[key] = helpers.clone(sval); + } + }, + + /** + * Recursively deep copies `source` properties into `target` with the given `options`. + * IMPORTANT: `target` is not cloned and will be updated with `source` properties. + * @param {object} target - The target object in which all sources are merged into. + * @param {object|object[]} source - Object(s) to merge into `target`. + * @param {object} [options] - Merging options: + * @param {function} [options.merger] - The merge method (key, target, source, options) + * @returns {object} The `target` object. + */ + merge: function(target, source, options) { + var sources = helpers.isArray(source) ? source : [source]; + var ilen = sources.length; + var merge, i, keys, klen, k; + + if (!helpers.isObject(target)) { + return target; + } + + options = options || {}; + merge = options.merger || helpers._merger; + + for (i = 0; i < ilen; ++i) { + source = sources[i]; + if (!helpers.isObject(source)) { + continue; + } + + keys = Object.keys(source); + for (k = 0, klen = keys.length; k < klen; ++k) { + merge(keys[k], target, source, options); + } + } + + return target; + }, + + /** + * Recursively deep copies `source` properties into `target` *only* if not defined in target. + * IMPORTANT: `target` is not cloned and will be updated with `source` properties. + * @param {object} target - The target object in which all sources are merged into. + * @param {object|object[]} source - Object(s) to merge into `target`. + * @returns {object} The `target` object. + */ + mergeIf: function(target, source) { + return helpers.merge(target, source, {merger: helpers._mergerIf}); + }, + + /** + * Applies the contents of two or more objects together into the first object. + * @param {object} target - The target object in which all objects are merged into. + * @param {object} arg1 - Object containing additional properties to merge in target. + * @param {object} argN - Additional objects containing properties to merge in target. + * @returns {object} The `target` object. + */ + extend: function(target) { + var setFn = function(value, key) { + target[key] = value; + }; + for (var i = 1, ilen = arguments.length; i < ilen; ++i) { + helpers.each(arguments[i], setFn); + } + return target; + }, + + /** + * Basic javascript inheritance based on the model created in Backbone.js + */ + inherits: function(extensions) { + var me = this; + var ChartElement = (extensions && extensions.hasOwnProperty('constructor')) ? extensions.constructor : function() { + return me.apply(this, arguments); + }; + + var Surrogate = function() { + this.constructor = ChartElement; + }; + + Surrogate.prototype = me.prototype; + ChartElement.prototype = new Surrogate(); + ChartElement.extend = helpers.inherits; + + if (extensions) { + helpers.extend(ChartElement.prototype, extensions); + } + + ChartElement.__super__ = me.prototype; + return ChartElement; + } +}; + +var helpers_core = helpers; + +// DEPRECATIONS + +/** + * Provided for backward compatibility, use Chart.helpers.callback instead. + * @function Chart.helpers.callCallback + * @deprecated since version 2.6.0 + * @todo remove at version 3 + * @private + */ +helpers.callCallback = helpers.callback; + +/** + * Provided for backward compatibility, use Array.prototype.indexOf instead. + * Array.prototype.indexOf compatibility: Chrome, Opera, Safari, FF1.5+, IE9+ + * @function Chart.helpers.indexOf + * @deprecated since version 2.7.0 + * @todo remove at version 3 + * @private + */ +helpers.indexOf = function(array, item, fromIndex) { + return Array.prototype.indexOf.call(array, item, fromIndex); +}; + +/** + * Provided for backward compatibility, use Chart.helpers.valueOrDefault instead. + * @function Chart.helpers.getValueOrDefault + * @deprecated since version 2.7.0 + * @todo remove at version 3 + * @private + */ +helpers.getValueOrDefault = helpers.valueOrDefault; + +/** + * Provided for backward compatibility, use Chart.helpers.valueAtIndexOrDefault instead. + * @function Chart.helpers.getValueAtIndexOrDefault + * @deprecated since version 2.7.0 + * @todo remove at version 3 + * @private + */ +helpers.getValueAtIndexOrDefault = helpers.valueAtIndexOrDefault; + +/** + * Easing functions adapted from Robert Penner's easing equations. + * @namespace Chart.helpers.easingEffects + * @see http://www.robertpenner.com/easing/ + */ +var effects = { + linear: function(t) { + return t; + }, + + easeInQuad: function(t) { + return t * t; + }, + + easeOutQuad: function(t) { + return -t * (t - 2); + }, + + easeInOutQuad: function(t) { + if ((t /= 0.5) < 1) { + return 0.5 * t * t; + } + return -0.5 * ((--t) * (t - 2) - 1); + }, + + easeInCubic: function(t) { + return t * t * t; + }, + + easeOutCubic: function(t) { + return (t = t - 1) * t * t + 1; + }, + + easeInOutCubic: function(t) { + if ((t /= 0.5) < 1) { + return 0.5 * t * t * t; + } + return 0.5 * ((t -= 2) * t * t + 2); + }, + + easeInQuart: function(t) { + return t * t * t * t; + }, + + easeOutQuart: function(t) { + return -((t = t - 1) * t * t * t - 1); + }, + + easeInOutQuart: function(t) { + if ((t /= 0.5) < 1) { + return 0.5 * t * t * t * t; + } + return -0.5 * ((t -= 2) * t * t * t - 2); + }, + + easeInQuint: function(t) { + return t * t * t * t * t; + }, + + easeOutQuint: function(t) { + return (t = t - 1) * t * t * t * t + 1; + }, + + easeInOutQuint: function(t) { + if ((t /= 0.5) < 1) { + return 0.5 * t * t * t * t * t; + } + return 0.5 * ((t -= 2) * t * t * t * t + 2); + }, + + easeInSine: function(t) { + return -Math.cos(t * (Math.PI / 2)) + 1; + }, + + easeOutSine: function(t) { + return Math.sin(t * (Math.PI / 2)); + }, + + easeInOutSine: function(t) { + return -0.5 * (Math.cos(Math.PI * t) - 1); + }, + + easeInExpo: function(t) { + return (t === 0) ? 0 : Math.pow(2, 10 * (t - 1)); + }, + + easeOutExpo: function(t) { + return (t === 1) ? 1 : -Math.pow(2, -10 * t) + 1; + }, + + easeInOutExpo: function(t) { + if (t === 0) { + return 0; + } + if (t === 1) { + return 1; + } + if ((t /= 0.5) < 1) { + return 0.5 * Math.pow(2, 10 * (t - 1)); + } + return 0.5 * (-Math.pow(2, -10 * --t) + 2); + }, + + easeInCirc: function(t) { + if (t >= 1) { + return t; + } + return -(Math.sqrt(1 - t * t) - 1); + }, + + easeOutCirc: function(t) { + return Math.sqrt(1 - (t = t - 1) * t); + }, + + easeInOutCirc: function(t) { + if ((t /= 0.5) < 1) { + return -0.5 * (Math.sqrt(1 - t * t) - 1); + } + return 0.5 * (Math.sqrt(1 - (t -= 2) * t) + 1); + }, + + easeInElastic: function(t) { + var s = 1.70158; + var p = 0; + var a = 1; + if (t === 0) { + return 0; + } + if (t === 1) { + return 1; + } + if (!p) { + p = 0.3; + } + if (a < 1) { + a = 1; + s = p / 4; + } else { + s = p / (2 * Math.PI) * Math.asin(1 / a); + } + return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t - s) * (2 * Math.PI) / p)); + }, + + easeOutElastic: function(t) { + var s = 1.70158; + var p = 0; + var a = 1; + if (t === 0) { + return 0; + } + if (t === 1) { + return 1; + } + if (!p) { + p = 0.3; + } + if (a < 1) { + a = 1; + s = p / 4; + } else { + s = p / (2 * Math.PI) * Math.asin(1 / a); + } + return a * Math.pow(2, -10 * t) * Math.sin((t - s) * (2 * Math.PI) / p) + 1; + }, + + easeInOutElastic: function(t) { + var s = 1.70158; + var p = 0; + var a = 1; + if (t === 0) { + return 0; + } + if ((t /= 0.5) === 2) { + return 1; + } + if (!p) { + p = 0.45; + } + if (a < 1) { + a = 1; + s = p / 4; + } else { + s = p / (2 * Math.PI) * Math.asin(1 / a); + } + if (t < 1) { + return -0.5 * (a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t - s) * (2 * Math.PI) / p)); + } + return a * Math.pow(2, -10 * (t -= 1)) * Math.sin((t - s) * (2 * Math.PI) / p) * 0.5 + 1; + }, + easeInBack: function(t) { + var s = 1.70158; + return t * t * ((s + 1) * t - s); + }, + + easeOutBack: function(t) { + var s = 1.70158; + return (t = t - 1) * t * ((s + 1) * t + s) + 1; + }, + + easeInOutBack: function(t) { + var s = 1.70158; + if ((t /= 0.5) < 1) { + return 0.5 * (t * t * (((s *= (1.525)) + 1) * t - s)); + } + return 0.5 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2); + }, + + easeInBounce: function(t) { + return 1 - effects.easeOutBounce(1 - t); + }, + + easeOutBounce: function(t) { + if (t < (1 / 2.75)) { + return 7.5625 * t * t; + } + if (t < (2 / 2.75)) { + return 7.5625 * (t -= (1.5 / 2.75)) * t + 0.75; + } + if (t < (2.5 / 2.75)) { + return 7.5625 * (t -= (2.25 / 2.75)) * t + 0.9375; + } + return 7.5625 * (t -= (2.625 / 2.75)) * t + 0.984375; + }, + + easeInOutBounce: function(t) { + if (t < 0.5) { + return effects.easeInBounce(t * 2) * 0.5; + } + return effects.easeOutBounce(t * 2 - 1) * 0.5 + 0.5; + } +}; + +var helpers_easing = { + effects: effects +}; + +// DEPRECATIONS + +/** + * Provided for backward compatibility, use Chart.helpers.easing.effects instead. + * @function Chart.helpers.easingEffects + * @deprecated since version 2.7.0 + * @todo remove at version 3 + * @private + */ +helpers_core.easingEffects = effects; + +var PI = Math.PI; +var RAD_PER_DEG = PI / 180; +var DOUBLE_PI = PI * 2; +var HALF_PI = PI / 2; +var QUARTER_PI = PI / 4; +var TWO_THIRDS_PI = PI * 2 / 3; + +/** + * @namespace Chart.helpers.canvas + */ +var exports$1 = { + /** + * Clears the entire canvas associated to the given `chart`. + * @param {Chart} chart - The chart for which to clear the canvas. + */ + clear: function(chart) { + chart.ctx.clearRect(0, 0, chart.width, chart.height); + }, + + /** + * Creates a "path" for a rectangle with rounded corners at position (x, y) with a + * given size (width, height) and the same `radius` for all corners. + * @param {CanvasRenderingContext2D} ctx - The canvas 2D Context. + * @param {number} x - The x axis of the coordinate for the rectangle starting point. + * @param {number} y - The y axis of the coordinate for the rectangle starting point. + * @param {number} width - The rectangle's width. + * @param {number} height - The rectangle's height. + * @param {number} radius - The rounded amount (in pixels) for the four corners. + * @todo handle `radius` as top-left, top-right, bottom-right, bottom-left array/object? + */ + roundedRect: function(ctx, x, y, width, height, radius) { + if (radius) { + var r = Math.min(radius, height / 2, width / 2); + var left = x + r; + var top = y + r; + var right = x + width - r; + var bottom = y + height - r; + + ctx.moveTo(x, top); + if (left < right && top < bottom) { + ctx.arc(left, top, r, -PI, -HALF_PI); + ctx.arc(right, top, r, -HALF_PI, 0); + ctx.arc(right, bottom, r, 0, HALF_PI); + ctx.arc(left, bottom, r, HALF_PI, PI); + } else if (left < right) { + ctx.moveTo(left, y); + ctx.arc(right, top, r, -HALF_PI, HALF_PI); + ctx.arc(left, top, r, HALF_PI, PI + HALF_PI); + } else if (top < bottom) { + ctx.arc(left, top, r, -PI, 0); + ctx.arc(left, bottom, r, 0, PI); + } else { + ctx.arc(left, top, r, -PI, PI); + } + ctx.closePath(); + ctx.moveTo(x, y); + } else { + ctx.rect(x, y, width, height); + } + }, + + drawPoint: function(ctx, style, radius, x, y, rotation) { + var type, xOffset, yOffset, size, cornerRadius; + var rad = (rotation || 0) * RAD_PER_DEG; + + if (style && typeof style === 'object') { + type = style.toString(); + if (type === '[object HTMLImageElement]' || type === '[object HTMLCanvasElement]') { + ctx.drawImage(style, x - style.width / 2, y - style.height / 2, style.width, style.height); + return; + } + } + + if (isNaN(radius) || radius <= 0) { + return; + } + + ctx.beginPath(); + + switch (style) { + // Default includes circle + default: + ctx.arc(x, y, radius, 0, DOUBLE_PI); + ctx.closePath(); + break; + case 'triangle': + ctx.moveTo(x + Math.sin(rad) * radius, y - Math.cos(rad) * radius); + rad += TWO_THIRDS_PI; + ctx.lineTo(x + Math.sin(rad) * radius, y - Math.cos(rad) * radius); + rad += TWO_THIRDS_PI; + ctx.lineTo(x + Math.sin(rad) * radius, y - Math.cos(rad) * radius); + ctx.closePath(); + break; + case 'rectRounded': + // NOTE: the rounded rect implementation changed to use `arc` instead of + // `quadraticCurveTo` since it generates better results when rect is + // almost a circle. 0.516 (instead of 0.5) produces results with visually + // closer proportion to the previous impl and it is inscribed in the + // circle with `radius`. For more details, see the following PRs: + // https://github.com/chartjs/Chart.js/issues/5597 + // https://github.com/chartjs/Chart.js/issues/5858 + cornerRadius = radius * 0.516; + size = radius - cornerRadius; + xOffset = Math.cos(rad + QUARTER_PI) * size; + yOffset = Math.sin(rad + QUARTER_PI) * size; + ctx.arc(x - xOffset, y - yOffset, cornerRadius, rad - PI, rad - HALF_PI); + ctx.arc(x + yOffset, y - xOffset, cornerRadius, rad - HALF_PI, rad); + ctx.arc(x + xOffset, y + yOffset, cornerRadius, rad, rad + HALF_PI); + ctx.arc(x - yOffset, y + xOffset, cornerRadius, rad + HALF_PI, rad + PI); + ctx.closePath(); + break; + case 'rect': + if (!rotation) { + size = Math.SQRT1_2 * radius; + ctx.rect(x - size, y - size, 2 * size, 2 * size); + break; + } + rad += QUARTER_PI; + /* falls through */ + case 'rectRot': + xOffset = Math.cos(rad) * radius; + yOffset = Math.sin(rad) * radius; + ctx.moveTo(x - xOffset, y - yOffset); + ctx.lineTo(x + yOffset, y - xOffset); + ctx.lineTo(x + xOffset, y + yOffset); + ctx.lineTo(x - yOffset, y + xOffset); + ctx.closePath(); + break; + case 'crossRot': + rad += QUARTER_PI; + /* falls through */ + case 'cross': + xOffset = Math.cos(rad) * radius; + yOffset = Math.sin(rad) * radius; + ctx.moveTo(x - xOffset, y - yOffset); + ctx.lineTo(x + xOffset, y + yOffset); + ctx.moveTo(x + yOffset, y - xOffset); + ctx.lineTo(x - yOffset, y + xOffset); + break; + case 'star': + xOffset = Math.cos(rad) * radius; + yOffset = Math.sin(rad) * radius; + ctx.moveTo(x - xOffset, y - yOffset); + ctx.lineTo(x + xOffset, y + yOffset); + ctx.moveTo(x + yOffset, y - xOffset); + ctx.lineTo(x - yOffset, y + xOffset); + rad += QUARTER_PI; + xOffset = Math.cos(rad) * radius; + yOffset = Math.sin(rad) * radius; + ctx.moveTo(x - xOffset, y - yOffset); + ctx.lineTo(x + xOffset, y + yOffset); + ctx.moveTo(x + yOffset, y - xOffset); + ctx.lineTo(x - yOffset, y + xOffset); + break; + case 'line': + xOffset = Math.cos(rad) * radius; + yOffset = Math.sin(rad) * radius; + ctx.moveTo(x - xOffset, y - yOffset); + ctx.lineTo(x + xOffset, y + yOffset); + break; + case 'dash': + ctx.moveTo(x, y); + ctx.lineTo(x + Math.cos(rad) * radius, y + Math.sin(rad) * radius); + break; + } + + ctx.fill(); + ctx.stroke(); + }, + + /** + * Returns true if the point is inside the rectangle + * @param {object} point - The point to test + * @param {object} area - The rectangle + * @returns {boolean} + * @private + */ + _isPointInArea: function(point, area) { + var epsilon = 1e-6; // 1e-6 is margin in pixels for accumulated error. + + return point.x > area.left - epsilon && point.x < area.right + epsilon && + point.y > area.top - epsilon && point.y < area.bottom + epsilon; + }, + + clipArea: function(ctx, area) { + ctx.save(); + ctx.beginPath(); + ctx.rect(area.left, area.top, area.right - area.left, area.bottom - area.top); + ctx.clip(); + }, + + unclipArea: function(ctx) { + ctx.restore(); + }, + + lineTo: function(ctx, previous, target, flip) { + var stepped = target.steppedLine; + if (stepped) { + if (stepped === 'middle') { + var midpoint = (previous.x + target.x) / 2.0; + ctx.lineTo(midpoint, flip ? target.y : previous.y); + ctx.lineTo(midpoint, flip ? previous.y : target.y); + } else if ((stepped === 'after' && !flip) || (stepped !== 'after' && flip)) { + ctx.lineTo(previous.x, target.y); + } else { + ctx.lineTo(target.x, previous.y); + } + ctx.lineTo(target.x, target.y); + return; + } + + if (!target.tension) { + ctx.lineTo(target.x, target.y); + return; + } + + ctx.bezierCurveTo( + flip ? previous.controlPointPreviousX : previous.controlPointNextX, + flip ? previous.controlPointPreviousY : previous.controlPointNextY, + flip ? target.controlPointNextX : target.controlPointPreviousX, + flip ? target.controlPointNextY : target.controlPointPreviousY, + target.x, + target.y); + } +}; + +var helpers_canvas = exports$1; + +// DEPRECATIONS + +/** + * Provided for backward compatibility, use Chart.helpers.canvas.clear instead. + * @namespace Chart.helpers.clear + * @deprecated since version 2.7.0 + * @todo remove at version 3 + * @private + */ +helpers_core.clear = exports$1.clear; + +/** + * Provided for backward compatibility, use Chart.helpers.canvas.roundedRect instead. + * @namespace Chart.helpers.drawRoundedRectangle + * @deprecated since version 2.7.0 + * @todo remove at version 3 + * @private + */ +helpers_core.drawRoundedRectangle = function(ctx) { + ctx.beginPath(); + exports$1.roundedRect.apply(exports$1, arguments); +}; + +var defaults = { + /** + * @private + */ + _set: function(scope, values) { + return helpers_core.merge(this[scope] || (this[scope] = {}), values); + } +}; + +defaults._set('global', { + defaultColor: 'rgba(0,0,0,0.1)', + defaultFontColor: '#666', + defaultFontFamily: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif", + defaultFontSize: 12, + defaultFontStyle: 'normal', + defaultLineHeight: 1.2, + showLines: true +}); + +var core_defaults = defaults; + +var valueOrDefault = helpers_core.valueOrDefault; + +/** + * Converts the given font object into a CSS font string. + * @param {object} font - A font object. + * @return {string} The CSS font string. See https://developer.mozilla.org/en-US/docs/Web/CSS/font + * @private + */ +function toFontString(font) { + if (!font || helpers_core.isNullOrUndef(font.size) || helpers_core.isNullOrUndef(font.family)) { + return null; + } + + return (font.style ? font.style + ' ' : '') + + (font.weight ? font.weight + ' ' : '') + + font.size + 'px ' + + font.family; +} + +/** + * @alias Chart.helpers.options + * @namespace + */ +var helpers_options = { + /** + * Converts the given line height `value` in pixels for a specific font `size`. + * @param {number|string} value - The lineHeight to parse (eg. 1.6, '14px', '75%', '1.6em'). + * @param {number} size - The font size (in pixels) used to resolve relative `value`. + * @returns {number} The effective line height in pixels (size * 1.2 if value is invalid). + * @see https://developer.mozilla.org/en-US/docs/Web/CSS/line-height + * @since 2.7.0 + */ + toLineHeight: function(value, size) { + var matches = ('' + value).match(/^(normal|(\d+(?:\.\d+)?)(px|em|%)?)$/); + if (!matches || matches[1] === 'normal') { + return size * 1.2; + } + + value = +matches[2]; + + switch (matches[3]) { + case 'px': + return value; + case '%': + value /= 100; + break; + default: + break; + } + + return size * value; + }, + + /** + * Converts the given value into a padding object with pre-computed width/height. + * @param {number|object} value - If a number, set the value to all TRBL component, + * else, if and object, use defined properties and sets undefined ones to 0. + * @returns {object} The padding values (top, right, bottom, left, width, height) + * @since 2.7.0 + */ + toPadding: function(value) { + var t, r, b, l; + + if (helpers_core.isObject(value)) { + t = +value.top || 0; + r = +value.right || 0; + b = +value.bottom || 0; + l = +value.left || 0; + } else { + t = r = b = l = +value || 0; + } + + return { + top: t, + right: r, + bottom: b, + left: l, + height: t + b, + width: l + r + }; + }, + + /** + * Parses font options and returns the font object. + * @param {object} options - A object that contains font options to be parsed. + * @return {object} The font object. + * @todo Support font.* options and renamed to toFont(). + * @private + */ + _parseFont: function(options) { + var globalDefaults = core_defaults.global; + var size = valueOrDefault(options.fontSize, globalDefaults.defaultFontSize); + var font = { + family: valueOrDefault(options.fontFamily, globalDefaults.defaultFontFamily), + lineHeight: helpers_core.options.toLineHeight(valueOrDefault(options.lineHeight, globalDefaults.defaultLineHeight), size), + size: size, + style: valueOrDefault(options.fontStyle, globalDefaults.defaultFontStyle), + weight: null, + string: '' + }; + + font.string = toFontString(font); + return font; + }, + + /** + * Evaluates the given `inputs` sequentially and returns the first defined value. + * @param {Array} inputs - An array of values, falling back to the last value. + * @param {object} [context] - If defined and the current value is a function, the value + * is called with `context` as first argument and the result becomes the new input. + * @param {number} [index] - If defined and the current value is an array, the value + * at `index` become the new input. + * @since 2.7.0 + */ + resolve: function(inputs, context, index) { + var i, ilen, value; + + for (i = 0, ilen = inputs.length; i < ilen; ++i) { + value = inputs[i]; + if (value === undefined) { + continue; + } + if (context !== undefined && typeof value === 'function') { + value = value(context); + } + if (index !== undefined && helpers_core.isArray(value)) { + value = value[index]; + } + if (value !== undefined) { + return value; + } + } + } +}; + +var helpers$1 = helpers_core; +var easing = helpers_easing; +var canvas = helpers_canvas; +var options = helpers_options; +helpers$1.easing = easing; +helpers$1.canvas = canvas; +helpers$1.options = options; + +function interpolate(start, view, model, ease) { + var keys = Object.keys(model); + var i, ilen, key, actual, origin, target, type, c0, c1; + + for (i = 0, ilen = keys.length; i < ilen; ++i) { + key = keys[i]; + + target = model[key]; + + // if a value is added to the model after pivot() has been called, the view + // doesn't contain it, so let's initialize the view to the target value. + if (!view.hasOwnProperty(key)) { + view[key] = target; + } + + actual = view[key]; + + if (actual === target || key[0] === '_') { + continue; + } + + if (!start.hasOwnProperty(key)) { + start[key] = actual; + } + + origin = start[key]; + + type = typeof target; + + if (type === typeof origin) { + if (type === 'string') { + c0 = chartjsColor(origin); + if (c0.valid) { + c1 = chartjsColor(target); + if (c1.valid) { + view[key] = c1.mix(c0, ease).rgbString(); + continue; + } + } + } else if (helpers$1.isFinite(origin) && helpers$1.isFinite(target)) { + view[key] = origin + (target - origin) * ease; + continue; + } + } + + view[key] = target; + } +} + +var Element = function(configuration) { + helpers$1.extend(this, configuration); + this.initialize.apply(this, arguments); +}; + +helpers$1.extend(Element.prototype, { + + initialize: function() { + this.hidden = false; + }, + + pivot: function() { + var me = this; + if (!me._view) { + me._view = helpers$1.clone(me._model); + } + me._start = {}; + return me; + }, + + transition: function(ease) { + var me = this; + var model = me._model; + var start = me._start; + var view = me._view; + + // No animation -> No Transition + if (!model || ease === 1) { + me._view = model; + me._start = null; + return me; + } + + if (!view) { + view = me._view = {}; + } + + if (!start) { + start = me._start = {}; + } + + interpolate(start, view, model, ease); + + return me; + }, + + tooltipPosition: function() { + return { + x: this._model.x, + y: this._model.y + }; + }, + + hasValue: function() { + return helpers$1.isNumber(this._model.x) && helpers$1.isNumber(this._model.y); + } +}); + +Element.extend = helpers$1.inherits; + +var core_element = Element; + +var exports$2 = core_element.extend({ + chart: null, // the animation associated chart instance + currentStep: 0, // the current animation step + numSteps: 60, // default number of steps + easing: '', // the easing to use for this animation + render: null, // render function used by the animation service + + onAnimationProgress: null, // user specified callback to fire on each step of the animation + onAnimationComplete: null, // user specified callback to fire when the animation finishes +}); + +var core_animation = exports$2; + +// DEPRECATIONS + +/** + * Provided for backward compatibility, use Chart.Animation instead + * @prop Chart.Animation#animationObject + * @deprecated since version 2.6.0 + * @todo remove at version 3 + */ +Object.defineProperty(exports$2.prototype, 'animationObject', { + get: function() { + return this; + } +}); + +/** + * Provided for backward compatibility, use Chart.Animation#chart instead + * @prop Chart.Animation#chartInstance + * @deprecated since version 2.6.0 + * @todo remove at version 3 + */ +Object.defineProperty(exports$2.prototype, 'chartInstance', { + get: function() { + return this.chart; + }, + set: function(value) { + this.chart = value; + } +}); + +core_defaults._set('global', { + animation: { + duration: 1000, + easing: 'easeOutQuart', + onProgress: helpers$1.noop, + onComplete: helpers$1.noop + } +}); + +var core_animations = { + animations: [], + request: null, + + /** + * @param {Chart} chart - The chart to animate. + * @param {Chart.Animation} animation - The animation that we will animate. + * @param {number} duration - The animation duration in ms. + * @param {boolean} lazy - if true, the chart is not marked as animating to enable more responsive interactions + */ + addAnimation: function(chart, animation, duration, lazy) { + var animations = this.animations; + var i, ilen; + + animation.chart = chart; + animation.startTime = Date.now(); + animation.duration = duration; + + if (!lazy) { + chart.animating = true; + } + + for (i = 0, ilen = animations.length; i < ilen; ++i) { + if (animations[i].chart === chart) { + animations[i] = animation; + return; + } + } + + animations.push(animation); + + // If there are no animations queued, manually kickstart a digest, for lack of a better word + if (animations.length === 1) { + this.requestAnimationFrame(); + } + }, + + cancelAnimation: function(chart) { + var index = helpers$1.findIndex(this.animations, function(animation) { + return animation.chart === chart; + }); + + if (index !== -1) { + this.animations.splice(index, 1); + chart.animating = false; + } + }, + + requestAnimationFrame: function() { + var me = this; + if (me.request === null) { + // Skip animation frame requests until the active one is executed. + // This can happen when processing mouse events, e.g. 'mousemove' + // and 'mouseout' events will trigger multiple renders. + me.request = helpers$1.requestAnimFrame.call(window, function() { + me.request = null; + me.startDigest(); + }); + } + }, + + /** + * @private + */ + startDigest: function() { + var me = this; + + me.advance(); + + // Do we have more stuff to animate? + if (me.animations.length > 0) { + me.requestAnimationFrame(); + } + }, + + /** + * @private + */ + advance: function() { + var animations = this.animations; + var animation, chart, numSteps, nextStep; + var i = 0; + + // 1 animation per chart, so we are looping charts here + while (i < animations.length) { + animation = animations[i]; + chart = animation.chart; + numSteps = animation.numSteps; + + // Make sure that currentStep starts at 1 + // https://github.com/chartjs/Chart.js/issues/6104 + nextStep = Math.floor((Date.now() - animation.startTime) / animation.duration * numSteps) + 1; + animation.currentStep = Math.min(nextStep, numSteps); + + helpers$1.callback(animation.render, [chart, animation], chart); + helpers$1.callback(animation.onAnimationProgress, [animation], chart); + + if (animation.currentStep >= numSteps) { + helpers$1.callback(animation.onAnimationComplete, [animation], chart); + chart.animating = false; + animations.splice(i, 1); + } else { + ++i; + } + } + } +}; + +var resolve = helpers$1.options.resolve; + +var arrayEvents = ['push', 'pop', 'shift', 'splice', 'unshift']; + +/** + * Hooks the array methods that add or remove values ('push', pop', 'shift', 'splice', + * 'unshift') and notify the listener AFTER the array has been altered. Listeners are + * called on the 'onData*' callbacks (e.g. onDataPush, etc.) with same arguments. + */ +function listenArrayEvents(array, listener) { + if (array._chartjs) { + array._chartjs.listeners.push(listener); + return; + } + + Object.defineProperty(array, '_chartjs', { + configurable: true, + enumerable: false, + value: { + listeners: [listener] + } + }); + + arrayEvents.forEach(function(key) { + var method = 'onData' + key.charAt(0).toUpperCase() + key.slice(1); + var base = array[key]; + + Object.defineProperty(array, key, { + configurable: true, + enumerable: false, + value: function() { + var args = Array.prototype.slice.call(arguments); + var res = base.apply(this, args); + + helpers$1.each(array._chartjs.listeners, function(object) { + if (typeof object[method] === 'function') { + object[method].apply(object, args); + } + }); + + return res; + } + }); + }); +} + +/** + * Removes the given array event listener and cleanup extra attached properties (such as + * the _chartjs stub and overridden methods) if array doesn't have any more listeners. + */ +function unlistenArrayEvents(array, listener) { + var stub = array._chartjs; + if (!stub) { + return; + } + + var listeners = stub.listeners; + var index = listeners.indexOf(listener); + if (index !== -1) { + listeners.splice(index, 1); + } + + if (listeners.length > 0) { + return; + } + + arrayEvents.forEach(function(key) { + delete array[key]; + }); + + delete array._chartjs; +} + +// Base class for all dataset controllers (line, bar, etc) +var DatasetController = function(chart, datasetIndex) { + this.initialize(chart, datasetIndex); +}; + +helpers$1.extend(DatasetController.prototype, { + + /** + * Element type used to generate a meta dataset (e.g. Chart.element.Line). + * @type {Chart.core.element} + */ + datasetElementType: null, + + /** + * Element type used to generate a meta data (e.g. Chart.element.Point). + * @type {Chart.core.element} + */ + dataElementType: null, + + initialize: function(chart, datasetIndex) { + var me = this; + me.chart = chart; + me.index = datasetIndex; + me.linkScales(); + me.addElements(); + }, + + updateIndex: function(datasetIndex) { + this.index = datasetIndex; + }, + + linkScales: function() { + var me = this; + var meta = me.getMeta(); + var dataset = me.getDataset(); + + if (meta.xAxisID === null || !(meta.xAxisID in me.chart.scales)) { + meta.xAxisID = dataset.xAxisID || me.chart.options.scales.xAxes[0].id; + } + if (meta.yAxisID === null || !(meta.yAxisID in me.chart.scales)) { + meta.yAxisID = dataset.yAxisID || me.chart.options.scales.yAxes[0].id; + } + }, + + getDataset: function() { + return this.chart.data.datasets[this.index]; + }, + + getMeta: function() { + return this.chart.getDatasetMeta(this.index); + }, + + getScaleForId: function(scaleID) { + return this.chart.scales[scaleID]; + }, + + /** + * @private + */ + _getValueScaleId: function() { + return this.getMeta().yAxisID; + }, + + /** + * @private + */ + _getIndexScaleId: function() { + return this.getMeta().xAxisID; + }, + + /** + * @private + */ + _getValueScale: function() { + return this.getScaleForId(this._getValueScaleId()); + }, + + /** + * @private + */ + _getIndexScale: function() { + return this.getScaleForId(this._getIndexScaleId()); + }, + + reset: function() { + this.update(true); + }, + + /** + * @private + */ + destroy: function() { + if (this._data) { + unlistenArrayEvents(this._data, this); + } + }, + + createMetaDataset: function() { + var me = this; + var type = me.datasetElementType; + return type && new type({ + _chart: me.chart, + _datasetIndex: me.index + }); + }, + + createMetaData: function(index) { + var me = this; + var type = me.dataElementType; + return type && new type({ + _chart: me.chart, + _datasetIndex: me.index, + _index: index + }); + }, + + addElements: function() { + var me = this; + var meta = me.getMeta(); + var data = me.getDataset().data || []; + var metaData = meta.data; + var i, ilen; + + for (i = 0, ilen = data.length; i < ilen; ++i) { + metaData[i] = metaData[i] || me.createMetaData(i); + } + + meta.dataset = meta.dataset || me.createMetaDataset(); + }, + + addElementAndReset: function(index) { + var element = this.createMetaData(index); + this.getMeta().data.splice(index, 0, element); + this.updateElement(element, index, true); + }, + + buildOrUpdateElements: function() { + var me = this; + var dataset = me.getDataset(); + var data = dataset.data || (dataset.data = []); + + // In order to correctly handle data addition/deletion animation (an thus simulate + // real-time charts), we need to monitor these data modifications and synchronize + // the internal meta data accordingly. + if (me._data !== data) { + if (me._data) { + // This case happens when the user replaced the data array instance. + unlistenArrayEvents(me._data, me); + } + + if (data && Object.isExtensible(data)) { + listenArrayEvents(data, me); + } + me._data = data; + } + + // Re-sync meta data in case the user replaced the data array or if we missed + // any updates and so make sure that we handle number of datapoints changing. + me.resyncElements(); + }, + + update: helpers$1.noop, + + transition: function(easingValue) { + var meta = this.getMeta(); + var elements = meta.data || []; + var ilen = elements.length; + var i = 0; + + for (; i < ilen; ++i) { + elements[i].transition(easingValue); + } + + if (meta.dataset) { + meta.dataset.transition(easingValue); + } + }, + + draw: function() { + var meta = this.getMeta(); + var elements = meta.data || []; + var ilen = elements.length; + var i = 0; + + if (meta.dataset) { + meta.dataset.draw(); + } + + for (; i < ilen; ++i) { + elements[i].draw(); + } + }, + + removeHoverStyle: function(element) { + helpers$1.merge(element._model, element.$previousStyle || {}); + delete element.$previousStyle; + }, + + setHoverStyle: function(element) { + var dataset = this.chart.data.datasets[element._datasetIndex]; + var index = element._index; + var custom = element.custom || {}; + var model = element._model; + var getHoverColor = helpers$1.getHoverColor; + + element.$previousStyle = { + backgroundColor: model.backgroundColor, + borderColor: model.borderColor, + borderWidth: model.borderWidth + }; + + model.backgroundColor = resolve([custom.hoverBackgroundColor, dataset.hoverBackgroundColor, getHoverColor(model.backgroundColor)], undefined, index); + model.borderColor = resolve([custom.hoverBorderColor, dataset.hoverBorderColor, getHoverColor(model.borderColor)], undefined, index); + model.borderWidth = resolve([custom.hoverBorderWidth, dataset.hoverBorderWidth, model.borderWidth], undefined, index); + }, + + /** + * @private + */ + resyncElements: function() { + var me = this; + var meta = me.getMeta(); + var data = me.getDataset().data; + var numMeta = meta.data.length; + var numData = data.length; + + if (numData < numMeta) { + meta.data.splice(numData, numMeta - numData); + } else if (numData > numMeta) { + me.insertElements(numMeta, numData - numMeta); + } + }, + + /** + * @private + */ + insertElements: function(start, count) { + for (var i = 0; i < count; ++i) { + this.addElementAndReset(start + i); + } + }, + + /** + * @private + */ + onDataPush: function() { + var count = arguments.length; + this.insertElements(this.getDataset().data.length - count, count); + }, + + /** + * @private + */ + onDataPop: function() { + this.getMeta().data.pop(); + }, + + /** + * @private + */ + onDataShift: function() { + this.getMeta().data.shift(); + }, + + /** + * @private + */ + onDataSplice: function(start, count) { + this.getMeta().data.splice(start, count); + this.insertElements(start, arguments.length - 2); + }, + + /** + * @private + */ + onDataUnshift: function() { + this.insertElements(0, arguments.length); + } +}); + +DatasetController.extend = helpers$1.inherits; + +var core_datasetController = DatasetController; + +core_defaults._set('global', { + elements: { + arc: { + backgroundColor: core_defaults.global.defaultColor, + borderColor: '#fff', + borderWidth: 2, + borderAlign: 'center' + } + } +}); + +var element_arc = core_element.extend({ + inLabelRange: function(mouseX) { + var vm = this._view; + + if (vm) { + return (Math.pow(mouseX - vm.x, 2) < Math.pow(vm.radius + vm.hoverRadius, 2)); + } + return false; + }, + + inRange: function(chartX, chartY) { + var vm = this._view; + + if (vm) { + var pointRelativePosition = helpers$1.getAngleFromPoint(vm, {x: chartX, y: chartY}); + var angle = pointRelativePosition.angle; + var distance = pointRelativePosition.distance; + + // Sanitise angle range + var startAngle = vm.startAngle; + var endAngle = vm.endAngle; + while (endAngle < startAngle) { + endAngle += 2.0 * Math.PI; + } + while (angle > endAngle) { + angle -= 2.0 * Math.PI; + } + while (angle < startAngle) { + angle += 2.0 * Math.PI; + } + + // Check if within the range of the open/close angle + var betweenAngles = (angle >= startAngle && angle <= endAngle); + var withinRadius = (distance >= vm.innerRadius && distance <= vm.outerRadius); + + return (betweenAngles && withinRadius); + } + return false; + }, + + getCenterPoint: function() { + var vm = this._view; + var halfAngle = (vm.startAngle + vm.endAngle) / 2; + var halfRadius = (vm.innerRadius + vm.outerRadius) / 2; + return { + x: vm.x + Math.cos(halfAngle) * halfRadius, + y: vm.y + Math.sin(halfAngle) * halfRadius + }; + }, + + getArea: function() { + var vm = this._view; + return Math.PI * ((vm.endAngle - vm.startAngle) / (2 * Math.PI)) * (Math.pow(vm.outerRadius, 2) - Math.pow(vm.innerRadius, 2)); + }, + + tooltipPosition: function() { + var vm = this._view; + var centreAngle = vm.startAngle + ((vm.endAngle - vm.startAngle) / 2); + var rangeFromCentre = (vm.outerRadius - vm.innerRadius) / 2 + vm.innerRadius; + + return { + x: vm.x + (Math.cos(centreAngle) * rangeFromCentre), + y: vm.y + (Math.sin(centreAngle) * rangeFromCentre) + }; + }, + + draw: function() { + var ctx = this._chart.ctx; + var vm = this._view; + var sA = vm.startAngle; + var eA = vm.endAngle; + var pixelMargin = (vm.borderAlign === 'inner') ? 0.33 : 0; + var angleMargin; + + ctx.save(); + + ctx.beginPath(); + ctx.arc(vm.x, vm.y, Math.max(vm.outerRadius - pixelMargin, 0), sA, eA); + ctx.arc(vm.x, vm.y, vm.innerRadius, eA, sA, true); + ctx.closePath(); + + ctx.fillStyle = vm.backgroundColor; + ctx.fill(); + + if (vm.borderWidth) { + if (vm.borderAlign === 'inner') { + // Draw an inner border by cliping the arc and drawing a double-width border + // Enlarge the clipping arc by 0.33 pixels to eliminate glitches between borders + ctx.beginPath(); + angleMargin = pixelMargin / vm.outerRadius; + ctx.arc(vm.x, vm.y, vm.outerRadius, sA - angleMargin, eA + angleMargin); + if (vm.innerRadius > pixelMargin) { + angleMargin = pixelMargin / vm.innerRadius; + ctx.arc(vm.x, vm.y, vm.innerRadius - pixelMargin, eA + angleMargin, sA - angleMargin, true); + } else { + ctx.arc(vm.x, vm.y, pixelMargin, eA + Math.PI / 2, sA - Math.PI / 2); + } + ctx.closePath(); + ctx.clip(); + + ctx.beginPath(); + ctx.arc(vm.x, vm.y, vm.outerRadius, sA, eA); + ctx.arc(vm.x, vm.y, vm.innerRadius, eA, sA, true); + ctx.closePath(); + + ctx.lineWidth = vm.borderWidth * 2; + ctx.lineJoin = 'round'; + } else { + ctx.lineWidth = vm.borderWidth; + ctx.lineJoin = 'bevel'; + } + + ctx.strokeStyle = vm.borderColor; + ctx.stroke(); + } + + ctx.restore(); + } +}); + +var valueOrDefault$1 = helpers$1.valueOrDefault; + +var defaultColor = core_defaults.global.defaultColor; + +core_defaults._set('global', { + elements: { + line: { + tension: 0.4, + backgroundColor: defaultColor, + borderWidth: 3, + borderColor: defaultColor, + borderCapStyle: 'butt', + borderDash: [], + borderDashOffset: 0.0, + borderJoinStyle: 'miter', + capBezierPoints: true, + fill: true, // do we fill in the area between the line and its base axis + } + } +}); + +var element_line = core_element.extend({ + draw: function() { + var me = this; + var vm = me._view; + var ctx = me._chart.ctx; + var spanGaps = vm.spanGaps; + var points = me._children.slice(); // clone array + var globalDefaults = core_defaults.global; + var globalOptionLineElements = globalDefaults.elements.line; + var lastDrawnIndex = -1; + var index, current, previous, currentVM; + + // If we are looping, adding the first point again + if (me._loop && points.length) { + points.push(points[0]); + } + + ctx.save(); + + // Stroke Line Options + ctx.lineCap = vm.borderCapStyle || globalOptionLineElements.borderCapStyle; + + // IE 9 and 10 do not support line dash + if (ctx.setLineDash) { + ctx.setLineDash(vm.borderDash || globalOptionLineElements.borderDash); + } + + ctx.lineDashOffset = valueOrDefault$1(vm.borderDashOffset, globalOptionLineElements.borderDashOffset); + ctx.lineJoin = vm.borderJoinStyle || globalOptionLineElements.borderJoinStyle; + ctx.lineWidth = valueOrDefault$1(vm.borderWidth, globalOptionLineElements.borderWidth); + ctx.strokeStyle = vm.borderColor || globalDefaults.defaultColor; + + // Stroke Line + ctx.beginPath(); + lastDrawnIndex = -1; + + for (index = 0; index < points.length; ++index) { + current = points[index]; + previous = helpers$1.previousItem(points, index); + currentVM = current._view; + + // First point moves to it's starting position no matter what + if (index === 0) { + if (!currentVM.skip) { + ctx.moveTo(currentVM.x, currentVM.y); + lastDrawnIndex = index; + } + } else { + previous = lastDrawnIndex === -1 ? previous : points[lastDrawnIndex]; + + if (!currentVM.skip) { + if ((lastDrawnIndex !== (index - 1) && !spanGaps) || lastDrawnIndex === -1) { + // There was a gap and this is the first point after the gap + ctx.moveTo(currentVM.x, currentVM.y); + } else { + // Line to next point + helpers$1.canvas.lineTo(ctx, previous._view, current._view); + } + lastDrawnIndex = index; + } + } + } + + ctx.stroke(); + ctx.restore(); + } +}); + +var valueOrDefault$2 = helpers$1.valueOrDefault; + +var defaultColor$1 = core_defaults.global.defaultColor; + +core_defaults._set('global', { + elements: { + point: { + radius: 3, + pointStyle: 'circle', + backgroundColor: defaultColor$1, + borderColor: defaultColor$1, + borderWidth: 1, + // Hover + hitRadius: 1, + hoverRadius: 4, + hoverBorderWidth: 1 + } + } +}); + +function xRange(mouseX) { + var vm = this._view; + return vm ? (Math.abs(mouseX - vm.x) < vm.radius + vm.hitRadius) : false; +} + +function yRange(mouseY) { + var vm = this._view; + return vm ? (Math.abs(mouseY - vm.y) < vm.radius + vm.hitRadius) : false; +} + +var element_point = core_element.extend({ + inRange: function(mouseX, mouseY) { + var vm = this._view; + return vm ? ((Math.pow(mouseX - vm.x, 2) + Math.pow(mouseY - vm.y, 2)) < Math.pow(vm.hitRadius + vm.radius, 2)) : false; + }, + + inLabelRange: xRange, + inXRange: xRange, + inYRange: yRange, + + getCenterPoint: function() { + var vm = this._view; + return { + x: vm.x, + y: vm.y + }; + }, + + getArea: function() { + return Math.PI * Math.pow(this._view.radius, 2); + }, + + tooltipPosition: function() { + var vm = this._view; + return { + x: vm.x, + y: vm.y, + padding: vm.radius + vm.borderWidth + }; + }, + + draw: function(chartArea) { + var vm = this._view; + var ctx = this._chart.ctx; + var pointStyle = vm.pointStyle; + var rotation = vm.rotation; + var radius = vm.radius; + var x = vm.x; + var y = vm.y; + var globalDefaults = core_defaults.global; + var defaultColor = globalDefaults.defaultColor; // eslint-disable-line no-shadow + + if (vm.skip) { + return; + } + + // Clipping for Points. + if (chartArea === undefined || helpers$1.canvas._isPointInArea(vm, chartArea)) { + ctx.strokeStyle = vm.borderColor || defaultColor; + ctx.lineWidth = valueOrDefault$2(vm.borderWidth, globalDefaults.elements.point.borderWidth); + ctx.fillStyle = vm.backgroundColor || defaultColor; + helpers$1.canvas.drawPoint(ctx, pointStyle, radius, x, y, rotation); + } + } +}); + +var defaultColor$2 = core_defaults.global.defaultColor; + +core_defaults._set('global', { + elements: { + rectangle: { + backgroundColor: defaultColor$2, + borderColor: defaultColor$2, + borderSkipped: 'bottom', + borderWidth: 0 + } + } +}); + +function isVertical(vm) { + return vm && vm.width !== undefined; +} + +/** + * Helper function to get the bounds of the bar regardless of the orientation + * @param bar {Chart.Element.Rectangle} the bar + * @return {Bounds} bounds of the bar + * @private + */ +function getBarBounds(vm) { + var x1, x2, y1, y2, half; + + if (isVertical(vm)) { + half = vm.width / 2; + x1 = vm.x - half; + x2 = vm.x + half; + y1 = Math.min(vm.y, vm.base); + y2 = Math.max(vm.y, vm.base); + } else { + half = vm.height / 2; + x1 = Math.min(vm.x, vm.base); + x2 = Math.max(vm.x, vm.base); + y1 = vm.y - half; + y2 = vm.y + half; + } + + return { + left: x1, + top: y1, + right: x2, + bottom: y2 + }; +} + +function swap(orig, v1, v2) { + return orig === v1 ? v2 : orig === v2 ? v1 : orig; +} + +function parseBorderSkipped(vm) { + var edge = vm.borderSkipped; + var res = {}; + + if (!edge) { + return res; + } + + if (vm.horizontal) { + if (vm.base > vm.x) { + edge = swap(edge, 'left', 'right'); + } + } else if (vm.base < vm.y) { + edge = swap(edge, 'bottom', 'top'); + } + + res[edge] = true; + return res; +} + +function parseBorderWidth(vm, maxW, maxH) { + var value = vm.borderWidth; + var skip = parseBorderSkipped(vm); + var t, r, b, l; + + if (helpers$1.isObject(value)) { + t = +value.top || 0; + r = +value.right || 0; + b = +value.bottom || 0; + l = +value.left || 0; + } else { + t = r = b = l = +value || 0; + } + + return { + t: skip.top || (t < 0) ? 0 : t > maxH ? maxH : t, + r: skip.right || (r < 0) ? 0 : r > maxW ? maxW : r, + b: skip.bottom || (b < 0) ? 0 : b > maxH ? maxH : b, + l: skip.left || (l < 0) ? 0 : l > maxW ? maxW : l + }; +} + +function boundingRects(vm) { + var bounds = getBarBounds(vm); + var width = bounds.right - bounds.left; + var height = bounds.bottom - bounds.top; + var border = parseBorderWidth(vm, width / 2, height / 2); + + return { + outer: { + x: bounds.left, + y: bounds.top, + w: width, + h: height + }, + inner: { + x: bounds.left + border.l, + y: bounds.top + border.t, + w: width - border.l - border.r, + h: height - border.t - border.b + } + }; +} + +function inRange(vm, x, y) { + var skipX = x === null; + var skipY = y === null; + var bounds = !vm || (skipX && skipY) ? false : getBarBounds(vm); + + return bounds + && (skipX || x >= bounds.left && x <= bounds.right) + && (skipY || y >= bounds.top && y <= bounds.bottom); +} + +var element_rectangle = core_element.extend({ + draw: function() { + var ctx = this._chart.ctx; + var vm = this._view; + var rects = boundingRects(vm); + var outer = rects.outer; + var inner = rects.inner; + + ctx.fillStyle = vm.backgroundColor; + ctx.fillRect(outer.x, outer.y, outer.w, outer.h); + + if (outer.w === inner.w && outer.h === inner.h) { + return; + } + + ctx.save(); + ctx.beginPath(); + ctx.rect(outer.x, outer.y, outer.w, outer.h); + ctx.clip(); + ctx.fillStyle = vm.borderColor; + ctx.rect(inner.x, inner.y, inner.w, inner.h); + ctx.fill('evenodd'); + ctx.restore(); + }, + + height: function() { + var vm = this._view; + return vm.base - vm.y; + }, + + inRange: function(mouseX, mouseY) { + return inRange(this._view, mouseX, mouseY); + }, + + inLabelRange: function(mouseX, mouseY) { + var vm = this._view; + return isVertical(vm) + ? inRange(vm, mouseX, null) + : inRange(vm, null, mouseY); + }, + + inXRange: function(mouseX) { + return inRange(this._view, mouseX, null); + }, + + inYRange: function(mouseY) { + return inRange(this._view, null, mouseY); + }, + + getCenterPoint: function() { + var vm = this._view; + var x, y; + if (isVertical(vm)) { + x = vm.x; + y = (vm.y + vm.base) / 2; + } else { + x = (vm.x + vm.base) / 2; + y = vm.y; + } + + return {x: x, y: y}; + }, + + getArea: function() { + var vm = this._view; + + return isVertical(vm) + ? vm.width * Math.abs(vm.y - vm.base) + : vm.height * Math.abs(vm.x - vm.base); + }, + + tooltipPosition: function() { + var vm = this._view; + return { + x: vm.x, + y: vm.y + }; + } +}); + +var elements = {}; +var Arc = element_arc; +var Line = element_line; +var Point = element_point; +var Rectangle = element_rectangle; +elements.Arc = Arc; +elements.Line = Line; +elements.Point = Point; +elements.Rectangle = Rectangle; + +var resolve$1 = helpers$1.options.resolve; + +core_defaults._set('bar', { + hover: { + mode: 'label' + }, + + scales: { + xAxes: [{ + type: 'category', + categoryPercentage: 0.8, + barPercentage: 0.9, + offset: true, + gridLines: { + offsetGridLines: true + } + }], + + yAxes: [{ + type: 'linear' + }] + } +}); + +/** + * Computes the "optimal" sample size to maintain bars equally sized while preventing overlap. + * @private + */ +function computeMinSampleSize(scale, pixels) { + var min = scale.isHorizontal() ? scale.width : scale.height; + var ticks = scale.getTicks(); + var prev, curr, i, ilen; + + for (i = 1, ilen = pixels.length; i < ilen; ++i) { + min = Math.min(min, Math.abs(pixels[i] - pixels[i - 1])); + } + + for (i = 0, ilen = ticks.length; i < ilen; ++i) { + curr = scale.getPixelForTick(i); + min = i > 0 ? Math.min(min, curr - prev) : min; + prev = curr; + } + + return min; +} + +/** + * Computes an "ideal" category based on the absolute bar thickness or, if undefined or null, + * uses the smallest interval (see computeMinSampleSize) that prevents bar overlapping. This + * mode currently always generates bars equally sized (until we introduce scriptable options?). + * @private + */ +function computeFitCategoryTraits(index, ruler, options) { + var thickness = options.barThickness; + var count = ruler.stackCount; + var curr = ruler.pixels[index]; + var size, ratio; + + if (helpers$1.isNullOrUndef(thickness)) { + size = ruler.min * options.categoryPercentage; + ratio = options.barPercentage; + } else { + // When bar thickness is enforced, category and bar percentages are ignored. + // Note(SB): we could add support for relative bar thickness (e.g. barThickness: '50%') + // and deprecate barPercentage since this value is ignored when thickness is absolute. + size = thickness * count; + ratio = 1; + } + + return { + chunk: size / count, + ratio: ratio, + start: curr - (size / 2) + }; +} + +/** + * Computes an "optimal" category that globally arranges bars side by side (no gap when + * percentage options are 1), based on the previous and following categories. This mode + * generates bars with different widths when data are not evenly spaced. + * @private + */ +function computeFlexCategoryTraits(index, ruler, options) { + var pixels = ruler.pixels; + var curr = pixels[index]; + var prev = index > 0 ? pixels[index - 1] : null; + var next = index < pixels.length - 1 ? pixels[index + 1] : null; + var percent = options.categoryPercentage; + var start, size; + + if (prev === null) { + // first data: its size is double based on the next point or, + // if it's also the last data, we use the scale size. + prev = curr - (next === null ? ruler.end - ruler.start : next - curr); + } + + if (next === null) { + // last data: its size is also double based on the previous point. + next = curr + curr - prev; + } + + start = curr - (curr - Math.min(prev, next)) / 2 * percent; + size = Math.abs(next - prev) / 2 * percent; + + return { + chunk: size / ruler.stackCount, + ratio: options.barPercentage, + start: start + }; +} + +var controller_bar = core_datasetController.extend({ + + dataElementType: elements.Rectangle, + + initialize: function() { + var me = this; + var meta; + + core_datasetController.prototype.initialize.apply(me, arguments); + + meta = me.getMeta(); + meta.stack = me.getDataset().stack; + meta.bar = true; + }, + + update: function(reset) { + var me = this; + var rects = me.getMeta().data; + var i, ilen; + + me._ruler = me.getRuler(); + + for (i = 0, ilen = rects.length; i < ilen; ++i) { + me.updateElement(rects[i], i, reset); + } + }, + + updateElement: function(rectangle, index, reset) { + var me = this; + var meta = me.getMeta(); + var dataset = me.getDataset(); + var options = me._resolveElementOptions(rectangle, index); + + rectangle._xScale = me.getScaleForId(meta.xAxisID); + rectangle._yScale = me.getScaleForId(meta.yAxisID); + rectangle._datasetIndex = me.index; + rectangle._index = index; + rectangle._model = { + backgroundColor: options.backgroundColor, + borderColor: options.borderColor, + borderSkipped: options.borderSkipped, + borderWidth: options.borderWidth, + datasetLabel: dataset.label, + label: me.chart.data.labels[index] + }; + + me._updateElementGeometry(rectangle, index, reset); + + rectangle.pivot(); + }, + + /** + * @private + */ + _updateElementGeometry: function(rectangle, index, reset) { + var me = this; + var model = rectangle._model; + var vscale = me._getValueScale(); + var base = vscale.getBasePixel(); + var horizontal = vscale.isHorizontal(); + var ruler = me._ruler || me.getRuler(); + var vpixels = me.calculateBarValuePixels(me.index, index); + var ipixels = me.calculateBarIndexPixels(me.index, index, ruler); + + model.horizontal = horizontal; + model.base = reset ? base : vpixels.base; + model.x = horizontal ? reset ? base : vpixels.head : ipixels.center; + model.y = horizontal ? ipixels.center : reset ? base : vpixels.head; + model.height = horizontal ? ipixels.size : undefined; + model.width = horizontal ? undefined : ipixels.size; + }, + + /** + * Returns the stacks based on groups and bar visibility. + * @param {number} [last] - The dataset index + * @returns {string[]} The list of stack IDs + * @private + */ + _getStacks: function(last) { + var me = this; + var chart = me.chart; + var scale = me._getIndexScale(); + var stacked = scale.options.stacked; + var ilen = last === undefined ? chart.data.datasets.length : last + 1; + var stacks = []; + var i, meta; + + for (i = 0; i < ilen; ++i) { + meta = chart.getDatasetMeta(i); + if (meta.bar && chart.isDatasetVisible(i) && + (stacked === false || + (stacked === true && stacks.indexOf(meta.stack) === -1) || + (stacked === undefined && (meta.stack === undefined || stacks.indexOf(meta.stack) === -1)))) { + stacks.push(meta.stack); + } + } + + return stacks; + }, + + /** + * Returns the effective number of stacks based on groups and bar visibility. + * @private + */ + getStackCount: function() { + return this._getStacks().length; + }, + + /** + * Returns the stack index for the given dataset based on groups and bar visibility. + * @param {number} [datasetIndex] - The dataset index + * @param {string} [name] - The stack name to find + * @returns {number} The stack index + * @private + */ + getStackIndex: function(datasetIndex, name) { + var stacks = this._getStacks(datasetIndex); + var index = (name !== undefined) + ? stacks.indexOf(name) + : -1; // indexOf returns -1 if element is not present + + return (index === -1) + ? stacks.length - 1 + : index; + }, + + /** + * @private + */ + getRuler: function() { + var me = this; + var scale = me._getIndexScale(); + var stackCount = me.getStackCount(); + var datasetIndex = me.index; + var isHorizontal = scale.isHorizontal(); + var start = isHorizontal ? scale.left : scale.top; + var end = start + (isHorizontal ? scale.width : scale.height); + var pixels = []; + var i, ilen, min; + + for (i = 0, ilen = me.getMeta().data.length; i < ilen; ++i) { + pixels.push(scale.getPixelForValue(null, i, datasetIndex)); + } + + min = helpers$1.isNullOrUndef(scale.options.barThickness) + ? computeMinSampleSize(scale, pixels) + : -1; + + return { + min: min, + pixels: pixels, + start: start, + end: end, + stackCount: stackCount, + scale: scale + }; + }, + + /** + * Note: pixel values are not clamped to the scale area. + * @private + */ + calculateBarValuePixels: function(datasetIndex, index) { + var me = this; + var chart = me.chart; + var meta = me.getMeta(); + var scale = me._getValueScale(); + var isHorizontal = scale.isHorizontal(); + var datasets = chart.data.datasets; + var value = +scale.getRightValue(datasets[datasetIndex].data[index]); + var minBarLength = scale.options.minBarLength; + var stacked = scale.options.stacked; + var stack = meta.stack; + var start = 0; + var i, imeta, ivalue, base, head, size; + + if (stacked || (stacked === undefined && stack !== undefined)) { + for (i = 0; i < datasetIndex; ++i) { + imeta = chart.getDatasetMeta(i); + + if (imeta.bar && + imeta.stack === stack && + imeta.controller._getValueScaleId() === scale.id && + chart.isDatasetVisible(i)) { + + ivalue = +scale.getRightValue(datasets[i].data[index]); + if ((value < 0 && ivalue < 0) || (value >= 0 && ivalue > 0)) { + start += ivalue; + } + } + } + } + + base = scale.getPixelForValue(start); + head = scale.getPixelForValue(start + value); + size = head - base; + + if (minBarLength !== undefined && Math.abs(size) < minBarLength) { + size = minBarLength; + if (value >= 0 && !isHorizontal || value < 0 && isHorizontal) { + head = base - minBarLength; + } else { + head = base + minBarLength; + } + } + + return { + size: size, + base: base, + head: head, + center: head + size / 2 + }; + }, + + /** + * @private + */ + calculateBarIndexPixels: function(datasetIndex, index, ruler) { + var me = this; + var options = ruler.scale.options; + var range = options.barThickness === 'flex' + ? computeFlexCategoryTraits(index, ruler, options) + : computeFitCategoryTraits(index, ruler, options); + + var stackIndex = me.getStackIndex(datasetIndex, me.getMeta().stack); + var center = range.start + (range.chunk * stackIndex) + (range.chunk / 2); + var size = Math.min( + helpers$1.valueOrDefault(options.maxBarThickness, Infinity), + range.chunk * range.ratio); + + return { + base: center - size / 2, + head: center + size / 2, + center: center, + size: size + }; + }, + + draw: function() { + var me = this; + var chart = me.chart; + var scale = me._getValueScale(); + var rects = me.getMeta().data; + var dataset = me.getDataset(); + var ilen = rects.length; + var i = 0; + + helpers$1.canvas.clipArea(chart.ctx, chart.chartArea); + + for (; i < ilen; ++i) { + if (!isNaN(scale.getRightValue(dataset.data[i]))) { + rects[i].draw(); + } + } + + helpers$1.canvas.unclipArea(chart.ctx); + }, + + /** + * @private + */ + _resolveElementOptions: function(rectangle, index) { + var me = this; + var chart = me.chart; + var datasets = chart.data.datasets; + var dataset = datasets[me.index]; + var custom = rectangle.custom || {}; + var options = chart.options.elements.rectangle; + var values = {}; + var i, ilen, key; + + // Scriptable options + var context = { + chart: chart, + dataIndex: index, + dataset: dataset, + datasetIndex: me.index + }; + + var keys = [ + 'backgroundColor', + 'borderColor', + 'borderSkipped', + 'borderWidth' + ]; + + for (i = 0, ilen = keys.length; i < ilen; ++i) { + key = keys[i]; + values[key] = resolve$1([ + custom[key], + dataset[key], + options[key] + ], context, index); + } + + return values; + } +}); + +var valueOrDefault$3 = helpers$1.valueOrDefault; +var resolve$2 = helpers$1.options.resolve; + +core_defaults._set('bubble', { + hover: { + mode: 'single' + }, + + scales: { + xAxes: [{ + type: 'linear', // bubble should probably use a linear scale by default + position: 'bottom', + id: 'x-axis-0' // need an ID so datasets can reference the scale + }], + yAxes: [{ + type: 'linear', + position: 'left', + id: 'y-axis-0' + }] + }, + + tooltips: { + callbacks: { + title: function() { + // Title doesn't make sense for scatter since we format the data as a point + return ''; + }, + label: function(item, data) { + var datasetLabel = data.datasets[item.datasetIndex].label || ''; + var dataPoint = data.datasets[item.datasetIndex].data[item.index]; + return datasetLabel + ': (' + item.xLabel + ', ' + item.yLabel + ', ' + dataPoint.r + ')'; + } + } + } +}); + +var controller_bubble = core_datasetController.extend({ + /** + * @protected + */ + dataElementType: elements.Point, + + /** + * @protected + */ + update: function(reset) { + var me = this; + var meta = me.getMeta(); + var points = meta.data; + + // Update Points + helpers$1.each(points, function(point, index) { + me.updateElement(point, index, reset); + }); + }, + + /** + * @protected + */ + updateElement: function(point, index, reset) { + var me = this; + var meta = me.getMeta(); + var custom = point.custom || {}; + var xScale = me.getScaleForId(meta.xAxisID); + var yScale = me.getScaleForId(meta.yAxisID); + var options = me._resolveElementOptions(point, index); + var data = me.getDataset().data[index]; + var dsIndex = me.index; + + var x = reset ? xScale.getPixelForDecimal(0.5) : xScale.getPixelForValue(typeof data === 'object' ? data : NaN, index, dsIndex); + var y = reset ? yScale.getBasePixel() : yScale.getPixelForValue(data, index, dsIndex); + + point._xScale = xScale; + point._yScale = yScale; + point._options = options; + point._datasetIndex = dsIndex; + point._index = index; + point._model = { + backgroundColor: options.backgroundColor, + borderColor: options.borderColor, + borderWidth: options.borderWidth, + hitRadius: options.hitRadius, + pointStyle: options.pointStyle, + rotation: options.rotation, + radius: reset ? 0 : options.radius, + skip: custom.skip || isNaN(x) || isNaN(y), + x: x, + y: y, + }; + + point.pivot(); + }, + + /** + * @protected + */ + setHoverStyle: function(point) { + var model = point._model; + var options = point._options; + var getHoverColor = helpers$1.getHoverColor; + + point.$previousStyle = { + backgroundColor: model.backgroundColor, + borderColor: model.borderColor, + borderWidth: model.borderWidth, + radius: model.radius + }; + + model.backgroundColor = valueOrDefault$3(options.hoverBackgroundColor, getHoverColor(options.backgroundColor)); + model.borderColor = valueOrDefault$3(options.hoverBorderColor, getHoverColor(options.borderColor)); + model.borderWidth = valueOrDefault$3(options.hoverBorderWidth, options.borderWidth); + model.radius = options.radius + options.hoverRadius; + }, + + /** + * @private + */ + _resolveElementOptions: function(point, index) { + var me = this; + var chart = me.chart; + var datasets = chart.data.datasets; + var dataset = datasets[me.index]; + var custom = point.custom || {}; + var options = chart.options.elements.point; + var data = dataset.data[index]; + var values = {}; + var i, ilen, key; + + // Scriptable options + var context = { + chart: chart, + dataIndex: index, + dataset: dataset, + datasetIndex: me.index + }; + + var keys = [ + 'backgroundColor', + 'borderColor', + 'borderWidth', + 'hoverBackgroundColor', + 'hoverBorderColor', + 'hoverBorderWidth', + 'hoverRadius', + 'hitRadius', + 'pointStyle', + 'rotation' + ]; + + for (i = 0, ilen = keys.length; i < ilen; ++i) { + key = keys[i]; + values[key] = resolve$2([ + custom[key], + dataset[key], + options[key] + ], context, index); + } + + // Custom radius resolution + values.radius = resolve$2([ + custom.radius, + data ? data.r : undefined, + dataset.radius, + options.radius + ], context, index); + + return values; + } +}); + +var resolve$3 = helpers$1.options.resolve; +var valueOrDefault$4 = helpers$1.valueOrDefault; + +core_defaults._set('doughnut', { + animation: { + // Boolean - Whether we animate the rotation of the Doughnut + animateRotate: true, + // Boolean - Whether we animate scaling the Doughnut from the centre + animateScale: false + }, + hover: { + mode: 'single' + }, + legendCallback: function(chart) { + var text = []; + text.push('