)]}'
{"version": 3, "sources": ["/web/static/lib/es6-promise/es6-promise-polyfill.js", "/web/static/src/legacy/js/promise_extension.js", "/web/static/src/boot.js", "/web/static/src/session.js", "/web/static/src/legacy/js/core/cookie_utils.js", "/web/static/src/legacy/js/core/menu.js", "/web/static/lib/underscore/underscore.js", "/web/static/lib/underscore.string/lib/underscore.string.js", "/web/static/lib/moment/moment.js", "/web/static/lib/owl/owl.js", "/web/static/src/legacy/js/component_extension.js", "/web/static/lib/jquery/jquery.js", "/web/static/lib/jquery.ui/jquery-ui.js", "/web/static/lib/jquery/jquery.browser.js", "/web/static/lib/jquery.blockUI/jquery.blockUI.js", "/web/static/lib/jquery.hotkeys/jquery.hotkeys.js", "/web/static/lib/jquery.placeholder/jquery.placeholder.js", "/web/static/lib/jquery.form/jquery.form.js", "/web/static/lib/jquery.ba-bbq/jquery.ba-bbq.js", "/web/static/lib/jquery.mjs.nestedSortable/jquery.mjs.nestedSortable.js", "/web/static/lib/popper/popper.js", "/web/static/lib/bootstrap/js/index.js", "/web/static/lib/bootstrap/js/util.js", "/web/static/lib/bootstrap/js/alert.js", "/web/static/lib/bootstrap/js/button.js", "/web/static/lib/bootstrap/js/carousel.js", "/web/static/lib/bootstrap/js/collapse.js", "/web/static/lib/bootstrap/js/dropdown.js", "/web/static/lib/bootstrap/js/modal.js", "/web/static/lib/bootstrap/js/tooltip.js", "/web/static/lib/bootstrap/js/popover.js", "/web/static/lib/bootstrap/js/scrollspy.js", "/web/static/lib/bootstrap/js/tab.js", "/web/static/lib/bootstrap/js/toast.js", "/web/static/lib/tempusdominus/tempusdominus.js", "/web/static/lib/select2/select2.js", "/web/static/lib/clipboard/clipboard.js", "/web/static/lib/jSignature/jSignatureCustom.js", "/web/static/lib/qweb/qweb2.js", "/web/static/src/legacy/js/libs/autocomplete.js", "/web/static/src/legacy/js/libs/bootstrap.js", "/web/static/src/legacy/js/libs/content-disposition.js", "/web/static/src/legacy/js/libs/download.js", "/web/static/src/legacy/js/libs/fullcalendar.js", "/web/static/src/legacy/js/libs/jquery.js", "/web/static/src/legacy/js/libs/moment.js", "/web/static/src/legacy/js/libs/underscore.js", "/web/static/src/legacy/js/libs/pdfjs.js", "/web/static/src/legacy/js/libs/popper.js", "/web/static/src/legacy/js/libs/zoomodoo.js", "/web/static/src/legacy/js/libs/jSignatureCustom.js", "/web/static/src/legacy/js/core/abstract_service.js", "/web/static/src/legacy/js/core/abstract_storage_service.js", "/web/static/src/legacy/js/core/ajax.js", "/web/static/src/legacy/js/core/browser_detection.js", "/web/static/src/legacy/js/core/bus.js", "/web/static/src/legacy/js/core/custom_hooks.js", "/web/static/src/legacy/js/core/class.js", "/web/static/src/legacy/js/core/collections.js", "/web/static/src/legacy/js/core/concurrency.js", "/web/static/src/legacy/js/core/dialog.js", "/web/static/src/legacy/js/core/owl_dialog.js", "/web/static/src/legacy/js/core/popover.js", "/web/static/src/legacy/js/core/dom.js", "/web/static/src/legacy/js/core/local_storage.js", "/web/static/src/legacy/js/core/mixins.js", "/web/static/src/legacy/js/core/qweb.js", "/web/static/src/legacy/js/core/ram_storage.js", "/web/static/src/legacy/js/core/registry.js", "/web/static/src/legacy/js/core/rpc.js", "/web/static/src/legacy/js/core/service_mixins.js", "/web/static/src/legacy/js/core/session.js", "/web/static/src/legacy/js/core/session_storage.js", "/web/static/src/legacy/js/core/time.js", "/web/static/src/legacy/js/core/translation.js", "/web/static/src/legacy/js/core/utils.js", "/web/static/src/legacy/js/core/widget.js", "/web/static/src/legacy/js/services/ajax_service.js", "/web/static/src/legacy/js/services/config.js", "/web/static/src/legacy/js/services/core.js", "/web/static/src/legacy/js/services/local_storage_service.js", "/web/static/src/legacy/js/core/error_utils.js", "/web/static/src/legacy/js/services/session_storage_service.js", "/web/static/src/legacy/js/common_env.js", "/web/static/src/legacy/js/widgets/name_and_signature.js", "/web/static/src/legacy/js/core/smooth_scroll_on_drag.js", "/web/static/src/legacy/js/widgets/colorpicker.js", "/web/static/src/legacy/js/widgets/translation_dialog.js", "/web_tour/static/src/js/running_tour_action_helper.js", "/web_tour/static/src/js/tip.js", "/web_tour/static/src/js/tour_manager.js", "/web_tour/static/src/js/tour_service.js", "/web_tour/static/src/js/tour_step_utils.js", "/web_tour/static/src/js/tour_utils.js", "/web_editor/static/lib/vkbeautify/vkbeautify.0.99.00.beta.js", "/web_editor/static/src/js/common/ace.js", "/web_editor/static/src/js/common/browser_extensions.js", "/web_editor/static/src/js/common/utils.js", "/web_editor/static/src/js/common/wysiwyg_utils.js", "/web_editor/static/lib/odoo-editor/src/utils/utils.js", "/website_sale/static/src/js/tours/tour_utils.js", "/website_sale/static/src/js/tours/website_sale_shop.js"], "mappings": "AAAA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;ACxpCA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;ACtBA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AClaA;;;;;;;;;AAAA;AACA;AACA;AACA;AACA;;;;ACJA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;ACzCA;;;;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;ACjQA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AC//CA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;ACjqBA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AC7sIA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AC1+KA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AC1CA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AC3nUA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;ACh4XA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;ACrCA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AC5mBA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AClGA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AC5JA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AC7vCA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;ACl2CA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AC14BA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AC/9EA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;ACtBA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AC3KA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;ACtMA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AC1LA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AC3pBA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AC3aA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;ACllBA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;ACzoBA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AC14BA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;ACpQA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;ACtXA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AC5QA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AC1RA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AC3vFA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;ACjpHA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AC16BA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;ACt6CA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AC12BA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;ACtCA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AC1IA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;ACzPA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;ACzJA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AClQA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AClQA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AClBA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;ACpDA;;;;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;AClEA;;;;;;;;;AAAA;AACA;AACA;;;;ACFA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;ACjWA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;ACjDA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AC3FA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;ACxFA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;ACpkBA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;ACfA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;ACnBA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;ACnHA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AC5JA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AC5CA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;ACnUA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AC3hBA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;ACtQA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;ACjVA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;ACpoBA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;ACtDA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AClaA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AC9DA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AClFA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AC1JA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AChIA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;ACnQA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AClZA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;ACxDA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AChWA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;ACxIA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AC5nCA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AC/bA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;ACzCA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;ACnIA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;ACjDA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;ACpBA;;;;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;AC7EA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;ACpBA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;ACrGA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;ACtpBA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AC7ZA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AChvBA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;ACzLA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;ACxMA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AC7pBA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AClhBA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AC/LA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;ACjKA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;ACxEA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;ACtWA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AC9gCA;;;;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;ACrBA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AC3aA;;;;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;AChBA;;;;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;ACx+EA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;ACpBA;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA", "sourcesContent": ["/*!\n * @overview es6-promise - a tiny implementation of Promises/A+.\n * @copyright Copyright (c) 2014 Yehuda Katz, Tom Dale, Stefan Penner and contributors (Conversion to ES6 API by Jake Archibald)\n * @license   Licensed under MIT license\n *            See https://raw.githubusercontent.com/stefanpenner/es6-promise/master/LICENSE\n * @version   v4.2.5+7f2b526d\n */\n(function (global, factory) {\n    typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :\n        typeof define === 'function' && define.amd ? define(factory) :\n            (global.ES6Promise = factory());\n}(this, (function () {\n    'use strict';\n\n    function objectOrFunction(x) {\n        var type = typeof x;\n        return x !== null && (type === 'object' || type === 'function');\n    }\n\n    function isFunction(x) {\n        return typeof x === 'function';\n    }\n\n\n\n    var _isArray = void 0;\n    if (Array.isArray) {\n        _isArray = Array.isArray;\n    } else {\n        _isArray = function (x) {\n            return Object.prototype.toString.call(x) === '[object Array]';\n        };\n    }\n\n    var isArray = _isArray;\n\n    var len = 0;\n    var vertxNext = void 0;\n    var customSchedulerFn = void 0;\n\n    var asap = function asap(callback, arg) {\n        queue[len] = callback;\n        queue[len + 1] = arg;\n        len += 2;\n        if (len === 2) {\n            // If len is 2, that means that we need to schedule an async flush.\n            // If additional callbacks are queued before the queue is flushed, they\n            // will be processed by this flush that we are scheduling.\n            if (customSchedulerFn) {\n                customSchedulerFn(flush);\n            } else {\n                scheduleFlush();\n            }\n        }\n    };\n\n    function setScheduler(scheduleFn) {\n        customSchedulerFn = scheduleFn;\n    }\n\n    function setAsap(asapFn) {\n        asap = asapFn;\n    }\n\n    var browserWindow = typeof window !== 'undefined' ? window : undefined;\n    var browserGlobal = browserWindow || {};\n    var BrowserMutationObserver = browserGlobal.MutationObserver || browserGlobal.WebKitMutationObserver;\n    var isNode = false;\n\n    // test for web worker but not in IE10\n    var isWorker = typeof Uint8ClampedArray !== 'undefined' && typeof importScripts !== 'undefined' && typeof MessageChannel !== 'undefined';\n\n    // node\n    function useNextTick() {\n        // node version 0.10.x displays a deprecation warning when nextTick is used recursively\n        // see https://github.com/cujojs/when/issues/410 for details\n        return function () {\n            return process.nextTick(flush);\n        };\n    }\n\n    // vertx\n    function useVertxTimer() {\n        if (typeof vertxNext !== 'undefined') {\n            return function () {\n                vertxNext(flush);\n            };\n        }\n\n        return useSetTimeout();\n    }\n\n    function useMutationObserver() {\n        var iterations = 0;\n        var observer = new BrowserMutationObserver(flush);\n        var node = document.createTextNode('');\n        observer.observe(node, { characterData: true });\n\n        return function () {\n            node.data = iterations = ++iterations % 2;\n        };\n    }\n\n    // web worker\n    function useMessageChannel() {\n        var channel = new MessageChannel();\n        channel.port1.onmessage = flush;\n        return function () {\n            return channel.port2.postMessage(0);\n        };\n    }\n\n    function useSetTimeout() {\n        // Store setTimeout reference so es6-promise will be unaffected by\n        // other code modifying setTimeout (like sinon.useFakeTimers())\n        var globalSetTimeout = setTimeout;\n        return function () {\n            return globalSetTimeout(flush, 1);\n        };\n    }\n\n    var queue = new Array(1000);\n    function flush() {\n        for (var i = 0; i < len; i += 2) {\n            var callback = queue[i];\n            var arg = queue[i + 1];\n\n            callback(arg);\n\n            queue[i] = undefined;\n            queue[i + 1] = undefined;\n        }\n\n        len = 0;\n    }\n\n    function attemptVertx() {\n        try {\n            var vertx = Function('return this')().require('vertx');\n            vertxNext = vertx.runOnLoop || vertx.runOnContext;\n            return useVertxTimer();\n        } catch (e) {\n            return useSetTimeout();\n        }\n    }\n\n    var scheduleFlush = void 0;\n    // Decide what async method to use to triggering processing of queued callbacks:\n    if (isNode) {\n        scheduleFlush = useNextTick();\n    } else if (BrowserMutationObserver) {\n        scheduleFlush = useMutationObserver();\n    } else if (isWorker) {\n        scheduleFlush = useMessageChannel();\n    } else if (browserWindow === undefined && typeof require === 'function') {\n        scheduleFlush = attemptVertx();\n    } else {\n        scheduleFlush = useSetTimeout();\n    }\n\n    function then(onFulfillment, onRejection) {\n        var parent = this;\n\n        var child = new this.constructor(noop);\n\n        if (child[PROMISE_ID] === undefined) {\n            makePromise(child);\n        }\n\n        var _state = parent._state;\n\n\n        if (_state) {\n            var callback = arguments[_state - 1];\n            asap(function () {\n                return invokeCallback(_state, child, callback, parent._result);\n            });\n        } else {\n            subscribe(parent, child, onFulfillment, onRejection);\n        }\n\n        return child;\n    }\n\n    /**\n      `Promise.resolve` returns a promise that will become resolved with the\n      passed `value`. It is shorthand for the following:\n\n      ```javascript\n      let promise = new Promise(function(resolve, reject){\n        resolve(1);\n      });\n\n      promise.then(function(value){\n        // value === 1\n      });\n      ```\n\n      Instead of writing the above, your code now simply becomes the following:\n\n      ```javascript\n      let promise = Promise.resolve(1);\n\n      promise.then(function(value){\n        // value === 1\n      });\n      ```\n\n      @method resolve\n      @static\n      @param {Any} value value that the returned promise will be resolved with\n      Useful for tooling.\n      @return {Promise} a promise that will become fulfilled with the given\n      `value`\n    */\n    function resolve$1(object) {\n        /*jshint validthis:true */\n        var Constructor = this;\n\n        if (object && typeof object === 'object' && object.constructor === Constructor) {\n            return object;\n        }\n\n        var promise = new Constructor(noop);\n        resolve(promise, object);\n        return promise;\n    }\n\n    var PROMISE_ID = Math.random().toString(36).substring(2);\n\n    function noop() { }\n\n    var PENDING = void 0;\n    var FULFILLED = 1;\n    var REJECTED = 2;\n\n    var TRY_CATCH_ERROR = { error: null };\n\n    function selfFulfillment() {\n        return new TypeError(\"You cannot resolve a promise with itself\");\n    }\n\n    function cannotReturnOwn() {\n        return new TypeError('A promises callback cannot return that same promise.');\n    }\n\n    function getThen(promise) {\n        try {\n            return promise.then;\n        } catch (error) {\n            TRY_CATCH_ERROR.error = error;\n            return TRY_CATCH_ERROR;\n        }\n    }\n\n    function tryThen(then$$1, value, fulfillmentHandler, rejectionHandler) {\n        try {\n            then$$1.call(value, fulfillmentHandler, rejectionHandler);\n        } catch (e) {\n            return e;\n        }\n    }\n\n    function handleForeignThenable(promise, thenable, then$$1) {\n        asap(function (promise) {\n            var sealed = false;\n            var error = tryThen(then$$1, thenable, function (value) {\n                if (sealed) {\n                    return;\n                }\n                sealed = true;\n                if (thenable !== value) {\n                    resolve(promise, value);\n                } else {\n                    fulfill(promise, value);\n                }\n            }, function (reason) {\n                if (sealed) {\n                    return;\n                }\n                sealed = true;\n\n                reject(promise, reason);\n            }, 'Settle: ' + (promise._label || ' unknown promise'));\n\n            if (!sealed && error) {\n                sealed = true;\n                reject(promise, error);\n            }\n        }, promise);\n    }\n\n    function handleOwnThenable(promise, thenable) {\n        if (thenable._state === FULFILLED) {\n            fulfill(promise, thenable._result);\n        } else if (thenable._state === REJECTED) {\n            reject(promise, thenable._result);\n        } else {\n            subscribe(thenable, undefined, function (value) {\n                return resolve(promise, value);\n            }, function (reason) {\n                return reject(promise, reason);\n            });\n        }\n    }\n\n    function handleMaybeThenable(promise, maybeThenable, then$$1) {\n        if (maybeThenable.constructor === promise.constructor && then$$1 === then && maybeThenable.constructor.resolve === resolve$1) {\n            handleOwnThenable(promise, maybeThenable);\n        } else {\n            if (then$$1 === TRY_CATCH_ERROR) {\n                reject(promise, TRY_CATCH_ERROR.error);\n                TRY_CATCH_ERROR.error = null;\n            } else if (then$$1 === undefined) {\n                fulfill(promise, maybeThenable);\n            } else if (isFunction(then$$1)) {\n                handleForeignThenable(promise, maybeThenable, then$$1);\n            } else {\n                fulfill(promise, maybeThenable);\n            }\n        }\n    }\n\n    function resolve(promise, value) {\n        if (promise === value) {\n            reject(promise, selfFulfillment());\n        } else if (objectOrFunction(value)) {\n            handleMaybeThenable(promise, value, getThen(value));\n        } else {\n            fulfill(promise, value);\n        }\n    }\n\n    function publishRejection(promise) {\n        if (promise._onerror) {\n            promise._onerror(promise._result);\n        }\n\n        publish(promise);\n    }\n\n    function fulfill(promise, value) {\n        if (promise._state !== PENDING) {\n            return;\n        }\n\n        promise._result = value;\n        promise._state = FULFILLED;\n\n        if (promise._subscribers.length !== 0) {\n            asap(publish, promise);\n        }\n    }\n\n    function reject(promise, reason) {\n        if (promise._state !== PENDING) {\n            return;\n        }\n        promise._state = REJECTED;\n        promise._result = reason;\n\n        asap(publishRejection, promise);\n    }\n\n    function subscribe(parent, child, onFulfillment, onRejection) {\n        var _subscribers = parent._subscribers;\n        var length = _subscribers.length;\n\n\n        parent._onerror = null;\n\n        _subscribers[length] = child;\n        _subscribers[length + FULFILLED] = onFulfillment;\n        _subscribers[length + REJECTED] = onRejection;\n\n        if (length === 0 && parent._state) {\n            asap(publish, parent);\n        }\n    }\n\n    function publish(promise) {\n        var subscribers = promise._subscribers;\n        var settled = promise._state;\n\n        if (subscribers.length === 0) {\n            return;\n        }\n\n        var child = void 0,\n            callback = void 0,\n            detail = promise._result;\n\n        for (var i = 0; i < subscribers.length; i += 3) {\n            child = subscribers[i];\n            callback = subscribers[i + settled];\n\n            if (child) {\n                invokeCallback(settled, child, callback, detail);\n            } else {\n                callback(detail);\n            }\n        }\n\n        promise._subscribers.length = 0;\n    }\n\n    function tryCatch(callback, detail) {\n        try {\n            return callback(detail);\n        } catch (e) {\n            TRY_CATCH_ERROR.error = e;\n            return TRY_CATCH_ERROR;\n        }\n    }\n\n    function invokeCallback(settled, promise, callback, detail) {\n        var hasCallback = isFunction(callback),\n            value = void 0,\n            error = void 0,\n            succeeded = void 0,\n            failed = void 0;\n\n        if (hasCallback) {\n            value = tryCatch(callback, detail);\n\n            if (value === TRY_CATCH_ERROR) {\n                failed = true;\n                error = value.error;\n                value.error = null;\n            } else {\n                succeeded = true;\n            }\n\n            if (promise === value) {\n                reject(promise, cannotReturnOwn());\n                return;\n            }\n        } else {\n            value = detail;\n            succeeded = true;\n        }\n\n        if (promise._state !== PENDING) {\n            // noop\n        } else if (hasCallback && succeeded) {\n            resolve(promise, value);\n        } else if (failed) {\n            reject(promise, error);\n        } else if (settled === FULFILLED) {\n            fulfill(promise, value);\n        } else if (settled === REJECTED) {\n            reject(promise, value);\n        }\n    }\n\n    function initializePromise(promise, resolver) {\n        try {\n            resolver(function resolvePromise(value) {\n                resolve(promise, value);\n            }, function rejectPromise(reason) {\n                reject(promise, reason);\n            });\n        } catch (e) {\n            reject(promise, e);\n        }\n    }\n\n    var id = 0;\n    function nextId() {\n        return id++;\n    }\n\n    function makePromise(promise) {\n        promise[PROMISE_ID] = id++;\n        promise._state = undefined;\n        promise._result = undefined;\n        promise._subscribers = [];\n    }\n\n    function validationError() {\n        return new Error('Array Methods must be provided an Array');\n    }\n\n    var Enumerator = function () {\n        function Enumerator(Constructor, input) {\n            this._instanceConstructor = Constructor;\n            this.promise = new Constructor(noop);\n\n            if (!this.promise[PROMISE_ID]) {\n                makePromise(this.promise);\n            }\n\n            if (isArray(input)) {\n                this.length = input.length;\n                this._remaining = input.length;\n\n                this._result = new Array(this.length);\n\n                if (this.length === 0) {\n                    fulfill(this.promise, this._result);\n                } else {\n                    this.length = this.length || 0;\n                    this._enumerate(input);\n                    if (this._remaining === 0) {\n                        fulfill(this.promise, this._result);\n                    }\n                }\n            } else {\n                reject(this.promise, validationError());\n            }\n        }\n\n        Enumerator.prototype._enumerate = function _enumerate(input) {\n            for (var i = 0; this._state === PENDING && i < input.length; i++) {\n                this._eachEntry(input[i], i);\n            }\n        };\n\n        Enumerator.prototype._eachEntry = function _eachEntry(entry, i) {\n            var c = this._instanceConstructor;\n            var resolve$$1 = c.resolve;\n\n\n            if (resolve$$1 === resolve$1) {\n                var _then = getThen(entry);\n\n                if (_then === then && entry._state !== PENDING) {\n                    this._settledAt(entry._state, i, entry._result);\n                } else if (typeof _then !== 'function') {\n                    this._remaining--;\n                    this._result[i] = entry;\n                } else if (c === Promise$2) {\n                    var promise = new c(noop);\n                    handleMaybeThenable(promise, entry, _then);\n                    this._willSettleAt(promise, i);\n                } else {\n                    this._willSettleAt(new c(function (resolve$$1) {\n                        return resolve$$1(entry);\n                    }), i);\n                }\n            } else {\n                this._willSettleAt(resolve$$1(entry), i);\n            }\n        };\n\n        Enumerator.prototype._settledAt = function _settledAt(state, i, value) {\n            var promise = this.promise;\n\n\n            if (promise._state === PENDING) {\n                this._remaining--;\n\n                if (state === REJECTED) {\n                    reject(promise, value);\n                } else {\n                    this._result[i] = value;\n                }\n            }\n\n            if (this._remaining === 0) {\n                fulfill(promise, this._result);\n            }\n        };\n\n        Enumerator.prototype._willSettleAt = function _willSettleAt(promise, i) {\n            var enumerator = this;\n\n            subscribe(promise, undefined, function (value) {\n                return enumerator._settledAt(FULFILLED, i, value);\n            }, function (reason) {\n                return enumerator._settledAt(REJECTED, i, reason);\n            });\n        };\n\n        return Enumerator;\n    }();\n\n    /**\n      `Promise.all` accepts an array of promises, and returns a new promise which\n      is fulfilled with an array of fulfillment values for the passed promises, or\n      rejected with the reason of the first passed promise to be rejected. It casts all\n      elements of the passed iterable to promises as it runs this algorithm.\n\n      Example:\n\n      ```javascript\n      let promise1 = resolve(1);\n      let promise2 = resolve(2);\n      let promise3 = resolve(3);\n      let promises = [ promise1, promise2, promise3 ];\n\n      Promise.all(promises).then(function(array){\n        // The array here would be [ 1, 2, 3 ];\n      });\n      ```\n\n      If any of the `promises` given to `all` are rejected, the first promise\n      that is rejected will be given as an argument to the returned promises's\n      rejection handler. For example:\n\n      Example:\n\n      ```javascript\n      let promise1 = resolve(1);\n      let promise2 = reject(new Error(\"2\"));\n      let promise3 = reject(new Error(\"3\"));\n      let promises = [ promise1, promise2, promise3 ];\n\n      Promise.all(promises).then(function(array){\n        // Code here never runs because there are rejected promises!\n      }, function(error) {\n        // error.message === \"2\"\n      });\n      ```\n\n      @method all\n      @static\n      @param {Array} entries array of promises\n      @param {String} label optional string for labeling the promise.\n      Useful for tooling.\n      @return {Promise} promise that is fulfilled when all `promises` have been\n      fulfilled, or rejected if any of them become rejected.\n      @static\n    */\n    function all(entries) {\n        return new Enumerator(this, entries).promise;\n    }\n\n    /**\n      `Promise.race` returns a new promise which is settled in the same way as the\n      first passed promise to settle.\n\n      Example:\n\n      ```javascript\n      let promise1 = new Promise(function(resolve, reject){\n        setTimeout(function(){\n          resolve('promise 1');\n        }, 200);\n      });\n\n      let promise2 = new Promise(function(resolve, reject){\n        setTimeout(function(){\n          resolve('promise 2');\n        }, 100);\n      });\n\n      Promise.race([promise1, promise2]).then(function(result){\n        // result === 'promise 2' because it was resolved before promise1\n        // was resolved.\n      });\n      ```\n\n      `Promise.race` is deterministic in that only the state of the first\n      settled promise matters. For example, even if other promises given to the\n      `promises` array argument are resolved, but the first settled promise has\n      become rejected before the other promises became fulfilled, the returned\n      promise will become rejected:\n\n      ```javascript\n      let promise1 = new Promise(function(resolve, reject){\n        setTimeout(function(){\n          resolve('promise 1');\n        }, 200);\n      });\n\n      let promise2 = new Promise(function(resolve, reject){\n        setTimeout(function(){\n          reject(new Error('promise 2'));\n        }, 100);\n      });\n\n      Promise.race([promise1, promise2]).then(function(result){\n        // Code here never runs\n      }, function(reason){\n        // reason.message === 'promise 2' because promise 2 became rejected before\n        // promise 1 became fulfilled\n      });\n      ```\n\n      An example real-world use case is implementing timeouts:\n\n      ```javascript\n      Promise.race([ajax('foo.json'), timeout(5000)])\n      ```\n\n      @method race\n      @static\n      @param {Array} promises array of promises to observe\n      Useful for tooling.\n      @return {Promise} a promise which settles in the same way as the first passed\n      promise to settle.\n    */\n    function race(entries) {\n        /*jshint validthis:true */\n        var Constructor = this;\n\n        if (!isArray(entries)) {\n            return new Constructor(function (_, reject) {\n                return reject(new TypeError('You must pass an array to race.'));\n            });\n        } else {\n            return new Constructor(function (resolve, reject) {\n                var length = entries.length;\n                for (var i = 0; i < length; i++) {\n                    Constructor.resolve(entries[i]).then(resolve, reject);\n                }\n            });\n        }\n    }\n\n    /**\n      `Promise.reject` returns a promise rejected with the passed `reason`.\n      It is shorthand for the following:\n\n      ```javascript\n      let promise = new Promise(function(resolve, reject){\n        reject(new Error('WHOOPS'));\n      });\n\n      promise.then(function(value){\n        // Code here doesn't run because the promise is rejected!\n      }, function(reason){\n        // reason.message === 'WHOOPS'\n      });\n      ```\n\n      Instead of writing the above, your code now simply becomes the following:\n\n      ```javascript\n      let promise = Promise.reject(new Error('WHOOPS'));\n\n      promise.then(function(value){\n        // Code here doesn't run because the promise is rejected!\n      }, function(reason){\n        // reason.message === 'WHOOPS'\n      });\n      ```\n\n      @method reject\n      @static\n      @param {Any} reason value that the returned promise will be rejected with.\n      Useful for tooling.\n      @return {Promise} a promise rejected with the given `reason`.\n    */\n    function reject$1(reason) {\n        /*jshint validthis:true */\n        var Constructor = this;\n        var promise = new Constructor(noop);\n        reject(promise, reason);\n        return promise;\n    }\n\n    function needsResolver() {\n        throw new TypeError('You must pass a resolver function as the first argument to the promise constructor');\n    }\n\n    function needsNew() {\n        throw new TypeError(\"Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.\");\n    }\n\n    /**\n      Promise objects represent the eventual result of an asynchronous operation. The\n      primary way of interacting with a promise is through its `then` method, which\n      registers callbacks to receive either a promise's eventual value or the reason\n      why the promise cannot be fulfilled.\n\n      Terminology\n      -----------\n\n      - `promise` is an object or function with a `then` method whose behavior conforms to this specification.\n      - `thenable` is an object or function that defines a `then` method.\n      - `value` is any legal JavaScript value (including undefined, a thenable, or a promise).\n      - `exception` is a value that is thrown using the throw statement.\n      - `reason` is a value that indicates why a promise was rejected.\n      - `settled` the final resting state of a promise, fulfilled or rejected.\n\n      A promise can be in one of three states: pending, fulfilled, or rejected.\n\n      Promises that are fulfilled have a fulfillment value and are in the fulfilled\n      state.  Promises that are rejected have a rejection reason and are in the\n      rejected state.  A fulfillment value is never a thenable.\n\n      Promises can also be said to *resolve* a value.  If this value is also a\n      promise, then the original promise's settled state will match the value's\n      settled state.  So a promise that *resolves* a promise that rejects will\n      itself reject, and a promise that *resolves* a promise that fulfills will\n      itself fulfill.\n\n\n      Basic Usage:\n      ------------\n\n      ```js\n      let promise = new Promise(function(resolve, reject) {\n        // on success\n        resolve(value);\n\n        // on failure\n        reject(reason);\n      });\n\n      promise.then(function(value) {\n        // on fulfillment\n      }, function(reason) {\n        // on rejection\n      });\n      ```\n\n      Advanced Usage:\n      ---------------\n\n      Promises shine when abstracting away asynchronous interactions such as\n      `XMLHttpRequest`s.\n\n      ```js\n      function getJSON(url) {\n        return new Promise(function(resolve, reject){\n          let xhr = new XMLHttpRequest();\n\n          xhr.open('GET', url);\n          xhr.onreadystatechange = handler;\n          xhr.responseType = 'json';\n          xhr.setRequestHeader('Accept', 'application/json');\n          xhr.send();\n\n          function handler() {\n            if (this.readyState === this.DONE) {\n              if (this.status === 200) {\n                resolve(this.response);\n              } else {\n                reject(new Error('getJSON: `' + url + '` failed with status: [' + this.status + ']'));\n              }\n            }\n          };\n        });\n      }\n\n      getJSON('/posts.json').then(function(json) {\n        // on fulfillment\n      }, function(reason) {\n        // on rejection\n      });\n      ```\n\n      Unlike callbacks, promises are great composable primitives.\n\n      ```js\n      Promise.all([\n        getJSON('/posts'),\n        getJSON('/comments')\n      ]).then(function(values){\n        values[0] // => postsJSON\n        values[1] // => commentsJSON\n\n        return values;\n      });\n      ```\n\n      @class Promise\n      @param {Function} resolver\n      Useful for tooling.\n      @constructor\n    */\n\n    var Promise$2 = function () {\n        function Promise(resolver) {\n            this[PROMISE_ID] = nextId();\n            this._result = this._state = undefined;\n            this._subscribers = [];\n\n            if (noop !== resolver) {\n                typeof resolver !== 'function' && needsResolver();\n                this instanceof Promise ? initializePromise(this, resolver) : needsNew();\n            }\n        }\n\n        /**\n        The primary way of interacting with a promise is through its `then` method,\n        which registers callbacks to receive either a promise's eventual value or the\n        reason why the promise cannot be fulfilled.\n         ```js\n        findUser().then(function(user){\n          // user is available\n        }, function(reason){\n          // user is unavailable, and you are given the reason why\n        });\n        ```\n         Chaining\n        --------\n         The return value of `then` is itself a promise.  This second, 'downstream'\n        promise is resolved with the return value of the first promise's fulfillment\n        or rejection handler, or rejected if the handler throws an exception.\n         ```js\n        findUser().then(function (user) {\n          return user.name;\n        }, function (reason) {\n          return 'default name';\n        }).then(function (userName) {\n          // If `findUser` fulfilled, `userName` will be the user's name, otherwise it\n          // will be `'default name'`\n        });\n         findUser().then(function (user) {\n          throw new Error('Found user, but still unhappy');\n        }, function (reason) {\n          throw new Error('`findUser` rejected and we're unhappy');\n        }).then(function (value) {\n          // never reached\n        }, function (reason) {\n          // if `findUser` fulfilled, `reason` will be 'Found user, but still unhappy'.\n          // If `findUser` rejected, `reason` will be '`findUser` rejected and we're unhappy'.\n        });\n        ```\n        If the downstream promise does not specify a rejection handler, rejection reasons will be propagated further downstream.\n         ```js\n        findUser().then(function (user) {\n          throw new PedagogicalException('Upstream error');\n        }).then(function (value) {\n          // never reached\n        }).then(function (value) {\n          // never reached\n        }, function (reason) {\n          // The `PedgagocialException` is propagated all the way down to here\n        });\n        ```\n         Assimilation\n        ------------\n         Sometimes the value you want to propagate to a downstream promise can only be\n        retrieved asynchronously. This can be achieved by returning a promise in the\n        fulfillment or rejection handler. The downstream promise will then be pending\n        until the returned promise is settled. This is called *assimilation*.\n         ```js\n        findUser().then(function (user) {\n          return findCommentsByAuthor(user);\n        }).then(function (comments) {\n          // The user's comments are now available\n        });\n        ```\n         If the assimliated promise rejects, then the downstream promise will also reject.\n         ```js\n        findUser().then(function (user) {\n          return findCommentsByAuthor(user);\n        }).then(function (comments) {\n          // If `findCommentsByAuthor` fulfills, we'll have the value here\n        }, function (reason) {\n          // If `findCommentsByAuthor` rejects, we'll have the reason here\n        });\n        ```\n         Simple Example\n        --------------\n         Synchronous Example\n         ```javascript\n        let result;\n         try {\n          result = findResult();\n          // success\n        } catch(reason) {\n          // failure\n        }\n        ```\n         Errback Example\n         ```js\n        findResult(function(result, err){\n          if (err) {\n            // failure\n          } else {\n            // success\n          }\n        });\n        ```\n         Promise Example;\n         ```javascript\n        findResult().then(function(result){\n          // success\n        }, function(reason){\n          // failure\n        });\n        ```\n         Advanced Example\n        --------------\n         Synchronous Example\n         ```javascript\n        let author, books;\n         try {\n          author = findAuthor();\n          books  = findBooksByAuthor(author);\n          // success\n        } catch(reason) {\n          // failure\n        }\n        ```\n         Errback Example\n         ```js\n         function foundBooks(books) {\n         }\n         function failure(reason) {\n         }\n         findAuthor(function(author, err){\n          if (err) {\n            failure(err);\n            // failure\n          } else {\n            try {\n              findBoooksByAuthor(author, function(books, err) {\n                if (err) {\n                  failure(err);\n                } else {\n                  try {\n                    foundBooks(books);\n                  } catch(reason) {\n                    failure(reason);\n                  }\n                }\n              });\n            } catch(error) {\n              failure(err);\n            }\n            // success\n          }\n        });\n        ```\n         Promise Example;\n         ```javascript\n        findAuthor().\n          then(findBooksByAuthor).\n          then(function(books){\n            // found books\n        }).catch(function(reason){\n          // something went wrong\n        });\n        ```\n         @method then\n        @param {Function} onFulfilled\n        @param {Function} onRejected\n        Useful for tooling.\n        @return {Promise}\n        */\n\n        /**\n        `catch` is simply sugar for `then(undefined, onRejection)` which makes it the same\n        as the catch block of a try/catch statement.\n        ```js\n        function findAuthor(){\n        throw new Error('couldn't find that author');\n        }\n        // synchronous\n        try {\n        findAuthor();\n        } catch(reason) {\n        // something went wrong\n        }\n        // async with promises\n        findAuthor().catch(function(reason){\n        // something went wrong\n        });\n        ```\n        @method catch\n        @param {Function} onRejection\n        Useful for tooling.\n        @return {Promise}\n        */\n\n\n        Promise.prototype.catch = function _catch(onRejection) {\n            return this.then(null, onRejection);\n        };\n\n        /**\n          `finally` will be invoked regardless of the promise's fate just as native\n          try/catch/finally behaves\n\n          Synchronous example:\n\n          ```js\n          findAuthor() {\n            if (Math.random() > 0.5) {\n              throw new Error();\n            }\n            return new Author();\n          }\n\n          try {\n            return findAuthor(); // succeed or fail\n          } catch(error) {\n            return findOtherAuther();\n          } finally {\n            // always runs\n            // doesn't affect the return value\n          }\n          ```\n\n          Asynchronous example:\n\n          ```js\n          findAuthor().catch(function(reason){\n            return findOtherAuther();\n          }).finally(function(){\n            // author was either found, or not\n          });\n          ```\n\n          @method finally\n          @param {Function} callback\n          @return {Promise}\n        */\n\n\n        Promise.prototype.finally = function _finally(callback) {\n            var promise = this;\n            var constructor = promise.constructor;\n\n            if (isFunction(callback)) {\n                return promise.then(function (value) {\n                    return constructor.resolve(callback()).then(function () {\n                        return value;\n                    });\n                }, function (reason) {\n                    return constructor.resolve(callback()).then(function () {\n                        throw reason;\n                    });\n                });\n            }\n\n            return promise.then(callback, callback);\n        };\n\n        return Promise;\n    }();\n\n    Promise$2.prototype.then = then;\n    Promise$2.all = all;\n    Promise$2.race = race;\n    Promise$2.resolve = resolve$1;\n    Promise$2.reject = reject$1;\n    Promise$2._setScheduler = setScheduler;\n    Promise$2._setAsap = setAsap;\n    Promise$2._asap = asap;\n\n    /*global self*/\n    function polyfill() {\n        var local = void 0;\n\n        try {\n            local = Function('return this')();\n        } catch (e) {\n            throw new Error('polyfill failed because global object is unavailable in this environment');\n        }\n\n\n        var P = local.Promise;\n\n        if (P) {\n            var promiseToString = null;\n            try {\n                promiseToString = Object.prototype.toString.call(P.resolve());\n            } catch (e) {\n                // silently ignored\n            }\n\n            if (promiseToString === '[object Promise]' && !P.cast) {\n                return;\n            }\n        }\n\n        local.Promise = Promise$2;\n    }\n\n    // Strange compat..\n    Promise$2.polyfill = polyfill;\n    Promise$2.Promise = Promise$2;\n\n    Promise$2.polyfill();\n\n    return Promise$2;\n\n})));\n", "/**\n * This file adds a 'guardedCatch' function to the Promise API. This function\n * has to be used when we don't want to swallow real errors (crashes), like\n * 'catch' does (i.e. basically all the time in Odoo). We only execute the\n * 'onRejected' handler if the rejection's reason is not an Error, and we always\n * return a rejected Promise to let the rejection bubble up (and trigger the\n * 'unhandledrejection' event).\n */\n\n(function () {\n    var _catch = Promise.prototype.catch;\n    Promise.prototype.guardedCatch = function (onRejected) {\n        return _catch.call(this, function (reason) {\n            if (!reason || !(reason instanceof Error)) {\n                if (onRejected) {\n                    onRejected.call(this, reason);\n                }\n            }\n            return Promise.reject(reason);\n        });\n    };\n})();\n", "/**\n *------------------------------------------------------------------------------\n * Odoo Web Boostrap Code\n *------------------------------------------------------------------------------\n *\n * Each module can return a promise. In that case, the module is marked as loaded\n * only when the promise is resolved, and its value is equal to the resolved value.\n * The module can be rejected (unloaded). This will be logged in the console as info.\n *\n * logs:\n *      Missing dependencies:\n *          These modules do not appear in the page. It is possible that the\n *          JavaScript file is not in the page or that the module name is wrong\n *      Failed modules:\n *          A javascript error is detected\n *      Rejected modules:\n *          The module returns a rejected promise. It (and its dependent modules)\n *          is not loaded.\n *      Rejected linked modules:\n *          Modules who depend on a rejected module\n *      Non loaded modules:\n *          Modules who depend on a missing or a failed module\n *      Debug:\n *          Non loaded or failed module informations for debugging\n */\n(function () {\n    \"use strict\";\n\n    var jobUID = Date.now();\n\n    var jobs = [];\n    var factories = Object.create(null);\n    var jobDeps = [];\n    var jobPromises = [];\n\n    var services = Object.create({});\n\n    var commentRegExp = /(\\/\\*([\\s\\S]*?)\\*\\/|([^:]|^)\\/\\/(.*)$)/gm;\n    var cjsRequireRegExp = /[^.]\\s*require\\s*\\(\\s*[\"']([^'\"\\s]+)[\"']\\s*\\)/g;\n\n    if (!window.odoo) {\n        window.odoo = {};\n    }\n    var odoo = window.odoo;\n    var debug = odoo.debug;\n\n    var didLogInfoResolve;\n    var didLogInfoPromise = new Promise(function (resolve) {\n        didLogInfoResolve = resolve;\n    });\n\n    odoo.testing = typeof QUnit === \"object\";\n    odoo.remainingJobs = jobs;\n    odoo.__DEBUG__ = {\n        didLogInfo: didLogInfoPromise,\n        getDependencies: function (name, transitive) {\n            var deps = name instanceof Array ? name : [name];\n            var changed;\n            do {\n                changed = false;\n                jobDeps.forEach(function (dep) {\n                    if (deps.indexOf(dep.to) >= 0 && deps.indexOf(dep.from) < 0) {\n                        deps.push(dep.from);\n                        changed = true;\n                    }\n                });\n            } while (changed && transitive);\n            return deps;\n        },\n        getDependents: function (name) {\n            return jobDeps\n                .filter(function (dep) {\n                    return dep.from === name;\n                })\n                .map(function (dep) {\n                    return dep.to;\n                });\n        },\n        getWaitedJobs: function () {\n            return jobs\n                .map(function (job) {\n                    return job.name;\n                })\n                .filter(function (item, index, self) {\n                    // uniq\n                    return self.indexOf(item) === index;\n                });\n        },\n        getMissingJobs: function () {\n            var self = this;\n            var waited = this.getWaitedJobs();\n            var missing = [];\n            waited.forEach(function (job) {\n                self.getDependencies(job).forEach(function (job) {\n                    if (!(job in self.services)) {\n                        missing.push(job);\n                    }\n                });\n            });\n            return missing\n                .filter(function (item, index, self) {\n                    return self.indexOf(item) === index;\n                })\n                .filter(function (item) {\n                    return waited.indexOf(item) < 0;\n                })\n                .filter(function (job) {\n                    return !job.error;\n                });\n        },\n        getFailedJobs: function () {\n            return jobs.filter(function (job) {\n                return !!job.error;\n            });\n        },\n        factories: factories,\n        services: services,\n    };\n    odoo.define = function () {\n        var args = Array.prototype.slice.call(arguments);\n        var name = typeof args[0] === \"string\" ? args.shift() : \"__odoo_job\" + jobUID++;\n        var factory = args[args.length - 1];\n        var deps;\n        if (args[0] instanceof Array) {\n            deps = args[0];\n        } else {\n            deps = [];\n            factory\n                .toString()\n                .replace(commentRegExp, \"\")\n                .replace(cjsRequireRegExp, function (match, dep) {\n                    deps.push(dep);\n                });\n        }\n\n        if (!(deps instanceof Array)) {\n            throw new Error(\"Dependencies should be defined by an array\", deps);\n        }\n        if (typeof factory !== \"function\") {\n            throw new Error(\"Factory should be defined by a function\", factory);\n        }\n        if (typeof name !== \"string\") {\n            throw new Error(\"Invalid name definition (should be a string\", name);\n        }\n        if (name in factories) {\n            throw new Error(\"Service \" + name + \" already defined\");\n        }\n\n        factory.deps = deps;\n        factories[name] = factory;\n\n        jobs.push({\n            name: name,\n            factory: factory,\n            deps: deps,\n        });\n\n        deps.forEach(function (dep) {\n            jobDeps.push({ from: dep, to: name });\n        });\n\n        this.processJobs(jobs, services);\n    };\n    odoo.log = function () {\n        var missing = [];\n        var failed = [];\n        var cycle = null;\n\n        if (jobs.length) {\n            var debugJobs = {};\n            var rejected = [];\n            var rejectedLinked = [];\n            var job;\n            var jobdep;\n\n            for (var k = 0; k < jobs.length; k++) {\n                debugJobs[jobs[k].name] = job = {\n                    dependencies: jobs[k].deps,\n                    dependents: odoo.__DEBUG__.getDependents(jobs[k].name),\n                    name: jobs[k].name,\n                };\n                if (jobs[k].error) {\n                    job.error = jobs[k].error;\n                }\n                if (jobs[k].rejected) {\n                    job.rejected = jobs[k].rejected;\n                    rejected.push(job.name);\n                }\n                var deps = odoo.__DEBUG__.getDependencies(job.name);\n                for (var i = 0; i < deps.length; i++) {\n                    if (job.name !== deps[i] && !(deps[i] in services)) {\n                        jobdep = debugJobs[deps[i]];\n                        if (!jobdep && deps[i] in factories) {\n                            for (var j = 0; j < jobs.length; j++) {\n                                if (jobs[j].name === deps[i]) {\n                                    jobdep = jobs[j];\n                                    break;\n                                }\n                            }\n                        }\n                        if (jobdep && jobdep.rejected) {\n                            if (!job.rejected) {\n                                job.rejected = [];\n                                rejectedLinked.push(job.name);\n                            }\n                            job.rejected.push(deps[i]);\n                        } else {\n                            if (!job.missing) {\n                                job.missing = [];\n                            }\n                            job.missing.push(deps[i]);\n                        }\n                    }\n                }\n            }\n            missing = odoo.__DEBUG__.getMissingJobs();\n            failed = odoo.__DEBUG__.getFailedJobs();\n            var unloaded = Object.keys(debugJobs) // Object.values is not supported\n                .map(function (key) {\n                    return debugJobs[key];\n                })\n                .filter(function (job) {\n                    return job.missing;\n                });\n\n            if (debug || failed.length || unloaded.length) {\n                var log = window.console[\n                    !failed.length || !unloaded.length ? \"info\" : \"error\"\n                ].bind(window.console);\n                log(\n                    (failed.length ? \"error\" : unloaded.length ? \"warning\" : \"info\") +\n                        \": Some modules could not be started\"\n                );\n                if (missing.length) {\n                    log(\"Missing dependencies:    \", missing);\n                }\n                if (failed.length) {\n                    log(\n                        \"Failed modules:          \",\n                        failed.map(function (fail) {\n                            return fail.name;\n                        })\n                    );\n                }\n                if (rejected.length) {\n                    log(\"Rejected modules:        \", rejected);\n                }\n                if (rejectedLinked.length) {\n                    log(\"Rejected linked modules: \", rejectedLinked);\n                }\n                if (unloaded.length) {\n                    cycle = findCycle(unloaded);\n                    if (cycle) {\n                        console.error(\"Cyclic dependencies: \" + cycle);\n                    }\n                    log(\n                        \"Non loaded modules:      \",\n                        unloaded.map(function (unload) {\n                            return unload.name;\n                        })\n                    );\n                }\n                if (debug && Object.keys(debugJobs).length) {\n                    log(\"Debug:                   \", debugJobs);\n                }\n            }\n        }\n        odoo.__DEBUG__.jsModules = {\n            missing: missing,\n            failed: failed.map((mod) => mod.name),\n            unloaded: unloaded ? unloaded.map((mod) => mod.name) : [],\n            cycle,\n        };\n        didLogInfoResolve();\n    };\n    odoo.processJobs = function (jobs, services) {\n        var job;\n\n        function processJob(job) {\n            var require = makeRequire(job);\n\n            var jobExec;\n            function onError(e) {\n                job.error = e;\n                console.error(`Error while loading ${job.name}: ${e.message}`, e);\n                Promise.reject(e);\n            }\n            var def = new Promise(function (resolve) {\n                try {\n                    jobExec = job.factory.call(null, require);\n                    jobs.splice(jobs.indexOf(job), 1);\n                } catch (e) {\n                    onError(e);\n                }\n                if (!job.error) {\n                    Promise.resolve(jobExec)\n                        .then(function (data) {\n                            services[job.name] = data;\n                            resolve();\n                            odoo.processJobs(jobs, services);\n                        })\n                        .guardedCatch(function (e) {\n                            job.rejected = e || true;\n                            jobs.push(job);\n                        })\n                        .catch(function (e) {\n                            if (e instanceof Error) {\n                                onError(e);\n                            }\n                            resolve();\n                        });\n                } else {\n                    resolve();\n                }\n            });\n            jobPromises.push(def);\n        }\n\n        function isReady(job) {\n            return (\n                !job.error &&\n                !job.rejected &&\n                job.factory.deps.every(function (name) {\n                    return name in services;\n                })\n            );\n        }\n\n        function makeRequire(job) {\n            var deps = {};\n            Object.keys(services)\n                .filter(function (item) {\n                    return job.deps.indexOf(item) >= 0;\n                })\n                .forEach(function (key) {\n                    deps[key] = services[key];\n                });\n\n            return function require(name) {\n                if (!(name in deps)) {\n                    console.error(\"Undefined dependency: \", name);\n                }\n                return deps[name];\n            };\n        }\n\n        while (jobs.length) {\n            job = undefined;\n            for (var i = 0; i < jobs.length; i++) {\n                if (isReady(jobs[i])) {\n                    job = jobs[i];\n                    break;\n                }\n            }\n            if (!job) {\n                break;\n            }\n            processJob(job);\n        }\n\n        return services;\n    };\n\n    // Automatically log errors detected when loading modules\n    window.addEventListener(\"load\", function logWhenLoaded() {\n        setTimeout(function () {\n            var len = jobPromises.length;\n            Promise.all(jobPromises).then(function () {\n                if (len === jobPromises.length) {\n                    odoo.log();\n                } else {\n                    logWhenLoaded();\n                }\n            });\n        }, 5000);\n    });\n\n    /**\n     * Visit the list of jobs, and return the first found cycle, if any\n     *\n     * @param {any[]} jobs\n     * @returns {null | string} either a string describing a cycle, or null\n     */\n    function findCycle(jobs) {\n        // build dependency graph\n        const dependencyGraph = new Map();\n        for (let job of jobs) {\n            dependencyGraph.set(job.name, job.dependencies);\n        }\n\n        // helpers\n        function visitJobs(jobs, visited = new Set()) {\n            for (let job of jobs) {\n                const result = visitJob(job, visited);\n                if (result) {\n                    return result;\n                }\n            }\n            return null;\n        }\n\n        function visitJob(job, visited) {\n            if (visited.has(job)) {\n                const jobs = Array.from(visited).concat([job]);\n                const index = jobs.indexOf(job);\n                return jobs\n                    .slice(index)\n                    .map((j) => `\"${j}\"`)\n                    .join(\" => \");\n            }\n            const deps = dependencyGraph.get(job);\n            return deps ? visitJobs(deps, new Set(visited).add(job)) : null;\n        }\n\n        // visit each root to find cycles\n        return visitJobs(jobs.map((j) => j.name));\n    }\n})();\n", "/** @odoo-module **/\n\nexport const session = odoo.__session_info__ || {};\ndelete odoo.__session_info__;\n", "odoo.define('web.utils.cookies', function (require) {\n\"use strict\";\n\nreturn {\n    /**\n     * Reads the cookie described by the given name.\n     *\n     * @param {string} cookieName\n     * @returns {string}\n     */\n    get_cookie(cookieName) {\n        var cookies = document.cookie ? document.cookie.split('; ') : [];\n        for (var i = 0, l = cookies.length; i < l; i++) {\n            var parts = cookies[i].split('=');\n            var name = parts.shift();\n            var cookie = parts.join('=');\n\n            if (cookieName && cookieName === name) {\n                return cookie;\n            }\n        }\n        return \"\";\n    },\n    /**\n     * Creates a cookie.\n     *\n     * @param {string} name the name of the cookie\n     * @param {string} value the value stored in the cookie\n     * @param {integer} ttl time to live of the cookie in millis. -1 to erase the cookie.\n     */\n    set_cookie(name, value, ttl) {\n        ttl = ttl || 24 * 60 * 60 * 365;\n        document.cookie = [\n            `${name}=${value}`,\n            'path=/',\n            `max-age=${ttl}`,\n            `expires=${new Date(new Date().getTime() + ttl * 1000).toGMTString()}`\n        ].join(';');\n    },\n};\n});\n", "/** @odoo-module **/\n\nconst BREAKPOINT_SIZES = ['sm', 'md', 'lg', 'xl'];\n\n/**\n * Creates an automatic 'more' dropdown-menu for a set of navbar items.\n *\n * @param {HTMLElement} el\n * @param {Object} [options]\n * @param {string} [options.unfoldable='none'] selector for items that do not\n * need to be added to dropdown-menu.\n * @param {float} [options.maxWidth] The max width value that menu content\n * can take => the overflowing (foldable) items are added in the dropdown-menu.\n * @param {string} [options.minSize] the menu auto-hide option will be disabled\n * if viewport is smaller than minSize.\n * @param {Array} [options.images=[]] images to wait for before menu update.\n * @param {Array} [options.loadingStyleClasses=[]] list of CSS classes to add while\n * updating the menu.\n*/\nexport async function initAutoMoreMenu(el, options) {\n    if (!el) {\n        return;\n    }\n    const navbar = el.closest('.navbar');\n    const computedStyles = window.getComputedStyle(el);\n    // Get breakpoint related information from the navbar to correctly handle\n    // the \"auto-hide\" on mobile menu.\n    const [breakpoint = 'md'] = navbar ? BREAKPOINT_SIZES\n        .filter(suffix => navbar.classList.contains(`navbar-expand-${suffix}`)) : [];\n    const isNoHamburgerMenu = !!navbar && navbar.classList.contains('navbar-expand');\n\n    options = Object.assign({\n        unfoldable: 'none',\n        maxWidth: false,\n        minSize: computedStyles.getPropertyValue(`--breakpoint-${breakpoint}`),\n        images: [],\n        loadingStyleClasses: [],\n    }, options || {});\n\n    const isUserNavbar = el.parentElement.classList.contains('o_main_navbar');\n    const dropdownSubMenuClasses = ['show', 'border-0', 'position-static'];\n    const dropdownToggleClasses = ['h-auto', 'py-2', 'text-secondary'];\n    var autoMarginLeftRegex = /\\bm[lx]?(?:-(?:sm|md|lg|xl))?-auto\\b/;\n    var autoMarginRightRegex = /\\bm[rx]?(?:-(?:sm|md|lg|xl))?-auto\\b/;\n    var extraItemsToggle = null;\n    let debounce;\n    const afterFontsloading = new Promise((resolve) => {\n        if (document.fonts) {\n            document.fonts.ready.then(resolve);\n        } else {\n            // IE: don't wait more than max .15s.\n            setTimeout(resolve, 150);\n        }\n    });\n    afterFontsloading.then(_adapt);\n\n    if (options.images.length) {\n        await _afterImagesLoading(options.images);\n        _adapt();\n    }\n\n    const debouncedAdapt = () => {\n        clearTimeout(debounce);\n        debounce = setTimeout(_adapt, 250);\n    };\n    window.addEventListener('resize', debouncedAdapt);\n\n    el.addEventListener('dom:autoMoreMenu:adapt', _adapt);\n    el.addEventListener('dom:autoMoreMenu:destroy', destroy, {once: true});\n\n    function _restore() {\n        if (!extraItemsToggle) {\n            return;\n        }\n        // Move extra menu items from dropdown-menu to menu element in the same order.\n        [...extraItemsToggle.querySelector('.dropdown-menu').children].forEach((item) => {\n            if (!isUserNavbar) {\n                item.classList.add('nav-item');\n                const itemLink = item.querySelector('.dropdown-item');\n                itemLink.classList.remove('dropdown-item');\n                itemLink.classList.add('nav-link');\n            } else {\n                item.classList.remove('dropdown-item');\n                const dropdownSubMenu = item.querySelector('.dropdown-menu');\n                const dropdownSubMenuButton = item.querySelector('.dropdown-toggle');\n                if (dropdownSubMenu) {\n                    dropdownSubMenu.classList.remove(...dropdownSubMenuClasses);\n                }\n                if (dropdownSubMenuButton) {\n                    dropdownSubMenuButton.classList.remove(...dropdownToggleClasses);\n                }\n            }\n            el.insertBefore(item, extraItemsToggle);\n        });\n        extraItemsToggle.remove();\n        extraItemsToggle = null;\n    }\n\n    function _adapt() {\n        el.dispatchEvent(new Event(\"autoMoreMenu.willAdapt\", {bubbles: true}));\n        if (options.loadingStyleClasses.length) {\n            el.classList.add(...options.loadingStyleClasses);\n        }\n        _restore();\n\n        // Ignore invisible/toggleable top menu element & small viewports.\n        if (!el.getClientRects().length || el.closest('.show')\n            || (window.matchMedia(`(max-width: ${options.minSize})`).matches && !isNoHamburgerMenu)) {\n            return _endAutoMoreMenu();\n        }\n\n        let unfoldableItems = [];\n        const items = [...el.children].filter((node) => {\n            if (node.matches && !node.matches(options.unfoldable)) {\n                return true;\n            }\n            unfoldableItems.push(node);\n            return false;\n        });\n        var nbItems = items.length;\n        var menuItemsWidth = items.reduce((sum, el) => sum + computeFloatOuterWidthWithMargins(el, true, true, false), 0);\n        let maxWidth = 0;\n\n        if (options.maxWidth) {\n            maxWidth = options.maxWidth();\n        }\n        if (!maxWidth) {\n            maxWidth = computeFloatOuterWidthWithMargins(el, true, true, true);\n            var style = window.getComputedStyle(el);\n            maxWidth -= (parseFloat(style.paddingLeft) + parseFloat(style.paddingRight) + parseFloat(style.borderLeftWidth) + parseFloat(style.borderRightWidth));\n            maxWidth -= unfoldableItems.reduce((sum, el) => sum + computeFloatOuterWidthWithMargins(el, true, true, false), 0);\n        }\n        // Ignore if there is no overflow.\n        if (maxWidth - menuItemsWidth >= -0.001) {\n            return _endAutoMoreMenu();\n        }\n\n        const dropdownMenu = _addExtraItemsButton(items[nbItems - 1].nextElementSibling);\n        menuItemsWidth += computeFloatOuterWidthWithMargins(extraItemsToggle, true, true, false);\n        do {\n            menuItemsWidth -= computeFloatOuterWidthWithMargins(items[--nbItems], true, true, false);\n        } while (!(maxWidth - menuItemsWidth >= -0.001) && (nbItems > 0));\n\n        const extraItems = items.slice(nbItems);\n        extraItems.forEach((el) => {\n            if (!isUserNavbar) {\n                const navLink = el.querySelector('.nav-link, a');\n                el.classList.remove('nav-item');\n                navLink.classList.remove('nav-link');\n                navLink.classList.add('dropdown-item');\n                navLink.classList.toggle('active', el.classList.contains('active'));\n            } else {\n                const dropdownSubMenu = el.querySelector('.dropdown-menu');\n                const dropdownSubMenuButton = el.querySelector('.dropdown-toggle');\n                el.classList.add('dropdown-item', 'p-0');\n                if (dropdownSubMenu) {\n                    dropdownSubMenu.classList.add(...dropdownSubMenuClasses);\n                }\n                if (dropdownSubMenuButton) {\n                    dropdownSubMenuButton.classList.add(...dropdownToggleClasses);\n                }\n            }\n            dropdownMenu.appendChild(el);\n        });\n        _endAutoMoreMenu();\n    }\n\n    function computeFloatOuterWidthWithMargins(el, mLeft, mRight, considerAutoMargins) {\n        var rect = el.getBoundingClientRect();\n        var style = window.getComputedStyle(el);\n        var outerWidth = rect.right - rect.left;\n        const isRTL = style.direction === 'rtl';\n        if (mLeft !== false && (considerAutoMargins || !(isRTL ? autoMarginRightRegex : autoMarginLeftRegex).test(el.getAttribute('class')))) {\n            outerWidth += parseFloat(style.marginLeft);\n        }\n        if (mRight !== false && (considerAutoMargins || !(isRTL ? autoMarginLeftRegex : autoMarginRightRegex).test(el.getAttribute('class')))) {\n            outerWidth += parseFloat(style.marginRight);\n        }\n        // Would be NaN for invisible elements for example\n        return isNaN(outerWidth) ? 0 : outerWidth;\n    }\n\n    function _addExtraItemsButton(target) {\n        let dropdownMenu = document.createElement('div');\n        extraItemsToggle = dropdownMenu.cloneNode();\n        const extraItemsToggleIcon = document.createElement('i');\n        const extraItemsToggleLink = document.createElement('a');\n\n        dropdownMenu.className = 'dropdown-menu';\n        extraItemsToggle.className = 'nav-item dropdown o_extra_menu_items';\n        extraItemsToggleIcon.className = 'fa fa-plus';\n        Object.entries({\n            role: 'button',\n            href: '#',\n            class: 'nav-link dropdown-toggle o-no-caret',\n            'data-toggle': 'dropdown',\n            'aria-expanded': false,\n        }).forEach(([key, value]) => {\n            extraItemsToggleLink.setAttribute(key, value);\n        });\n\n        extraItemsToggleLink.appendChild(extraItemsToggleIcon);\n        extraItemsToggle.appendChild(extraItemsToggleLink);\n        extraItemsToggle.appendChild(dropdownMenu);\n        el.insertBefore(extraItemsToggle, target);\n        // TODO Adapt in 16.0: The dropdown menu is closed when clicking inside\n        // the extra menu items. The goal here is to prevent this default\n        // behaviour on \"edit\" mode to allow correct editing of extra menu\n        // items, mega menu content... This should be simply replaced by the BS5\n        // `autoClose` option.\n        if (window.jQuery && document.body.classList.contains(\"editor_enable\")) {\n            $(extraItemsToggle).on(\"hide.bs.dropdown\", e => {\n                return !e.clickEvent || !e.clickEvent.target.closest(\".o_extra_menu_items\");\n            });\n        }\n        return dropdownMenu;\n    }\n\n    function destroy() {\n        _restore();\n        window.removeEventListener('resize', debouncedAdapt);\n        el.removeEventListener('dom:autoMoreMenu:adapt', _adapt);\n    }\n\n    function _afterImagesLoading(images) {\n        const defs = images.map((image) => {\n            if (image.complete || !image.getClientRects().length) {\n                return null;\n            }\n            return new Promise(function (resolve, reject) {\n                if (!image.width) {\n                    // The purpose of the 'o_menu_image_placeholder' class is to add a default\n                    // size to non loaded images (on the first update) to prevent flickering.\n                    image.classList.add('o_menu_image_placeholder');\n                }\n                image.addEventListener('load', () => {\n                    image.classList.remove('o_menu_image_placeholder');\n                    resolve();\n                });\n            });\n        });\n        return Promise.all(defs);\n    }\n\n    function _endAutoMoreMenu() {\n        el.classList.remove(...options.loadingStyleClasses);\n    }\n}\n\n/**\n * Cleans what has been done by ``initAutoMoreMenu``.\n *\n * @param {HTMLElement} el\n */\nexport function destroyAutoMoreMenu(el) {\n    el.dispatchEvent(new Event('dom:autoMoreMenu:destroy'));\n}\n", "//     Underscore.js 1.8.2\n//     http://underscorejs.org\n//     (c) 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors\n//     Underscore may be freely distributed under the MIT license.\n\n(function() {\n\n  // Baseline setup\n  // --------------\n\n  // Establish the root object, `window` in the browser, or `exports` on the server.\n  var root = this;\n\n  // Save the previous value of the `_` variable.\n  var previousUnderscore = root._;\n\n  // Save bytes in the minified (but not gzipped) version:\n  var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;\n\n  // Create quick reference variables for speed access to core prototypes.\n  var\n    push             = ArrayProto.push,\n    slice            = ArrayProto.slice,\n    toString         = ObjProto.toString,\n    hasOwnProperty   = ObjProto.hasOwnProperty;\n\n  // All **ECMAScript 5** native function implementations that we hope to use\n  // are declared here.\n  var\n    nativeIsArray      = Array.isArray,\n    nativeKeys         = Object.keys,\n    nativeBind         = FuncProto.bind,\n    nativeCreate       = Object.create;\n\n  // Naked function reference for surrogate-prototype-swapping.\n  var Ctor = function(){};\n\n  // Create a safe reference to the Underscore object for use below.\n  var _ = function(obj) {\n    if (obj instanceof _) return obj;\n    if (!(this instanceof _)) return new _(obj);\n    this._wrapped = obj;\n  };\n\n  // Export the Underscore object for **Node.js**, with\n  // backwards-compatibility for the old `require()` API. If we're in\n  // the browser, add `_` as a global object.\n  if (typeof exports !== 'undefined') {\n    if (typeof module !== 'undefined' && module.exports) {\n      exports = module.exports = _;\n    }\n    exports._ = _;\n  } else {\n    root._ = _;\n  }\n\n  // Current version.\n  _.VERSION = '1.8.2';\n\n  // Internal function that returns an efficient (for current engines) version\n  // of the passed-in callback, to be repeatedly applied in other Underscore\n  // functions.\n  var optimizeCb = function(func, context, argCount) {\n    if (context === void 0) return func;\n    switch (argCount == null ? 3 : argCount) {\n      case 1: return function(value) {\n        return func.call(context, value);\n      };\n      case 2: return function(value, other) {\n        return func.call(context, value, other);\n      };\n      case 3: return function(value, index, collection) {\n        return func.call(context, value, index, collection);\n      };\n      case 4: return function(accumulator, value, index, collection) {\n        return func.call(context, accumulator, value, index, collection);\n      };\n    }\n    return function() {\n      return func.apply(context, arguments);\n    };\n  };\n\n  // A mostly-internal function to generate callbacks that can be applied\n  // to each element in a collection, returning the desired result \u2014 either\n  // identity, an arbitrary callback, a property matcher, or a property accessor.\n  var cb = function(value, context, argCount) {\n    if (value == null) return _.identity;\n    if (_.isFunction(value)) return optimizeCb(value, context, argCount);\n    if (_.isObject(value)) return _.matcher(value);\n    return _.property(value);\n  };\n  _.iteratee = function(value, context) {\n    return cb(value, context, Infinity);\n  };\n\n  // An internal function for creating assigner functions.\n  var createAssigner = function(keysFunc, undefinedOnly) {\n    return function(obj) {\n      var length = arguments.length;\n      if (length < 2 || obj == null) return obj;\n      for (var index = 1; index < length; index++) {\n        var source = arguments[index],\n            keys = keysFunc(source),\n            l = keys.length;\n        for (var i = 0; i < l; i++) {\n          var key = keys[i];\n          if (!undefinedOnly || obj[key] === void 0) obj[key] = source[key];\n        }\n      }\n      return obj;\n    };\n  };\n\n  // An internal function for creating a new object that inherits from another.\n  var baseCreate = function(prototype) {\n    if (!_.isObject(prototype)) return {};\n    if (nativeCreate) return nativeCreate(prototype);\n    Ctor.prototype = prototype;\n    var result = new Ctor;\n    Ctor.prototype = null;\n    return result;\n  };\n\n  // Helper for collection methods to determine whether a collection\n  // should be iterated as an array or as an object\n  // Related: http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength\n  var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1;\n  var isArrayLike = function(collection) {\n    var length = collection && collection.length;\n    return typeof length == 'number' && length >= 0 && length <= MAX_ARRAY_INDEX;\n  };\n\n  // Collection Functions\n  // --------------------\n\n  // The cornerstone, an `each` implementation, aka `forEach`.\n  // Handles raw objects in addition to array-likes. Treats all\n  // sparse array-likes as if they were dense.\n  _.each = _.forEach = function(obj, iteratee, context) {\n    iteratee = optimizeCb(iteratee, context);\n    var i, length;\n    if (isArrayLike(obj)) {\n      for (i = 0, length = obj.length; i < length; i++) {\n        iteratee(obj[i], i, obj);\n      }\n    } else {\n      var keys = _.keys(obj);\n      for (i = 0, length = keys.length; i < length; i++) {\n        iteratee(obj[keys[i]], keys[i], obj);\n      }\n    }\n    return obj;\n  };\n\n  // Return the results of applying the iteratee to each element.\n  _.map = _.collect = function(obj, iteratee, context) {\n    iteratee = cb(iteratee, context);\n    var keys = !isArrayLike(obj) && _.keys(obj),\n        length = (keys || obj).length,\n        results = Array(length);\n    for (var index = 0; index < length; index++) {\n      var currentKey = keys ? keys[index] : index;\n      results[index] = iteratee(obj[currentKey], currentKey, obj);\n    }\n    return results;\n  };\n\n  // Create a reducing function iterating left or right.\n  function createReduce(dir) {\n    // Optimized iterator function as using arguments.length\n    // in the main function will deoptimize the, see #1991.\n    function iterator(obj, iteratee, memo, keys, index, length) {\n      for (; index >= 0 && index < length; index += dir) {\n        var currentKey = keys ? keys[index] : index;\n        memo = iteratee(memo, obj[currentKey], currentKey, obj);\n      }\n      return memo;\n    }\n\n    return function(obj, iteratee, memo, context) {\n      iteratee = optimizeCb(iteratee, context, 4);\n      var keys = !isArrayLike(obj) && _.keys(obj),\n          length = (keys || obj).length,\n          index = dir > 0 ? 0 : length - 1;\n      // Determine the initial value if none is provided.\n      if (arguments.length < 3) {\n        memo = obj[keys ? keys[index] : index];\n        index += dir;\n      }\n      return iterator(obj, iteratee, memo, keys, index, length);\n    };\n  }\n\n  // **Reduce** builds up a single result from a list of values, aka `inject`,\n  // or `foldl`.\n  _.reduce = _.foldl = _.inject = createReduce(1);\n\n  // The right-associative version of reduce, also known as `foldr`.\n  _.reduceRight = _.foldr = createReduce(-1);\n\n  // Return the first value which passes a truth test. Aliased as `detect`.\n  _.find = _.detect = function(obj, predicate, context) {\n    var key;\n    if (isArrayLike(obj)) {\n      key = _.findIndex(obj, predicate, context);\n    } else {\n      key = _.findKey(obj, predicate, context);\n    }\n    if (key !== void 0 && key !== -1) return obj[key];\n  };\n\n  // Return all the elements that pass a truth test.\n  // Aliased as `select`.\n  _.filter = _.select = function(obj, predicate, context) {\n    var results = [];\n    predicate = cb(predicate, context);\n    _.each(obj, function(value, index, list) {\n      if (predicate(value, index, list)) results.push(value);\n    });\n    return results;\n  };\n\n  // Return all the elements for which a truth test fails.\n  _.reject = function(obj, predicate, context) {\n    return _.filter(obj, _.negate(cb(predicate)), context);\n  };\n\n  // Determine whether all of the elements match a truth test.\n  // Aliased as `all`.\n  _.every = _.all = function(obj, predicate, context) {\n    predicate = cb(predicate, context);\n    var keys = !isArrayLike(obj) && _.keys(obj),\n        length = (keys || obj).length;\n    for (var index = 0; index < length; index++) {\n      var currentKey = keys ? keys[index] : index;\n      if (!predicate(obj[currentKey], currentKey, obj)) return false;\n    }\n    return true;\n  };\n\n  // Determine if at least one element in the object matches a truth test.\n  // Aliased as `any`.\n  _.some = _.any = function(obj, predicate, context) {\n    predicate = cb(predicate, context);\n    var keys = !isArrayLike(obj) && _.keys(obj),\n        length = (keys || obj).length;\n    for (var index = 0; index < length; index++) {\n      var currentKey = keys ? keys[index] : index;\n      if (predicate(obj[currentKey], currentKey, obj)) return true;\n    }\n    return false;\n  };\n\n  // Determine if the array or object contains a given value (using `===`).\n  // Aliased as `includes` and `include`.\n  _.contains = _.includes = _.include = function(obj, target, fromIndex) {\n    if (!isArrayLike(obj)) obj = _.values(obj);\n    return _.indexOf(obj, target, typeof fromIndex == 'number' && fromIndex) >= 0;\n  };\n\n  // Invoke a method (with arguments) on every item in a collection.\n  _.invoke = function(obj, method) {\n    var args = slice.call(arguments, 2);\n    var isFunc = _.isFunction(method);\n    return _.map(obj, function(value) {\n      var func = isFunc ? method : value[method];\n      return func == null ? func : func.apply(value, args);\n    });\n  };\n\n  // Convenience version of a common use case of `map`: fetching a property.\n  _.pluck = function(obj, key) {\n    return _.map(obj, _.property(key));\n  };\n\n  // Convenience version of a common use case of `filter`: selecting only objects\n  // containing specific `key:value` pairs.\n  _.where = function(obj, attrs) {\n    return _.filter(obj, _.matcher(attrs));\n  };\n\n  // Convenience version of a common use case of `find`: getting the first object\n  // containing specific `key:value` pairs.\n  _.findWhere = function(obj, attrs) {\n    return _.find(obj, _.matcher(attrs));\n  };\n\n  // Return the maximum element (or element-based computation).\n  _.max = function(obj, iteratee, context) {\n    var result = -Infinity, lastComputed = -Infinity,\n        value, computed;\n    if (iteratee == null && obj != null) {\n      obj = isArrayLike(obj) ? obj : _.values(obj);\n      for (var i = 0, length = obj.length; i < length; i++) {\n        value = obj[i];\n        if (value > result) {\n          result = value;\n        }\n      }\n    } else {\n      iteratee = cb(iteratee, context);\n      _.each(obj, function(value, index, list) {\n        computed = iteratee(value, index, list);\n        if (computed > lastComputed || computed === -Infinity && result === -Infinity) {\n          result = value;\n          lastComputed = computed;\n        }\n      });\n    }\n    return result;\n  };\n\n  // Return the minimum element (or element-based computation).\n  _.min = function(obj, iteratee, context) {\n    var result = Infinity, lastComputed = Infinity,\n        value, computed;\n    if (iteratee == null && obj != null) {\n      obj = isArrayLike(obj) ? obj : _.values(obj);\n      for (var i = 0, length = obj.length; i < length; i++) {\n        value = obj[i];\n        if (value < result) {\n          result = value;\n        }\n      }\n    } else {\n      iteratee = cb(iteratee, context);\n      _.each(obj, function(value, index, list) {\n        computed = iteratee(value, index, list);\n        if (computed < lastComputed || computed === Infinity && result === Infinity) {\n          result = value;\n          lastComputed = computed;\n        }\n      });\n    }\n    return result;\n  };\n\n  // Shuffle a collection, using the modern version of the\n  // [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher\u2013Yates_shuffle).\n  _.shuffle = function(obj) {\n    var set = isArrayLike(obj) ? obj : _.values(obj);\n    var length = set.length;\n    var shuffled = Array(length);\n    for (var index = 0, rand; index < length; index++) {\n      rand = _.random(0, index);\n      if (rand !== index) shuffled[index] = shuffled[rand];\n      shuffled[rand] = set[index];\n    }\n    return shuffled;\n  };\n\n  // Sample **n** random values from a collection.\n  // If **n** is not specified, returns a single random element.\n  // The internal `guard` argument allows it to work with `map`.\n  _.sample = function(obj, n, guard) {\n    if (n == null || guard) {\n      if (!isArrayLike(obj)) obj = _.values(obj);\n      return obj[_.random(obj.length - 1)];\n    }\n    return _.shuffle(obj).slice(0, Math.max(0, n));\n  };\n\n  // Sort the object's values by a criterion produced by an iteratee.\n  _.sortBy = function(obj, iteratee, context) {\n    iteratee = cb(iteratee, context);\n    return _.pluck(_.map(obj, function(value, index, list) {\n      return {\n        value: value,\n        index: index,\n        criteria: iteratee(value, index, list)\n      };\n    }).sort(function(left, right) {\n      var a = left.criteria;\n      var b = right.criteria;\n      if (a !== b) {\n        if (a > b || a === void 0) return 1;\n        if (a < b || b === void 0) return -1;\n      }\n      return left.index - right.index;\n    }), 'value');\n  };\n\n  // An internal function used for aggregate \"group by\" operations.\n  var group = function(behavior) {\n    return function(obj, iteratee, context) {\n      var result = {};\n      iteratee = cb(iteratee, context);\n      _.each(obj, function(value, index) {\n        var key = iteratee(value, index, obj);\n        behavior(result, value, key);\n      });\n      return result;\n    };\n  };\n\n  // Groups the object's values by a criterion. Pass either a string attribute\n  // to group by, or a function that returns the criterion.\n  _.groupBy = group(function(result, value, key) {\n    if (_.has(result, key)) result[key].push(value); else result[key] = [value];\n  });\n\n  // Indexes the object's values by a criterion, similar to `groupBy`, but for\n  // when you know that your index values will be unique.\n  _.indexBy = group(function(result, value, key) {\n    result[key] = value;\n  });\n\n  // Counts instances of an object that group by a certain criterion. Pass\n  // either a string attribute to count by, or a function that returns the\n  // criterion.\n  _.countBy = group(function(result, value, key) {\n    if (_.has(result, key)) result[key]++; else result[key] = 1;\n  });\n\n  // Safely create a real, live array from anything iterable.\n  _.toArray = function(obj) {\n    if (!obj) return [];\n    if (_.isArray(obj)) return slice.call(obj);\n    if (isArrayLike(obj)) return _.map(obj, _.identity);\n    return _.values(obj);\n  };\n\n  // Return the number of elements in an object.\n  _.size = function(obj) {\n    if (obj == null) return 0;\n    return isArrayLike(obj) ? obj.length : _.keys(obj).length;\n  };\n\n  // Split a collection into two arrays: one whose elements all satisfy the given\n  // predicate, and one whose elements all do not satisfy the predicate.\n  _.partition = function(obj, predicate, context) {\n    predicate = cb(predicate, context);\n    var pass = [], fail = [];\n    _.each(obj, function(value, key, obj) {\n      (predicate(value, key, obj) ? pass : fail).push(value);\n    });\n    return [pass, fail];\n  };\n\n  // Array Functions\n  // ---------------\n\n  // Get the first element of an array. Passing **n** will return the first N\n  // values in the array. Aliased as `head` and `take`. The **guard** check\n  // allows it to work with `_.map`.\n  _.first = _.head = _.take = function(array, n, guard) {\n    if (array == null) return void 0;\n    if (n == null || guard) return array[0];\n    return _.initial(array, array.length - n);\n  };\n\n  // Returns everything but the last entry of the array. Especially useful on\n  // the arguments object. Passing **n** will return all the values in\n  // the array, excluding the last N.\n  _.initial = function(array, n, guard) {\n    return slice.call(array, 0, Math.max(0, array.length - (n == null || guard ? 1 : n)));\n  };\n\n  // Get the last element of an array. Passing **n** will return the last N\n  // values in the array.\n  _.last = function(array, n, guard) {\n    if (array == null) return void 0;\n    if (n == null || guard) return array[array.length - 1];\n    return _.rest(array, Math.max(0, array.length - n));\n  };\n\n  // Returns everything but the first entry of the array. Aliased as `tail` and `drop`.\n  // Especially useful on the arguments object. Passing an **n** will return\n  // the rest N values in the array.\n  _.rest = _.tail = _.drop = function(array, n, guard) {\n    return slice.call(array, n == null || guard ? 1 : n);\n  };\n\n  // Trim out all falsy values from an array.\n  _.compact = function(array) {\n    return _.filter(array, _.identity);\n  };\n\n  // Internal implementation of a recursive `flatten` function.\n  var flatten = function(input, shallow, strict, startIndex) {\n    var output = [], idx = 0;\n    for (var i = startIndex || 0, length = input && input.length; i < length; i++) {\n      var value = input[i];\n      if (isArrayLike(value) && (_.isArray(value) || _.isArguments(value))) {\n        //flatten current level of array or arguments object\n        if (!shallow) value = flatten(value, shallow, strict);\n        var j = 0, len = value.length;\n        output.length += len;\n        while (j < len) {\n          output[idx++] = value[j++];\n        }\n      } else if (!strict) {\n        output[idx++] = value;\n      }\n    }\n    return output;\n  };\n\n  // Flatten out an array, either recursively (by default), or just one level.\n  _.flatten = function(array, shallow) {\n    return flatten(array, shallow, false);\n  };\n\n  // Return a version of the array that does not contain the specified value(s).\n  _.without = function(array) {\n    return _.difference(array, slice.call(arguments, 1));\n  };\n\n  // Produce a duplicate-free version of the array. If the array has already\n  // been sorted, you have the option of using a faster algorithm.\n  // Aliased as `unique`.\n  _.uniq = _.unique = function(array, isSorted, iteratee, context) {\n    if (array == null) return [];\n    if (!_.isBoolean(isSorted)) {\n      context = iteratee;\n      iteratee = isSorted;\n      isSorted = false;\n    }\n    if (iteratee != null) iteratee = cb(iteratee, context);\n    var result = [];\n    var seen = [];\n    for (var i = 0, length = array.length; i < length; i++) {\n      var value = array[i],\n          computed = iteratee ? iteratee(value, i, array) : value;\n      if (isSorted) {\n        if (!i || seen !== computed) result.push(value);\n        seen = computed;\n      } else if (iteratee) {\n        if (!_.contains(seen, computed)) {\n          seen.push(computed);\n          result.push(value);\n        }\n      } else if (!_.contains(result, value)) {\n        result.push(value);\n      }\n    }\n    return result;\n  };\n\n  // Produce an array that contains the union: each distinct element from all of\n  // the passed-in arrays.\n  _.union = function() {\n    return _.uniq(flatten(arguments, true, true));\n  };\n\n  // Produce an array that contains every item shared between all the\n  // passed-in arrays.\n  _.intersection = function(array) {\n    if (array == null) return [];\n    var result = [];\n    var argsLength = arguments.length;\n    for (var i = 0, length = array.length; i < length; i++) {\n      var item = array[i];\n      if (_.contains(result, item)) continue;\n      for (var j = 1; j < argsLength; j++) {\n        if (!_.contains(arguments[j], item)) break;\n      }\n      if (j === argsLength) result.push(item);\n    }\n    return result;\n  };\n\n  // Take the difference between one array and a number of other arrays.\n  // Only the elements present in just the first array will remain.\n  _.difference = function(array) {\n    var rest = flatten(arguments, true, true, 1);\n    return _.filter(array, function(value){\n      return !_.contains(rest, value);\n    });\n  };\n\n  // Zip together multiple lists into a single array -- elements that share\n  // an index go together.\n  _.zip = function() {\n    return _.unzip(arguments);\n  };\n\n  // Complement of _.zip. Unzip accepts an array of arrays and groups\n  // each array's elements on shared indices\n  _.unzip = function(array) {\n    var length = array && _.max(array, 'length').length || 0;\n    var result = Array(length);\n\n    for (var index = 0; index < length; index++) {\n      result[index] = _.pluck(array, index);\n    }\n    return result;\n  };\n\n  // Converts lists into objects. Pass either a single array of `[key, value]`\n  // pairs, or two parallel arrays of the same length -- one of keys, and one of\n  // the corresponding values.\n  _.object = function(list, values) {\n    var result = {};\n    for (var i = 0, length = list && list.length; i < length; i++) {\n      if (values) {\n        result[list[i]] = values[i];\n      } else {\n        result[list[i][0]] = list[i][1];\n      }\n    }\n    return result;\n  };\n\n  // Return the position of the first occurrence of an item in an array,\n  // or -1 if the item is not included in the array.\n  // If the array is large and already in sort order, pass `true`\n  // for **isSorted** to use binary search.\n  _.indexOf = function(array, item, isSorted) {\n    var i = 0, length = array && array.length;\n    if (typeof isSorted == 'number') {\n      i = isSorted < 0 ? Math.max(0, length + isSorted) : isSorted;\n    } else if (isSorted && length) {\n      i = _.sortedIndex(array, item);\n      return array[i] === item ? i : -1;\n    }\n    if (item !== item) {\n      return _.findIndex(slice.call(array, i), _.isNaN);\n    }\n    for (; i < length; i++) if (array[i] === item) return i;\n    return -1;\n  };\n\n  _.lastIndexOf = function(array, item, from) {\n    var idx = array ? array.length : 0;\n    if (typeof from == 'number') {\n      idx = from < 0 ? idx + from + 1 : Math.min(idx, from + 1);\n    }\n    if (item !== item) {\n      return _.findLastIndex(slice.call(array, 0, idx), _.isNaN);\n    }\n    while (--idx >= 0) if (array[idx] === item) return idx;\n    return -1;\n  };\n\n  // Generator function to create the findIndex and findLastIndex functions\n  function createIndexFinder(dir) {\n    return function(array, predicate, context) {\n      predicate = cb(predicate, context);\n      var length = array != null && array.length;\n      var index = dir > 0 ? 0 : length - 1;\n      for (; index >= 0 && index < length; index += dir) {\n        if (predicate(array[index], index, array)) return index;\n      }\n      return -1;\n    };\n  }\n\n  // Returns the first index on an array-like that passes a predicate test\n  _.findIndex = createIndexFinder(1);\n\n  _.findLastIndex = createIndexFinder(-1);\n\n  // Use a comparator function to figure out the smallest index at which\n  // an object should be inserted so as to maintain order. Uses binary search.\n  _.sortedIndex = function(array, obj, iteratee, context) {\n    iteratee = cb(iteratee, context, 1);\n    var value = iteratee(obj);\n    var low = 0, high = array.length;\n    while (low < high) {\n      var mid = Math.floor((low + high) / 2);\n      if (iteratee(array[mid]) < value) low = mid + 1; else high = mid;\n    }\n    return low;\n  };\n\n  // Generate an integer Array containing an arithmetic progression. A port of\n  // the native Python `range()` function. See\n  // [the Python documentation](http://docs.python.org/library/functions.html#range).\n  _.range = function(start, stop, step) {\n    if (arguments.length <= 1) {\n      stop = start || 0;\n      start = 0;\n    }\n    step = step || 1;\n\n    var length = Math.max(Math.ceil((stop - start) / step), 0);\n    var range = Array(length);\n\n    for (var idx = 0; idx < length; idx++, start += step) {\n      range[idx] = start;\n    }\n\n    return range;\n  };\n\n  // Function (ahem) Functions\n  // ------------------\n\n  // Determines whether to execute a function as a constructor\n  // or a normal function with the provided arguments\n  var executeBound = function(sourceFunc, boundFunc, context, callingContext, args) {\n    if (!(callingContext instanceof boundFunc)) return sourceFunc.apply(context, args);\n    var self = baseCreate(sourceFunc.prototype);\n    var result = sourceFunc.apply(self, args);\n    if (_.isObject(result)) return result;\n    return self;\n  };\n\n  // Create a function bound to a given object (assigning `this`, and arguments,\n  // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if\n  // available.\n  _.bind = function(func, context) {\n    if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));\n    if (!_.isFunction(func)) throw new TypeError('Bind must be called on a function');\n    var args = slice.call(arguments, 2);\n    var bound = function() {\n      return executeBound(func, bound, context, this, args.concat(slice.call(arguments)));\n    };\n    return bound;\n  };\n\n  // Partially apply a function by creating a version that has had some of its\n  // arguments pre-filled, without changing its dynamic `this` context. _ acts\n  // as a placeholder, allowing any combination of arguments to be pre-filled.\n  _.partial = function(func) {\n    var boundArgs = slice.call(arguments, 1);\n    var bound = function() {\n      var position = 0, length = boundArgs.length;\n      var args = Array(length);\n      for (var i = 0; i < length; i++) {\n        args[i] = boundArgs[i] === _ ? arguments[position++] : boundArgs[i];\n      }\n      while (position < arguments.length) args.push(arguments[position++]);\n      return executeBound(func, bound, this, this, args);\n    };\n    return bound;\n  };\n\n  // Bind a number of an object's methods to that object. Remaining arguments\n  // are the method names to be bound. Useful for ensuring that all callbacks\n  // defined on an object belong to it.\n  _.bindAll = function(obj) {\n    var i, length = arguments.length, key;\n    if (length <= 1) throw new Error('bindAll must be passed function names');\n    for (i = 1; i < length; i++) {\n      key = arguments[i];\n      obj[key] = _.bind(obj[key], obj);\n    }\n    return obj;\n  };\n\n  // Memoize an expensive function by storing its results.\n  _.memoize = function(func, hasher) {\n    var memoize = function(key) {\n      var cache = memoize.cache;\n      var address = '' + (hasher ? hasher.apply(this, arguments) : key);\n      if (!_.has(cache, address)) cache[address] = func.apply(this, arguments);\n      return cache[address];\n    };\n    memoize.cache = {};\n    return memoize;\n  };\n\n  // Delays a function for the given number of milliseconds, and then calls\n  // it with the arguments supplied.\n  _.delay = function(func, wait) {\n    var args = slice.call(arguments, 2);\n    return setTimeout(function(){\n      return func.apply(null, args);\n    }, wait);\n  };\n\n  // Defers a function, scheduling it to run after the current call stack has\n  // cleared.\n  _.defer = _.partial(_.delay, _, 1);\n\n  // Returns a function, that, when invoked, will only be triggered at most once\n  // during a given window of time. Normally, the throttled function will run\n  // as much as it can, without ever going more than once per `wait` duration;\n  // but if you'd like to disable the execution on the leading edge, pass\n  // `{leading: false}`. To disable execution on the trailing edge, ditto.\n  _.throttle = function(func, wait, options) {\n    var context, args, result;\n    var timeout = null;\n    var previous = 0;\n    if (!options) options = {};\n    var later = function() {\n      previous = options.leading === false ? 0 : _.now();\n      timeout = null;\n      result = func.apply(context, args);\n      if (!timeout) context = args = null;\n    };\n    return function() {\n      var now = _.now();\n      if (!previous && options.leading === false) previous = now;\n      var remaining = wait - (now - previous);\n      context = this;\n      args = arguments;\n      if (remaining <= 0 || remaining > wait) {\n        if (timeout) {\n          clearTimeout(timeout);\n          timeout = null;\n        }\n        previous = now;\n        result = func.apply(context, args);\n        if (!timeout) context = args = null;\n      } else if (!timeout && options.trailing !== false) {\n        timeout = setTimeout(later, remaining);\n      }\n      return result;\n    };\n  };\n\n  // Returns a function, that, as long as it continues to be invoked, will not\n  // be triggered. The function will be called after it stops being called for\n  // N milliseconds. If `immediate` is passed, trigger the function on the\n  // leading edge, instead of the trailing.\n  _.debounce = function(func, wait, immediate) {\n    var timeout, args, context, timestamp, result;\n\n    var later = function() {\n      var last = _.now() - timestamp;\n\n      if (last < wait && last >= 0) {\n        timeout = setTimeout(later, wait - last);\n      } else {\n        timeout = null;\n        if (!immediate) {\n          result = func.apply(context, args);\n          if (!timeout) context = args = null;\n        }\n      }\n    };\n\n    return function() {\n      context = this;\n      args = arguments;\n      timestamp = _.now();\n      var callNow = immediate && !timeout;\n      if (!timeout) timeout = setTimeout(later, wait);\n      if (callNow) {\n        result = func.apply(context, args);\n        context = args = null;\n      }\n\n      return result;\n    };\n  };\n\n  // Returns the first function passed as an argument to the second,\n  // allowing you to adjust arguments, run code before and after, and\n  // conditionally execute the original function.\n  _.wrap = function(func, wrapper) {\n    return _.partial(wrapper, func);\n  };\n\n  // Returns a negated version of the passed-in predicate.\n  _.negate = function(predicate) {\n    return function() {\n      return !predicate.apply(this, arguments);\n    };\n  };\n\n  // Returns a function that is the composition of a list of functions, each\n  // consuming the return value of the function that follows.\n  _.compose = function() {\n    var args = arguments;\n    var start = args.length - 1;\n    return function() {\n      var i = start;\n      var result = args[start].apply(this, arguments);\n      while (i--) result = args[i].call(this, result);\n      return result;\n    };\n  };\n\n  // Returns a function that will only be executed on and after the Nth call.\n  _.after = function(times, func) {\n    return function() {\n      if (--times < 1) {\n        return func.apply(this, arguments);\n      }\n    };\n  };\n\n  // Returns a function that will only be executed up to (but not including) the Nth call.\n  _.before = function(times, func) {\n    var memo;\n    return function() {\n      if (--times > 0) {\n        memo = func.apply(this, arguments);\n      }\n      if (times <= 1) func = null;\n      return memo;\n    };\n  };\n\n  // Returns a function that will be executed at most one time, no matter how\n  // often you call it. Useful for lazy initialization.\n  _.once = _.partial(_.before, 2);\n\n  // Object Functions\n  // ----------------\n\n  // Keys in IE < 9 that won't be iterated by `for key in ...` and thus missed.\n  var hasEnumBug = !{toString: null}.propertyIsEnumerable('toString');\n  var nonEnumerableProps = ['valueOf', 'isPrototypeOf', 'toString',\n                      'propertyIsEnumerable', 'hasOwnProperty', 'toLocaleString'];\n\n  function collectNonEnumProps(obj, keys) {\n    var nonEnumIdx = nonEnumerableProps.length;\n    var constructor = obj.constructor;\n    var proto = (_.isFunction(constructor) && constructor.prototype) || ObjProto;\n\n    // Constructor is a special case.\n    var prop = 'constructor';\n    if (_.has(obj, prop) && !_.contains(keys, prop)) keys.push(prop);\n\n    while (nonEnumIdx--) {\n      prop = nonEnumerableProps[nonEnumIdx];\n      if (prop in obj && obj[prop] !== proto[prop] && !_.contains(keys, prop)) {\n        keys.push(prop);\n      }\n    }\n  }\n\n  // Retrieve the names of an object's own properties.\n  // Delegates to **ECMAScript 5**'s native `Object.keys`\n  _.keys = function(obj) {\n    if (!_.isObject(obj)) return [];\n    if (nativeKeys) return nativeKeys(obj);\n    var keys = [];\n    for (var key in obj) if (_.has(obj, key)) keys.push(key);\n    // Ahem, IE < 9.\n    if (hasEnumBug) collectNonEnumProps(obj, keys);\n    return keys;\n  };\n\n  // Retrieve all the property names of an object.\n  _.allKeys = function(obj) {\n    if (!_.isObject(obj)) return [];\n    var keys = [];\n    for (var key in obj) keys.push(key);\n    // Ahem, IE < 9.\n    if (hasEnumBug) collectNonEnumProps(obj, keys);\n    return keys;\n  };\n\n  // Retrieve the values of an object's properties.\n  _.values = function(obj) {\n    var keys = _.keys(obj);\n    var length = keys.length;\n    var values = Array(length);\n    for (var i = 0; i < length; i++) {\n      values[i] = obj[keys[i]];\n    }\n    return values;\n  };\n\n  // Returns the results of applying the iteratee to each element of the object\n  // In contrast to _.map it returns an object\n  _.mapObject = function(obj, iteratee, context) {\n    iteratee = cb(iteratee, context);\n    var keys =  _.keys(obj),\n          length = keys.length,\n          results = {},\n          currentKey;\n      for (var index = 0; index < length; index++) {\n        currentKey = keys[index];\n        results[currentKey] = iteratee(obj[currentKey], currentKey, obj);\n      }\n      return results;\n  };\n\n  // Convert an object into a list of `[key, value]` pairs.\n  _.pairs = function(obj) {\n    var keys = _.keys(obj);\n    var length = keys.length;\n    var pairs = Array(length);\n    for (var i = 0; i < length; i++) {\n      pairs[i] = [keys[i], obj[keys[i]]];\n    }\n    return pairs;\n  };\n\n  // Invert the keys and values of an object. The values must be serializable.\n  _.invert = function(obj) {\n    var result = {};\n    var keys = _.keys(obj);\n    for (var i = 0, length = keys.length; i < length; i++) {\n      result[obj[keys[i]]] = keys[i];\n    }\n    return result;\n  };\n\n  // Return a sorted list of the function names available on the object.\n  // Aliased as `methods`\n  _.functions = _.methods = function(obj) {\n    var names = [];\n    for (var key in obj) {\n      if (_.isFunction(obj[key])) names.push(key);\n    }\n    return names.sort();\n  };\n\n  // Extend a given object with all the properties in passed-in object(s).\n  _.extend = createAssigner(_.allKeys);\n\n  // Assigns a given object with all the own properties in the passed-in object(s)\n  // (https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/assign)\n  _.extendOwn = _.assign = createAssigner(_.keys);\n\n  // Returns the first key on an object that passes a predicate test\n  _.findKey = function(obj, predicate, context) {\n    predicate = cb(predicate, context);\n    var keys = _.keys(obj), key;\n    for (var i = 0, length = keys.length; i < length; i++) {\n      key = keys[i];\n      if (predicate(obj[key], key, obj)) return key;\n    }\n  };\n\n  // Return a copy of the object only containing the whitelisted properties.\n  _.pick = function(object, oiteratee, context) {\n    var result = {}, obj = object, iteratee, keys;\n    if (obj == null) return result;\n    if (_.isFunction(oiteratee)) {\n      keys = _.allKeys(obj);\n      iteratee = optimizeCb(oiteratee, context);\n    } else {\n      keys = flatten(arguments, false, false, 1);\n      iteratee = function(value, key, obj) { return key in obj; };\n      obj = Object(obj);\n    }\n    for (var i = 0, length = keys.length; i < length; i++) {\n      var key = keys[i];\n      var value = obj[key];\n      if (iteratee(value, key, obj)) result[key] = value;\n    }\n    return result;\n  };\n\n   // Return a copy of the object without the blacklisted properties.\n  _.omit = function(obj, iteratee, context) {\n    if (_.isFunction(iteratee)) {\n      iteratee = _.negate(iteratee);\n    } else {\n      var keys = _.map(flatten(arguments, false, false, 1), String);\n      iteratee = function(value, key) {\n        return !_.contains(keys, key);\n      };\n    }\n    return _.pick(obj, iteratee, context);\n  };\n\n  // Fill in a given object with default properties.\n  _.defaults = createAssigner(_.allKeys, true);\n\n  // Create a (shallow-cloned) duplicate of an object.\n  _.clone = function(obj) {\n    if (!_.isObject(obj)) return obj;\n    return _.isArray(obj) ? obj.slice() : _.extend({}, obj);\n  };\n\n  // Invokes interceptor with the obj, and then returns obj.\n  // The primary purpose of this method is to \"tap into\" a method chain, in\n  // order to perform operations on intermediate results within the chain.\n  _.tap = function(obj, interceptor) {\n    interceptor(obj);\n    return obj;\n  };\n\n  // Returns whether an object has a given set of `key:value` pairs.\n  _.isMatch = function(object, attrs) {\n    var keys = _.keys(attrs), length = keys.length;\n    if (object == null) return !length;\n    var obj = Object(object);\n    for (var i = 0; i < length; i++) {\n      var key = keys[i];\n      if (attrs[key] !== obj[key] || !(key in obj)) return false;\n    }\n    return true;\n  };\n\n\n  // Internal recursive comparison function for `isEqual`.\n  var eq = function(a, b, aStack, bStack) {\n    // Identical objects are equal. `0 === -0`, but they aren't identical.\n    // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal).\n    if (a === b) return a !== 0 || 1 / a === 1 / b;\n    // A strict comparison is necessary because `null == undefined`.\n    if (a == null || b == null) return a === b;\n    // Unwrap any wrapped objects.\n    if (a instanceof _) a = a._wrapped;\n    if (b instanceof _) b = b._wrapped;\n    // Compare `[[Class]]` names.\n    var className = toString.call(a);\n    if (className !== toString.call(b)) return false;\n    switch (className) {\n      // Strings, numbers, regular expressions, dates, and booleans are compared by value.\n      case '[object RegExp]':\n      // RegExps are coerced to strings for comparison (Note: '' + /a/i === '/a/i')\n      case '[object String]':\n        // Primitives and their corresponding object wrappers are equivalent; thus, `\"5\"` is\n        // equivalent to `new String(\"5\")`.\n        return '' + a === '' + b;\n      case '[object Number]':\n        // `NaN`s are equivalent, but non-reflexive.\n        // Object(NaN) is equivalent to NaN\n        if (+a !== +a) return +b !== +b;\n        // An `egal` comparison is performed for other numeric values.\n        return +a === 0 ? 1 / +a === 1 / b : +a === +b;\n      case '[object Date]':\n      case '[object Boolean]':\n        // Coerce dates and booleans to numeric primitive values. Dates are compared by their\n        // millisecond representations. Note that invalid dates with millisecond representations\n        // of `NaN` are not equivalent.\n        return +a === +b;\n    }\n\n    var areArrays = className === '[object Array]';\n    if (!areArrays) {\n      if (typeof a != 'object' || typeof b != 'object') return false;\n\n      // Objects with different constructors are not equivalent, but `Object`s or `Array`s\n      // from different frames are.\n      var aCtor = a.constructor, bCtor = b.constructor;\n      if (aCtor !== bCtor && !(_.isFunction(aCtor) && aCtor instanceof aCtor &&\n                               _.isFunction(bCtor) && bCtor instanceof bCtor)\n                          && ('constructor' in a && 'constructor' in b)) {\n        return false;\n      }\n    }\n    // Assume equality for cyclic structures. The algorithm for detecting cyclic\n    // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.\n    \n    // Initializing stack of traversed objects.\n    // It's done here since we only need them for objects and arrays comparison.\n    aStack = aStack || [];\n    bStack = bStack || [];\n    var length = aStack.length;\n    while (length--) {\n      // Linear search. Performance is inversely proportional to the number of\n      // unique nested structures.\n      if (aStack[length] === a) return bStack[length] === b;\n    }\n\n    // Add the first object to the stack of traversed objects.\n    aStack.push(a);\n    bStack.push(b);\n\n    // Recursively compare objects and arrays.\n    if (areArrays) {\n      // Compare array lengths to determine if a deep comparison is necessary.\n      length = a.length;\n      if (length !== b.length) return false;\n      // Deep compare the contents, ignoring non-numeric properties.\n      while (length--) {\n        if (!eq(a[length], b[length], aStack, bStack)) return false;\n      }\n    } else {\n      // Deep compare objects.\n      var keys = _.keys(a), key;\n      length = keys.length;\n      // Ensure that both objects contain the same number of properties before comparing deep equality.\n      if (_.keys(b).length !== length) return false;\n      while (length--) {\n        // Deep compare each member\n        key = keys[length];\n        if (!(_.has(b, key) && eq(a[key], b[key], aStack, bStack))) return false;\n      }\n    }\n    // Remove the first object from the stack of traversed objects.\n    aStack.pop();\n    bStack.pop();\n    return true;\n  };\n\n  // Perform a deep comparison to check if two objects are equal.\n  _.isEqual = function(a, b) {\n    return eq(a, b);\n  };\n\n  // Is a given array, string, or object empty?\n  // An \"empty\" object has no enumerable own-properties.\n  _.isEmpty = function(obj) {\n    if (obj == null) return true;\n    if (isArrayLike(obj) && (_.isArray(obj) || _.isString(obj) || _.isArguments(obj))) return obj.length === 0;\n    return _.keys(obj).length === 0;\n  };\n\n  // Is a given value a DOM element?\n  _.isElement = function(obj) {\n    return !!(obj && obj.nodeType === 1);\n  };\n\n  // Is a given value an array?\n  // Delegates to ECMA5's native Array.isArray\n  _.isArray = nativeIsArray || function(obj) {\n    return toString.call(obj) === '[object Array]';\n  };\n\n  // Is a given variable an object?\n  _.isObject = function(obj) {\n    var type = typeof obj;\n    return type === 'function' || type === 'object' && !!obj;\n  };\n\n  // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp, isError.\n  _.each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp', 'Error'], function(name) {\n    _['is' + name] = function(obj) {\n      return toString.call(obj) === '[object ' + name + ']';\n    };\n  });\n\n  // Define a fallback version of the method in browsers (ahem, IE < 9), where\n  // there isn't any inspectable \"Arguments\" type.\n  if (!_.isArguments(arguments)) {\n    _.isArguments = function(obj) {\n      return _.has(obj, 'callee');\n    };\n  }\n\n  // Optimize `isFunction` if appropriate. Work around some typeof bugs in old v8,\n  // IE 11 (#1621), and in Safari 8 (#1929).\n  if (typeof /./ != 'function' && typeof Int8Array != 'object') {\n    _.isFunction = function(obj) {\n      return typeof obj == 'function' || false;\n    };\n  }\n\n  // Is a given object a finite number?\n  _.isFinite = function(obj) {\n    return isFinite(obj) && !isNaN(parseFloat(obj));\n  };\n\n  // Is the given value `NaN`? (NaN is the only number which does not equal itself).\n  _.isNaN = function(obj) {\n    return _.isNumber(obj) && obj !== +obj;\n  };\n\n  // Is a given value a boolean?\n  _.isBoolean = function(obj) {\n    return obj === true || obj === false || toString.call(obj) === '[object Boolean]';\n  };\n\n  // Is a given value equal to null?\n  _.isNull = function(obj) {\n    return obj === null;\n  };\n\n  // Is a given variable undefined?\n  _.isUndefined = function(obj) {\n    return obj === void 0;\n  };\n\n  // Shortcut function for checking if an object has a given property directly\n  // on itself (in other words, not on a prototype).\n  _.has = function(obj, key) {\n    return obj != null && hasOwnProperty.call(obj, key);\n  };\n\n  // Utility Functions\n  // -----------------\n\n  // Run Underscore.js in *noConflict* mode, returning the `_` variable to its\n  // previous owner. Returns a reference to the Underscore object.\n  _.noConflict = function() {\n    root._ = previousUnderscore;\n    return this;\n  };\n\n  // Keep the identity function around for default iteratees.\n  _.identity = function(value) {\n    return value;\n  };\n\n  // Predicate-generating functions. Often useful outside of Underscore.\n  _.constant = function(value) {\n    return function() {\n      return value;\n    };\n  };\n\n  _.noop = function(){};\n\n  _.property = function(key) {\n    return function(obj) {\n      return obj == null ? void 0 : obj[key];\n    };\n  };\n\n  // Generates a function for a given object that returns a given property.\n  _.propertyOf = function(obj) {\n    return obj == null ? function(){} : function(key) {\n      return obj[key];\n    };\n  };\n\n  // Returns a predicate for checking whether an object has a given set of \n  // `key:value` pairs.\n  _.matcher = _.matches = function(attrs) {\n    attrs = _.extendOwn({}, attrs);\n    return function(obj) {\n      return _.isMatch(obj, attrs);\n    };\n  };\n\n  // Run a function **n** times.\n  _.times = function(n, iteratee, context) {\n    var accum = Array(Math.max(0, n));\n    iteratee = optimizeCb(iteratee, context, 1);\n    for (var i = 0; i < n; i++) accum[i] = iteratee(i);\n    return accum;\n  };\n\n  // Return a random integer between min and max (inclusive).\n  _.random = function(min, max) {\n    if (max == null) {\n      max = min;\n      min = 0;\n    }\n    return min + Math.floor(Math.random() * (max - min + 1));\n  };\n\n  // A (possibly faster) way to get the current timestamp as an integer.\n  _.now = Date.now || function() {\n    return new Date().getTime();\n  };\n\n   // List of HTML entities for escaping.\n  var escapeMap = {\n    '&': '&amp;',\n    '<': '&lt;',\n    '>': '&gt;',\n    '\"': '&quot;',\n    \"'\": '&#x27;',\n    '`': '&#x60;'\n  };\n  var unescapeMap = _.invert(escapeMap);\n\n  // Functions for escaping and unescaping strings to/from HTML interpolation.\n  var createEscaper = function(map) {\n    var escaper = function(match) {\n      return map[match];\n    };\n    // Regexes for identifying a key that needs to be escaped\n    var source = '(?:' + _.keys(map).join('|') + ')';\n    var testRegexp = RegExp(source);\n    var replaceRegexp = RegExp(source, 'g');\n    return function(string) {\n      string = string == null ? '' : '' + string;\n      return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string;\n    };\n  };\n  _.escape = createEscaper(escapeMap);\n  _.unescape = createEscaper(unescapeMap);\n\n  // If the value of the named `property` is a function then invoke it with the\n  // `object` as context; otherwise, return it.\n  _.result = function(object, property, fallback) {\n    var value = object == null ? void 0 : object[property];\n    if (value === void 0) {\n      value = fallback;\n    }\n    return _.isFunction(value) ? value.call(object) : value;\n  };\n\n  // Generate a unique integer id (unique within the entire client session).\n  // Useful for temporary DOM ids.\n  var idCounter = 0;\n  _.uniqueId = function(prefix) {\n    var id = ++idCounter + '';\n    return prefix ? prefix + id : id;\n  };\n\n  // By default, Underscore uses ERB-style template delimiters, change the\n  // following template settings to use alternative delimiters.\n  _.templateSettings = {\n    evaluate    : /<%([\\s\\S]+?)%>/g,\n    interpolate : /<%=([\\s\\S]+?)%>/g,\n    escape      : /<%-([\\s\\S]+?)%>/g\n  };\n\n  // When customizing `templateSettings`, if you don't want to define an\n  // interpolation, evaluation or escaping regex, we need one that is\n  // guaranteed not to match.\n  var noMatch = /(.)^/;\n\n  // Certain characters need to be escaped so that they can be put into a\n  // string literal.\n  var escapes = {\n    \"'\":      \"'\",\n    '\\\\':     '\\\\',\n    '\\r':     'r',\n    '\\n':     'n',\n    '\\u2028': 'u2028',\n    '\\u2029': 'u2029'\n  };\n\n  var escaper = /\\\\|'|\\r|\\n|\\u2028|\\u2029/g;\n\n  var escapeChar = function(match) {\n    return '\\\\' + escapes[match];\n  };\n\n  // JavaScript micro-templating, similar to John Resig's implementation.\n  // Underscore templating handles arbitrary delimiters, preserves whitespace,\n  // and correctly escapes quotes within interpolated code.\n  // NB: `oldSettings` only exists for backwards compatibility.\n  _.template = function(text, settings, oldSettings) {\n    if (!settings && oldSettings) settings = oldSettings;\n    settings = _.defaults({}, settings, _.templateSettings);\n\n    // Combine delimiters into one regular expression via alternation.\n    var matcher = RegExp([\n      (settings.escape || noMatch).source,\n      (settings.interpolate || noMatch).source,\n      (settings.evaluate || noMatch).source\n    ].join('|') + '|$', 'g');\n\n    // Compile the template source, escaping string literals appropriately.\n    var index = 0;\n    var source = \"__p+='\";\n    text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {\n      source += text.slice(index, offset).replace(escaper, escapeChar);\n      index = offset + match.length;\n\n      if (escape) {\n        source += \"'+\\n((__t=(\" + escape + \"))==null?'':_.escape(__t))+\\n'\";\n      } else if (interpolate) {\n        source += \"'+\\n((__t=(\" + interpolate + \"))==null?'':__t)+\\n'\";\n      } else if (evaluate) {\n        source += \"';\\n\" + evaluate + \"\\n__p+='\";\n      }\n\n      // Adobe VMs need the match returned to produce the correct offest.\n      return match;\n    });\n    source += \"';\\n\";\n\n    // If a variable is not specified, place data values in local scope.\n    if (!settings.variable) source = 'with(obj||{}){\\n' + source + '}\\n';\n\n    source = \"var __t,__p='',__j=Array.prototype.join,\" +\n      \"print=function(){__p+=__j.call(arguments,'');};\\n\" +\n      source + 'return __p;\\n';\n\n    try {\n      var render = new Function(settings.variable || 'obj', '_', source);\n    } catch (e) {\n      e.source = source;\n      throw e;\n    }\n\n    var template = function(data) {\n      return render.call(this, data, _);\n    };\n\n    // Provide the compiled source as a convenience for precompilation.\n    var argument = settings.variable || 'obj';\n    template.source = 'function(' + argument + '){\\n' + source + '}';\n\n    return template;\n  };\n\n  // Add a \"chain\" function. Start chaining a wrapped Underscore object.\n  _.chain = function(obj) {\n    var instance = _(obj);\n    instance._chain = true;\n    return instance;\n  };\n\n  // OOP\n  // ---------------\n  // If Underscore is called as a function, it returns a wrapped object that\n  // can be used OO-style. This wrapper holds altered versions of all the\n  // underscore functions. Wrapped objects may be chained.\n\n  // Helper function to continue chaining intermediate results.\n  var result = function(instance, obj) {\n    return instance._chain ? _(obj).chain() : obj;\n  };\n\n  // Add your own custom functions to the Underscore object.\n  _.mixin = function(obj) {\n    _.each(_.functions(obj), function(name) {\n      var func = _[name] = obj[name];\n      _.prototype[name] = function() {\n        var args = [this._wrapped];\n        push.apply(args, arguments);\n        return result(this, func.apply(_, args));\n      };\n    });\n  };\n\n  // Add all of the Underscore functions to the wrapper object.\n  _.mixin(_);\n\n  // Add all mutator Array functions to the wrapper.\n  _.each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {\n    var method = ArrayProto[name];\n    _.prototype[name] = function() {\n      var obj = this._wrapped;\n      method.apply(obj, arguments);\n      if ((name === 'shift' || name === 'splice') && obj.length === 0) delete obj[0];\n      return result(this, obj);\n    };\n  });\n\n  // Add all accessor Array functions to the wrapper.\n  _.each(['concat', 'join', 'slice'], function(name) {\n    var method = ArrayProto[name];\n    _.prototype[name] = function() {\n      return result(this, method.apply(this._wrapped, arguments));\n    };\n  });\n\n  // Extracts the result from a wrapped and chained object.\n  _.prototype.value = function() {\n    return this._wrapped;\n  };\n\n  // Provide unwrapping proxy for some methods used in engine operations\n  // such as arithmetic and JSON stringification.\n  _.prototype.valueOf = _.prototype.toJSON = _.prototype.value;\n  \n  _.prototype.toString = function() {\n    return '' + this._wrapped;\n  };\n\n  // AMD registration happens at the end for compatibility with AMD loaders\n  // that may not enforce next-turn semantics on modules. Even though general\n  // practice for AMD registration is to be anonymous, underscore registers\n  // as a named module because, like jQuery, it is a base library that is\n  // popular enough to be bundled in a third party lib, but not be part of\n  // an AMD load request. Those cases could generate an error when an\n  // anonymous define() is called outside of a loader request.\n  if (typeof define === 'function' && define.amd) {\n    define('underscore', [], function() {\n      return _;\n    });\n  }\n}.call(this));", "//  Underscore.string\n//  (c) 2010 Esa-Matti Suuronen <esa-matti aet suuronen dot org>\n//  Underscore.string is freely distributable under the terms of the MIT license.\n//  Documentation: https://github.com/epeli/underscore.string\n//  Some code is borrowed from MooTools and Alexandru Marasteanu.\n//  Version '2.3.2'\n\n!function(root, String){\n  'use strict';\n\n  // Defining helper functions.\n\n  var nativeTrim = String.prototype.trim;\n  var nativeTrimRight = String.prototype.trimRight;\n  var nativeTrimLeft = String.prototype.trimLeft;\n\n  var parseNumber = function(source) { return source * 1 || 0; };\n\n  var strRepeat = function(str, qty){\n    if (qty < 1) return '';\n    var result = '';\n    while (qty > 0) {\n      if (qty & 1) result += str;\n      qty >>= 1, str += str;\n    }\n    return result;\n  };\n\n  var slice = [].slice;\n\n  var defaultToWhiteSpace = function(characters) {\n    if (characters == null)\n      return '\\\\s';\n    else if (characters.source)\n      return characters.source;\n    else\n      return '[' + _s.escapeRegExp(characters) + ']';\n  };\n\n  // Helper for toBoolean\n  function boolMatch(s, matchers) {\n    var i, matcher, down = s.toLowerCase();\n    matchers = [].concat(matchers);\n    for (i = 0; i < matchers.length; i += 1) {\n      matcher = matchers[i];\n      if (!matcher) continue;\n      if (matcher.test && matcher.test(s)) return true;\n      if (matcher.toLowerCase() === down) return true;\n    }\n  }\n\n  var escapeChars = {\n    lt: '<',\n    gt: '>',\n    quot: '\"',\n    amp: '&',\n    apos: \"'\"\n  };\n\n  var reversedEscapeChars = {};\n  for(var key in escapeChars) reversedEscapeChars[escapeChars[key]] = key;\n  reversedEscapeChars[\"'\"] = '#39';\n\n  // sprintf() for JavaScript 0.7-beta1\n  // http://www.diveintojavascript.com/projects/javascript-sprintf\n  //\n  // Copyright (c) Alexandru Marasteanu <alexaholic [at) gmail (dot] com>\n  // All rights reserved.\n\n  var sprintf = (function() {\n    function get_type(variable) {\n      return Object.prototype.toString.call(variable).slice(8, -1).toLowerCase();\n    }\n\n    var str_repeat = strRepeat;\n\n    var str_format = function() {\n      if (!str_format.cache.hasOwnProperty(arguments[0])) {\n        str_format.cache[arguments[0]] = str_format.parse(arguments[0]);\n      }\n      return str_format.format.call(null, str_format.cache[arguments[0]], arguments);\n    };\n\n    str_format.format = function(parse_tree, argv) {\n      var cursor = 1, tree_length = parse_tree.length, node_type = '', arg, output = [], i, k, match, pad, pad_character, pad_length;\n      for (i = 0; i < tree_length; i++) {\n        node_type = get_type(parse_tree[i]);\n        if (node_type === 'string') {\n          output.push(parse_tree[i]);\n        }\n        else if (node_type === 'array') {\n          match = parse_tree[i]; // convenience purposes only\n          if (match[2]) { // keyword argument\n            arg = argv[cursor];\n            for (k = 0; k < match[2].length; k++) {\n              if (!arg.hasOwnProperty(match[2][k])) {\n                throw new Error(sprintf('[_.sprintf] property \"%s\" does not exist', match[2][k]));\n              }\n              arg = arg[match[2][k]];\n            }\n          } else if (match[1]) { // positional argument (explicit)\n            arg = argv[match[1]];\n          }\n          else { // positional argument (implicit)\n            arg = argv[cursor++];\n          }\n\n          if (/[^s]/.test(match[8]) && (get_type(arg) != 'number')) {\n            throw new Error(sprintf('[_.sprintf] expecting number but found %s', get_type(arg)));\n          }\n          switch (match[8]) {\n            case 'b': arg = arg.toString(2); break;\n            case 'c': arg = String.fromCharCode(arg); break;\n            case 'd': arg = parseInt(arg, 10); break;\n            case 'e': arg = match[7] ? arg.toExponential(match[7]) : arg.toExponential(); break;\n            case 'f': arg = match[7] ? parseFloat(arg).toFixed(match[7]) : parseFloat(arg); break;\n            case 'o': arg = arg.toString(8); break;\n            case 's': arg = ((arg = String(arg)) && match[7] ? arg.substring(0, match[7]) : arg); break;\n            case 'u': arg = Math.abs(arg); break;\n            case 'x': arg = arg.toString(16); break;\n            case 'X': arg = arg.toString(16).toUpperCase(); break;\n          }\n          arg = (/[def]/.test(match[8]) && match[3] && arg >= 0 ? '+'+ arg : arg);\n          pad_character = match[4] ? match[4] == '0' ? '0' : match[4].charAt(1) : ' ';\n          pad_length = match[6] - String(arg).length;\n          pad = match[6] ? str_repeat(pad_character, pad_length) : '';\n          output.push(match[5] ? arg + pad : pad + arg);\n        }\n      }\n      return output.join('');\n    };\n\n    str_format.cache = {};\n\n    str_format.parse = function(fmt) {\n      var _fmt = fmt, match = [], parse_tree = [], arg_names = 0;\n      while (_fmt) {\n        if ((match = /^[^\\x25]+/.exec(_fmt)) !== null) {\n          parse_tree.push(match[0]);\n        }\n        else if ((match = /^\\x25{2}/.exec(_fmt)) !== null) {\n          parse_tree.push('%');\n        }\n        else if ((match = /^\\x25(?:([1-9]\\d*)\\$|\\(([^\\)]+)\\))?(\\+)?(0|'[^$])?(-)?(\\d+)?(?:\\.(\\d+))?([b-fosuxX])/.exec(_fmt)) !== null) {\n          if (match[2]) {\n            arg_names |= 1;\n            var field_list = [], replacement_field = match[2], field_match = [];\n            if ((field_match = /^([a-z_][a-z_\\d]*)/i.exec(replacement_field)) !== null) {\n              field_list.push(field_match[1]);\n              while ((replacement_field = replacement_field.substring(field_match[0].length)) !== '') {\n                if ((field_match = /^\\.([a-z_][a-z_\\d]*)/i.exec(replacement_field)) !== null) {\n                  field_list.push(field_match[1]);\n                }\n                else if ((field_match = /^\\[(\\d+)\\]/.exec(replacement_field)) !== null) {\n                  field_list.push(field_match[1]);\n                }\n                else {\n                  throw new Error('[_.sprintf] huh?');\n                }\n              }\n            }\n            else {\n              throw new Error('[_.sprintf] huh?');\n            }\n            match[2] = field_list;\n          }\n          else {\n            arg_names |= 2;\n          }\n          if (arg_names === 3) {\n            throw new Error('[_.sprintf] mixing positional and named placeholders is not (yet) supported');\n          }\n          parse_tree.push(match);\n        }\n        else {\n          throw new Error('[_.sprintf] huh?');\n        }\n        _fmt = _fmt.substring(match[0].length);\n      }\n      return parse_tree;\n    };\n\n    return str_format;\n  })();\n\n\n\n  // Defining underscore.string\n\n  var _s = {\n\n    VERSION: '2.3.0',\n\n    isBlank: function(str){\n      if (str == null) str = '';\n      return (/^\\s*$/).test(str);\n    },\n\n    stripTags: function(str){\n      if (str == null) return '';\n      return String(str).replace(/<\\/?[^>]+>/g, '');\n    },\n\n    capitalize : function(str){\n      str = str == null ? '' : String(str);\n      return str.charAt(0).toUpperCase() + str.slice(1);\n    },\n\n    chop: function(str, step){\n      if (str == null) return [];\n      str = String(str);\n      step = ~~step;\n      return step > 0 ? str.match(new RegExp('.{1,' + step + '}', 'g')) : [str];\n    },\n\n    clean: function(str){\n      return _s.strip(str).replace(/\\s+/g, ' ');\n    },\n\n    count: function(str, substr){\n      if (str == null || substr == null) return 0;\n\n      str = String(str);\n      substr = String(substr);\n\n      var count = 0,\n        pos = 0,\n        length = substr.length;\n\n      while (true) {\n        pos = str.indexOf(substr, pos);\n        if (pos === -1) break;\n        count++;\n        pos += length;\n      }\n\n      return count;\n    },\n\n    chars: function(str) {\n      if (str == null) return [];\n      return String(str).split('');\n    },\n\n    swapCase: function(str) {\n      if (str == null) return '';\n      return String(str).replace(/\\S/g, function(c){\n        return c === c.toUpperCase() ? c.toLowerCase() : c.toUpperCase();\n      });\n    },\n\n    escapeHTML: function(str) {\n      if (str == null) return '';\n      return String(str).replace(/[&<>\"']/g, function(m){ return '&' + reversedEscapeChars[m] + ';'; });\n    },\n\n    unescapeHTML: function(str) {\n      if (str == null) return '';\n      return String(str).replace(/\\&([^;]+);/g, function(entity, entityCode){\n        var match;\n\n        if (entityCode in escapeChars) {\n          return escapeChars[entityCode];\n        } else if (match = entityCode.match(/^#x([\\da-fA-F]+)$/)) {\n          return String.fromCharCode(parseInt(match[1], 16));\n        } else if (match = entityCode.match(/^#(\\d+)$/)) {\n          return String.fromCharCode(~~match[1]);\n        } else {\n          return entity;\n        }\n      });\n    },\n\n    escapeRegExp: function(str){\n      if (str == null) return '';\n      return String(str).replace(/([.*+?^=!:${}()|[\\]\\/\\\\])/g, '\\\\$1');\n    },\n\n    splice: function(str, i, howmany, substr){\n      var arr = _s.chars(str);\n      arr.splice(~~i, ~~howmany, substr);\n      return arr.join('');\n    },\n\n    insert: function(str, i, substr){\n      return _s.splice(str, i, 0, substr);\n    },\n\n    include: function(str, needle){\n      if (needle === '') return true;\n      if (str == null) return false;\n      return String(str).indexOf(needle) !== -1;\n    },\n\n    join: function() {\n      var args = slice.call(arguments),\n        separator = args.shift();\n\n      if (separator == null) separator = '';\n\n      return args.join(separator);\n    },\n\n    lines: function(str) {\n      if (str == null) return [];\n      return String(str).split(\"\\n\");\n    },\n\n    reverse: function(str){\n      return _s.chars(str).reverse().join('');\n    },\n\n    startsWith: function(str, starts){\n      if (starts === '') return true;\n      if (str == null || starts == null) return false;\n      str = String(str); starts = String(starts);\n      return str.length >= starts.length && str.slice(0, starts.length) === starts;\n    },\n\n    endsWith: function(str, ends){\n      if (ends === '') return true;\n      if (str == null || ends == null) return false;\n      str = String(str); ends = String(ends);\n      return str.length >= ends.length && str.slice(str.length - ends.length) === ends;\n    },\n\n    succ: function(str){\n      if (str == null) return '';\n      str = String(str);\n      return str.slice(0, -1) + String.fromCharCode(str.charCodeAt(str.length-1) + 1);\n    },\n\n    titleize: function(str){\n      if (str == null) return '';\n      str  = String(str).toLowerCase();\n      return str.replace(/(?:^|\\s|-)\\S/g, function(c){ return c.toUpperCase(); });\n    },\n\n    camelize: function(str){\n      return _s.trim(str).replace(/[-_\\s]+(.)?/g, function(match, c){ return c ? c.toUpperCase() : \"\"; });\n    },\n\n    underscored: function(str){\n      return _s.trim(str).replace(/([a-z\\d])([A-Z]+)/g, '$1_$2').replace(/[-\\s]+/g, '_').toLowerCase();\n    },\n\n    dasherize: function(str){\n      return _s.trim(str).replace(/([A-Z])/g, '-$1').replace(/[-_\\s]+/g, '-').toLowerCase();\n    },\n\n    classify: function(str){\n      return _s.titleize(String(str).replace(/[\\W_]/g, ' ')).replace(/\\s/g, '');\n    },\n\n    humanize: function(str){\n      return _s.capitalize(_s.underscored(str).replace(/_id$/,'').replace(/_/g, ' '));\n    },\n\n    trim: function(str, characters){\n      if (str == null) return '';\n      if (!characters && nativeTrim) return nativeTrim.call(str);\n      characters = defaultToWhiteSpace(characters);\n      return String(str).replace(new RegExp('\\^' + characters + '+|' + characters + '+$', 'g'), '');\n    },\n\n    ltrim: function(str, characters){\n      if (str == null) return '';\n      if (!characters && nativeTrimLeft) return nativeTrimLeft.call(str);\n      characters = defaultToWhiteSpace(characters);\n      return String(str).replace(new RegExp('^' + characters + '+'), '');\n    },\n\n    rtrim: function(str, characters){\n      if (str == null) return '';\n      if (!characters && nativeTrimRight) return nativeTrimRight.call(str);\n      characters = defaultToWhiteSpace(characters);\n      return String(str).replace(new RegExp(characters + '+$'), '');\n    },\n\n    truncate: function(str, length, truncateStr){\n      if (str == null) return '';\n      str = String(str); truncateStr = truncateStr || '...';\n      length = ~~length;\n      return str.length > length ? str.slice(0, length) + truncateStr : str;\n    },\n\n    /**\n     * _s.prune: a more elegant version of truncate\n     * prune extra chars, never leaving a half-chopped word.\n     * @author github.com/rwz\n     */\n    prune: function(str, length, pruneStr){\n      if (str == null) return '';\n\n      str = String(str); length = ~~length;\n      pruneStr = pruneStr != null ? String(pruneStr) : '...';\n\n      if (str.length <= length) return str;\n\n      var tmpl = function(c){ return c.toUpperCase() !== c.toLowerCase() ? 'A' : ' '; },\n        template = str.slice(0, length+1).replace(/.(?=\\W*\\w*$)/g, tmpl); // 'Hello, world' -> 'HellAA AAAAA'\n\n      if (template.slice(template.length-2).match(/\\w\\w/))\n        template = template.replace(/\\s*\\S+$/, '');\n      else\n        template = _s.rtrim(template.slice(0, template.length-1));\n\n      return (template+pruneStr).length > str.length ? str : str.slice(0, template.length)+pruneStr;\n    },\n\n    words: function(str, delimiter) {\n      if (_s.isBlank(str)) return [];\n      return _s.trim(str, delimiter).split(delimiter || /\\s+/);\n    },\n\n    pad: function(str, length, padStr, type) {\n      str = str == null ? '' : String(str);\n      length = ~~length;\n\n      var padlen  = 0;\n\n      if (!padStr)\n        padStr = ' ';\n      else if (padStr.length > 1)\n        padStr = padStr.charAt(0);\n\n      switch(type) {\n        case 'right':\n          padlen = length - str.length;\n          return str + strRepeat(padStr, padlen);\n        case 'both':\n          padlen = length - str.length;\n          return strRepeat(padStr, Math.ceil(padlen/2)) + str\n                  + strRepeat(padStr, Math.floor(padlen/2));\n        default: // 'left'\n          padlen = length - str.length;\n          return strRepeat(padStr, padlen) + str;\n        }\n    },\n\n    lpad: function(str, length, padStr) {\n      return _s.pad(str, length, padStr);\n    },\n\n    rpad: function(str, length, padStr) {\n      return _s.pad(str, length, padStr, 'right');\n    },\n\n    lrpad: function(str, length, padStr) {\n      return _s.pad(str, length, padStr, 'both');\n    },\n\n    sprintf: sprintf,\n\n    vsprintf: function(fmt, argv){\n      argv.unshift(fmt);\n      return sprintf.apply(null, argv);\n    },\n\n    toNumber: function(str, decimals) {\n      if (!str) return 0;\n      str = _s.trim(str);\n      if (!str.match(/^-?\\d+(?:\\.\\d+)?$/)) return NaN;\n      return parseNumber(parseNumber(str).toFixed(~~decimals));\n    },\n\n    numberFormat : function(number, dec, dsep, tsep) {\n      if (isNaN(number) || number == null) return '';\n\n      number = number.toFixed(~~dec);\n      tsep = typeof tsep == 'string' ? tsep : ',';\n\n      var parts = number.split('.'), fnums = parts[0],\n        decimals = parts[1] ? (dsep || '.') + parts[1] : '';\n\n      return fnums.replace(/(\\d)(?=(?:\\d{3})+$)/g, '$1' + tsep) + decimals;\n    },\n\n    strRight: function(str, sep){\n      if (str == null) return '';\n      str = String(str); sep = sep != null ? String(sep) : sep;\n      var pos = !sep ? -1 : str.indexOf(sep);\n      return ~pos ? str.slice(pos+sep.length, str.length) : str;\n    },\n\n    strRightBack: function(str, sep){\n      if (str == null) return '';\n      str = String(str); sep = sep != null ? String(sep) : sep;\n      var pos = !sep ? -1 : str.lastIndexOf(sep);\n      return ~pos ? str.slice(pos+sep.length, str.length) : str;\n    },\n\n    strLeft: function(str, sep){\n      if (str == null) return '';\n      str = String(str); sep = sep != null ? String(sep) : sep;\n      var pos = !sep ? -1 : str.indexOf(sep);\n      return ~pos ? str.slice(0, pos) : str;\n    },\n\n    strLeftBack: function(str, sep){\n      if (str == null) return '';\n      str += ''; sep = sep != null ? ''+sep : sep;\n      var pos = str.lastIndexOf(sep);\n      return ~pos ? str.slice(0, pos) : str;\n    },\n\n    toSentence: function(array, separator, lastSeparator, serial) {\n      separator = separator || ', ';\n      lastSeparator = lastSeparator || ' and ';\n      var a = array.slice(), lastMember = a.pop();\n\n      if (array.length > 2 && serial) lastSeparator = _s.rtrim(separator) + lastSeparator;\n\n      return a.length ? a.join(separator) + lastSeparator + lastMember : lastMember;\n    },\n\n    toSentenceSerial: function() {\n      var args = slice.call(arguments);\n      args[3] = true;\n      return _s.toSentence.apply(_s, args);\n    },\n\n    slugify: function(str) {\n      if (str == null) return '';\n\n      var from  = \"\u0105\u00e0\u00e1\u00e4\u00e2\u00e3\u00e5\u00e6\u0103\u0107\u0119\u00e8\u00e9\u00eb\u00ea\u00ec\u00ed\u00ef\u00ee\u0142\u0144\u00f2\u00f3\u00f6\u00f4\u00f5\u00f8\u015b\u0219\u021b\u00f9\u00fa\u00fc\u00fb\u00f1\u00e7\u017c\u017a\",\n          to    = \"aaaaaaaaaceeeeeiiiilnoooooosstuuuunczz\",\n          regex = new RegExp(defaultToWhiteSpace(from), 'g');\n\n      str = String(str).toLowerCase().replace(regex, function(c){\n        var index = from.indexOf(c);\n        return to.charAt(index) || '-';\n      });\n\n      return _s.dasherize(str.replace(/[^\\w\\s-]/g, ''));\n    },\n\n    surround: function(str, wrapper) {\n      return [wrapper, str, wrapper].join('');\n    },\n\n    quote: function(str, quoteChar) {\n      return _s.surround(str, quoteChar || '\"');\n    },\n\n    unquote: function(str, quoteChar) {\n      quoteChar = quoteChar || '\"';\n      if (str[0] === quoteChar && str[str.length-1] === quoteChar)\n        return str.slice(1,str.length-1);\n      else return str;\n    },\n\n    exports: function() {\n      var result = {};\n\n      for (var prop in this) {\n        if (!this.hasOwnProperty(prop) || prop.match(/^(?:include|contains|reverse)$/)) continue;\n        result[prop] = this[prop];\n      }\n\n      return result;\n    },\n\n    repeat: function(str, qty, separator){\n      if (str == null) return '';\n\n      qty = ~~qty;\n\n      // using faster implementation if separator is not needed;\n      if (separator == null) return strRepeat(String(str), qty);\n\n      // this one is about 300x slower in Google Chrome\n      for (var repeat = []; qty > 0; repeat[--qty] = str) {}\n      return repeat.join(separator);\n    },\n\n    naturalCmp: function(str1, str2){\n      if (str1 == str2) return 0;\n      if (!str1) return -1;\n      if (!str2) return 1;\n\n      var cmpRegex = /(\\.\\d+)|(\\d+)|(\\D+)/g,\n        tokens1 = String(str1).toLowerCase().match(cmpRegex),\n        tokens2 = String(str2).toLowerCase().match(cmpRegex),\n        count = Math.min(tokens1.length, tokens2.length);\n\n      for(var i = 0; i < count; i++) {\n        var a = tokens1[i], b = tokens2[i];\n\n        if (a !== b){\n          var num1 = parseInt(a, 10);\n          if (!isNaN(num1)){\n            var num2 = parseInt(b, 10);\n            if (!isNaN(num2) && num1 - num2)\n              return num1 - num2;\n          }\n          return a < b ? -1 : 1;\n        }\n      }\n\n      if (tokens1.length === tokens2.length)\n        return tokens1.length - tokens2.length;\n\n      return str1 < str2 ? -1 : 1;\n    },\n\n    levenshtein: function(str1, str2) {\n      if (str1 == null && str2 == null) return 0;\n      if (str1 == null) return String(str2).length;\n      if (str2 == null) return String(str1).length;\n\n      str1 = String(str1); str2 = String(str2);\n\n      var current = [], prev, value;\n\n      for (var i = 0; i <= str2.length; i++)\n        for (var j = 0; j <= str1.length; j++) {\n          if (i && j)\n            if (str1.charAt(j - 1) === str2.charAt(i - 1))\n              value = prev;\n            else\n              value = Math.min(current[j], current[j - 1], prev) + 1;\n          else\n            value = i + j;\n\n          prev = current[j];\n          current[j] = value;\n        }\n\n      return current.pop();\n    },\n\n    toBoolean: function(str, trueValues, falseValues) {\n      if (typeof str === \"number\") str = \"\" + str;\n      if (typeof str !== \"string\") return !!str;\n      str = _s.trim(str);\n      if (boolMatch(str, trueValues || [\"true\", \"1\"])) return true;\n      if (boolMatch(str, falseValues || [\"false\", \"0\"])) return false;\n    }\n  };\n\n  // Aliases\n\n  _s.strip    = _s.trim;\n  _s.lstrip   = _s.ltrim;\n  _s.rstrip   = _s.rtrim;\n  _s.center   = _s.lrpad;\n  _s.rjust    = _s.lpad;\n  _s.ljust    = _s.rpad;\n  _s.contains = _s.include;\n  _s.q        = _s.quote;\n  _s.toBool   = _s.toBoolean;\n\n  // Exporting\n\n  // CommonJS module is defined\n  if (typeof exports !== 'undefined') {\n    if (typeof module !== 'undefined' && module.exports)\n      module.exports = _s;\n\n    exports._s = _s;\n  }\n\n  // Register as a named module with AMD.\n  if (typeof define === 'function' && define.amd)\n    define('underscore.string', [], function(){ return _s; });\n\n\n  // Integrate with Underscore.js if defined\n  // or create our own underscore object.\n  root._ = root._ || {};\n  root._.string = root._.str = _s;\n}(this, String);\n", "//! moment.js\n//! version : 2.17.1\n//! authors : Tim Wood, Iskren Chernev, Moment.js contributors\n//! license : MIT\n//! momentjs.com\n\n;(function (global, factory) {\n    typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :\n    typeof define === 'function' && define.amd ? define(factory) :\n    global.moment = factory()\n}(this, (function () { 'use strict';\n\nvar hookCallback;\n\nfunction hooks () {\n    return hookCallback.apply(null, arguments);\n}\n\n// This is done to register the method called with moment()\n// without creating circular dependencies.\nfunction setHookCallback (callback) {\n    hookCallback = callback;\n}\n\nfunction isArray(input) {\n    return input instanceof Array || Object.prototype.toString.call(input) === '[object Array]';\n}\n\nfunction isObject(input) {\n    // IE8 will treat undefined and null as object if it wasn't for\n    // input != null\n    return input != null && Object.prototype.toString.call(input) === '[object Object]';\n}\n\nfunction isObjectEmpty(obj) {\n    var k;\n    for (k in obj) {\n        // even if its not own property I'd still call it non-empty\n        return false;\n    }\n    return true;\n}\n\nfunction isNumber(input) {\n    return typeof input === 'number' || Object.prototype.toString.call(input) === '[object Number]';\n}\n\nfunction isDate(input) {\n    return input instanceof Date || Object.prototype.toString.call(input) === '[object Date]';\n}\n\nfunction map(arr, fn) {\n    var res = [], i;\n    for (i = 0; i < arr.length; ++i) {\n        res.push(fn(arr[i], i));\n    }\n    return res;\n}\n\nfunction hasOwnProp(a, b) {\n    return Object.prototype.hasOwnProperty.call(a, b);\n}\n\nfunction extend(a, b) {\n    for (var i in b) {\n        if (hasOwnProp(b, i)) {\n            a[i] = b[i];\n        }\n    }\n\n    if (hasOwnProp(b, 'toString')) {\n        a.toString = b.toString;\n    }\n\n    if (hasOwnProp(b, 'valueOf')) {\n        a.valueOf = b.valueOf;\n    }\n\n    return a;\n}\n\nfunction createUTC (input, format, locale, strict) {\n    return createLocalOrUTC(input, format, locale, strict, true).utc();\n}\n\nfunction defaultParsingFlags() {\n    // We need to deep clone this object.\n    return {\n        empty           : false,\n        unusedTokens    : [],\n        unusedInput     : [],\n        overflow        : -2,\n        charsLeftOver   : 0,\n        nullInput       : false,\n        invalidMonth    : null,\n        invalidFormat   : false,\n        userInvalidated : false,\n        iso             : false,\n        parsedDateParts : [],\n        meridiem        : null\n    };\n}\n\nfunction getParsingFlags(m) {\n    if (m._pf == null) {\n        m._pf = defaultParsingFlags();\n    }\n    return m._pf;\n}\n\nvar some;\nif (Array.prototype.some) {\n    some = Array.prototype.some;\n} else {\n    some = function (fun) {\n        var t = Object(this);\n        var len = t.length >>> 0;\n\n        for (var i = 0; i < len; i++) {\n            if (i in t && fun.call(this, t[i], i, t)) {\n                return true;\n            }\n        }\n\n        return false;\n    };\n}\n\nvar some$1 = some;\n\nfunction isValid(m) {\n    if (m._isValid == null) {\n        var flags = getParsingFlags(m);\n        var parsedParts = some$1.call(flags.parsedDateParts, function (i) {\n            return i != null;\n        });\n        var isNowValid = !isNaN(m._d.getTime()) &&\n            flags.overflow < 0 &&\n            !flags.empty &&\n            !flags.invalidMonth &&\n            !flags.invalidWeekday &&\n            !flags.nullInput &&\n            !flags.invalidFormat &&\n            !flags.userInvalidated &&\n            (!flags.meridiem || (flags.meridiem && parsedParts));\n\n        if (m._strict) {\n            isNowValid = isNowValid &&\n                flags.charsLeftOver === 0 &&\n                flags.unusedTokens.length === 0 &&\n                flags.bigHour === undefined;\n        }\n\n        if (Object.isFrozen == null || !Object.isFrozen(m)) {\n            m._isValid = isNowValid;\n        }\n        else {\n            return isNowValid;\n        }\n    }\n    return m._isValid;\n}\n\nfunction createInvalid (flags) {\n    var m = createUTC(NaN);\n    if (flags != null) {\n        extend(getParsingFlags(m), flags);\n    }\n    else {\n        getParsingFlags(m).userInvalidated = true;\n    }\n\n    return m;\n}\n\nfunction isUndefined(input) {\n    return input === void 0;\n}\n\n// Plugins that add properties should also add the key here (null value),\n// so we can properly clone ourselves.\nvar momentProperties = hooks.momentProperties = [];\n\nfunction copyConfig(to, from) {\n    var i, prop, val;\n\n    if (!isUndefined(from._isAMomentObject)) {\n        to._isAMomentObject = from._isAMomentObject;\n    }\n    if (!isUndefined(from._i)) {\n        to._i = from._i;\n    }\n    if (!isUndefined(from._f)) {\n        to._f = from._f;\n    }\n    if (!isUndefined(from._l)) {\n        to._l = from._l;\n    }\n    if (!isUndefined(from._strict)) {\n        to._strict = from._strict;\n    }\n    if (!isUndefined(from._tzm)) {\n        to._tzm = from._tzm;\n    }\n    if (!isUndefined(from._isUTC)) {\n        to._isUTC = from._isUTC;\n    }\n    if (!isUndefined(from._offset)) {\n        to._offset = from._offset;\n    }\n    if (!isUndefined(from._pf)) {\n        to._pf = getParsingFlags(from);\n    }\n    if (!isUndefined(from._locale)) {\n        to._locale = from._locale;\n    }\n\n    if (momentProperties.length > 0) {\n        for (i in momentProperties) {\n            prop = momentProperties[i];\n            val = from[prop];\n            if (!isUndefined(val)) {\n                to[prop] = val;\n            }\n        }\n    }\n\n    return to;\n}\n\nvar updateInProgress = false;\n\n// Moment prototype object\nfunction Moment(config) {\n    copyConfig(this, config);\n    this._d = new Date(config._d != null ? config._d.getTime() : NaN);\n    if (!this.isValid()) {\n        this._d = new Date(NaN);\n    }\n    // Prevent infinite loop in case updateOffset creates new moment\n    // objects.\n    if (updateInProgress === false) {\n        updateInProgress = true;\n        hooks.updateOffset(this);\n        updateInProgress = false;\n    }\n}\n\nfunction isMoment (obj) {\n    return obj instanceof Moment || (obj != null && obj._isAMomentObject != null);\n}\n\nfunction absFloor (number) {\n    if (number < 0) {\n        // -0 -> 0\n        return Math.ceil(number) || 0;\n    } else {\n        return Math.floor(number);\n    }\n}\n\nfunction toInt(argumentForCoercion) {\n    var coercedNumber = +argumentForCoercion,\n        value = 0;\n\n    if (coercedNumber !== 0 && isFinite(coercedNumber)) {\n        value = absFloor(coercedNumber);\n    }\n\n    return value;\n}\n\n// compare two arrays, return the number of differences\nfunction compareArrays(array1, array2, dontConvert) {\n    var len = Math.min(array1.length, array2.length),\n        lengthDiff = Math.abs(array1.length - array2.length),\n        diffs = 0,\n        i;\n    for (i = 0; i < len; i++) {\n        if ((dontConvert && array1[i] !== array2[i]) ||\n            (!dontConvert && toInt(array1[i]) !== toInt(array2[i]))) {\n            diffs++;\n        }\n    }\n    return diffs + lengthDiff;\n}\n\nfunction warn(msg) {\n    if (hooks.suppressDeprecationWarnings === false &&\n            (typeof console !==  'undefined') && console.warn) {\n        console.warn('Deprecation warning: ' + msg);\n    }\n}\n\nfunction deprecate(msg, fn) {\n    var firstTime = true;\n\n    return extend(function () {\n        if (hooks.deprecationHandler != null) {\n            hooks.deprecationHandler(null, msg);\n        }\n        if (firstTime) {\n            var args = [];\n            var arg;\n            for (var i = 0; i < arguments.length; i++) {\n                arg = '';\n                if (typeof arguments[i] === 'object') {\n                    arg += '\\n[' + i + '] ';\n                    for (var key in arguments[0]) {\n                        arg += key + ': ' + arguments[0][key] + ', ';\n                    }\n                    arg = arg.slice(0, -2); // Remove trailing comma and space\n                } else {\n                    arg = arguments[i];\n                }\n                args.push(arg);\n            }\n            warn(msg + '\\nArguments: ' + Array.prototype.slice.call(args).join('') + '\\n' + (new Error()).stack);\n            firstTime = false;\n        }\n        return fn.apply(this, arguments);\n    }, fn);\n}\n\nvar deprecations = {};\n\nfunction deprecateSimple(name, msg) {\n    if (hooks.deprecationHandler != null) {\n        hooks.deprecationHandler(name, msg);\n    }\n    if (!deprecations[name]) {\n        warn(msg);\n        deprecations[name] = true;\n    }\n}\n\nhooks.suppressDeprecationWarnings = false;\nhooks.deprecationHandler = null;\n\nfunction isFunction(input) {\n    return input instanceof Function || Object.prototype.toString.call(input) === '[object Function]';\n}\n\nfunction set (config) {\n    var prop, i;\n    for (i in config) {\n        prop = config[i];\n        if (isFunction(prop)) {\n            this[i] = prop;\n        } else {\n            this['_' + i] = prop;\n        }\n    }\n    this._config = config;\n    // Lenient ordinal parsing accepts just a number in addition to\n    // number + (possibly) stuff coming from _ordinalParseLenient.\n    this._ordinalParseLenient = new RegExp(this._ordinalParse.source + '|' + (/\\d{1,2}/).source);\n}\n\nfunction mergeConfigs(parentConfig, childConfig) {\n    var res = extend({}, parentConfig), prop;\n    for (prop in childConfig) {\n        if (hasOwnProp(childConfig, prop)) {\n            if (isObject(parentConfig[prop]) && isObject(childConfig[prop])) {\n                res[prop] = {};\n                extend(res[prop], parentConfig[prop]);\n                extend(res[prop], childConfig[prop]);\n            } else if (childConfig[prop] != null) {\n                res[prop] = childConfig[prop];\n            } else {\n                delete res[prop];\n            }\n        }\n    }\n    for (prop in parentConfig) {\n        if (hasOwnProp(parentConfig, prop) &&\n                !hasOwnProp(childConfig, prop) &&\n                isObject(parentConfig[prop])) {\n            // make sure changes to properties don't modify parent config\n            res[prop] = extend({}, res[prop]);\n        }\n    }\n    return res;\n}\n\nfunction Locale(config) {\n    if (config != null) {\n        this.set(config);\n    }\n}\n\nvar keys;\n\nif (Object.keys) {\n    keys = Object.keys;\n} else {\n    keys = function (obj) {\n        var i, res = [];\n        for (i in obj) {\n            if (hasOwnProp(obj, i)) {\n                res.push(i);\n            }\n        }\n        return res;\n    };\n}\n\nvar keys$1 = keys;\n\nvar defaultCalendar = {\n    sameDay : '[Today at] LT',\n    nextDay : '[Tomorrow at] LT',\n    nextWeek : 'dddd [at] LT',\n    lastDay : '[Yesterday at] LT',\n    lastWeek : '[Last] dddd [at] LT',\n    sameElse : 'L'\n};\n\nfunction calendar (key, mom, now) {\n    var output = this._calendar[key] || this._calendar['sameElse'];\n    return isFunction(output) ? output.call(mom, now) : output;\n}\n\nvar defaultLongDateFormat = {\n    LTS  : 'h:mm:ss A',\n    LT   : 'h:mm A',\n    L    : 'MM/DD/YYYY',\n    LL   : 'MMMM D, YYYY',\n    LLL  : 'MMMM D, YYYY h:mm A',\n    LLLL : 'dddd, MMMM D, YYYY h:mm A'\n};\n\nfunction longDateFormat (key) {\n    var format = this._longDateFormat[key],\n        formatUpper = this._longDateFormat[key.toUpperCase()];\n\n    if (format || !formatUpper) {\n        return format;\n    }\n\n    this._longDateFormat[key] = formatUpper.replace(/MMMM|MM|DD|dddd/g, function (val) {\n        return val.slice(1);\n    });\n\n    return this._longDateFormat[key];\n}\n\nvar defaultInvalidDate = 'Invalid date';\n\nfunction invalidDate () {\n    return this._invalidDate;\n}\n\nvar defaultOrdinal = '%d';\nvar defaultOrdinalParse = /\\d{1,2}/;\n\nfunction ordinal (number) {\n    return this._ordinal.replace('%d', number);\n}\n\nvar defaultRelativeTime = {\n    future : 'in %s',\n    past   : '%s ago',\n    s  : 'a few seconds',\n    m  : 'a minute',\n    mm : '%d minutes',\n    h  : 'an hour',\n    hh : '%d hours',\n    d  : 'a day',\n    dd : '%d days',\n    M  : 'a month',\n    MM : '%d months',\n    y  : 'a year',\n    yy : '%d years'\n};\n\nfunction relativeTime (number, withoutSuffix, string, isFuture) {\n    var output = this._relativeTime[string];\n    return (isFunction(output)) ?\n        output(number, withoutSuffix, string, isFuture) :\n        output.replace(/%d/i, number);\n}\n\nfunction pastFuture (diff, output) {\n    var format = this._relativeTime[diff > 0 ? 'future' : 'past'];\n    return isFunction(format) ? format(output) : format.replace(/%s/i, output);\n}\n\nvar aliases = {};\n\nfunction addUnitAlias (unit, shorthand) {\n    var lowerCase = unit.toLowerCase();\n    aliases[lowerCase] = aliases[lowerCase + 's'] = aliases[shorthand] = unit;\n}\n\nfunction normalizeUnits(units) {\n    return typeof units === 'string' ? aliases[units] || aliases[units.toLowerCase()] : undefined;\n}\n\nfunction normalizeObjectUnits(inputObject) {\n    var normalizedInput = {},\n        normalizedProp,\n        prop;\n\n    for (prop in inputObject) {\n        if (hasOwnProp(inputObject, prop)) {\n            normalizedProp = normalizeUnits(prop);\n            if (normalizedProp) {\n                normalizedInput[normalizedProp] = inputObject[prop];\n            }\n        }\n    }\n\n    return normalizedInput;\n}\n\nvar priorities = {};\n\nfunction addUnitPriority(unit, priority) {\n    priorities[unit] = priority;\n}\n\nfunction getPrioritizedUnits(unitsObj) {\n    var units = [];\n    for (var u in unitsObj) {\n        units.push({unit: u, priority: priorities[u]});\n    }\n    units.sort(function (a, b) {\n        return a.priority - b.priority;\n    });\n    return units;\n}\n\nfunction makeGetSet (unit, keepTime) {\n    return function (value) {\n        if (value != null) {\n            set$1(this, unit, value);\n            hooks.updateOffset(this, keepTime);\n            return this;\n        } else {\n            return get(this, unit);\n        }\n    };\n}\n\nfunction get (mom, unit) {\n    return mom.isValid() ?\n        mom._d['get' + (mom._isUTC ? 'UTC' : '') + unit]() : NaN;\n}\n\nfunction set$1 (mom, unit, value) {\n    if (mom.isValid()) {\n        mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value);\n    }\n}\n\n// MOMENTS\n\nfunction stringGet (units) {\n    units = normalizeUnits(units);\n    if (isFunction(this[units])) {\n        return this[units]();\n    }\n    return this;\n}\n\n\nfunction stringSet (units, value) {\n    if (typeof units === 'object') {\n        units = normalizeObjectUnits(units);\n        var prioritized = getPrioritizedUnits(units);\n        for (var i = 0; i < prioritized.length; i++) {\n            this[prioritized[i].unit](units[prioritized[i].unit]);\n        }\n    } else {\n        units = normalizeUnits(units);\n        if (isFunction(this[units])) {\n            return this[units](value);\n        }\n    }\n    return this;\n}\n\nfunction zeroFill(number, targetLength, forceSign) {\n    var absNumber = '' + Math.abs(number),\n        zerosToFill = targetLength - absNumber.length,\n        sign = number >= 0;\n    return (sign ? (forceSign ? '+' : '') : '-') +\n        Math.pow(10, Math.max(0, zerosToFill)).toString().substr(1) + absNumber;\n}\n\nvar 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;\n\nvar localFormattingTokens = /(\\[[^\\[]*\\])|(\\\\)?(LTS|LT|LL?L?L?|l{1,4})/g;\n\nvar formatFunctions = {};\n\nvar formatTokenFunctions = {};\n\n// token:    'M'\n// padded:   ['MM', 2]\n// ordinal:  'Mo'\n// callback: function () { this.month() + 1 }\nfunction addFormatToken (token, padded, ordinal, callback) {\n    var func = callback;\n    if (typeof callback === 'string') {\n        func = function () {\n            return this[callback]();\n        };\n    }\n    if (token) {\n        formatTokenFunctions[token] = func;\n    }\n    if (padded) {\n        formatTokenFunctions[padded[0]] = function () {\n            return zeroFill(func.apply(this, arguments), padded[1], padded[2]);\n        };\n    }\n    if (ordinal) {\n        formatTokenFunctions[ordinal] = function () {\n            return this.localeData().ordinal(func.apply(this, arguments), token);\n        };\n    }\n}\n\nfunction removeFormattingTokens(input) {\n    if (input.match(/\\[[\\s\\S]/)) {\n        return input.replace(/^\\[|\\]$/g, '');\n    }\n    return input.replace(/\\\\/g, '');\n}\n\nfunction makeFormatFunction(format) {\n    var array = format.match(formattingTokens), i, length;\n\n    for (i = 0, length = array.length; i < length; i++) {\n        if (formatTokenFunctions[array[i]]) {\n            array[i] = formatTokenFunctions[array[i]];\n        } else {\n            array[i] = removeFormattingTokens(array[i]);\n        }\n    }\n\n    return function (mom) {\n        var output = '', i;\n        for (i = 0; i < length; i++) {\n            output += array[i] instanceof Function ? array[i].call(mom, format) : array[i];\n        }\n        return output;\n    };\n}\n\n// format date using native date object\nfunction formatMoment(m, format) {\n    if (!m.isValid()) {\n        return m.localeData().invalidDate();\n    }\n\n    format = expandFormat(format, m.localeData());\n    formatFunctions[format] = formatFunctions[format] || makeFormatFunction(format);\n\n    return formatFunctions[format](m);\n}\n\nfunction expandFormat(format, locale) {\n    var i = 5;\n\n    function replaceLongDateFormatTokens(input) {\n        return locale.longDateFormat(input) || input;\n    }\n\n    localFormattingTokens.lastIndex = 0;\n    while (i >= 0 && localFormattingTokens.test(format)) {\n        format = format.replace(localFormattingTokens, replaceLongDateFormatTokens);\n        localFormattingTokens.lastIndex = 0;\n        i -= 1;\n    }\n\n    return format;\n}\n\nvar match1         = /\\d/;            //       0 - 9\nvar match2         = /\\d\\d/;          //      00 - 99\nvar match3         = /\\d{3}/;         //     000 - 999\nvar match4         = /\\d{4}/;         //    0000 - 9999\nvar match6         = /[+-]?\\d{6}/;    // -999999 - 999999\nvar match1to2      = /\\d\\d?/;         //       0 - 99\nvar match3to4      = /\\d\\d\\d\\d?/;     //     999 - 9999\nvar match5to6      = /\\d\\d\\d\\d\\d\\d?/; //   99999 - 999999\nvar match1to3      = /\\d{1,3}/;       //       0 - 999\nvar match1to4      = /\\d{1,4}/;       //       0 - 9999\nvar match1to6      = /[+-]?\\d{1,6}/;  // -999999 - 999999\n\nvar matchUnsigned  = /\\d+/;           //       0 - inf\nvar matchSigned    = /[+-]?\\d+/;      //    -inf - inf\n\nvar matchOffset    = /Z|[+-]\\d\\d:?\\d\\d/gi; // +00:00 -00:00 +0000 -0000 or Z\nvar matchShortOffset = /Z|[+-]\\d\\d(?::?\\d\\d)?/gi; // +00 -00 +00:00 -00:00 +0000 -0000 or Z\n\nvar matchTimestamp = /[+-]?\\d+(\\.\\d{1,3})?/; // 123456789 123456789.123\n\n// any word (or two) characters or numbers including two/three word month in arabic.\n// includes scottish gaelic two word and hyphenated months\nvar matchWord = /[0-9]*['a-z\\u00A0-\\u05FF\\u0700-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF]+|[\\u0600-\\u06FF\\/]+(\\s*?[\\u0600-\\u06FF]+){1,2}/i;\n\n\nvar regexes = {};\n\nfunction addRegexToken (token, regex, strictRegex) {\n    regexes[token] = isFunction(regex) ? regex : function (isStrict, localeData) {\n        return (isStrict && strictRegex) ? strictRegex : regex;\n    };\n}\n\nfunction getParseRegexForToken (token, config) {\n    if (!hasOwnProp(regexes, token)) {\n        return new RegExp(unescapeFormat(token));\n    }\n\n    return regexes[token](config._strict, config._locale);\n}\n\n// Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript\nfunction unescapeFormat(s) {\n    return regexEscape(s.replace('\\\\', '').replace(/\\\\(\\[)|\\\\(\\])|\\[([^\\]\\[]*)\\]|\\\\(.)/g, function (matched, p1, p2, p3, p4) {\n        return p1 || p2 || p3 || p4;\n    }));\n}\n\nfunction regexEscape(s) {\n    return s.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n}\n\nvar tokens = {};\n\nfunction addParseToken (token, callback) {\n    var i, func = callback;\n    if (typeof token === 'string') {\n        token = [token];\n    }\n    if (isNumber(callback)) {\n        func = function (input, array) {\n            array[callback] = toInt(input);\n        };\n    }\n    for (i = 0; i < token.length; i++) {\n        tokens[token[i]] = func;\n    }\n}\n\nfunction addWeekParseToken (token, callback) {\n    addParseToken(token, function (input, array, config, token) {\n        config._w = config._w || {};\n        callback(input, config._w, config, token);\n    });\n}\n\nfunction addTimeToArrayFromToken(token, input, config) {\n    if (input != null && hasOwnProp(tokens, token)) {\n        tokens[token](input, config._a, config, token);\n    }\n}\n\nvar YEAR = 0;\nvar MONTH = 1;\nvar DATE = 2;\nvar HOUR = 3;\nvar MINUTE = 4;\nvar SECOND = 5;\nvar MILLISECOND = 6;\nvar WEEK = 7;\nvar WEEKDAY = 8;\n\nvar indexOf;\n\nif (Array.prototype.indexOf) {\n    indexOf = Array.prototype.indexOf;\n} else {\n    indexOf = function (o) {\n        // I know\n        var i;\n        for (i = 0; i < this.length; ++i) {\n            if (this[i] === o) {\n                return i;\n            }\n        }\n        return -1;\n    };\n}\n\nvar indexOf$1 = indexOf;\n\nfunction daysInMonth(year, month) {\n    return new Date(Date.UTC(year, month + 1, 0)).getUTCDate();\n}\n\n// FORMATTING\n\naddFormatToken('M', ['MM', 2], 'Mo', function () {\n    return this.month() + 1;\n});\n\naddFormatToken('MMM', 0, 0, function (format) {\n    return this.localeData().monthsShort(this, format);\n});\n\naddFormatToken('MMMM', 0, 0, function (format) {\n    return this.localeData().months(this, format);\n});\n\n// ALIASES\n\naddUnitAlias('month', 'M');\n\n// PRIORITY\n\naddUnitPriority('month', 8);\n\n// PARSING\n\naddRegexToken('M',    match1to2);\naddRegexToken('MM',   match1to2, match2);\naddRegexToken('MMM',  function (isStrict, locale) {\n    return locale.monthsShortRegex(isStrict);\n});\naddRegexToken('MMMM', function (isStrict, locale) {\n    return locale.monthsRegex(isStrict);\n});\n\naddParseToken(['M', 'MM'], function (input, array) {\n    array[MONTH] = toInt(input) - 1;\n});\n\naddParseToken(['MMM', 'MMMM'], function (input, array, config, token) {\n    var month = config._locale.monthsParse(input, token, config._strict);\n    // if we didn't find a month name, mark the date as invalid.\n    if (month != null) {\n        array[MONTH] = month;\n    } else {\n        getParsingFlags(config).invalidMonth = input;\n    }\n});\n\n// LOCALES\n\nvar MONTHS_IN_FORMAT = /D[oD]?(\\[[^\\[\\]]*\\]|\\s)+MMMM?/;\nvar defaultLocaleMonths = 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_');\nfunction localeMonths (m, format) {\n    if (!m) {\n        return this._months;\n    }\n    return isArray(this._months) ? this._months[m.month()] :\n        this._months[(this._months.isFormat || MONTHS_IN_FORMAT).test(format) ? 'format' : 'standalone'][m.month()];\n}\n\nvar defaultLocaleMonthsShort = 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_');\nfunction localeMonthsShort (m, format) {\n    if (!m) {\n        return this._monthsShort;\n    }\n    return isArray(this._monthsShort) ? this._monthsShort[m.month()] :\n        this._monthsShort[MONTHS_IN_FORMAT.test(format) ? 'format' : 'standalone'][m.month()];\n}\n\nfunction handleStrictParse(monthName, format, strict) {\n    var i, ii, mom, llc = monthName.toLocaleLowerCase();\n    if (!this._monthsParse) {\n        // this is not used\n        this._monthsParse = [];\n        this._longMonthsParse = [];\n        this._shortMonthsParse = [];\n        for (i = 0; i < 12; ++i) {\n            mom = createUTC([2000, i]);\n            this._shortMonthsParse[i] = this.monthsShort(mom, '').toLocaleLowerCase();\n            this._longMonthsParse[i] = this.months(mom, '').toLocaleLowerCase();\n        }\n    }\n\n    if (strict) {\n        if (format === 'MMM') {\n            ii = indexOf$1.call(this._shortMonthsParse, llc);\n            return ii !== -1 ? ii : null;\n        } else {\n            ii = indexOf$1.call(this._longMonthsParse, llc);\n            return ii !== -1 ? ii : null;\n        }\n    } else {\n        if (format === 'MMM') {\n            ii = indexOf$1.call(this._shortMonthsParse, llc);\n            if (ii !== -1) {\n                return ii;\n            }\n            ii = indexOf$1.call(this._longMonthsParse, llc);\n            return ii !== -1 ? ii : null;\n        } else {\n            ii = indexOf$1.call(this._longMonthsParse, llc);\n            if (ii !== -1) {\n                return ii;\n            }\n            ii = indexOf$1.call(this._shortMonthsParse, llc);\n            return ii !== -1 ? ii : null;\n        }\n    }\n}\n\nfunction localeMonthsParse (monthName, format, strict) {\n    var i, mom, regex;\n\n    if (this._monthsParseExact) {\n        return handleStrictParse.call(this, monthName, format, strict);\n    }\n\n    if (!this._monthsParse) {\n        this._monthsParse = [];\n        this._longMonthsParse = [];\n        this._shortMonthsParse = [];\n    }\n\n    // TODO: add sorting\n    // Sorting makes sure if one month (or abbr) is a prefix of another\n    // see sorting in computeMonthsParse\n    for (i = 0; i < 12; i++) {\n        // make the regex if we don't have it already\n        mom = createUTC([2000, i]);\n        if (strict && !this._longMonthsParse[i]) {\n            this._longMonthsParse[i] = new RegExp('^' + this.months(mom, '').replace('.', '') + '$', 'i');\n            this._shortMonthsParse[i] = new RegExp('^' + this.monthsShort(mom, '').replace('.', '') + '$', 'i');\n        }\n        if (!strict && !this._monthsParse[i]) {\n            regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, '');\n            this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i');\n        }\n        // test the regex\n        if (strict && format === 'MMMM' && this._longMonthsParse[i].test(monthName)) {\n            return i;\n        } else if (strict && format === 'MMM' && this._shortMonthsParse[i].test(monthName)) {\n            return i;\n        } else if (!strict && this._monthsParse[i].test(monthName)) {\n            return i;\n        }\n    }\n}\n\n// MOMENTS\n\nfunction setMonth (mom, value) {\n    var dayOfMonth;\n\n    if (!mom.isValid()) {\n        // No op\n        return mom;\n    }\n\n    if (typeof value === 'string') {\n        if (/^\\d+$/.test(value)) {\n            value = toInt(value);\n        } else {\n            value = mom.localeData().monthsParse(value);\n            // TODO: Another silent failure?\n            if (!isNumber(value)) {\n                return mom;\n            }\n        }\n    }\n\n    dayOfMonth = Math.min(mom.date(), daysInMonth(mom.year(), value));\n    mom._d['set' + (mom._isUTC ? 'UTC' : '') + 'Month'](value, dayOfMonth);\n    return mom;\n}\n\nfunction getSetMonth (value) {\n    if (value != null) {\n        setMonth(this, value);\n        hooks.updateOffset(this, true);\n        return this;\n    } else {\n        return get(this, 'Month');\n    }\n}\n\nfunction getDaysInMonth () {\n    return daysInMonth(this.year(), this.month());\n}\n\nvar defaultMonthsShortRegex = matchWord;\nfunction monthsShortRegex (isStrict) {\n    if (this._monthsParseExact) {\n        if (!hasOwnProp(this, '_monthsRegex')) {\n            computeMonthsParse.call(this);\n        }\n        if (isStrict) {\n            return this._monthsShortStrictRegex;\n        } else {\n            return this._monthsShortRegex;\n        }\n    } else {\n        if (!hasOwnProp(this, '_monthsShortRegex')) {\n            this._monthsShortRegex = defaultMonthsShortRegex;\n        }\n        return this._monthsShortStrictRegex && isStrict ?\n            this._monthsShortStrictRegex : this._monthsShortRegex;\n    }\n}\n\nvar defaultMonthsRegex = matchWord;\nfunction monthsRegex (isStrict) {\n    if (this._monthsParseExact) {\n        if (!hasOwnProp(this, '_monthsRegex')) {\n            computeMonthsParse.call(this);\n        }\n        if (isStrict) {\n            return this._monthsStrictRegex;\n        } else {\n            return this._monthsRegex;\n        }\n    } else {\n        if (!hasOwnProp(this, '_monthsRegex')) {\n            this._monthsRegex = defaultMonthsRegex;\n        }\n        return this._monthsStrictRegex && isStrict ?\n            this._monthsStrictRegex : this._monthsRegex;\n    }\n}\n\nfunction computeMonthsParse () {\n    function cmpLenRev(a, b) {\n        return b.length - a.length;\n    }\n\n    var shortPieces = [], longPieces = [], mixedPieces = [],\n        i, mom;\n    for (i = 0; i < 12; i++) {\n        // make the regex if we don't have it already\n        mom = createUTC([2000, i]);\n        shortPieces.push(this.monthsShort(mom, ''));\n        longPieces.push(this.months(mom, ''));\n        mixedPieces.push(this.months(mom, ''));\n        mixedPieces.push(this.monthsShort(mom, ''));\n    }\n    // Sorting makes sure if one month (or abbr) is a prefix of another it\n    // will match the longer piece.\n    shortPieces.sort(cmpLenRev);\n    longPieces.sort(cmpLenRev);\n    mixedPieces.sort(cmpLenRev);\n    for (i = 0; i < 12; i++) {\n        shortPieces[i] = regexEscape(shortPieces[i]);\n        longPieces[i] = regexEscape(longPieces[i]);\n    }\n    for (i = 0; i < 24; i++) {\n        mixedPieces[i] = regexEscape(mixedPieces[i]);\n    }\n\n    this._monthsRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i');\n    this._monthsShortRegex = this._monthsRegex;\n    this._monthsStrictRegex = new RegExp('^(' + longPieces.join('|') + ')', 'i');\n    this._monthsShortStrictRegex = new RegExp('^(' + shortPieces.join('|') + ')', 'i');\n}\n\n// FORMATTING\n\naddFormatToken('Y', 0, 0, function () {\n    var y = this.year();\n    return y <= 9999 ? '' + y : '+' + y;\n});\n\naddFormatToken(0, ['YY', 2], 0, function () {\n    return this.year() % 100;\n});\n\naddFormatToken(0, ['YYYY',   4],       0, 'year');\naddFormatToken(0, ['YYYYY',  5],       0, 'year');\naddFormatToken(0, ['YYYYYY', 6, true], 0, 'year');\n\n// ALIASES\n\naddUnitAlias('year', 'y');\n\n// PRIORITIES\n\naddUnitPriority('year', 1);\n\n// PARSING\n\naddRegexToken('Y',      matchSigned);\naddRegexToken('YY',     match1to2, match2);\naddRegexToken('YYYY',   match1to4, match4);\naddRegexToken('YYYYY',  match1to6, match6);\naddRegexToken('YYYYYY', match1to6, match6);\n\naddParseToken(['YYYYY', 'YYYYYY'], YEAR);\naddParseToken('YYYY', function (input, array) {\n    array[YEAR] = input.length === 2 ? hooks.parseTwoDigitYear(input) : toInt(input);\n});\naddParseToken('YY', function (input, array) {\n    array[YEAR] = hooks.parseTwoDigitYear(input);\n});\naddParseToken('Y', function (input, array) {\n    array[YEAR] = parseInt(input, 10);\n});\n\n// HELPERS\n\nfunction daysInYear(year) {\n    return isLeapYear(year) ? 366 : 365;\n}\n\nfunction isLeapYear(year) {\n    return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;\n}\n\n// HOOKS\n\nhooks.parseTwoDigitYear = function (input) {\n    return toInt(input) + (toInt(input) > 68 ? 1900 : 2000);\n};\n\n// MOMENTS\n\nvar getSetYear = makeGetSet('FullYear', true);\n\nfunction getIsLeapYear () {\n    return isLeapYear(this.year());\n}\n\nfunction createDate (y, m, d, h, M, s, ms) {\n    //can't just apply() to create a date:\n    //http://stackoverflow.com/questions/181348/instantiating-a-javascript-object-by-calling-prototype-constructor-apply\n    var date = new Date(y, m, d, h, M, s, ms);\n\n    //the date constructor remaps years 0-99 to 1900-1999\n    if (y < 100 && y >= 0 && isFinite(date.getFullYear())) {\n        date.setFullYear(y);\n    }\n    return date;\n}\n\nfunction createUTCDate (y) {\n    var date = new Date(Date.UTC.apply(null, arguments));\n\n    //the Date.UTC function remaps years 0-99 to 1900-1999\n    if (y < 100 && y >= 0 && isFinite(date.getUTCFullYear())) {\n        date.setUTCFullYear(y);\n    }\n    return date;\n}\n\n// start-of-first-week - start-of-year\nfunction firstWeekOffset(year, dow, doy) {\n    var // first-week day -- which january is always in the first week (4 for iso, 1 for other)\n        fwd = 7 + dow - doy,\n        // first-week day local weekday -- which local weekday is fwd\n        fwdlw = (7 + createUTCDate(year, 0, fwd).getUTCDay() - dow) % 7;\n\n    return -fwdlw + fwd - 1;\n}\n\n//http://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday\nfunction dayOfYearFromWeeks(year, week, weekday, dow, doy) {\n    var localWeekday = (7 + weekday - dow) % 7,\n        weekOffset = firstWeekOffset(year, dow, doy),\n        dayOfYear = 1 + 7 * (week - 1) + localWeekday + weekOffset,\n        resYear, resDayOfYear;\n\n    if (dayOfYear <= 0) {\n        resYear = year - 1;\n        resDayOfYear = daysInYear(resYear) + dayOfYear;\n    } else if (dayOfYear > daysInYear(year)) {\n        resYear = year + 1;\n        resDayOfYear = dayOfYear - daysInYear(year);\n    } else {\n        resYear = year;\n        resDayOfYear = dayOfYear;\n    }\n\n    return {\n        year: resYear,\n        dayOfYear: resDayOfYear\n    };\n}\n\nfunction weekOfYear(mom, dow, doy) {\n    var weekOffset = firstWeekOffset(mom.year(), dow, doy),\n        week = Math.floor((mom.dayOfYear() - weekOffset - 1) / 7) + 1,\n        resWeek, resYear;\n\n    if (week < 1) {\n        resYear = mom.year() - 1;\n        resWeek = week + weeksInYear(resYear, dow, doy);\n    } else if (week > weeksInYear(mom.year(), dow, doy)) {\n        resWeek = week - weeksInYear(mom.year(), dow, doy);\n        resYear = mom.year() + 1;\n    } else {\n        resYear = mom.year();\n        resWeek = week;\n    }\n\n    return {\n        week: resWeek,\n        year: resYear\n    };\n}\n\nfunction weeksInYear(year, dow, doy) {\n    var weekOffset = firstWeekOffset(year, dow, doy),\n        weekOffsetNext = firstWeekOffset(year + 1, dow, doy);\n    return (daysInYear(year) - weekOffset + weekOffsetNext) / 7;\n}\n\n// FORMATTING\n\naddFormatToken('w', ['ww', 2], 'wo', 'week');\naddFormatToken('W', ['WW', 2], 'Wo', 'isoWeek');\n\n// ALIASES\n\naddUnitAlias('week', 'w');\naddUnitAlias('isoWeek', 'W');\n\n// PRIORITIES\n\naddUnitPriority('week', 5);\naddUnitPriority('isoWeek', 5);\n\n// PARSING\n\naddRegexToken('w',  match1to2);\naddRegexToken('ww', match1to2, match2);\naddRegexToken('W',  match1to2);\naddRegexToken('WW', match1to2, match2);\n\naddWeekParseToken(['w', 'ww', 'W', 'WW'], function (input, week, config, token) {\n    week[token.substr(0, 1)] = toInt(input);\n});\n\n// HELPERS\n\n// LOCALES\n\nfunction localeWeek (mom) {\n    return weekOfYear(mom, this._week.dow, this._week.doy).week;\n}\n\nvar defaultLocaleWeek = {\n    dow : 0, // Sunday is the first day of the week.\n    doy : 6  // The week that contains Jan 1st is the first week of the year.\n};\n\nfunction localeFirstDayOfWeek () {\n    return this._week.dow;\n}\n\nfunction localeFirstDayOfYear () {\n    return this._week.doy;\n}\n\n// MOMENTS\n\nfunction getSetWeek (input) {\n    var week = this.localeData().week(this);\n    return input == null ? week : this.add((input - week) * 7, 'd');\n}\n\nfunction getSetISOWeek (input) {\n    var week = weekOfYear(this, 1, 4).week;\n    return input == null ? week : this.add((input - week) * 7, 'd');\n}\n\n// FORMATTING\n\naddFormatToken('d', 0, 'do', 'day');\n\naddFormatToken('dd', 0, 0, function (format) {\n    return this.localeData().weekdaysMin(this, format);\n});\n\naddFormatToken('ddd', 0, 0, function (format) {\n    return this.localeData().weekdaysShort(this, format);\n});\n\naddFormatToken('dddd', 0, 0, function (format) {\n    return this.localeData().weekdays(this, format);\n});\n\naddFormatToken('e', 0, 0, 'weekday');\naddFormatToken('E', 0, 0, 'isoWeekday');\n\n// ALIASES\n\naddUnitAlias('day', 'd');\naddUnitAlias('weekday', 'e');\naddUnitAlias('isoWeekday', 'E');\n\n// PRIORITY\naddUnitPriority('day', 11);\naddUnitPriority('weekday', 11);\naddUnitPriority('isoWeekday', 11);\n\n// PARSING\n\naddRegexToken('d',    match1to2);\naddRegexToken('e',    match1to2);\naddRegexToken('E',    match1to2);\naddRegexToken('dd',   function (isStrict, locale) {\n    return locale.weekdaysMinRegex(isStrict);\n});\naddRegexToken('ddd',   function (isStrict, locale) {\n    return locale.weekdaysShortRegex(isStrict);\n});\naddRegexToken('dddd',   function (isStrict, locale) {\n    return locale.weekdaysRegex(isStrict);\n});\n\naddWeekParseToken(['dd', 'ddd', 'dddd'], function (input, week, config, token) {\n    var weekday = config._locale.weekdaysParse(input, token, config._strict);\n    // if we didn't get a weekday name, mark the date as invalid\n    if (weekday != null) {\n        week.d = weekday;\n    } else {\n        getParsingFlags(config).invalidWeekday = input;\n    }\n});\n\naddWeekParseToken(['d', 'e', 'E'], function (input, week, config, token) {\n    week[token] = toInt(input);\n});\n\n// HELPERS\n\nfunction parseWeekday(input, locale) {\n    if (typeof input !== 'string') {\n        return input;\n    }\n\n    if (!isNaN(input)) {\n        return parseInt(input, 10);\n    }\n\n    input = locale.weekdaysParse(input);\n    if (typeof input === 'number') {\n        return input;\n    }\n\n    return null;\n}\n\nfunction parseIsoWeekday(input, locale) {\n    if (typeof input === 'string') {\n        return locale.weekdaysParse(input) % 7 || 7;\n    }\n    return isNaN(input) ? null : input;\n}\n\n// LOCALES\n\nvar defaultLocaleWeekdays = 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_');\nfunction localeWeekdays (m, format) {\n    if (!m) {\n        return this._weekdays;\n    }\n    return isArray(this._weekdays) ? this._weekdays[m.day()] :\n        this._weekdays[this._weekdays.isFormat.test(format) ? 'format' : 'standalone'][m.day()];\n}\n\nvar defaultLocaleWeekdaysShort = 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_');\nfunction localeWeekdaysShort (m) {\n    return (m) ? this._weekdaysShort[m.day()] : this._weekdaysShort;\n}\n\nvar defaultLocaleWeekdaysMin = 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_');\nfunction localeWeekdaysMin (m) {\n    return (m) ? this._weekdaysMin[m.day()] : this._weekdaysMin;\n}\n\nfunction handleStrictParse$1(weekdayName, format, strict) {\n    var i, ii, mom, llc = weekdayName.toLocaleLowerCase();\n    if (!this._weekdaysParse) {\n        this._weekdaysParse = [];\n        this._shortWeekdaysParse = [];\n        this._minWeekdaysParse = [];\n\n        for (i = 0; i < 7; ++i) {\n            mom = createUTC([2000, 1]).day(i);\n            this._minWeekdaysParse[i] = this.weekdaysMin(mom, '').toLocaleLowerCase();\n            this._shortWeekdaysParse[i] = this.weekdaysShort(mom, '').toLocaleLowerCase();\n            this._weekdaysParse[i] = this.weekdays(mom, '').toLocaleLowerCase();\n        }\n    }\n\n    if (strict) {\n        if (format === 'dddd') {\n            ii = indexOf$1.call(this._weekdaysParse, llc);\n            return ii !== -1 ? ii : null;\n        } else if (format === 'ddd') {\n            ii = indexOf$1.call(this._shortWeekdaysParse, llc);\n            return ii !== -1 ? ii : null;\n        } else {\n            ii = indexOf$1.call(this._minWeekdaysParse, llc);\n            return ii !== -1 ? ii : null;\n        }\n    } else {\n        if (format === 'dddd') {\n            ii = indexOf$1.call(this._weekdaysParse, llc);\n            if (ii !== -1) {\n                return ii;\n            }\n            ii = indexOf$1.call(this._shortWeekdaysParse, llc);\n            if (ii !== -1) {\n                return ii;\n            }\n            ii = indexOf$1.call(this._minWeekdaysParse, llc);\n            return ii !== -1 ? ii : null;\n        } else if (format === 'ddd') {\n            ii = indexOf$1.call(this._shortWeekdaysParse, llc);\n            if (ii !== -1) {\n                return ii;\n            }\n            ii = indexOf$1.call(this._weekdaysParse, llc);\n            if (ii !== -1) {\n                return ii;\n            }\n            ii = indexOf$1.call(this._minWeekdaysParse, llc);\n            return ii !== -1 ? ii : null;\n        } else {\n            ii = indexOf$1.call(this._minWeekdaysParse, llc);\n            if (ii !== -1) {\n                return ii;\n            }\n            ii = indexOf$1.call(this._weekdaysParse, llc);\n            if (ii !== -1) {\n                return ii;\n            }\n            ii = indexOf$1.call(this._shortWeekdaysParse, llc);\n            return ii !== -1 ? ii : null;\n        }\n    }\n}\n\nfunction localeWeekdaysParse (weekdayName, format, strict) {\n    var i, mom, regex;\n\n    if (this._weekdaysParseExact) {\n        return handleStrictParse$1.call(this, weekdayName, format, strict);\n    }\n\n    if (!this._weekdaysParse) {\n        this._weekdaysParse = [];\n        this._minWeekdaysParse = [];\n        this._shortWeekdaysParse = [];\n        this._fullWeekdaysParse = [];\n    }\n\n    for (i = 0; i < 7; i++) {\n        // make the regex if we don't have it already\n\n        mom = createUTC([2000, 1]).day(i);\n        if (strict && !this._fullWeekdaysParse[i]) {\n            this._fullWeekdaysParse[i] = new RegExp('^' + this.weekdays(mom, '').replace('.', '\\.?') + '$', 'i');\n            this._shortWeekdaysParse[i] = new RegExp('^' + this.weekdaysShort(mom, '').replace('.', '\\.?') + '$', 'i');\n            this._minWeekdaysParse[i] = new RegExp('^' + this.weekdaysMin(mom, '').replace('.', '\\.?') + '$', 'i');\n        }\n        if (!this._weekdaysParse[i]) {\n            regex = '^' + this.weekdays(mom, '') + '|^' + this.weekdaysShort(mom, '') + '|^' + this.weekdaysMin(mom, '');\n            this._weekdaysParse[i] = new RegExp(regex.replace('.', ''), 'i');\n        }\n        // test the regex\n        if (strict && format === 'dddd' && this._fullWeekdaysParse[i].test(weekdayName)) {\n            return i;\n        } else if (strict && format === 'ddd' && this._shortWeekdaysParse[i].test(weekdayName)) {\n            return i;\n        } else if (strict && format === 'dd' && this._minWeekdaysParse[i].test(weekdayName)) {\n            return i;\n        } else if (!strict && this._weekdaysParse[i].test(weekdayName)) {\n            return i;\n        }\n    }\n}\n\n// MOMENTS\n\nfunction getSetDayOfWeek (input) {\n    if (!this.isValid()) {\n        return input != null ? this : NaN;\n    }\n    var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay();\n    if (input != null) {\n        input = parseWeekday(input, this.localeData());\n        return this.add(input - day, 'd');\n    } else {\n        return day;\n    }\n}\n\nfunction getSetLocaleDayOfWeek (input) {\n    if (!this.isValid()) {\n        return input != null ? this : NaN;\n    }\n    var weekday = (this.day() + 7 - this.localeData()._week.dow) % 7;\n    return input == null ? weekday : this.add(input - weekday, 'd');\n}\n\nfunction getSetISODayOfWeek (input) {\n    if (!this.isValid()) {\n        return input != null ? this : NaN;\n    }\n\n    // behaves the same as moment#day except\n    // as a getter, returns 7 instead of 0 (1-7 range instead of 0-6)\n    // as a setter, sunday should belong to the previous week.\n\n    if (input != null) {\n        var weekday = parseIsoWeekday(input, this.localeData());\n        return this.day(this.day() % 7 ? weekday : weekday - 7);\n    } else {\n        return this.day() || 7;\n    }\n}\n\nvar defaultWeekdaysRegex = matchWord;\nfunction weekdaysRegex (isStrict) {\n    if (this._weekdaysParseExact) {\n        if (!hasOwnProp(this, '_weekdaysRegex')) {\n            computeWeekdaysParse.call(this);\n        }\n        if (isStrict) {\n            return this._weekdaysStrictRegex;\n        } else {\n            return this._weekdaysRegex;\n        }\n    } else {\n        if (!hasOwnProp(this, '_weekdaysRegex')) {\n            this._weekdaysRegex = defaultWeekdaysRegex;\n        }\n        return this._weekdaysStrictRegex && isStrict ?\n            this._weekdaysStrictRegex : this._weekdaysRegex;\n    }\n}\n\nvar defaultWeekdaysShortRegex = matchWord;\nfunction weekdaysShortRegex (isStrict) {\n    if (this._weekdaysParseExact) {\n        if (!hasOwnProp(this, '_weekdaysRegex')) {\n            computeWeekdaysParse.call(this);\n        }\n        if (isStrict) {\n            return this._weekdaysShortStrictRegex;\n        } else {\n            return this._weekdaysShortRegex;\n        }\n    } else {\n        if (!hasOwnProp(this, '_weekdaysShortRegex')) {\n            this._weekdaysShortRegex = defaultWeekdaysShortRegex;\n        }\n        return this._weekdaysShortStrictRegex && isStrict ?\n            this._weekdaysShortStrictRegex : this._weekdaysShortRegex;\n    }\n}\n\nvar defaultWeekdaysMinRegex = matchWord;\nfunction weekdaysMinRegex (isStrict) {\n    if (this._weekdaysParseExact) {\n        if (!hasOwnProp(this, '_weekdaysRegex')) {\n            computeWeekdaysParse.call(this);\n        }\n        if (isStrict) {\n            return this._weekdaysMinStrictRegex;\n        } else {\n            return this._weekdaysMinRegex;\n        }\n    } else {\n        if (!hasOwnProp(this, '_weekdaysMinRegex')) {\n            this._weekdaysMinRegex = defaultWeekdaysMinRegex;\n        }\n        return this._weekdaysMinStrictRegex && isStrict ?\n            this._weekdaysMinStrictRegex : this._weekdaysMinRegex;\n    }\n}\n\n\nfunction computeWeekdaysParse () {\n    function cmpLenRev(a, b) {\n        return b.length - a.length;\n    }\n\n    var minPieces = [], shortPieces = [], longPieces = [], mixedPieces = [],\n        i, mom, minp, shortp, longp;\n    for (i = 0; i < 7; i++) {\n        // make the regex if we don't have it already\n        mom = createUTC([2000, 1]).day(i);\n        minp = this.weekdaysMin(mom, '');\n        shortp = this.weekdaysShort(mom, '');\n        longp = this.weekdays(mom, '');\n        minPieces.push(minp);\n        shortPieces.push(shortp);\n        longPieces.push(longp);\n        mixedPieces.push(minp);\n        mixedPieces.push(shortp);\n        mixedPieces.push(longp);\n    }\n    // Sorting makes sure if one weekday (or abbr) is a prefix of another it\n    // will match the longer piece.\n    minPieces.sort(cmpLenRev);\n    shortPieces.sort(cmpLenRev);\n    longPieces.sort(cmpLenRev);\n    mixedPieces.sort(cmpLenRev);\n    for (i = 0; i < 7; i++) {\n        shortPieces[i] = regexEscape(shortPieces[i]);\n        longPieces[i] = regexEscape(longPieces[i]);\n        mixedPieces[i] = regexEscape(mixedPieces[i]);\n    }\n\n    this._weekdaysRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i');\n    this._weekdaysShortRegex = this._weekdaysRegex;\n    this._weekdaysMinRegex = this._weekdaysRegex;\n\n    this._weekdaysStrictRegex = new RegExp('^(' + longPieces.join('|') + ')', 'i');\n    this._weekdaysShortStrictRegex = new RegExp('^(' + shortPieces.join('|') + ')', 'i');\n    this._weekdaysMinStrictRegex = new RegExp('^(' + minPieces.join('|') + ')', 'i');\n}\n\n// FORMATTING\n\nfunction hFormat() {\n    return this.hours() % 12 || 12;\n}\n\nfunction kFormat() {\n    return this.hours() || 24;\n}\n\naddFormatToken('H', ['HH', 2], 0, 'hour');\naddFormatToken('h', ['hh', 2], 0, hFormat);\naddFormatToken('k', ['kk', 2], 0, kFormat);\n\naddFormatToken('hmm', 0, 0, function () {\n    return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2);\n});\n\naddFormatToken('hmmss', 0, 0, function () {\n    return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2) +\n        zeroFill(this.seconds(), 2);\n});\n\naddFormatToken('Hmm', 0, 0, function () {\n    return '' + this.hours() + zeroFill(this.minutes(), 2);\n});\n\naddFormatToken('Hmmss', 0, 0, function () {\n    return '' + this.hours() + zeroFill(this.minutes(), 2) +\n        zeroFill(this.seconds(), 2);\n});\n\nfunction meridiem (token, lowercase) {\n    addFormatToken(token, 0, 0, function () {\n        return this.localeData().meridiem(this.hours(), this.minutes(), lowercase);\n    });\n}\n\nmeridiem('a', true);\nmeridiem('A', false);\n\n// ALIASES\n\naddUnitAlias('hour', 'h');\n\n// PRIORITY\naddUnitPriority('hour', 13);\n\n// PARSING\n\nfunction matchMeridiem (isStrict, locale) {\n    return locale._meridiemParse;\n}\n\naddRegexToken('a',  matchMeridiem);\naddRegexToken('A',  matchMeridiem);\naddRegexToken('H',  match1to2);\naddRegexToken('h',  match1to2);\naddRegexToken('HH', match1to2, match2);\naddRegexToken('hh', match1to2, match2);\n\naddRegexToken('hmm', match3to4);\naddRegexToken('hmmss', match5to6);\naddRegexToken('Hmm', match3to4);\naddRegexToken('Hmmss', match5to6);\n\naddParseToken(['H', 'HH'], HOUR);\naddParseToken(['a', 'A'], function (input, array, config) {\n    config._isPm = config._locale.isPM(input);\n    config._meridiem = input;\n});\naddParseToken(['h', 'hh'], function (input, array, config) {\n    array[HOUR] = toInt(input);\n    getParsingFlags(config).bigHour = true;\n});\naddParseToken('hmm', function (input, array, config) {\n    var pos = input.length - 2;\n    array[HOUR] = toInt(input.substr(0, pos));\n    array[MINUTE] = toInt(input.substr(pos));\n    getParsingFlags(config).bigHour = true;\n});\naddParseToken('hmmss', function (input, array, config) {\n    var pos1 = input.length - 4;\n    var pos2 = input.length - 2;\n    array[HOUR] = toInt(input.substr(0, pos1));\n    array[MINUTE] = toInt(input.substr(pos1, 2));\n    array[SECOND] = toInt(input.substr(pos2));\n    getParsingFlags(config).bigHour = true;\n});\naddParseToken('Hmm', function (input, array, config) {\n    var pos = input.length - 2;\n    array[HOUR] = toInt(input.substr(0, pos));\n    array[MINUTE] = toInt(input.substr(pos));\n});\naddParseToken('Hmmss', function (input, array, config) {\n    var pos1 = input.length - 4;\n    var pos2 = input.length - 2;\n    array[HOUR] = toInt(input.substr(0, pos1));\n    array[MINUTE] = toInt(input.substr(pos1, 2));\n    array[SECOND] = toInt(input.substr(pos2));\n});\n\n// LOCALES\n\nfunction localeIsPM (input) {\n    // IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays\n    // Using charAt should be more compatible.\n    return ((input + '').toLowerCase().charAt(0) === 'p');\n}\n\nvar defaultLocaleMeridiemParse = /[ap]\\.?m?\\.?/i;\nfunction localeMeridiem (hours, minutes, isLower) {\n    if (hours > 11) {\n        return isLower ? 'pm' : 'PM';\n    } else {\n        return isLower ? 'am' : 'AM';\n    }\n}\n\n\n// MOMENTS\n\n// Setting the hour should keep the time, because the user explicitly\n// specified which hour he wants. So trying to maintain the same hour (in\n// a new timezone) makes sense. Adding/subtracting hours does not follow\n// this rule.\nvar getSetHour = makeGetSet('Hours', true);\n\n// months\n// week\n// weekdays\n// meridiem\nvar baseConfig = {\n    calendar: defaultCalendar,\n    longDateFormat: defaultLongDateFormat,\n    invalidDate: defaultInvalidDate,\n    ordinal: defaultOrdinal,\n    ordinalParse: defaultOrdinalParse,\n    relativeTime: defaultRelativeTime,\n\n    months: defaultLocaleMonths,\n    monthsShort: defaultLocaleMonthsShort,\n\n    week: defaultLocaleWeek,\n\n    weekdays: defaultLocaleWeekdays,\n    weekdaysMin: defaultLocaleWeekdaysMin,\n    weekdaysShort: defaultLocaleWeekdaysShort,\n\n    meridiemParse: defaultLocaleMeridiemParse\n};\n\n// internal storage for locale config files\nvar locales = {};\nvar localeFamilies = {};\nvar globalLocale;\n\nfunction normalizeLocale(key) {\n    return key ? key.toLowerCase().replace('_', '-') : key;\n}\n\n// pick the locale from the array\n// try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each\n// substring from most specific to least, but move to the next array item if it's a more specific variant than the current root\nfunction chooseLocale(names) {\n    var i = 0, j, next, locale, split;\n\n    while (i < names.length) {\n        split = normalizeLocale(names[i]).split('-');\n        j = split.length;\n        next = normalizeLocale(names[i + 1]);\n        next = next ? next.split('-') : null;\n        while (j > 0) {\n            locale = loadLocale(split.slice(0, j).join('-'));\n            if (locale) {\n                return locale;\n            }\n            if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) {\n                //the next array item is better than a shallower substring of this one\n                break;\n            }\n            j--;\n        }\n        i++;\n    }\n    return null;\n}\n\nfunction loadLocale(name) {\n    var oldLocale = null;\n    // TODO: Find a better way to register and load all the locales in Node\n    if (!locales[name] && (typeof module !== 'undefined') &&\n            module && module.exports) {\n        try {\n            oldLocale = globalLocale._abbr;\n            require('./locale/' + name);\n            // because defineLocale currently also sets the global locale, we\n            // want to undo that for lazy loaded locales\n            getSetGlobalLocale(oldLocale);\n        } catch (e) { }\n    }\n    return locales[name];\n}\n\n// This function will load locale and then set the global locale.  If\n// no arguments are passed in, it will simply return the current global\n// locale key.\nfunction getSetGlobalLocale (key, values) {\n    var data;\n    if (key) {\n        if (isUndefined(values)) {\n            data = getLocale(key);\n        }\n        else {\n            data = defineLocale(key, values);\n        }\n\n        if (data) {\n            // moment.duration._locale = moment._locale = data;\n            globalLocale = data;\n        }\n    }\n\n    return globalLocale._abbr;\n}\n\nfunction defineLocale (name, config) {\n    if (config !== null) {\n        var parentConfig = baseConfig;\n        config.abbr = name;\n        if (locales[name] != null) {\n            deprecateSimple('defineLocaleOverride',\n                    'use moment.updateLocale(localeName, config) to change ' +\n                    'an existing locale. moment.defineLocale(localeName, ' +\n                    'config) should only be used for creating a new locale ' +\n                    'See http://momentjs.com/guides/#/warnings/define-locale/ for more info.');\n            parentConfig = locales[name]._config;\n        } else if (config.parentLocale != null) {\n            if (locales[config.parentLocale] != null) {\n                parentConfig = locales[config.parentLocale]._config;\n            } else {\n                if (!localeFamilies[config.parentLocale]) {\n                    localeFamilies[config.parentLocale] = [];\n                }\n                localeFamilies[config.parentLocale].push({\n                    name: name,\n                    config: config\n                });\n                return null;\n            }\n        }\n        locales[name] = new Locale(mergeConfigs(parentConfig, config));\n\n        if (localeFamilies[name]) {\n            localeFamilies[name].forEach(function (x) {\n                defineLocale(x.name, x.config);\n            });\n        }\n\n        // backwards compat for now: also set the locale\n        // make sure we set the locale AFTER all child locales have been\n        // created, so we won't end up with the child locale set.\n        getSetGlobalLocale(name);\n\n\n        return locales[name];\n    } else {\n        // useful for testing\n        delete locales[name];\n        return null;\n    }\n}\n\nfunction updateLocale(name, config) {\n    if (config != null) {\n        var locale, parentConfig = baseConfig;\n        // MERGE\n        if (locales[name] != null) {\n            parentConfig = locales[name]._config;\n        }\n        config = mergeConfigs(parentConfig, config);\n        locale = new Locale(config);\n        locale.parentLocale = locales[name];\n        locales[name] = locale;\n\n        // backwards compat for now: also set the locale\n        getSetGlobalLocale(name);\n    } else {\n        // pass null for config to unupdate, useful for tests\n        if (locales[name] != null) {\n            if (locales[name].parentLocale != null) {\n                locales[name] = locales[name].parentLocale;\n            } else if (locales[name] != null) {\n                delete locales[name];\n            }\n        }\n    }\n    return locales[name];\n}\n\n// returns locale data\nfunction getLocale (key) {\n    var locale;\n\n    if (key && key._locale && key._locale._abbr) {\n        key = key._locale._abbr;\n    }\n\n    if (!key) {\n        return globalLocale;\n    }\n\n    if (!isArray(key)) {\n        //short-circuit everything else\n        locale = loadLocale(key);\n        if (locale) {\n            return locale;\n        }\n        key = [key];\n    }\n\n    return chooseLocale(key);\n}\n\nfunction listLocales() {\n    return keys$1(locales);\n}\n\nfunction checkOverflow (m) {\n    var overflow;\n    var a = m._a;\n\n    if (a && getParsingFlags(m).overflow === -2) {\n        overflow =\n            a[MONTH]       < 0 || a[MONTH]       > 11  ? MONTH :\n            a[DATE]        < 1 || a[DATE]        > daysInMonth(a[YEAR], a[MONTH]) ? DATE :\n            a[HOUR]        < 0 || a[HOUR]        > 24 || (a[HOUR] === 24 && (a[MINUTE] !== 0 || a[SECOND] !== 0 || a[MILLISECOND] !== 0)) ? HOUR :\n            a[MINUTE]      < 0 || a[MINUTE]      > 59  ? MINUTE :\n            a[SECOND]      < 0 || a[SECOND]      > 59  ? SECOND :\n            a[MILLISECOND] < 0 || a[MILLISECOND] > 999 ? MILLISECOND :\n            -1;\n\n        if (getParsingFlags(m)._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) {\n            overflow = DATE;\n        }\n        if (getParsingFlags(m)._overflowWeeks && overflow === -1) {\n            overflow = WEEK;\n        }\n        if (getParsingFlags(m)._overflowWeekday && overflow === -1) {\n            overflow = WEEKDAY;\n        }\n\n        getParsingFlags(m).overflow = overflow;\n    }\n\n    return m;\n}\n\n// iso 8601 regex\n// 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)\nvar 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)?)?$/;\nvar 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)?)?$/;\n\nvar tzRegex = /Z|[+-]\\d\\d(?::?\\d\\d)?/;\n\nvar isoDates = [\n    ['YYYYYY-MM-DD', /[+-]\\d{6}-\\d\\d-\\d\\d/],\n    ['YYYY-MM-DD', /\\d{4}-\\d\\d-\\d\\d/],\n    ['GGGG-[W]WW-E', /\\d{4}-W\\d\\d-\\d/],\n    ['GGGG-[W]WW', /\\d{4}-W\\d\\d/, false],\n    ['YYYY-DDD', /\\d{4}-\\d{3}/],\n    ['YYYY-MM', /\\d{4}-\\d\\d/, false],\n    ['YYYYYYMMDD', /[+-]\\d{10}/],\n    ['YYYYMMDD', /\\d{8}/],\n    // YYYYMM is NOT allowed by the standard\n    ['GGGG[W]WWE', /\\d{4}W\\d{3}/],\n    ['GGGG[W]WW', /\\d{4}W\\d{2}/, false],\n    ['YYYYDDD', /\\d{7}/]\n];\n\n// iso time formats and regexes\nvar isoTimes = [\n    ['HH:mm:ss.SSSS', /\\d\\d:\\d\\d:\\d\\d\\.\\d+/],\n    ['HH:mm:ss,SSSS', /\\d\\d:\\d\\d:\\d\\d,\\d+/],\n    ['HH:mm:ss', /\\d\\d:\\d\\d:\\d\\d/],\n    ['HH:mm', /\\d\\d:\\d\\d/],\n    ['HHmmss.SSSS', /\\d\\d\\d\\d\\d\\d\\.\\d+/],\n    ['HHmmss,SSSS', /\\d\\d\\d\\d\\d\\d,\\d+/],\n    ['HHmmss', /\\d\\d\\d\\d\\d\\d/],\n    ['HHmm', /\\d\\d\\d\\d/],\n    ['HH', /\\d\\d/]\n];\n\nvar aspNetJsonRegex = /^\\/?Date\\((\\-?\\d+)/i;\n\n// date from iso format\nfunction configFromISO(config) {\n    var i, l,\n        string = config._i,\n        match = extendedIsoRegex.exec(string) || basicIsoRegex.exec(string),\n        allowTime, dateFormat, timeFormat, tzFormat;\n\n    if (match) {\n        getParsingFlags(config).iso = true;\n\n        for (i = 0, l = isoDates.length; i < l; i++) {\n            if (isoDates[i][1].exec(match[1])) {\n                dateFormat = isoDates[i][0];\n                allowTime = isoDates[i][2] !== false;\n                break;\n            }\n        }\n        if (dateFormat == null) {\n            config._isValid = false;\n            return;\n        }\n        if (match[3]) {\n            for (i = 0, l = isoTimes.length; i < l; i++) {\n                if (isoTimes[i][1].exec(match[3])) {\n                    // match[2] should be 'T' or space\n                    timeFormat = (match[2] || ' ') + isoTimes[i][0];\n                    break;\n                }\n            }\n            if (timeFormat == null) {\n                config._isValid = false;\n                return;\n            }\n        }\n        if (!allowTime && timeFormat != null) {\n            config._isValid = false;\n            return;\n        }\n        if (match[4]) {\n            if (tzRegex.exec(match[4])) {\n                tzFormat = 'Z';\n            } else {\n                config._isValid = false;\n                return;\n            }\n        }\n        config._f = dateFormat + (timeFormat || '') + (tzFormat || '');\n        configFromStringAndFormat(config);\n    } else {\n        config._isValid = false;\n    }\n}\n\n// date from iso format or fallback\nfunction configFromString(config) {\n    var matched = aspNetJsonRegex.exec(config._i);\n\n    if (matched !== null) {\n        config._d = new Date(+matched[1]);\n        return;\n    }\n\n    configFromISO(config);\n    if (config._isValid === false) {\n        delete config._isValid;\n        hooks.createFromInputFallback(config);\n    }\n}\n\nhooks.createFromInputFallback = deprecate(\n    'value provided is not in a recognized ISO format. moment construction falls back to js Date(), ' +\n    'which is not reliable across all browsers and versions. Non ISO date formats are ' +\n    'discouraged and will be removed in an upcoming major release. Please refer to ' +\n    'http://momentjs.com/guides/#/warnings/js-date/ for more info.',\n    function (config) {\n        config._d = new Date(config._i + (config._useUTC ? ' UTC' : ''));\n    }\n);\n\n// Pick the first defined of two or three arguments.\nfunction defaults(a, b, c) {\n    if (a != null) {\n        return a;\n    }\n    if (b != null) {\n        return b;\n    }\n    return c;\n}\n\nfunction currentDateArray(config) {\n    // hooks is actually the exported moment object\n    var nowValue = new Date(hooks.now());\n    if (config._useUTC) {\n        return [nowValue.getUTCFullYear(), nowValue.getUTCMonth(), nowValue.getUTCDate()];\n    }\n    return [nowValue.getFullYear(), nowValue.getMonth(), nowValue.getDate()];\n}\n\n// convert an array to a date.\n// the array should mirror the parameters below\n// note: all values past the year are optional and will default to the lowest possible value.\n// [year, month, day , hour, minute, second, millisecond]\nfunction configFromArray (config) {\n    var i, date, input = [], currentDate, yearToUse;\n\n    if (config._d) {\n        return;\n    }\n\n    currentDate = currentDateArray(config);\n\n    //compute day of the year from weeks and weekdays\n    if (config._w && config._a[DATE] == null && config._a[MONTH] == null) {\n        dayOfYearFromWeekInfo(config);\n    }\n\n    //if the day of the year is set, figure out what it is\n    if (config._dayOfYear) {\n        yearToUse = defaults(config._a[YEAR], currentDate[YEAR]);\n\n        if (config._dayOfYear > daysInYear(yearToUse)) {\n            getParsingFlags(config)._overflowDayOfYear = true;\n        }\n\n        date = createUTCDate(yearToUse, 0, config._dayOfYear);\n        config._a[MONTH] = date.getUTCMonth();\n        config._a[DATE] = date.getUTCDate();\n    }\n\n    // Default to current date.\n    // * if no year, month, day of month are given, default to today\n    // * if day of month is given, default month and year\n    // * if month is given, default only year\n    // * if year is given, don't default anything\n    for (i = 0; i < 3 && config._a[i] == null; ++i) {\n        config._a[i] = input[i] = currentDate[i];\n    }\n\n    // Zero out whatever was not defaulted, including time\n    for (; i < 7; i++) {\n        config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i];\n    }\n\n    // Check for 24:00:00.000\n    if (config._a[HOUR] === 24 &&\n            config._a[MINUTE] === 0 &&\n            config._a[SECOND] === 0 &&\n            config._a[MILLISECOND] === 0) {\n        config._nextDay = true;\n        config._a[HOUR] = 0;\n    }\n\n    config._d = (config._useUTC ? createUTCDate : createDate).apply(null, input);\n    // Apply timezone offset from input. The actual utcOffset can be changed\n    // with parseZone.\n    if (config._tzm != null) {\n        config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm);\n    }\n\n    if (config._nextDay) {\n        config._a[HOUR] = 24;\n    }\n}\n\nfunction dayOfYearFromWeekInfo(config) {\n    var w, weekYear, week, weekday, dow, doy, temp, weekdayOverflow;\n\n    w = config._w;\n    if (w.GG != null || w.W != null || w.E != null) {\n        dow = 1;\n        doy = 4;\n\n        // TODO: We need to take the current isoWeekYear, but that depends on\n        // how we interpret now (local, utc, fixed offset). So create\n        // a now version of current config (take local/utc/offset flags, and\n        // create now).\n        weekYear = defaults(w.GG, config._a[YEAR], weekOfYear(createLocal(), 1, 4).year);\n        week = defaults(w.W, 1);\n        weekday = defaults(w.E, 1);\n        if (weekday < 1 || weekday > 7) {\n            weekdayOverflow = true;\n        }\n    } else {\n        dow = config._locale._week.dow;\n        doy = config._locale._week.doy;\n\n        var curWeek = weekOfYear(createLocal(), dow, doy);\n\n        weekYear = defaults(w.gg, config._a[YEAR], curWeek.year);\n\n        // Default to current week.\n        week = defaults(w.w, curWeek.week);\n\n        if (w.d != null) {\n            // weekday -- low day numbers are considered next week\n            weekday = w.d;\n            if (weekday < 0 || weekday > 6) {\n                weekdayOverflow = true;\n            }\n        } else if (w.e != null) {\n            // local weekday -- counting starts from beginning of week\n            weekday = w.e + dow;\n            if (w.e < 0 || w.e > 6) {\n                weekdayOverflow = true;\n            }\n        } else {\n            // default to beginning of week\n            weekday = dow;\n        }\n    }\n    if (week < 1 || week > weeksInYear(weekYear, dow, doy)) {\n        getParsingFlags(config)._overflowWeeks = true;\n    } else if (weekdayOverflow != null) {\n        getParsingFlags(config)._overflowWeekday = true;\n    } else {\n        temp = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy);\n        config._a[YEAR] = temp.year;\n        config._dayOfYear = temp.dayOfYear;\n    }\n}\n\n// constant that refers to the ISO standard\nhooks.ISO_8601 = function () {};\n\n// date from string and format string\nfunction configFromStringAndFormat(config) {\n    // TODO: Move this to another part of the creation flow to prevent circular deps\n    if (config._f === hooks.ISO_8601) {\n        configFromISO(config);\n        return;\n    }\n\n    config._a = [];\n    getParsingFlags(config).empty = true;\n\n    // This array is used to make a Date, either with `new Date` or `Date.UTC`\n    var string = '' + config._i,\n        i, parsedInput, tokens, token, skipped,\n        stringLength = string.length,\n        totalParsedInputLength = 0;\n\n    tokens = expandFormat(config._f, config._locale).match(formattingTokens) || [];\n\n    for (i = 0; i < tokens.length; i++) {\n        token = tokens[i];\n        parsedInput = (string.match(getParseRegexForToken(token, config)) || [])[0];\n        // console.log('token', token, 'parsedInput', parsedInput,\n        //         'regex', getParseRegexForToken(token, config));\n        if (parsedInput) {\n            skipped = string.substr(0, string.indexOf(parsedInput));\n            if (skipped.length > 0) {\n                getParsingFlags(config).unusedInput.push(skipped);\n            }\n            string = string.slice(string.indexOf(parsedInput) + parsedInput.length);\n            totalParsedInputLength += parsedInput.length;\n        }\n        // don't parse if it's not a known token\n        if (formatTokenFunctions[token]) {\n            if (parsedInput) {\n                getParsingFlags(config).empty = false;\n            }\n            else {\n                getParsingFlags(config).unusedTokens.push(token);\n            }\n            addTimeToArrayFromToken(token, parsedInput, config);\n        }\n        else if (config._strict && !parsedInput) {\n            getParsingFlags(config).unusedTokens.push(token);\n        }\n    }\n\n    // add remaining unparsed input length to the string\n    getParsingFlags(config).charsLeftOver = stringLength - totalParsedInputLength;\n    if (string.length > 0) {\n        getParsingFlags(config).unusedInput.push(string);\n    }\n\n    // clear _12h flag if hour is <= 12\n    if (config._a[HOUR] <= 12 &&\n        getParsingFlags(config).bigHour === true &&\n        config._a[HOUR] > 0) {\n        getParsingFlags(config).bigHour = undefined;\n    }\n\n    getParsingFlags(config).parsedDateParts = config._a.slice(0);\n    getParsingFlags(config).meridiem = config._meridiem;\n    // handle meridiem\n    config._a[HOUR] = meridiemFixWrap(config._locale, config._a[HOUR], config._meridiem);\n\n    configFromArray(config);\n    checkOverflow(config);\n}\n\n\nfunction meridiemFixWrap (locale, hour, meridiem) {\n    var isPm;\n\n    if (meridiem == null) {\n        // nothing to do\n        return hour;\n    }\n    if (locale.meridiemHour != null) {\n        return locale.meridiemHour(hour, meridiem);\n    } else if (locale.isPM != null) {\n        // Fallback\n        isPm = locale.isPM(meridiem);\n        if (isPm && hour < 12) {\n            hour += 12;\n        }\n        if (!isPm && hour === 12) {\n            hour = 0;\n        }\n        return hour;\n    } else {\n        // this is not supposed to happen\n        return hour;\n    }\n}\n\n// date from string and array of format strings\nfunction configFromStringAndArray(config) {\n    var tempConfig,\n        bestMoment,\n\n        scoreToBeat,\n        i,\n        currentScore;\n\n    if (config._f.length === 0) {\n        getParsingFlags(config).invalidFormat = true;\n        config._d = new Date(NaN);\n        return;\n    }\n\n    for (i = 0; i < config._f.length; i++) {\n        currentScore = 0;\n        tempConfig = copyConfig({}, config);\n        if (config._useUTC != null) {\n            tempConfig._useUTC = config._useUTC;\n        }\n        tempConfig._f = config._f[i];\n        configFromStringAndFormat(tempConfig);\n\n        if (!isValid(tempConfig)) {\n            continue;\n        }\n\n        // if there is any input that was not parsed add a penalty for that format\n        currentScore += getParsingFlags(tempConfig).charsLeftOver;\n\n        //or tokens\n        currentScore += getParsingFlags(tempConfig).unusedTokens.length * 10;\n\n        getParsingFlags(tempConfig).score = currentScore;\n\n        if (scoreToBeat == null || currentScore < scoreToBeat) {\n            scoreToBeat = currentScore;\n            bestMoment = tempConfig;\n        }\n    }\n\n    extend(config, bestMoment || tempConfig);\n}\n\nfunction configFromObject(config) {\n    if (config._d) {\n        return;\n    }\n\n    var i = normalizeObjectUnits(config._i);\n    config._a = map([i.year, i.month, i.day || i.date, i.hour, i.minute, i.second, i.millisecond], function (obj) {\n        return obj && parseInt(obj, 10);\n    });\n\n    configFromArray(config);\n}\n\nfunction createFromConfig (config) {\n    var res = new Moment(checkOverflow(prepareConfig(config)));\n    if (res._nextDay) {\n        // Adding is smart enough around DST\n        res.add(1, 'd');\n        res._nextDay = undefined;\n    }\n\n    return res;\n}\n\nfunction prepareConfig (config) {\n    var input = config._i,\n        format = config._f;\n\n    config._locale = config._locale || getLocale(config._l);\n\n    if (input === null || (format === undefined && input === '')) {\n        return createInvalid({nullInput: true});\n    }\n\n    if (typeof input === 'string') {\n        config._i = input = config._locale.preparse(input);\n    }\n\n    if (isMoment(input)) {\n        return new Moment(checkOverflow(input));\n    } else if (isDate(input)) {\n        config._d = input;\n    } else if (isArray(format)) {\n        configFromStringAndArray(config);\n    } else if (format) {\n        configFromStringAndFormat(config);\n    }  else {\n        configFromInput(config);\n    }\n\n    if (!isValid(config)) {\n        config._d = null;\n    }\n\n    return config;\n}\n\nfunction configFromInput(config) {\n    var input = config._i;\n    if (input === undefined) {\n        config._d = new Date(hooks.now());\n    } else if (isDate(input)) {\n        config._d = new Date(input.valueOf());\n    } else if (typeof input === 'string') {\n        configFromString(config);\n    } else if (isArray(input)) {\n        config._a = map(input.slice(0), function (obj) {\n            return parseInt(obj, 10);\n        });\n        configFromArray(config);\n    } else if (typeof(input) === 'object') {\n        configFromObject(config);\n    } else if (isNumber(input)) {\n        // from milliseconds\n        config._d = new Date(input);\n    } else {\n        hooks.createFromInputFallback(config);\n    }\n}\n\nfunction createLocalOrUTC (input, format, locale, strict, isUTC) {\n    var c = {};\n\n    if (locale === true || locale === false) {\n        strict = locale;\n        locale = undefined;\n    }\n\n    if ((isObject(input) && isObjectEmpty(input)) ||\n            (isArray(input) && input.length === 0)) {\n        input = undefined;\n    }\n    // object construction must be done this way.\n    // https://github.com/moment/moment/issues/1423\n    c._isAMomentObject = true;\n    c._useUTC = c._isUTC = isUTC;\n    c._l = locale;\n    c._i = input;\n    c._f = format;\n    c._strict = strict;\n\n    return createFromConfig(c);\n}\n\nfunction createLocal (input, format, locale, strict) {\n    return createLocalOrUTC(input, format, locale, strict, false);\n}\n\nvar prototypeMin = deprecate(\n    'moment().min is deprecated, use moment.max instead. http://momentjs.com/guides/#/warnings/min-max/',\n    function () {\n        var other = createLocal.apply(null, arguments);\n        if (this.isValid() && other.isValid()) {\n            return other < this ? this : other;\n        } else {\n            return createInvalid();\n        }\n    }\n);\n\nvar prototypeMax = deprecate(\n    'moment().max is deprecated, use moment.min instead. http://momentjs.com/guides/#/warnings/min-max/',\n    function () {\n        var other = createLocal.apply(null, arguments);\n        if (this.isValid() && other.isValid()) {\n            return other > this ? this : other;\n        } else {\n            return createInvalid();\n        }\n    }\n);\n\n// Pick a moment m from moments so that m[fn](other) is true for all\n// other. This relies on the function fn to be transitive.\n//\n// moments should either be an array of moment objects or an array, whose\n// first element is an array of moment objects.\nfunction pickBy(fn, moments) {\n    var res, i;\n    if (moments.length === 1 && isArray(moments[0])) {\n        moments = moments[0];\n    }\n    if (!moments.length) {\n        return createLocal();\n    }\n    res = moments[0];\n    for (i = 1; i < moments.length; ++i) {\n        if (!moments[i].isValid() || moments[i][fn](res)) {\n            res = moments[i];\n        }\n    }\n    return res;\n}\n\n// TODO: Use [].sort instead?\nfunction min () {\n    var args = [].slice.call(arguments, 0);\n\n    return pickBy('isBefore', args);\n}\n\nfunction max () {\n    var args = [].slice.call(arguments, 0);\n\n    return pickBy('isAfter', args);\n}\n\nvar now = function () {\n    return Date.now ? Date.now() : +(new Date());\n};\n\nfunction Duration (duration) {\n    var normalizedInput = normalizeObjectUnits(duration),\n        years = normalizedInput.year || 0,\n        quarters = normalizedInput.quarter || 0,\n        months = normalizedInput.month || 0,\n        weeks = normalizedInput.week || 0,\n        days = normalizedInput.day || 0,\n        hours = normalizedInput.hour || 0,\n        minutes = normalizedInput.minute || 0,\n        seconds = normalizedInput.second || 0,\n        milliseconds = normalizedInput.millisecond || 0;\n\n    // representation for dateAddRemove\n    this._milliseconds = +milliseconds +\n        seconds * 1e3 + // 1000\n        minutes * 6e4 + // 1000 * 60\n        hours * 1000 * 60 * 60; //using 1000 * 60 * 60 instead of 36e5 to avoid floating point rounding errors https://github.com/moment/moment/issues/2978\n    // Because of dateAddRemove treats 24 hours as different from a\n    // day when working around DST, we need to store them separately\n    this._days = +days +\n        weeks * 7;\n    // It is impossible translate months into days without knowing\n    // which months you are are talking about, so we have to store\n    // it separately.\n    this._months = +months +\n        quarters * 3 +\n        years * 12;\n\n    this._data = {};\n\n    this._locale = getLocale();\n\n    this._bubble();\n}\n\nfunction isDuration (obj) {\n    return obj instanceof Duration;\n}\n\nfunction absRound (number) {\n    if (number < 0) {\n        return Math.round(-1 * number) * -1;\n    } else {\n        return Math.round(number);\n    }\n}\n\n// FORMATTING\n\nfunction offset (token, separator) {\n    addFormatToken(token, 0, 0, function () {\n        var offset = this.utcOffset();\n        var sign = '+';\n        if (offset < 0) {\n            offset = -offset;\n            sign = '-';\n        }\n        return sign + zeroFill(~~(offset / 60), 2) + separator + zeroFill(~~(offset) % 60, 2);\n    });\n}\n\noffset('Z', ':');\noffset('ZZ', '');\n\n// PARSING\n\naddRegexToken('Z',  matchShortOffset);\naddRegexToken('ZZ', matchShortOffset);\naddParseToken(['Z', 'ZZ'], function (input, array, config) {\n    config._useUTC = true;\n    config._tzm = offsetFromString(matchShortOffset, input);\n});\n\n// HELPERS\n\n// timezone chunker\n// '+10:00' > ['10',  '00']\n// '-1530'  > ['-15', '30']\nvar chunkOffset = /([\\+\\-]|\\d\\d)/gi;\n\nfunction offsetFromString(matcher, string) {\n    var matches = (string || '').match(matcher);\n\n    if (matches === null) {\n        return null;\n    }\n\n    var chunk   = matches[matches.length - 1] || [];\n    var parts   = (chunk + '').match(chunkOffset) || ['-', 0, 0];\n    var minutes = +(parts[1] * 60) + toInt(parts[2]);\n\n    return minutes === 0 ?\n      0 :\n      parts[0] === '+' ? minutes : -minutes;\n}\n\n// Return a moment from input, that is local/utc/zone equivalent to model.\nfunction cloneWithOffset(input, model) {\n    var res, diff;\n    if (model._isUTC) {\n        res = model.clone();\n        diff = (isMoment(input) || isDate(input) ? input.valueOf() : createLocal(input).valueOf()) - res.valueOf();\n        // Use low-level api, because this fn is low-level api.\n        res._d.setTime(res._d.valueOf() + diff);\n        hooks.updateOffset(res, false);\n        return res;\n    } else {\n        return createLocal(input).local();\n    }\n}\n\nfunction getDateOffset (m) {\n    // On Firefox.24 Date#getTimezoneOffset returns a floating point.\n    // https://github.com/moment/moment/pull/1871\n    return -Math.round(m._d.getTimezoneOffset() / 15) * 15;\n}\n\n// HOOKS\n\n// This function will be called whenever a moment is mutated.\n// It is intended to keep the offset in sync with the timezone.\nhooks.updateOffset = function () {};\n\n// MOMENTS\n\n// keepLocalTime = true means only change the timezone, without\n// affecting the local hour. So 5:31:26 +0300 --[utcOffset(2, true)]-->\n// 5:31:26 +0200 It is possible that 5:31:26 doesn't exist with offset\n// +0200, so we adjust the time as needed, to be valid.\n//\n// Keeping the time actually adds/subtracts (one hour)\n// from the actual represented time. That is why we call updateOffset\n// a second time. In case it wants us to change the offset again\n// _changeInProgress == true case, then we have to adjust, because\n// there is no such time in the given timezone.\nfunction getSetOffset (input, keepLocalTime) {\n    var offset = this._offset || 0,\n        localAdjust;\n    if (!this.isValid()) {\n        return input != null ? this : NaN;\n    }\n    if (input != null) {\n        if (typeof input === 'string') {\n            input = offsetFromString(matchShortOffset, input);\n            if (input === null) {\n                return this;\n            }\n        } else if (Math.abs(input) < 16) {\n            input = input * 60;\n        }\n        if (!this._isUTC && keepLocalTime) {\n            localAdjust = getDateOffset(this);\n        }\n        this._offset = input;\n        this._isUTC = true;\n        if (localAdjust != null) {\n            this.add(localAdjust, 'm');\n        }\n        if (offset !== input) {\n            if (!keepLocalTime || this._changeInProgress) {\n                addSubtract(this, createDuration(input - offset, 'm'), 1, false);\n            } else if (!this._changeInProgress) {\n                this._changeInProgress = true;\n                hooks.updateOffset(this, true);\n                this._changeInProgress = null;\n            }\n        }\n        return this;\n    } else {\n        return this._isUTC ? offset : getDateOffset(this);\n    }\n}\n\nfunction getSetZone (input, keepLocalTime) {\n    if (input != null) {\n        if (typeof input !== 'string') {\n            input = -input;\n        }\n\n        this.utcOffset(input, keepLocalTime);\n\n        return this;\n    } else {\n        return -this.utcOffset();\n    }\n}\n\nfunction setOffsetToUTC (keepLocalTime) {\n    return this.utcOffset(0, keepLocalTime);\n}\n\nfunction setOffsetToLocal (keepLocalTime) {\n    if (this._isUTC) {\n        this.utcOffset(0, keepLocalTime);\n        this._isUTC = false;\n\n        if (keepLocalTime) {\n            this.subtract(getDateOffset(this), 'm');\n        }\n    }\n    return this;\n}\n\nfunction setOffsetToParsedOffset () {\n    if (this._tzm != null) {\n        this.utcOffset(this._tzm);\n    } else if (typeof this._i === 'string') {\n        var tZone = offsetFromString(matchOffset, this._i);\n        if (tZone != null) {\n            this.utcOffset(tZone);\n        }\n        else {\n            this.utcOffset(0, true);\n        }\n    }\n    return this;\n}\n\nfunction hasAlignedHourOffset (input) {\n    if (!this.isValid()) {\n        return false;\n    }\n    input = input ? createLocal(input).utcOffset() : 0;\n\n    return (this.utcOffset() - input) % 60 === 0;\n}\n\nfunction isDaylightSavingTime () {\n    return (\n        this.utcOffset() > this.clone().month(0).utcOffset() ||\n        this.utcOffset() > this.clone().month(5).utcOffset()\n    );\n}\n\nfunction isDaylightSavingTimeShifted () {\n    if (!isUndefined(this._isDSTShifted)) {\n        return this._isDSTShifted;\n    }\n\n    var c = {};\n\n    copyConfig(c, this);\n    c = prepareConfig(c);\n\n    if (c._a) {\n        var other = c._isUTC ? createUTC(c._a) : createLocal(c._a);\n        this._isDSTShifted = this.isValid() &&\n            compareArrays(c._a, other.toArray()) > 0;\n    } else {\n        this._isDSTShifted = false;\n    }\n\n    return this._isDSTShifted;\n}\n\nfunction isLocal () {\n    return this.isValid() ? !this._isUTC : false;\n}\n\nfunction isUtcOffset () {\n    return this.isValid() ? this._isUTC : false;\n}\n\nfunction isUtc () {\n    return this.isValid() ? this._isUTC && this._offset === 0 : false;\n}\n\n// ASP.NET json date format regex\nvar aspNetRegex = /^(\\-)?(?:(\\d*)[. ])?(\\d+)\\:(\\d+)(?:\\:(\\d+)(\\.\\d*)?)?$/;\n\n// from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html\n// somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere\n// and further modified to allow for strings containing both week and day\nvar isoRegex = /^(-)?P(?:(-?[0-9,.]*)Y)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)W)?(?:(-?[0-9,.]*)D)?(?:T(?:(-?[0-9,.]*)H)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)S)?)?$/;\n\nfunction createDuration (input, key) {\n    var duration = input,\n        // matching against regexp is expensive, do it on demand\n        match = null,\n        sign,\n        ret,\n        diffRes;\n\n    if (isDuration(input)) {\n        duration = {\n            ms : input._milliseconds,\n            d  : input._days,\n            M  : input._months\n        };\n    } else if (isNumber(input)) {\n        duration = {};\n        if (key) {\n            duration[key] = input;\n        } else {\n            duration.milliseconds = input;\n        }\n    } else if (!!(match = aspNetRegex.exec(input))) {\n        sign = (match[1] === '-') ? -1 : 1;\n        duration = {\n            y  : 0,\n            d  : toInt(match[DATE])                         * sign,\n            h  : toInt(match[HOUR])                         * sign,\n            m  : toInt(match[MINUTE])                       * sign,\n            s  : toInt(match[SECOND])                       * sign,\n            ms : toInt(absRound(match[MILLISECOND] * 1000)) * sign // the millisecond decimal point is included in the match\n        };\n    } else if (!!(match = isoRegex.exec(input))) {\n        sign = (match[1] === '-') ? -1 : 1;\n        duration = {\n            y : parseIso(match[2], sign),\n            M : parseIso(match[3], sign),\n            w : parseIso(match[4], sign),\n            d : parseIso(match[5], sign),\n            h : parseIso(match[6], sign),\n            m : parseIso(match[7], sign),\n            s : parseIso(match[8], sign)\n        };\n    } else if (duration == null) {// checks for null or undefined\n        duration = {};\n    } else if (typeof duration === 'object' && ('from' in duration || 'to' in duration)) {\n        diffRes = momentsDifference(createLocal(duration.from), createLocal(duration.to));\n\n        duration = {};\n        duration.ms = diffRes.milliseconds;\n        duration.M = diffRes.months;\n    }\n\n    ret = new Duration(duration);\n\n    if (isDuration(input) && hasOwnProp(input, '_locale')) {\n        ret._locale = input._locale;\n    }\n\n    return ret;\n}\n\ncreateDuration.fn = Duration.prototype;\n\nfunction parseIso (inp, sign) {\n    // We'd normally use ~~inp for this, but unfortunately it also\n    // converts floats to ints.\n    // inp may be undefined, so careful calling replace on it.\n    var res = inp && parseFloat(inp.replace(',', '.'));\n    // apply sign while we're at it\n    return (isNaN(res) ? 0 : res) * sign;\n}\n\nfunction positiveMomentsDifference(base, other) {\n    var res = {milliseconds: 0, months: 0};\n\n    res.months = other.month() - base.month() +\n        (other.year() - base.year()) * 12;\n    if (base.clone().add(res.months, 'M').isAfter(other)) {\n        --res.months;\n    }\n\n    res.milliseconds = +other - +(base.clone().add(res.months, 'M'));\n\n    return res;\n}\n\nfunction momentsDifference(base, other) {\n    var res;\n    if (!(base.isValid() && other.isValid())) {\n        return {milliseconds: 0, months: 0};\n    }\n\n    other = cloneWithOffset(other, base);\n    if (base.isBefore(other)) {\n        res = positiveMomentsDifference(base, other);\n    } else {\n        res = positiveMomentsDifference(other, base);\n        res.milliseconds = -res.milliseconds;\n        res.months = -res.months;\n    }\n\n    return res;\n}\n\n// TODO: remove 'name' arg after deprecation is removed\nfunction createAdder(direction, name) {\n    return function (val, period) {\n        var dur, tmp;\n        //invert the arguments, but complain about it\n        if (period !== null && !isNaN(+period)) {\n            deprecateSimple(name, 'moment().' + name  + '(period, number) is deprecated. Please use moment().' + name + '(number, period). ' +\n            'See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info.');\n            tmp = val; val = period; period = tmp;\n        }\n\n        val = typeof val === 'string' ? +val : val;\n        dur = createDuration(val, period);\n        addSubtract(this, dur, direction);\n        return this;\n    };\n}\n\nfunction addSubtract (mom, duration, isAdding, updateOffset) {\n    var milliseconds = duration._milliseconds,\n        days = absRound(duration._days),\n        months = absRound(duration._months);\n\n    if (!mom.isValid()) {\n        // No op\n        return;\n    }\n\n    updateOffset = updateOffset == null ? true : updateOffset;\n\n    if (milliseconds) {\n        mom._d.setTime(mom._d.valueOf() + milliseconds * isAdding);\n    }\n    if (days) {\n        set$1(mom, 'Date', get(mom, 'Date') + days * isAdding);\n    }\n    if (months) {\n        setMonth(mom, get(mom, 'Month') + months * isAdding);\n    }\n    if (updateOffset) {\n        hooks.updateOffset(mom, days || months);\n    }\n}\n\nvar add      = createAdder(1, 'add');\nvar subtract = createAdder(-1, 'subtract');\n\nfunction getCalendarFormat(myMoment, now) {\n    var diff = myMoment.diff(now, 'days', true);\n    return diff < -6 ? 'sameElse' :\n            diff < -1 ? 'lastWeek' :\n            diff < 0 ? 'lastDay' :\n            diff < 1 ? 'sameDay' :\n            diff < 2 ? 'nextDay' :\n            diff < 7 ? 'nextWeek' : 'sameElse';\n}\n\nfunction calendar$1 (time, formats) {\n    // We want to compare the start of today, vs this.\n    // Getting start-of-today depends on whether we're local/utc/offset or not.\n    var now = time || createLocal(),\n        sod = cloneWithOffset(now, this).startOf('day'),\n        format = hooks.calendarFormat(this, sod) || 'sameElse';\n\n    var output = formats && (isFunction(formats[format]) ? formats[format].call(this, now) : formats[format]);\n\n    return this.format(output || this.localeData().calendar(format, this, createLocal(now)));\n}\n\nfunction clone () {\n    return new Moment(this);\n}\n\nfunction isAfter (input, units) {\n    var localInput = isMoment(input) ? input : createLocal(input);\n    if (!(this.isValid() && localInput.isValid())) {\n        return false;\n    }\n    units = normalizeUnits(!isUndefined(units) ? units : 'millisecond');\n    if (units === 'millisecond') {\n        return this.valueOf() > localInput.valueOf();\n    } else {\n        return localInput.valueOf() < this.clone().startOf(units).valueOf();\n    }\n}\n\nfunction isBefore (input, units) {\n    var localInput = isMoment(input) ? input : createLocal(input);\n    if (!(this.isValid() && localInput.isValid())) {\n        return false;\n    }\n    units = normalizeUnits(!isUndefined(units) ? units : 'millisecond');\n    if (units === 'millisecond') {\n        return this.valueOf() < localInput.valueOf();\n    } else {\n        return this.clone().endOf(units).valueOf() < localInput.valueOf();\n    }\n}\n\nfunction isBetween (from, to, units, inclusivity) {\n    inclusivity = inclusivity || '()';\n    return (inclusivity[0] === '(' ? this.isAfter(from, units) : !this.isBefore(from, units)) &&\n        (inclusivity[1] === ')' ? this.isBefore(to, units) : !this.isAfter(to, units));\n}\n\nfunction isSame (input, units) {\n    var localInput = isMoment(input) ? input : createLocal(input),\n        inputMs;\n    if (!(this.isValid() && localInput.isValid())) {\n        return false;\n    }\n    units = normalizeUnits(units || 'millisecond');\n    if (units === 'millisecond') {\n        return this.valueOf() === localInput.valueOf();\n    } else {\n        inputMs = localInput.valueOf();\n        return this.clone().startOf(units).valueOf() <= inputMs && inputMs <= this.clone().endOf(units).valueOf();\n    }\n}\n\nfunction isSameOrAfter (input, units) {\n    return this.isSame(input, units) || this.isAfter(input,units);\n}\n\nfunction isSameOrBefore (input, units) {\n    return this.isSame(input, units) || this.isBefore(input,units);\n}\n\nfunction diff (input, units, asFloat) {\n    var that,\n        zoneDelta,\n        delta, output;\n\n    if (!this.isValid()) {\n        return NaN;\n    }\n\n    that = cloneWithOffset(input, this);\n\n    if (!that.isValid()) {\n        return NaN;\n    }\n\n    zoneDelta = (that.utcOffset() - this.utcOffset()) * 6e4;\n\n    units = normalizeUnits(units);\n\n    if (units === 'year' || units === 'month' || units === 'quarter') {\n        output = monthDiff(this, that);\n        if (units === 'quarter') {\n            output = output / 3;\n        } else if (units === 'year') {\n            output = output / 12;\n        }\n    } else {\n        delta = this - that;\n        output = units === 'second' ? delta / 1e3 : // 1000\n            units === 'minute' ? delta / 6e4 : // 1000 * 60\n            units === 'hour' ? delta / 36e5 : // 1000 * 60 * 60\n            units === 'day' ? (delta - zoneDelta) / 864e5 : // 1000 * 60 * 60 * 24, negate dst\n            units === 'week' ? (delta - zoneDelta) / 6048e5 : // 1000 * 60 * 60 * 24 * 7, negate dst\n            delta;\n    }\n    return asFloat ? output : absFloor(output);\n}\n\nfunction monthDiff (a, b) {\n    // difference in months\n    var wholeMonthDiff = ((b.year() - a.year()) * 12) + (b.month() - a.month()),\n        // b is in (anchor - 1 month, anchor + 1 month)\n        anchor = a.clone().add(wholeMonthDiff, 'months'),\n        anchor2, adjust;\n\n    if (b - anchor < 0) {\n        anchor2 = a.clone().add(wholeMonthDiff - 1, 'months');\n        // linear across the month\n        adjust = (b - anchor) / (anchor - anchor2);\n    } else {\n        anchor2 = a.clone().add(wholeMonthDiff + 1, 'months');\n        // linear across the month\n        adjust = (b - anchor) / (anchor2 - anchor);\n    }\n\n    //check for negative zero, return zero if negative zero\n    return -(wholeMonthDiff + adjust) || 0;\n}\n\nhooks.defaultFormat = 'YYYY-MM-DDTHH:mm:ssZ';\nhooks.defaultFormatUtc = 'YYYY-MM-DDTHH:mm:ss[Z]';\n\nfunction toString () {\n    return this.clone().locale('en').format('ddd MMM DD YYYY HH:mm:ss [GMT]ZZ');\n}\n\nfunction toISOString () {\n    var m = this.clone().utc();\n    if (0 < m.year() && m.year() <= 9999) {\n        if (isFunction(Date.prototype.toISOString)) {\n            // native implementation is ~50x faster, use it when we can\n            return this.toDate().toISOString();\n        } else {\n            return formatMoment(m, 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]');\n        }\n    } else {\n        return formatMoment(m, 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]');\n    }\n}\n\n/**\n * Return a human readable representation of a moment that can\n * also be evaluated to get a new moment which is the same\n *\n * @link https://nodejs.org/dist/latest/docs/api/util.html#util_custom_inspect_function_on_objects\n */\nfunction inspect () {\n    if (!this.isValid()) {\n        return 'moment.invalid(/* ' + this._i + ' */)';\n    }\n    var func = 'moment';\n    var zone = '';\n    if (!this.isLocal()) {\n        func = this.utcOffset() === 0 ? 'moment.utc' : 'moment.parseZone';\n        zone = 'Z';\n    }\n    var prefix = '[' + func + '(\"]';\n    var year = (0 < this.year() && this.year() <= 9999) ? 'YYYY' : 'YYYYYY';\n    var datetime = '-MM-DD[T]HH:mm:ss.SSS';\n    var suffix = zone + '[\")]';\n\n    return this.format(prefix + year + datetime + suffix);\n}\n\nfunction format (inputString) {\n    if (!inputString) {\n        inputString = this.isUtc() ? hooks.defaultFormatUtc : hooks.defaultFormat;\n    }\n    var output = formatMoment(this, inputString);\n    return this.localeData().postformat(output);\n}\n\nfunction from (time, withoutSuffix) {\n    if (this.isValid() &&\n            ((isMoment(time) && time.isValid()) ||\n             createLocal(time).isValid())) {\n        return createDuration({to: this, from: time}).locale(this.locale()).humanize(!withoutSuffix);\n    } else {\n        return this.localeData().invalidDate();\n    }\n}\n\nfunction fromNow (withoutSuffix) {\n    return this.from(createLocal(), withoutSuffix);\n}\n\nfunction to (time, withoutSuffix) {\n    if (this.isValid() &&\n            ((isMoment(time) && time.isValid()) ||\n             createLocal(time).isValid())) {\n        return createDuration({from: this, to: time}).locale(this.locale()).humanize(!withoutSuffix);\n    } else {\n        return this.localeData().invalidDate();\n    }\n}\n\nfunction toNow (withoutSuffix) {\n    return this.to(createLocal(), withoutSuffix);\n}\n\n// If passed a locale key, it will set the locale for this\n// instance.  Otherwise, it will return the locale configuration\n// variables for this instance.\nfunction locale (key) {\n    var newLocaleData;\n\n    if (key === undefined) {\n        return this._locale._abbr;\n    } else {\n        newLocaleData = getLocale(key);\n        if (newLocaleData != null) {\n            this._locale = newLocaleData;\n        }\n        return this;\n    }\n}\n\nvar lang = deprecate(\n    'moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.',\n    function (key) {\n        if (key === undefined) {\n            return this.localeData();\n        } else {\n            return this.locale(key);\n        }\n    }\n);\n\nfunction localeData () {\n    return this._locale;\n}\n\nfunction startOf (units) {\n    units = normalizeUnits(units);\n    // the following switch intentionally omits break keywords\n    // to utilize falling through the cases.\n    switch (units) {\n        case 'year':\n            this.month(0);\n            /* falls through */\n        case 'quarter':\n        case 'month':\n            this.date(1);\n            /* falls through */\n        case 'week':\n        case 'isoWeek':\n        case 'day':\n        case 'date':\n            this.hours(0);\n            /* falls through */\n        case 'hour':\n            this.minutes(0);\n            /* falls through */\n        case 'minute':\n            this.seconds(0);\n            /* falls through */\n        case 'second':\n            this.milliseconds(0);\n    }\n\n    // weeks are a special case\n    if (units === 'week') {\n        this.weekday(0);\n    }\n    if (units === 'isoWeek') {\n        this.isoWeekday(1);\n    }\n\n    // quarters are also special\n    if (units === 'quarter') {\n        this.month(Math.floor(this.month() / 3) * 3);\n    }\n\n    return this;\n}\n\nfunction endOf (units) {\n    units = normalizeUnits(units);\n    if (units === undefined || units === 'millisecond') {\n        return this;\n    }\n\n    // 'date' is an alias for 'day', so it should be considered as such.\n    if (units === 'date') {\n        units = 'day';\n    }\n\n    return this.startOf(units).add(1, (units === 'isoWeek' ? 'week' : units)).subtract(1, 'ms');\n}\n\nfunction valueOf () {\n    return this._d.valueOf() - ((this._offset || 0) * 60000);\n}\n\nfunction unix () {\n    return Math.floor(this.valueOf() / 1000);\n}\n\nfunction toDate () {\n    return new Date(this.valueOf());\n}\n\nfunction toArray () {\n    var m = this;\n    return [m.year(), m.month(), m.date(), m.hour(), m.minute(), m.second(), m.millisecond()];\n}\n\nfunction toObject () {\n    var m = this;\n    return {\n        years: m.year(),\n        months: m.month(),\n        date: m.date(),\n        hours: m.hours(),\n        minutes: m.minutes(),\n        seconds: m.seconds(),\n        milliseconds: m.milliseconds()\n    };\n}\n\nfunction toJSON () {\n    // new Date(NaN).toJSON() === null\n    return this.isValid() ? this.toISOString() : null;\n}\n\nfunction isValid$1 () {\n    return isValid(this);\n}\n\nfunction parsingFlags () {\n    return extend({}, getParsingFlags(this));\n}\n\nfunction invalidAt () {\n    return getParsingFlags(this).overflow;\n}\n\nfunction creationData() {\n    return {\n        input: this._i,\n        format: this._f,\n        locale: this._locale,\n        isUTC: this._isUTC,\n        strict: this._strict\n    };\n}\n\n// FORMATTING\n\naddFormatToken(0, ['gg', 2], 0, function () {\n    return this.weekYear() % 100;\n});\n\naddFormatToken(0, ['GG', 2], 0, function () {\n    return this.isoWeekYear() % 100;\n});\n\nfunction addWeekYearFormatToken (token, getter) {\n    addFormatToken(0, [token, token.length], 0, getter);\n}\n\naddWeekYearFormatToken('gggg',     'weekYear');\naddWeekYearFormatToken('ggggg',    'weekYear');\naddWeekYearFormatToken('GGGG',  'isoWeekYear');\naddWeekYearFormatToken('GGGGG', 'isoWeekYear');\n\n// ALIASES\n\naddUnitAlias('weekYear', 'gg');\naddUnitAlias('isoWeekYear', 'GG');\n\n// PRIORITY\n\naddUnitPriority('weekYear', 1);\naddUnitPriority('isoWeekYear', 1);\n\n\n// PARSING\n\naddRegexToken('G',      matchSigned);\naddRegexToken('g',      matchSigned);\naddRegexToken('GG',     match1to2, match2);\naddRegexToken('gg',     match1to2, match2);\naddRegexToken('GGGG',   match1to4, match4);\naddRegexToken('gggg',   match1to4, match4);\naddRegexToken('GGGGG',  match1to6, match6);\naddRegexToken('ggggg',  match1to6, match6);\n\naddWeekParseToken(['gggg', 'ggggg', 'GGGG', 'GGGGG'], function (input, week, config, token) {\n    week[token.substr(0, 2)] = toInt(input);\n});\n\naddWeekParseToken(['gg', 'GG'], function (input, week, config, token) {\n    week[token] = hooks.parseTwoDigitYear(input);\n});\n\n// MOMENTS\n\nfunction getSetWeekYear (input) {\n    return getSetWeekYearHelper.call(this,\n            input,\n            this.week(),\n            this.weekday(),\n            this.localeData()._week.dow,\n            this.localeData()._week.doy);\n}\n\nfunction getSetISOWeekYear (input) {\n    return getSetWeekYearHelper.call(this,\n            input, this.isoWeek(), this.isoWeekday(), 1, 4);\n}\n\nfunction getISOWeeksInYear () {\n    return weeksInYear(this.year(), 1, 4);\n}\n\nfunction getWeeksInYear () {\n    var weekInfo = this.localeData()._week;\n    return weeksInYear(this.year(), weekInfo.dow, weekInfo.doy);\n}\n\nfunction getSetWeekYearHelper(input, week, weekday, dow, doy) {\n    var weeksTarget;\n    if (input == null) {\n        return weekOfYear(this, dow, doy).year;\n    } else {\n        weeksTarget = weeksInYear(input, dow, doy);\n        if (week > weeksTarget) {\n            week = weeksTarget;\n        }\n        return setWeekAll.call(this, input, week, weekday, dow, doy);\n    }\n}\n\nfunction setWeekAll(weekYear, week, weekday, dow, doy) {\n    var dayOfYearData = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy),\n        date = createUTCDate(dayOfYearData.year, 0, dayOfYearData.dayOfYear);\n\n    this.year(date.getUTCFullYear());\n    this.month(date.getUTCMonth());\n    this.date(date.getUTCDate());\n    return this;\n}\n\n// FORMATTING\n\naddFormatToken('Q', 0, 'Qo', 'quarter');\n\n// ALIASES\n\naddUnitAlias('quarter', 'Q');\n\n// PRIORITY\n\naddUnitPriority('quarter', 7);\n\n// PARSING\n\naddRegexToken('Q', match1);\naddParseToken('Q', function (input, array) {\n    array[MONTH] = (toInt(input) - 1) * 3;\n});\n\n// MOMENTS\n\nfunction getSetQuarter (input) {\n    return input == null ? Math.ceil((this.month() + 1) / 3) : this.month((input - 1) * 3 + this.month() % 3);\n}\n\n// FORMATTING\n\naddFormatToken('D', ['DD', 2], 'Do', 'date');\n\n// ALIASES\n\naddUnitAlias('date', 'D');\n\n// PRIOROITY\naddUnitPriority('date', 9);\n\n// PARSING\n\naddRegexToken('D',  match1to2);\naddRegexToken('DD', match1to2, match2);\naddRegexToken('Do', function (isStrict, locale) {\n    return isStrict ? locale._ordinalParse : locale._ordinalParseLenient;\n});\n\naddParseToken(['D', 'DD'], DATE);\naddParseToken('Do', function (input, array) {\n    array[DATE] = toInt(input.match(match1to2)[0], 10);\n});\n\n// MOMENTS\n\nvar getSetDayOfMonth = makeGetSet('Date', true);\n\n// FORMATTING\n\naddFormatToken('DDD', ['DDDD', 3], 'DDDo', 'dayOfYear');\n\n// ALIASES\n\naddUnitAlias('dayOfYear', 'DDD');\n\n// PRIORITY\naddUnitPriority('dayOfYear', 4);\n\n// PARSING\n\naddRegexToken('DDD',  match1to3);\naddRegexToken('DDDD', match3);\naddParseToken(['DDD', 'DDDD'], function (input, array, config) {\n    config._dayOfYear = toInt(input);\n});\n\n// HELPERS\n\n// MOMENTS\n\nfunction getSetDayOfYear (input) {\n    var dayOfYear = Math.round((this.clone().startOf('day') - this.clone().startOf('year')) / 864e5) + 1;\n    return input == null ? dayOfYear : this.add((input - dayOfYear), 'd');\n}\n\n// FORMATTING\n\naddFormatToken('m', ['mm', 2], 0, 'minute');\n\n// ALIASES\n\naddUnitAlias('minute', 'm');\n\n// PRIORITY\n\naddUnitPriority('minute', 14);\n\n// PARSING\n\naddRegexToken('m',  match1to2);\naddRegexToken('mm', match1to2, match2);\naddParseToken(['m', 'mm'], MINUTE);\n\n// MOMENTS\n\nvar getSetMinute = makeGetSet('Minutes', false);\n\n// FORMATTING\n\naddFormatToken('s', ['ss', 2], 0, 'second');\n\n// ALIASES\n\naddUnitAlias('second', 's');\n\n// PRIORITY\n\naddUnitPriority('second', 15);\n\n// PARSING\n\naddRegexToken('s',  match1to2);\naddRegexToken('ss', match1to2, match2);\naddParseToken(['s', 'ss'], SECOND);\n\n// MOMENTS\n\nvar getSetSecond = makeGetSet('Seconds', false);\n\n// FORMATTING\n\naddFormatToken('S', 0, 0, function () {\n    return ~~(this.millisecond() / 100);\n});\n\naddFormatToken(0, ['SS', 2], 0, function () {\n    return ~~(this.millisecond() / 10);\n});\n\naddFormatToken(0, ['SSS', 3], 0, 'millisecond');\naddFormatToken(0, ['SSSS', 4], 0, function () {\n    return this.millisecond() * 10;\n});\naddFormatToken(0, ['SSSSS', 5], 0, function () {\n    return this.millisecond() * 100;\n});\naddFormatToken(0, ['SSSSSS', 6], 0, function () {\n    return this.millisecond() * 1000;\n});\naddFormatToken(0, ['SSSSSSS', 7], 0, function () {\n    return this.millisecond() * 10000;\n});\naddFormatToken(0, ['SSSSSSSS', 8], 0, function () {\n    return this.millisecond() * 100000;\n});\naddFormatToken(0, ['SSSSSSSSS', 9], 0, function () {\n    return this.millisecond() * 1000000;\n});\n\n\n// ALIASES\n\naddUnitAlias('millisecond', 'ms');\n\n// PRIORITY\n\naddUnitPriority('millisecond', 16);\n\n// PARSING\n\naddRegexToken('S',    match1to3, match1);\naddRegexToken('SS',   match1to3, match2);\naddRegexToken('SSS',  match1to3, match3);\n\nvar token;\nfor (token = 'SSSS'; token.length <= 9; token += 'S') {\n    addRegexToken(token, matchUnsigned);\n}\n\nfunction parseMs(input, array) {\n    array[MILLISECOND] = toInt(('0.' + input) * 1000);\n}\n\nfor (token = 'S'; token.length <= 9; token += 'S') {\n    addParseToken(token, parseMs);\n}\n// MOMENTS\n\nvar getSetMillisecond = makeGetSet('Milliseconds', false);\n\n// FORMATTING\n\naddFormatToken('z',  0, 0, 'zoneAbbr');\naddFormatToken('zz', 0, 0, 'zoneName');\n\n// MOMENTS\n\nfunction getZoneAbbr () {\n    return this._isUTC ? 'UTC' : '';\n}\n\nfunction getZoneName () {\n    return this._isUTC ? 'Coordinated Universal Time' : '';\n}\n\nvar proto = Moment.prototype;\n\nproto.add               = add;\nproto.calendar          = calendar$1;\nproto.clone             = clone;\nproto.diff              = diff;\nproto.endOf             = endOf;\nproto.format            = format;\nproto.from              = from;\nproto.fromNow           = fromNow;\nproto.to                = to;\nproto.toNow             = toNow;\nproto.get               = stringGet;\nproto.invalidAt         = invalidAt;\nproto.isAfter           = isAfter;\nproto.isBefore          = isBefore;\nproto.isBetween         = isBetween;\nproto.isSame            = isSame;\nproto.isSameOrAfter     = isSameOrAfter;\nproto.isSameOrBefore    = isSameOrBefore;\nproto.isValid           = isValid$1;\nproto.lang              = lang;\nproto.locale            = locale;\nproto.localeData        = localeData;\nproto.max               = prototypeMax;\nproto.min               = prototypeMin;\nproto.parsingFlags      = parsingFlags;\nproto.set               = stringSet;\nproto.startOf           = startOf;\nproto.subtract          = subtract;\nproto.toArray           = toArray;\nproto.toObject          = toObject;\nproto.toDate            = toDate;\nproto.toISOString       = toISOString;\nproto.inspect           = inspect;\nproto.toJSON            = toJSON;\nproto.toString          = toString;\nproto.unix              = unix;\nproto.valueOf           = valueOf;\nproto.creationData      = creationData;\n\n// Year\nproto.year       = getSetYear;\nproto.isLeapYear = getIsLeapYear;\n\n// Week Year\nproto.weekYear    = getSetWeekYear;\nproto.isoWeekYear = getSetISOWeekYear;\n\n// Quarter\nproto.quarter = proto.quarters = getSetQuarter;\n\n// Month\nproto.month       = getSetMonth;\nproto.daysInMonth = getDaysInMonth;\n\n// Week\nproto.week           = proto.weeks        = getSetWeek;\nproto.isoWeek        = proto.isoWeeks     = getSetISOWeek;\nproto.weeksInYear    = getWeeksInYear;\nproto.isoWeeksInYear = getISOWeeksInYear;\n\n// Day\nproto.date       = getSetDayOfMonth;\nproto.day        = proto.days             = getSetDayOfWeek;\nproto.weekday    = getSetLocaleDayOfWeek;\nproto.isoWeekday = getSetISODayOfWeek;\nproto.dayOfYear  = getSetDayOfYear;\n\n// Hour\nproto.hour = proto.hours = getSetHour;\n\n// Minute\nproto.minute = proto.minutes = getSetMinute;\n\n// Second\nproto.second = proto.seconds = getSetSecond;\n\n// Millisecond\nproto.millisecond = proto.milliseconds = getSetMillisecond;\n\n// Offset\nproto.utcOffset            = getSetOffset;\nproto.utc                  = setOffsetToUTC;\nproto.local                = setOffsetToLocal;\nproto.parseZone            = setOffsetToParsedOffset;\nproto.hasAlignedHourOffset = hasAlignedHourOffset;\nproto.isDST                = isDaylightSavingTime;\nproto.isLocal              = isLocal;\nproto.isUtcOffset          = isUtcOffset;\nproto.isUtc                = isUtc;\nproto.isUTC                = isUtc;\n\n// Timezone\nproto.zoneAbbr = getZoneAbbr;\nproto.zoneName = getZoneName;\n\n// Deprecations\nproto.dates  = deprecate('dates accessor is deprecated. Use date instead.', getSetDayOfMonth);\nproto.months = deprecate('months accessor is deprecated. Use month instead', getSetMonth);\nproto.years  = deprecate('years accessor is deprecated. Use year instead', getSetYear);\nproto.zone   = deprecate('moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/', getSetZone);\nproto.isDSTShifted = deprecate('isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information', isDaylightSavingTimeShifted);\n\nfunction createUnix (input) {\n    return createLocal(input * 1000);\n}\n\nfunction createInZone () {\n    return createLocal.apply(null, arguments).parseZone();\n}\n\nfunction preParsePostFormat (string) {\n    return string;\n}\n\nvar proto$1 = Locale.prototype;\n\nproto$1.calendar        = calendar;\nproto$1.longDateFormat  = longDateFormat;\nproto$1.invalidDate     = invalidDate;\nproto$1.ordinal         = ordinal;\nproto$1.preparse        = preParsePostFormat;\nproto$1.postformat      = preParsePostFormat;\nproto$1.relativeTime    = relativeTime;\nproto$1.pastFuture      = pastFuture;\nproto$1.set             = set;\n\n// Month\nproto$1.months            =        localeMonths;\nproto$1.monthsShort       =        localeMonthsShort;\nproto$1.monthsParse       =        localeMonthsParse;\nproto$1.monthsRegex       = monthsRegex;\nproto$1.monthsShortRegex  = monthsShortRegex;\n\n// Week\nproto$1.week = localeWeek;\nproto$1.firstDayOfYear = localeFirstDayOfYear;\nproto$1.firstDayOfWeek = localeFirstDayOfWeek;\n\n// Day of Week\nproto$1.weekdays       =        localeWeekdays;\nproto$1.weekdaysMin    =        localeWeekdaysMin;\nproto$1.weekdaysShort  =        localeWeekdaysShort;\nproto$1.weekdaysParse  =        localeWeekdaysParse;\n\nproto$1.weekdaysRegex       =        weekdaysRegex;\nproto$1.weekdaysShortRegex  =        weekdaysShortRegex;\nproto$1.weekdaysMinRegex    =        weekdaysMinRegex;\n\n// Hours\nproto$1.isPM = localeIsPM;\nproto$1.meridiem = localeMeridiem;\n\nfunction get$1 (format, index, field, setter) {\n    var locale = getLocale();\n    var utc = createUTC().set(setter, index);\n    return locale[field](utc, format);\n}\n\nfunction listMonthsImpl (format, index, field) {\n    if (isNumber(format)) {\n        index = format;\n        format = undefined;\n    }\n\n    format = format || '';\n\n    if (index != null) {\n        return get$1(format, index, field, 'month');\n    }\n\n    var i;\n    var out = [];\n    for (i = 0; i < 12; i++) {\n        out[i] = get$1(format, i, field, 'month');\n    }\n    return out;\n}\n\n// ()\n// (5)\n// (fmt, 5)\n// (fmt)\n// (true)\n// (true, 5)\n// (true, fmt, 5)\n// (true, fmt)\nfunction listWeekdaysImpl (localeSorted, format, index, field) {\n    if (typeof localeSorted === 'boolean') {\n        if (isNumber(format)) {\n            index = format;\n            format = undefined;\n        }\n\n        format = format || '';\n    } else {\n        format = localeSorted;\n        index = format;\n        localeSorted = false;\n\n        if (isNumber(format)) {\n            index = format;\n            format = undefined;\n        }\n\n        format = format || '';\n    }\n\n    var locale = getLocale(),\n        shift = localeSorted ? locale._week.dow : 0;\n\n    if (index != null) {\n        return get$1(format, (index + shift) % 7, field, 'day');\n    }\n\n    var i;\n    var out = [];\n    for (i = 0; i < 7; i++) {\n        out[i] = get$1(format, (i + shift) % 7, field, 'day');\n    }\n    return out;\n}\n\nfunction listMonths (format, index) {\n    return listMonthsImpl(format, index, 'months');\n}\n\nfunction listMonthsShort (format, index) {\n    return listMonthsImpl(format, index, 'monthsShort');\n}\n\nfunction listWeekdays (localeSorted, format, index) {\n    return listWeekdaysImpl(localeSorted, format, index, 'weekdays');\n}\n\nfunction listWeekdaysShort (localeSorted, format, index) {\n    return listWeekdaysImpl(localeSorted, format, index, 'weekdaysShort');\n}\n\nfunction listWeekdaysMin (localeSorted, format, index) {\n    return listWeekdaysImpl(localeSorted, format, index, 'weekdaysMin');\n}\n\ngetSetGlobalLocale('en', {\n    ordinalParse: /\\d{1,2}(th|st|nd|rd)/,\n    ordinal : function (number) {\n        var b = number % 10,\n            output = (toInt(number % 100 / 10) === 1) ? 'th' :\n            (b === 1) ? 'st' :\n            (b === 2) ? 'nd' :\n            (b === 3) ? 'rd' : 'th';\n        return number + output;\n    }\n});\n\n// Side effect imports\nhooks.lang = deprecate('moment.lang is deprecated. Use moment.locale instead.', getSetGlobalLocale);\nhooks.langData = deprecate('moment.langData is deprecated. Use moment.localeData instead.', getLocale);\n\nvar mathAbs = Math.abs;\n\nfunction abs () {\n    var data           = this._data;\n\n    this._milliseconds = mathAbs(this._milliseconds);\n    this._days         = mathAbs(this._days);\n    this._months       = mathAbs(this._months);\n\n    data.milliseconds  = mathAbs(data.milliseconds);\n    data.seconds       = mathAbs(data.seconds);\n    data.minutes       = mathAbs(data.minutes);\n    data.hours         = mathAbs(data.hours);\n    data.months        = mathAbs(data.months);\n    data.years         = mathAbs(data.years);\n\n    return this;\n}\n\nfunction addSubtract$1 (duration, input, value, direction) {\n    var other = createDuration(input, value);\n\n    duration._milliseconds += direction * other._milliseconds;\n    duration._days         += direction * other._days;\n    duration._months       += direction * other._months;\n\n    return duration._bubble();\n}\n\n// supports only 2.0-style add(1, 's') or add(duration)\nfunction add$1 (input, value) {\n    return addSubtract$1(this, input, value, 1);\n}\n\n// supports only 2.0-style subtract(1, 's') or subtract(duration)\nfunction subtract$1 (input, value) {\n    return addSubtract$1(this, input, value, -1);\n}\n\nfunction absCeil (number) {\n    if (number < 0) {\n        return Math.floor(number);\n    } else {\n        return Math.ceil(number);\n    }\n}\n\nfunction bubble () {\n    var milliseconds = this._milliseconds;\n    var days         = this._days;\n    var months       = this._months;\n    var data         = this._data;\n    var seconds, minutes, hours, years, monthsFromDays;\n\n    // if we have a mix of positive and negative values, bubble down first\n    // check: https://github.com/moment/moment/issues/2166\n    if (!((milliseconds >= 0 && days >= 0 && months >= 0) ||\n            (milliseconds <= 0 && days <= 0 && months <= 0))) {\n        milliseconds += absCeil(monthsToDays(months) + days) * 864e5;\n        days = 0;\n        months = 0;\n    }\n\n    // The following code bubbles up values, see the tests for\n    // examples of what that means.\n    data.milliseconds = milliseconds % 1000;\n\n    seconds           = absFloor(milliseconds / 1000);\n    data.seconds      = seconds % 60;\n\n    minutes           = absFloor(seconds / 60);\n    data.minutes      = minutes % 60;\n\n    hours             = absFloor(minutes / 60);\n    data.hours        = hours % 24;\n\n    days += absFloor(hours / 24);\n\n    // convert days to months\n    monthsFromDays = absFloor(daysToMonths(days));\n    months += monthsFromDays;\n    days -= absCeil(monthsToDays(monthsFromDays));\n\n    // 12 months -> 1 year\n    years = absFloor(months / 12);\n    months %= 12;\n\n    data.days   = days;\n    data.months = months;\n    data.years  = years;\n\n    return this;\n}\n\nfunction daysToMonths (days) {\n    // 400 years have 146097 days (taking into account leap year rules)\n    // 400 years have 12 months === 4800\n    return days * 4800 / 146097;\n}\n\nfunction monthsToDays (months) {\n    // the reverse of daysToMonths\n    return months * 146097 / 4800;\n}\n\nfunction as (units) {\n    var days;\n    var months;\n    var milliseconds = this._milliseconds;\n\n    units = normalizeUnits(units);\n\n    if (units === 'month' || units === 'year') {\n        days   = this._days   + milliseconds / 864e5;\n        months = this._months + daysToMonths(days);\n        return units === 'month' ? months : months / 12;\n    } else {\n        // handle milliseconds separately because of floating point math errors (issue #1867)\n        days = this._days + Math.round(monthsToDays(this._months));\n        switch (units) {\n            case 'week'   : return days / 7     + milliseconds / 6048e5;\n            case 'day'    : return days         + milliseconds / 864e5;\n            case 'hour'   : return days * 24    + milliseconds / 36e5;\n            case 'minute' : return days * 1440  + milliseconds / 6e4;\n            case 'second' : return days * 86400 + milliseconds / 1000;\n            // Math.floor prevents floating point math errors here\n            case 'millisecond': return Math.floor(days * 864e5) + milliseconds;\n            default: throw new Error('Unknown unit ' + units);\n        }\n    }\n}\n\n// TODO: Use this.as('ms')?\nfunction valueOf$1 () {\n    return (\n        this._milliseconds +\n        this._days * 864e5 +\n        (this._months % 12) * 2592e6 +\n        toInt(this._months / 12) * 31536e6\n    );\n}\n\nfunction makeAs (alias) {\n    return function () {\n        return this.as(alias);\n    };\n}\n\nvar asMilliseconds = makeAs('ms');\nvar asSeconds      = makeAs('s');\nvar asMinutes      = makeAs('m');\nvar asHours        = makeAs('h');\nvar asDays         = makeAs('d');\nvar asWeeks        = makeAs('w');\nvar asMonths       = makeAs('M');\nvar asYears        = makeAs('y');\n\nfunction get$2 (units) {\n    units = normalizeUnits(units);\n    return this[units + 's']();\n}\n\nfunction makeGetter(name) {\n    return function () {\n        return this._data[name];\n    };\n}\n\nvar milliseconds = makeGetter('milliseconds');\nvar seconds      = makeGetter('seconds');\nvar minutes      = makeGetter('minutes');\nvar hours        = makeGetter('hours');\nvar days         = makeGetter('days');\nvar months       = makeGetter('months');\nvar years        = makeGetter('years');\n\nfunction weeks () {\n    return absFloor(this.days() / 7);\n}\n\nvar round = Math.round;\nvar thresholds = {\n    s: 45,  // seconds to minute\n    m: 45,  // minutes to hour\n    h: 22,  // hours to day\n    d: 26,  // days to month\n    M: 11   // months to year\n};\n\n// helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize\nfunction substituteTimeAgo(string, number, withoutSuffix, isFuture, locale) {\n    return locale.relativeTime(number || 1, !!withoutSuffix, string, isFuture);\n}\n\nfunction relativeTime$1 (posNegDuration, withoutSuffix, locale) {\n    var duration = createDuration(posNegDuration).abs();\n    var seconds  = round(duration.as('s'));\n    var minutes  = round(duration.as('m'));\n    var hours    = round(duration.as('h'));\n    var days     = round(duration.as('d'));\n    var months   = round(duration.as('M'));\n    var years    = round(duration.as('y'));\n\n    var a = seconds < thresholds.s && ['s', seconds]  ||\n            minutes <= 1           && ['m']           ||\n            minutes < thresholds.m && ['mm', minutes] ||\n            hours   <= 1           && ['h']           ||\n            hours   < thresholds.h && ['hh', hours]   ||\n            days    <= 1           && ['d']           ||\n            days    < thresholds.d && ['dd', days]    ||\n            months  <= 1           && ['M']           ||\n            months  < thresholds.M && ['MM', months]  ||\n            years   <= 1           && ['y']           || ['yy', years];\n\n    a[2] = withoutSuffix;\n    a[3] = +posNegDuration > 0;\n    a[4] = locale;\n    return substituteTimeAgo.apply(null, a);\n}\n\n// This function allows you to set the rounding function for relative time strings\nfunction getSetRelativeTimeRounding (roundingFunction) {\n    if (roundingFunction === undefined) {\n        return round;\n    }\n    if (typeof(roundingFunction) === 'function') {\n        round = roundingFunction;\n        return true;\n    }\n    return false;\n}\n\n// This function allows you to set a threshold for relative time strings\nfunction getSetRelativeTimeThreshold (threshold, limit) {\n    if (thresholds[threshold] === undefined) {\n        return false;\n    }\n    if (limit === undefined) {\n        return thresholds[threshold];\n    }\n    thresholds[threshold] = limit;\n    return true;\n}\n\nfunction humanize (withSuffix) {\n    var locale = this.localeData();\n    var output = relativeTime$1(this, !withSuffix, locale);\n\n    if (withSuffix) {\n        output = locale.pastFuture(+this, output);\n    }\n\n    return locale.postformat(output);\n}\n\nvar abs$1 = Math.abs;\n\nfunction toISOString$1() {\n    // for ISO strings we do not use the normal bubbling rules:\n    //  * milliseconds bubble up until they become hours\n    //  * days do not bubble at all\n    //  * months bubble up until they become years\n    // This is because there is no context-free conversion between hours and days\n    // (think of clock changes)\n    // and also not between days and months (28-31 days per month)\n    var seconds = abs$1(this._milliseconds) / 1000;\n    var days         = abs$1(this._days);\n    var months       = abs$1(this._months);\n    var minutes, hours, years;\n\n    // 3600 seconds -> 60 minutes -> 1 hour\n    minutes           = absFloor(seconds / 60);\n    hours             = absFloor(minutes / 60);\n    seconds %= 60;\n    minutes %= 60;\n\n    // 12 months -> 1 year\n    years  = absFloor(months / 12);\n    months %= 12;\n\n\n    // inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js\n    var Y = years;\n    var M = months;\n    var D = days;\n    var h = hours;\n    var m = minutes;\n    var s = seconds;\n    var total = this.asSeconds();\n\n    if (!total) {\n        // this is the same as C#'s (Noda) and python (isodate)...\n        // but not other JS (goog.date)\n        return 'P0D';\n    }\n\n    return (total < 0 ? '-' : '') +\n        'P' +\n        (Y ? Y + 'Y' : '') +\n        (M ? M + 'M' : '') +\n        (D ? D + 'D' : '') +\n        ((h || m || s) ? 'T' : '') +\n        (h ? h + 'H' : '') +\n        (m ? m + 'M' : '') +\n        (s ? s + 'S' : '');\n}\n\nvar proto$2 = Duration.prototype;\n\nproto$2.abs            = abs;\nproto$2.add            = add$1;\nproto$2.subtract       = subtract$1;\nproto$2.as             = as;\nproto$2.asMilliseconds = asMilliseconds;\nproto$2.asSeconds      = asSeconds;\nproto$2.asMinutes      = asMinutes;\nproto$2.asHours        = asHours;\nproto$2.asDays         = asDays;\nproto$2.asWeeks        = asWeeks;\nproto$2.asMonths       = asMonths;\nproto$2.asYears        = asYears;\nproto$2.valueOf        = valueOf$1;\nproto$2._bubble        = bubble;\nproto$2.get            = get$2;\nproto$2.milliseconds   = milliseconds;\nproto$2.seconds        = seconds;\nproto$2.minutes        = minutes;\nproto$2.hours          = hours;\nproto$2.days           = days;\nproto$2.weeks          = weeks;\nproto$2.months         = months;\nproto$2.years          = years;\nproto$2.humanize       = humanize;\nproto$2.toISOString    = toISOString$1;\nproto$2.toString       = toISOString$1;\nproto$2.toJSON         = toISOString$1;\nproto$2.locale         = locale;\nproto$2.localeData     = localeData;\n\n// Deprecations\nproto$2.toIsoString = deprecate('toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)', toISOString$1);\nproto$2.lang = lang;\n\n// Side effect imports\n\n// FORMATTING\n\naddFormatToken('X', 0, 0, 'unix');\naddFormatToken('x', 0, 0, 'valueOf');\n\n// PARSING\n\naddRegexToken('x', matchSigned);\naddRegexToken('X', matchTimestamp);\naddParseToken('X', function (input, array, config) {\n    config._d = new Date(parseFloat(input, 10) * 1000);\n});\naddParseToken('x', function (input, array, config) {\n    config._d = new Date(toInt(input));\n});\n\n// Side effect imports\n\n\nhooks.version = '2.17.1';\n\nsetHookCallback(createLocal);\n\nhooks.fn                    = proto;\nhooks.min                   = min;\nhooks.max                   = max;\nhooks.now                   = now;\nhooks.utc                   = createUTC;\nhooks.unix                  = createUnix;\nhooks.months                = listMonths;\nhooks.isDate                = isDate;\nhooks.locale                = getSetGlobalLocale;\nhooks.invalid               = createInvalid;\nhooks.duration              = createDuration;\nhooks.isMoment              = isMoment;\nhooks.weekdays              = listWeekdays;\nhooks.parseZone             = createInZone;\nhooks.localeData            = getLocale;\nhooks.isDuration            = isDuration;\nhooks.monthsShort           = listMonthsShort;\nhooks.weekdaysMin           = listWeekdaysMin;\nhooks.defineLocale          = defineLocale;\nhooks.updateLocale          = updateLocale;\nhooks.locales               = listLocales;\nhooks.weekdaysShort         = listWeekdaysShort;\nhooks.normalizeUnits        = normalizeUnits;\nhooks.relativeTimeRounding = getSetRelativeTimeRounding;\nhooks.relativeTimeThreshold = getSetRelativeTimeThreshold;\nhooks.calendarFormat        = getCalendarFormat;\nhooks.prototype             = proto;\n\nreturn hooks;\n\n})));\n", "(function (exports) {\r\n    'use strict';\r\n\r\n    /**\r\n     * We define here a simple event bus: it can\r\n     * - emit events\r\n     * - add/remove listeners.\r\n     *\r\n     * This is a useful pattern of communication in many cases.  For OWL, each\r\n     * components and stores are event buses.\r\n     */\r\n    //------------------------------------------------------------------------------\r\n    // EventBus\r\n    //------------------------------------------------------------------------------\r\n    class EventBus {\r\n        constructor() {\r\n            this.subscriptions = {};\r\n        }\r\n        /**\r\n         * Add a listener for the 'eventType' events.\r\n         *\r\n         * Note that the 'owner' of this event can be anything, but will more likely\r\n         * be a component or a class. The idea is that the callback will be called with\r\n         * the proper owner bound.\r\n         *\r\n         * Also, the owner should be kind of unique. This will be used to remove the\r\n         * listener.\r\n         */\r\n        on(eventType, owner, callback) {\r\n            if (!callback) {\r\n                throw new Error(\"Missing callback\");\r\n            }\r\n            if (!this.subscriptions[eventType]) {\r\n                this.subscriptions[eventType] = [];\r\n            }\r\n            this.subscriptions[eventType].push({\r\n                owner,\r\n                callback,\r\n            });\r\n        }\r\n        /**\r\n         * Remove a listener\r\n         */\r\n        off(eventType, owner) {\r\n            const subs = this.subscriptions[eventType];\r\n            if (subs) {\r\n                this.subscriptions[eventType] = subs.filter((s) => s.owner !== owner);\r\n            }\r\n        }\r\n        /**\r\n         * Emit an event of type 'eventType'.  Any extra arguments will be passed to\r\n         * the listeners callback.\r\n         */\r\n        trigger(eventType, ...args) {\r\n            const subs = this.subscriptions[eventType] || [];\r\n            for (let i = 0, iLen = subs.length; i < iLen; i++) {\r\n                const sub = subs[i];\r\n                sub.callback.call(sub.owner, ...args);\r\n            }\r\n        }\r\n        /**\r\n         * Remove all subscriptions.\r\n         */\r\n        clear() {\r\n            this.subscriptions = {};\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Owl Observer\r\n     *\r\n     * This code contains the logic that allows Owl to observe and react to state\r\n     * changes.\r\n     *\r\n     * This is a Observer class that can observe any JS values.  The way it works\r\n     * can be summarized thusly:\r\n     * - primitive values are not observed at all\r\n     * - Objects and arrays are observed by replacing them with a Proxy\r\n     * - each object/array metadata are tracked in a weakmap, and keep a revision\r\n     *   number\r\n     *\r\n     * Note that this code is loosely inspired by Vue.\r\n     */\r\n    //------------------------------------------------------------------------------\r\n    // Observer\r\n    //------------------------------------------------------------------------------\r\n    class Observer {\r\n        constructor() {\r\n            this.rev = 1;\r\n            this.allowMutations = true;\r\n            this.weakMap = new WeakMap();\r\n        }\r\n        notifyCB() { }\r\n        observe(value, parent) {\r\n            if (value === null ||\r\n                typeof value !== \"object\" ||\r\n                value instanceof Date ||\r\n                value instanceof Promise) {\r\n                // fun fact: typeof null === 'object'\r\n                return value;\r\n            }\r\n            let metadata = this.weakMap.get(value) || this._observe(value, parent);\r\n            return metadata.proxy;\r\n        }\r\n        revNumber(value) {\r\n            const metadata = this.weakMap.get(value);\r\n            return metadata ? metadata.rev : 0;\r\n        }\r\n        _observe(value, parent) {\r\n            var self = this;\r\n            const proxy = new Proxy(value, {\r\n                get(target, k) {\r\n                    const targetValue = target[k];\r\n                    return self.observe(targetValue, value);\r\n                },\r\n                set(target, key, newVal) {\r\n                    const value = target[key];\r\n                    if (newVal !== value) {\r\n                        if (!self.allowMutations) {\r\n                            throw new Error(`Observed state cannot be changed here! (key: \"${key}\", val: \"${newVal}\")`);\r\n                        }\r\n                        self._updateRevNumber(target);\r\n                        target[key] = newVal;\r\n                        self.notifyCB();\r\n                    }\r\n                    return true;\r\n                },\r\n                deleteProperty(target, key) {\r\n                    if (key in target) {\r\n                        delete target[key];\r\n                        self._updateRevNumber(target);\r\n                        self.notifyCB();\r\n                    }\r\n                    return true;\r\n                },\r\n            });\r\n            const metadata = {\r\n                value,\r\n                proxy,\r\n                rev: this.rev,\r\n                parent,\r\n            };\r\n            this.weakMap.set(value, metadata);\r\n            this.weakMap.set(metadata.proxy, metadata);\r\n            return metadata;\r\n        }\r\n        _updateRevNumber(target) {\r\n            this.rev++;\r\n            let metadata = this.weakMap.get(target);\r\n            let parent = target;\r\n            do {\r\n                metadata = this.weakMap.get(parent);\r\n                metadata.rev++;\r\n            } while ((parent = metadata.parent) && parent !== target);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Owl QWeb Expression Parser\r\n     *\r\n     * Owl needs in various contexts to be able to understand the structure of a\r\n     * string representing a javascript expression.  The usual goal is to be able\r\n     * to rewrite some variables.  For example, if a template has\r\n     *\r\n     *  ```xml\r\n     *  <t t-if=\"computeSomething({val: state.val})\">...</t>\r\n     * ```\r\n     *\r\n     * this needs to be translated in something like this:\r\n     *\r\n     * ```js\r\n     *   if (context[\"computeSomething\"]({val: context[\"state\"].val})) { ... }\r\n     * ```\r\n     *\r\n     * This file contains the implementation of an extremely naive tokenizer/parser\r\n     * and evaluator for javascript expressions.  The supported grammar is basically\r\n     * only expressive enough to understand the shape of objects, of arrays, and\r\n     * various operators.\r\n     */\r\n    //------------------------------------------------------------------------------\r\n    // Misc types, constants and helpers\r\n    //------------------------------------------------------------------------------\r\n    const RESERVED_WORDS = \"true,false,NaN,null,undefined,debugger,console,window,in,instanceof,new,function,return,this,eval,void,Math,RegExp,Array,Object,Date\".split(\",\");\r\n    const WORD_REPLACEMENT = Object.assign(Object.create(null), {\r\n        and: \"&&\",\r\n        or: \"||\",\r\n        gt: \">\",\r\n        gte: \">=\",\r\n        lt: \"<\",\r\n        lte: \"<=\",\r\n    });\r\n    const STATIC_TOKEN_MAP = Object.assign(Object.create(null), {\r\n        \"{\": \"LEFT_BRACE\",\r\n        \"}\": \"RIGHT_BRACE\",\r\n        \"[\": \"LEFT_BRACKET\",\r\n        \"]\": \"RIGHT_BRACKET\",\r\n        \":\": \"COLON\",\r\n        \",\": \"COMMA\",\r\n        \"(\": \"LEFT_PAREN\",\r\n        \")\": \"RIGHT_PAREN\",\r\n    });\r\n    // note that the space after typeof is relevant. It makes sure that the formatted\r\n    // expression has a space after typeof\r\n    const OPERATORS = \"...,.,===,==,+,!==,!=,!,||,&&,>=,>,<=,<,?,-,*,/,%,typeof ,=>,=,;,in \".split(\",\");\r\n    let tokenizeString = function (expr) {\r\n        let s = expr[0];\r\n        let start = s;\r\n        if (s !== \"'\" && s !== '\"' && s !== \"`\") {\r\n            return false;\r\n        }\r\n        let i = 1;\r\n        let cur;\r\n        while (expr[i] && expr[i] !== start) {\r\n            cur = expr[i];\r\n            s += cur;\r\n            if (cur === \"\\\\\") {\r\n                i++;\r\n                cur = expr[i];\r\n                if (!cur) {\r\n                    throw new Error(\"Invalid expression\");\r\n                }\r\n                s += cur;\r\n            }\r\n            i++;\r\n        }\r\n        if (expr[i] !== start) {\r\n            throw new Error(\"Invalid expression\");\r\n        }\r\n        s += start;\r\n        if (start === \"`\") {\r\n            return {\r\n                type: \"TEMPLATE_STRING\",\r\n                value: s,\r\n                replace(replacer) {\r\n                    return s.replace(/\\$\\{(.*?)\\}/g, (match, group) => {\r\n                        return \"${\" + replacer(group) + \"}\";\r\n                    });\r\n                },\r\n            };\r\n        }\r\n        return { type: \"VALUE\", value: s };\r\n    };\r\n    let tokenizeNumber = function (expr) {\r\n        let s = expr[0];\r\n        if (s && s.match(/[0-9]/)) {\r\n            let i = 1;\r\n            while (expr[i] && expr[i].match(/[0-9]|\\./)) {\r\n                s += expr[i];\r\n                i++;\r\n            }\r\n            return { type: \"VALUE\", value: s };\r\n        }\r\n        else {\r\n            return false;\r\n        }\r\n    };\r\n    let tokenizeSymbol = function (expr) {\r\n        let s = expr[0];\r\n        if (s && s.match(/[a-zA-Z_\\$]/)) {\r\n            let i = 1;\r\n            while (expr[i] && expr[i].match(/\\w/)) {\r\n                s += expr[i];\r\n                i++;\r\n            }\r\n            if (s in WORD_REPLACEMENT) {\r\n                return { type: \"OPERATOR\", value: WORD_REPLACEMENT[s], size: s.length };\r\n            }\r\n            return { type: \"SYMBOL\", value: s };\r\n        }\r\n        else {\r\n            return false;\r\n        }\r\n    };\r\n    const tokenizeStatic = function (expr) {\r\n        const char = expr[0];\r\n        if (char && char in STATIC_TOKEN_MAP) {\r\n            return { type: STATIC_TOKEN_MAP[char], value: char };\r\n        }\r\n        return false;\r\n    };\r\n    const tokenizeOperator = function (expr) {\r\n        for (let op of OPERATORS) {\r\n            if (expr.startsWith(op)) {\r\n                return { type: \"OPERATOR\", value: op };\r\n            }\r\n        }\r\n        return false;\r\n    };\r\n    const TOKENIZERS = [\r\n        tokenizeString,\r\n        tokenizeNumber,\r\n        tokenizeOperator,\r\n        tokenizeSymbol,\r\n        tokenizeStatic,\r\n    ];\r\n    /**\r\n     * Convert a javascript expression (as a string) into a list of tokens. For\r\n     * example: `tokenize(\"1 + b\")` will return:\r\n     * ```js\r\n     *  [\r\n     *   {type: \"VALUE\", value: \"1\"},\r\n     *   {type: \"OPERATOR\", value: \"+\"},\r\n     *   {type: \"SYMBOL\", value: \"b\"}\r\n     * ]\r\n     * ```\r\n     */\r\n    function tokenize(expr) {\r\n        const result = [];\r\n        let token = true;\r\n        while (token) {\r\n            expr = expr.trim();\r\n            if (expr) {\r\n                for (let tokenizer of TOKENIZERS) {\r\n                    token = tokenizer(expr);\r\n                    if (token) {\r\n                        result.push(token);\r\n                        expr = expr.slice(token.size || token.value.length);\r\n                        break;\r\n                    }\r\n                }\r\n            }\r\n            else {\r\n                token = false;\r\n            }\r\n        }\r\n        if (expr.length) {\r\n            throw new Error(`Tokenizer error: could not tokenize \"${expr}\"`);\r\n        }\r\n        return result;\r\n    }\r\n    //------------------------------------------------------------------------------\r\n    // Expression \"evaluator\"\r\n    //------------------------------------------------------------------------------\r\n    const isLeftSeparator = (token) => token && (token.type === \"LEFT_BRACE\" || token.type === \"COMMA\");\r\n    const isRightSeparator = (token) => token && (token.type === \"RIGHT_BRACE\" || token.type === \"COMMA\");\r\n    /**\r\n     * This is the main function exported by this file. This is the code that will\r\n     * process an expression (given as a string) and returns another expression with\r\n     * proper lookups in the context.\r\n     *\r\n     * Usually, this kind of code would be very simple to do if we had an AST (so,\r\n     * if we had a javascript parser), since then, we would only need to find the\r\n     * variables and replace them.  However, a parser is more complicated, and there\r\n     * are no standard builtin parser API.\r\n     *\r\n     * Since this method is applied to simple javasript expressions, and the work to\r\n     * be done is actually quite simple, we actually can get away with not using a\r\n     * parser, which helps with the code size.\r\n     *\r\n     * Here is the heuristic used by this method to determine if a token is a\r\n     * variable:\r\n     * - by default, all symbols are considered a variable\r\n     * - unless the previous token is a dot (in that case, this is a property: `a.b`)\r\n     * - or if the previous token is a left brace or a comma, and the next token is\r\n     *   a colon (in that case, this is an object key: `{a: b}`)\r\n     *\r\n     * Some specific code is also required to support arrow functions. If we detect\r\n     * the arrow operator, then we add the current (or some previous tokens) token to\r\n     * the list of variables so it does not get replaced by a lookup in the context\r\n     */\r\n    function compileExprToArray(expr, scope) {\r\n        const localVars = new Set();\r\n        scope = Object.create(scope);\r\n        const tokens = tokenize(expr);\r\n        let i = 0;\r\n        let stack = []; // to track last opening [ or {\r\n        while (i < tokens.length) {\r\n            let token = tokens[i];\r\n            let prevToken = tokens[i - 1];\r\n            let nextToken = tokens[i + 1];\r\n            let groupType = stack[stack.length - 1];\r\n            switch (token.type) {\r\n                case \"LEFT_BRACE\":\r\n                case \"LEFT_BRACKET\":\r\n                    stack.push(token.type);\r\n                    break;\r\n                case \"RIGHT_BRACE\":\r\n                case \"RIGHT_BRACKET\":\r\n                    stack.pop();\r\n            }\r\n            let isVar = token.type === \"SYMBOL\" && !RESERVED_WORDS.includes(token.value);\r\n            if (token.type === \"SYMBOL\" && !RESERVED_WORDS.includes(token.value)) {\r\n                if (prevToken) {\r\n                    // normalize missing tokens: {a} should be equivalent to {a:a}\r\n                    if (groupType === \"LEFT_BRACE\" &&\r\n                        isLeftSeparator(prevToken) &&\r\n                        isRightSeparator(nextToken)) {\r\n                        tokens.splice(i + 1, 0, { type: \"COLON\", value: \":\" }, Object.assign({}, token));\r\n                        nextToken = tokens[i + 1];\r\n                    }\r\n                    if (prevToken.type === \"OPERATOR\" && prevToken.value === \".\") {\r\n                        isVar = false;\r\n                    }\r\n                    else if (prevToken.type === \"LEFT_BRACE\" || prevToken.type === \"COMMA\") {\r\n                        if (nextToken && nextToken.type === \"COLON\") {\r\n                            isVar = false;\r\n                        }\r\n                    }\r\n                }\r\n            }\r\n            if (token.type === \"TEMPLATE_STRING\") {\r\n                token.value = token.replace((expr) => compileExpr(expr, scope));\r\n            }\r\n            if (nextToken && nextToken.type === \"OPERATOR\" && nextToken.value === \"=>\") {\r\n                if (token.type === \"RIGHT_PAREN\") {\r\n                    let j = i - 1;\r\n                    while (j > 0 && tokens[j].type !== \"LEFT_PAREN\") {\r\n                        if (tokens[j].type === \"SYMBOL\" && tokens[j].originalValue) {\r\n                            tokens[j].value = tokens[j].originalValue;\r\n                            scope[tokens[j].value] = { id: tokens[j].value, expr: tokens[j].value };\r\n                            localVars.add(tokens[j].value);\r\n                        }\r\n                        j--;\r\n                    }\r\n                }\r\n                else {\r\n                    scope[token.value] = { id: token.value, expr: token.value };\r\n                    localVars.add(token.value);\r\n                }\r\n            }\r\n            if (isVar) {\r\n                token.varName = token.value;\r\n                if (token.value in scope && \"id\" in scope[token.value]) {\r\n                    token.value = scope[token.value].expr;\r\n                }\r\n                else {\r\n                    token.originalValue = token.value;\r\n                    token.value = `scope['${token.value}']`;\r\n                }\r\n            }\r\n            i++;\r\n        }\r\n        // Mark all variables that have been used locally.\r\n        // This assumes the expression has only one scope (incorrect but \"good enough for now\")\r\n        for (const token of tokens) {\r\n            if (token.type === \"SYMBOL\" && localVars.has(token.value)) {\r\n                token.isLocal = true;\r\n            }\r\n        }\r\n        return tokens;\r\n    }\r\n    function compileExpr(expr, scope) {\r\n        return compileExprToArray(expr, scope)\r\n            .map((t) => t.value)\r\n            .join(\"\");\r\n    }\r\n\r\n    const INTERP_REGEXP = /\\{\\{.*?\\}\\}/g;\r\n    //------------------------------------------------------------------------------\r\n    // Compilation Context\r\n    //------------------------------------------------------------------------------\r\n    class CompilationContext {\r\n        constructor(name) {\r\n            this.code = [];\r\n            this.variables = {};\r\n            this.escaping = false;\r\n            this.parentNode = null;\r\n            this.parentTextNode = null;\r\n            this.rootNode = null;\r\n            this.indentLevel = 0;\r\n            this.shouldDefineParent = false;\r\n            this.shouldDefineScope = false;\r\n            this.protectedScopeNumber = 0;\r\n            this.shouldDefineQWeb = false;\r\n            this.shouldDefineUtils = false;\r\n            this.shouldDefineRefs = false;\r\n            this.shouldDefineResult = true;\r\n            this.loopNumber = 0;\r\n            this.inPreTag = false;\r\n            this.allowMultipleRoots = false;\r\n            this.hasParentWidget = false;\r\n            this.hasKey0 = false;\r\n            this.keyStack = [];\r\n            this.rootContext = this;\r\n            this.templateName = name || \"noname\";\r\n            this.addLine(\"let h = this.h;\");\r\n        }\r\n        generateID() {\r\n            return CompilationContext.nextID++;\r\n        }\r\n        /**\r\n         * This method generates a \"template key\", which is basically a unique key\r\n         * which depends on the currently set keys, and on the iteration numbers (if\r\n         * we are in a loop).\r\n         *\r\n         * Such a key is necessary when we need to associate an id to some element\r\n         * generated by a template (for example, a component)\r\n         */\r\n        generateTemplateKey(prefix = \"\") {\r\n            const id = this.generateID();\r\n            if (this.loopNumber === 0 && !this.hasKey0) {\r\n                return `'${prefix}__${id}__'`;\r\n            }\r\n            let key = `\\`${prefix}__${id}__`;\r\n            let start = this.hasKey0 ? 0 : 1;\r\n            for (let i = start; i < this.loopNumber + 1; i++) {\r\n                key += `\\${key${i}}__`;\r\n            }\r\n            this.addLine(`let k${id} = ${key}\\`;`);\r\n            return `k${id}`;\r\n        }\r\n        generateCode() {\r\n            if (this.shouldDefineResult) {\r\n                this.code.unshift(\"    let result;\");\r\n            }\r\n            if (this.shouldDefineScope) {\r\n                this.code.unshift(\"    let scope = Object.create(context);\");\r\n            }\r\n            if (this.shouldDefineRefs) {\r\n                this.code.unshift(\"    context.__owl__.refs = context.__owl__.refs || {};\");\r\n            }\r\n            if (this.shouldDefineParent) {\r\n                if (this.hasParentWidget) {\r\n                    this.code.unshift(\"    let parent = extra.parent;\");\r\n                }\r\n                else {\r\n                    this.code.unshift(\"    let parent = context;\");\r\n                }\r\n            }\r\n            if (this.shouldDefineQWeb) {\r\n                this.code.unshift(\"    let QWeb = this.constructor;\");\r\n            }\r\n            if (this.shouldDefineUtils) {\r\n                this.code.unshift(\"    let utils = this.constructor.utils;\");\r\n            }\r\n            return this.code;\r\n        }\r\n        withParent(node) {\r\n            if (!this.allowMultipleRoots &&\r\n                this === this.rootContext &&\r\n                (this.parentNode || this.parentTextNode)) {\r\n                throw new Error(\"A template should not have more than one root node\");\r\n            }\r\n            if (!this.rootContext.rootNode) {\r\n                this.rootContext.rootNode = node;\r\n            }\r\n            if (!this.parentNode && this.rootContext.shouldDefineResult) {\r\n                this.addLine(`result = vn${node};`);\r\n            }\r\n            return this.subContext(\"parentNode\", node);\r\n        }\r\n        subContext(key, value) {\r\n            const newContext = Object.create(this);\r\n            newContext[key] = value;\r\n            return newContext;\r\n        }\r\n        indent() {\r\n            this.rootContext.indentLevel++;\r\n        }\r\n        dedent() {\r\n            this.rootContext.indentLevel--;\r\n        }\r\n        addLine(line) {\r\n            const prefix = new Array(this.indentLevel + 2).join(\"    \");\r\n            this.code.push(prefix + line);\r\n            return this.code.length - 1;\r\n        }\r\n        addIf(condition) {\r\n            this.addLine(`if (${condition}) {`);\r\n            this.indent();\r\n        }\r\n        addElse() {\r\n            this.dedent();\r\n            this.addLine(\"} else {\");\r\n            this.indent();\r\n        }\r\n        closeIf() {\r\n            this.dedent();\r\n            this.addLine(\"}\");\r\n        }\r\n        getValue(val) {\r\n            return val in this.variables ? this.getValue(this.variables[val]) : val;\r\n        }\r\n        /**\r\n         * Prepare an expression for being consumed at render time.  Its main job\r\n         * is to\r\n         * - replace unknown variables by a lookup in the context\r\n         * - replace already defined variables by their internal name\r\n         */\r\n        formatExpression(expr) {\r\n            this.rootContext.shouldDefineScope = true;\r\n            return compileExpr(expr, this.variables);\r\n        }\r\n        captureExpression(expr) {\r\n            this.rootContext.shouldDefineScope = true;\r\n            const argId = this.generateID();\r\n            const tokens = compileExprToArray(expr, this.variables);\r\n            const done = new Set();\r\n            return tokens\r\n                .map((tok, i) => {\r\n                // \"this\" in captured expressions should be the current component\r\n                if (tok.value === \"this\") {\r\n                    if (!done.has(\"this\")) {\r\n                        done.add(\"this\");\r\n                        this.addLine(`const this_${argId} = utils.getComponent(context);`);\r\n                    }\r\n                    tok.value = `this_${argId}`;\r\n                }\r\n                // Variables that should be looked up in the scope. isLocal is for arrow\r\n                // function arguments that should stay untouched (eg \"ev => ev\" should\r\n                // not become \"const ev_1 = scope['ev']; ev_1 => ev_1\")\r\n                if (tok.varName &&\r\n                    !tok.isLocal &&\r\n                    // HACK: for backwards compatibility, we don't capture bare methods\r\n                    // this allows them to be called with the rendering context/scope\r\n                    // as their this value.\r\n                    (!tokens[i + 1] || tokens[i + 1].type !== \"LEFT_PAREN\")) {\r\n                    if (!done.has(tok.varName)) {\r\n                        done.add(tok.varName);\r\n                        this.addLine(`const ${tok.varName}_${argId} = ${tok.value};`);\r\n                    }\r\n                    tok.value = `${tok.varName}_${argId}`;\r\n                }\r\n                return tok.value;\r\n            })\r\n                .join(\"\");\r\n        }\r\n        /**\r\n         * Perform string interpolation on the given string. Note that if the whole\r\n         * string is an expression, it simply returns it (formatted and enclosed in\r\n         * parentheses).\r\n         * For instance:\r\n         *   'Hello {{x}}!' -> `Hello ${x}`\r\n         *   '{{x ? 'a': 'b'}}' -> (x ? 'a' : 'b')\r\n         */\r\n        interpolate(s) {\r\n            let matches = s.match(INTERP_REGEXP);\r\n            if (matches && matches[0].length === s.length) {\r\n                return `(${this.formatExpression(s.slice(2, -2))})`;\r\n            }\r\n            let r = s.replace(/\\{\\{.*?\\}\\}/g, (s) => \"${\" + this.formatExpression(s.slice(2, -2)) + \"}\");\r\n            return \"`\" + r + \"`\";\r\n        }\r\n        startProtectScope(codeBlock) {\r\n            const protectID = this.generateID();\r\n            this.rootContext.protectedScopeNumber++;\r\n            this.rootContext.shouldDefineScope = true;\r\n            const scopeExpr = `Object.create(scope);`;\r\n            this.addLine(`let _origScope${protectID} = scope;`);\r\n            this.addLine(`scope = ${scopeExpr}`);\r\n            if (!codeBlock) {\r\n                this.addLine(`scope.__access_mode__ = 'ro';`);\r\n            }\r\n            return protectID;\r\n        }\r\n        stopProtectScope(protectID) {\r\n            this.rootContext.protectedScopeNumber--;\r\n            this.addLine(`scope = _origScope${protectID};`);\r\n        }\r\n    }\r\n    CompilationContext.nextID = 1;\r\n\r\n    //------------------------------------------------------------------------------\r\n    // module/props.ts\r\n    //------------------------------------------------------------------------------\r\n    function updateProps(oldVnode, vnode) {\r\n        var key, cur, old, elm = vnode.elm, oldProps = oldVnode.data.props, props = vnode.data.props;\r\n        if (!oldProps && !props)\r\n            return;\r\n        if (oldProps === props)\r\n            return;\r\n        oldProps = oldProps || {};\r\n        props = props || {};\r\n        for (key in oldProps) {\r\n            if (!props[key]) {\r\n                delete elm[key];\r\n            }\r\n        }\r\n        for (key in props) {\r\n            cur = props[key];\r\n            old = oldProps[key];\r\n            if (old !== cur && (key !== \"value\" || elm[key] !== cur)) {\r\n                elm[key] = cur;\r\n            }\r\n        }\r\n    }\r\n    const propsModule = {\r\n        create: updateProps,\r\n        update: updateProps,\r\n    };\r\n    //------------------------------------------------------------------------------\r\n    // module/eventlisteners.ts\r\n    //------------------------------------------------------------------------------\r\n    function invokeHandler(handler, vnode, event) {\r\n        if (typeof handler === \"function\") {\r\n            // call function handler\r\n            handler.call(vnode, event, vnode);\r\n        }\r\n        else if (typeof handler === \"object\") {\r\n            // call handler with arguments\r\n            if (typeof handler[0] === \"function\") {\r\n                // special case for single argument for performance\r\n                if (handler.length === 2) {\r\n                    handler[0].call(vnode, handler[1], event, vnode);\r\n                }\r\n                else {\r\n                    var args = handler.slice(1);\r\n                    args.push(event);\r\n                    args.push(vnode);\r\n                    handler[0].apply(vnode, args);\r\n                }\r\n            }\r\n            else {\r\n                // call multiple handlers\r\n                for (let i = 0, iLen = handler.length; i < iLen; i++) {\r\n                    invokeHandler(handler[i], vnode, event);\r\n                }\r\n            }\r\n        }\r\n    }\r\n    function handleEvent(event, vnode) {\r\n        var name = event.type, on = vnode.data.on;\r\n        // call event handler(s) if exists\r\n        if (on) {\r\n            if (on[name]) {\r\n                invokeHandler(on[name], vnode, event);\r\n            }\r\n            else if (on[\"!\" + name]) {\r\n                invokeHandler(on[\"!\" + name], vnode, event);\r\n            }\r\n        }\r\n    }\r\n    function createListener() {\r\n        return function handler(event) {\r\n            handleEvent(event, handler.vnode);\r\n        };\r\n    }\r\n    function updateEventListeners(oldVnode, vnode) {\r\n        var oldOn = oldVnode.data.on, oldListener = oldVnode.listener, oldElm = oldVnode.elm, on = vnode && vnode.data.on, elm = (vnode && vnode.elm), name;\r\n        // optimization for reused immutable handlers\r\n        if (oldOn === on) {\r\n            return;\r\n        }\r\n        // remove existing listeners which no longer used\r\n        if (oldOn && oldListener) {\r\n            // if element changed or deleted we remove all existing listeners unconditionally\r\n            if (!on) {\r\n                for (name in oldOn) {\r\n                    // remove listener if element was changed or existing listeners removed\r\n                    const capture = name.charAt(0) === \"!\";\r\n                    name = capture ? name.slice(1) : name;\r\n                    oldElm.removeEventListener(name, oldListener, capture);\r\n                }\r\n            }\r\n            else {\r\n                for (name in oldOn) {\r\n                    // remove listener if existing listener removed\r\n                    if (!on[name]) {\r\n                        const capture = name.charAt(0) === \"!\";\r\n                        name = capture ? name.slice(1) : name;\r\n                        oldElm.removeEventListener(name, oldListener, capture);\r\n                    }\r\n                }\r\n            }\r\n        }\r\n        // add new listeners which has not already attached\r\n        if (on) {\r\n            // reuse existing listener or create new\r\n            var listener = (vnode.listener = oldVnode.listener || createListener());\r\n            // update vnode for listener\r\n            listener.vnode = vnode;\r\n            // if element changed or added we add all needed listeners unconditionally\r\n            if (!oldOn) {\r\n                for (name in on) {\r\n                    // add listener if element was changed or new listeners added\r\n                    const capture = name.charAt(0) === \"!\";\r\n                    name = capture ? name.slice(1) : name;\r\n                    elm.addEventListener(name, listener, capture);\r\n                }\r\n            }\r\n            else {\r\n                for (name in on) {\r\n                    // add listener if new listener added\r\n                    if (!oldOn[name]) {\r\n                        const capture = name.charAt(0) === \"!\";\r\n                        name = capture ? name.slice(1) : name;\r\n                        elm.addEventListener(name, listener, capture);\r\n                    }\r\n                }\r\n            }\r\n        }\r\n    }\r\n    const eventListenersModule = {\r\n        create: updateEventListeners,\r\n        update: updateEventListeners,\r\n        destroy: updateEventListeners,\r\n    };\r\n    //------------------------------------------------------------------------------\r\n    // attributes.ts\r\n    //------------------------------------------------------------------------------\r\n    const xlinkNS = \"http://www.w3.org/1999/xlink\";\r\n    const xmlNS = \"http://www.w3.org/XML/1998/namespace\";\r\n    const colonChar = 58;\r\n    const xChar = 120;\r\n    function updateAttrs(oldVnode, vnode) {\r\n        var key, elm = vnode.elm, oldAttrs = oldVnode.data.attrs, attrs = vnode.data.attrs;\r\n        if (!oldAttrs && !attrs)\r\n            return;\r\n        if (oldAttrs === attrs)\r\n            return;\r\n        oldAttrs = oldAttrs || {};\r\n        attrs = attrs || {};\r\n        // update modified attributes, add new attributes\r\n        for (key in attrs) {\r\n            const cur = attrs[key];\r\n            const old = oldAttrs[key];\r\n            if (old !== cur) {\r\n                if (cur === true) {\r\n                    elm.setAttribute(key, \"\");\r\n                }\r\n                else if (cur === false) {\r\n                    elm.removeAttribute(key);\r\n                }\r\n                else {\r\n                    if (key.charCodeAt(0) !== xChar) {\r\n                        elm.setAttribute(key, cur);\r\n                    }\r\n                    else if (key.charCodeAt(3) === colonChar) {\r\n                        // Assume xml namespace\r\n                        elm.setAttributeNS(xmlNS, key, cur);\r\n                    }\r\n                    else if (key.charCodeAt(5) === colonChar) {\r\n                        // Assume xlink namespace\r\n                        elm.setAttributeNS(xlinkNS, key, cur);\r\n                    }\r\n                    else {\r\n                        elm.setAttribute(key, cur);\r\n                    }\r\n                }\r\n            }\r\n        }\r\n        // remove removed attributes\r\n        // use `in` operator since the previous `for` iteration uses it (.i.e. add even attributes with undefined value)\r\n        // the other option is to remove all attributes with value == undefined\r\n        for (key in oldAttrs) {\r\n            if (!(key in attrs)) {\r\n                elm.removeAttribute(key);\r\n            }\r\n        }\r\n    }\r\n    const attrsModule = {\r\n        create: updateAttrs,\r\n        update: updateAttrs,\r\n    };\r\n    //------------------------------------------------------------------------------\r\n    // class.ts\r\n    //------------------------------------------------------------------------------\r\n    function updateClass(oldVnode, vnode) {\r\n        var cur, name, elm, oldClass = oldVnode.data.class, klass = vnode.data.class;\r\n        if (!oldClass && !klass)\r\n            return;\r\n        if (oldClass === klass)\r\n            return;\r\n        oldClass = oldClass || {};\r\n        klass = klass || {};\r\n        elm = vnode.elm;\r\n        for (name in oldClass) {\r\n            if (name && !klass[name] && !Object.prototype.hasOwnProperty.call(klass, name)) {\r\n                // was `true` and now not provided\r\n                elm.classList.remove(name);\r\n            }\r\n        }\r\n        for (name in klass) {\r\n            cur = klass[name];\r\n            if (cur !== oldClass[name]) {\r\n                elm.classList[cur ? \"add\" : \"remove\"](name);\r\n            }\r\n        }\r\n    }\r\n    const classModule = { create: updateClass, update: updateClass };\r\n\r\n    /**\r\n     * Owl VDOM\r\n     *\r\n     * This file contains an implementation of a virtual DOM, which is a system that\r\n     * can generate in-memory representations of a DOM tree, compare them, and\r\n     * eventually change a concrete DOM tree to match its representation, in an\r\n     * hopefully efficient way.\r\n     *\r\n     * Note that this code is a fork of Snabbdom, slightly tweaked/optimized for our\r\n     * needs (see https://github.com/snabbdom/snabbdom).\r\n     *\r\n     * The main exported values are:\r\n     * - interface VNode\r\n     * - h function (a helper function to generate a vnode)\r\n     * - patch function (to apply a vnode to an actual DOM node)\r\n     */\r\n    function vnode(sel, data, children, text, elm) {\r\n        let key = data === undefined ? undefined : data.key;\r\n        return { sel, data, children, text, elm, key };\r\n    }\r\n    //------------------------------------------------------------------------------\r\n    // snabbdom.ts\r\n    //------------------------------------------------------------------------------\r\n    function isUndef(s) {\r\n        return s === undefined;\r\n    }\r\n    function isDef(s) {\r\n        return s !== undefined;\r\n    }\r\n    const emptyNode = vnode(\"\", {}, [], undefined, undefined);\r\n    function sameVnode(vnode1, vnode2) {\r\n        return vnode1.key === vnode2.key && vnode1.sel === vnode2.sel;\r\n    }\r\n    function isVnode(vnode) {\r\n        return vnode.sel !== undefined;\r\n    }\r\n    function createKeyToOldIdx(children, beginIdx, endIdx) {\r\n        let i, map = {}, key, ch;\r\n        for (i = beginIdx; i <= endIdx; ++i) {\r\n            ch = children[i];\r\n            if (ch != null) {\r\n                key = ch.key;\r\n                if (key !== undefined)\r\n                    map[key] = i;\r\n            }\r\n        }\r\n        return map;\r\n    }\r\n    const hooks$1 = [\"create\", \"update\", \"remove\", \"destroy\", \"pre\", \"post\"];\r\n    function init(modules, domApi) {\r\n        let i, j, cbs = {};\r\n        const api = domApi !== undefined ? domApi : htmlDomApi;\r\n        for (i = 0; i < hooks$1.length; ++i) {\r\n            cbs[hooks$1[i]] = [];\r\n            for (j = 0; j < modules.length; ++j) {\r\n                const hook = modules[j][hooks$1[i]];\r\n                if (hook !== undefined) {\r\n                    cbs[hooks$1[i]].push(hook);\r\n                }\r\n            }\r\n        }\r\n        function emptyNodeAt(elm) {\r\n            const id = elm.id ? \"#\" + elm.id : \"\";\r\n            const c = elm.className ? \".\" + elm.className.split(\" \").join(\".\") : \"\";\r\n            return vnode(api.tagName(elm).toLowerCase() + id + c, {}, [], undefined, elm);\r\n        }\r\n        function createRmCb(childElm, listeners) {\r\n            return function rmCb() {\r\n                if (--listeners === 0) {\r\n                    const parent = api.parentNode(childElm);\r\n                    api.removeChild(parent, childElm);\r\n                }\r\n            };\r\n        }\r\n        function createElm(vnode, insertedVnodeQueue) {\r\n            let i, iLen, data = vnode.data;\r\n            if (data !== undefined) {\r\n                if (isDef((i = data.hook)) && isDef((i = i.init))) {\r\n                    i(vnode);\r\n                    data = vnode.data;\r\n                }\r\n            }\r\n            let children = vnode.children, sel = vnode.sel;\r\n            if (sel === \"!\") {\r\n                if (isUndef(vnode.text)) {\r\n                    vnode.text = \"\";\r\n                }\r\n                vnode.elm = api.createComment(vnode.text);\r\n            }\r\n            else if (sel !== undefined) {\r\n                const elm = vnode.elm ||\r\n                    (vnode.elm =\r\n                        isDef(data) && isDef((i = data.ns))\r\n                            ? api.createElementNS(i, sel)\r\n                            : api.createElement(sel));\r\n                for (i = 0, iLen = cbs.create.length; i < iLen; ++i)\r\n                    cbs.create[i](emptyNode, vnode);\r\n                if (array(children)) {\r\n                    for (i = 0, iLen = children.length; i < iLen; ++i) {\r\n                        const ch = children[i];\r\n                        if (ch != null) {\r\n                            api.appendChild(elm, createElm(ch, insertedVnodeQueue));\r\n                        }\r\n                    }\r\n                }\r\n                else if (primitive(vnode.text)) {\r\n                    api.appendChild(elm, api.createTextNode(vnode.text));\r\n                }\r\n                i = vnode.data.hook; // Reuse variable\r\n                if (isDef(i)) {\r\n                    if (i.create)\r\n                        i.create(emptyNode, vnode);\r\n                    if (i.insert)\r\n                        insertedVnodeQueue.push(vnode);\r\n                }\r\n            }\r\n            else {\r\n                vnode.elm = api.createTextNode(vnode.text);\r\n            }\r\n            return vnode.elm;\r\n        }\r\n        function addVnodes(parentElm, before, vnodes, startIdx, endIdx, insertedVnodeQueue) {\r\n            for (; startIdx <= endIdx; ++startIdx) {\r\n                const ch = vnodes[startIdx];\r\n                if (ch != null) {\r\n                    api.insertBefore(parentElm, createElm(ch, insertedVnodeQueue), before);\r\n                }\r\n            }\r\n        }\r\n        function invokeDestroyHook(vnode) {\r\n            let i, iLen, j, jLen, data = vnode.data;\r\n            if (data !== undefined) {\r\n                if (isDef((i = data.hook)) && isDef((i = i.destroy)))\r\n                    i(vnode);\r\n                for (i = 0, iLen = cbs.destroy.length; i < iLen; ++i)\r\n                    cbs.destroy[i](vnode);\r\n                if (vnode.children !== undefined) {\r\n                    for (j = 0, jLen = vnode.children.length; j < jLen; ++j) {\r\n                        i = vnode.children[j];\r\n                        if (i != null && typeof i !== \"string\") {\r\n                            invokeDestroyHook(i);\r\n                        }\r\n                    }\r\n                }\r\n            }\r\n        }\r\n        function removeVnodes(parentElm, vnodes, startIdx, endIdx) {\r\n            for (; startIdx <= endIdx; ++startIdx) {\r\n                let i, iLen, listeners, rm, ch = vnodes[startIdx];\r\n                if (ch != null) {\r\n                    if (isDef(ch.sel)) {\r\n                        invokeDestroyHook(ch);\r\n                        listeners = cbs.remove.length + 1;\r\n                        rm = createRmCb(ch.elm, listeners);\r\n                        for (i = 0, iLen = cbs.remove.length; i < iLen; ++i)\r\n                            cbs.remove[i](ch, rm);\r\n                        if (isDef((i = ch.data)) && isDef((i = i.hook)) && isDef((i = i.remove))) {\r\n                            i(ch, rm);\r\n                        }\r\n                        else {\r\n                            rm();\r\n                        }\r\n                    }\r\n                    else {\r\n                        // Text node\r\n                        api.removeChild(parentElm, ch.elm);\r\n                    }\r\n                }\r\n            }\r\n        }\r\n        function updateChildren(parentElm, oldCh, newCh, insertedVnodeQueue) {\r\n            let oldStartIdx = 0, newStartIdx = 0;\r\n            let oldEndIdx = oldCh.length - 1;\r\n            let oldStartVnode = oldCh[0];\r\n            let oldEndVnode = oldCh[oldEndIdx];\r\n            let newEndIdx = newCh.length - 1;\r\n            let newStartVnode = newCh[0];\r\n            let newEndVnode = newCh[newEndIdx];\r\n            let oldKeyToIdx;\r\n            let idxInOld;\r\n            let elmToMove;\r\n            let before;\r\n            while (oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx) {\r\n                if (oldStartVnode == null) {\r\n                    oldStartVnode = oldCh[++oldStartIdx]; // Vnode might have been moved left\r\n                }\r\n                else if (oldEndVnode == null) {\r\n                    oldEndVnode = oldCh[--oldEndIdx];\r\n                }\r\n                else if (newStartVnode == null) {\r\n                    newStartVnode = newCh[++newStartIdx];\r\n                }\r\n                else if (newEndVnode == null) {\r\n                    newEndVnode = newCh[--newEndIdx];\r\n                }\r\n                else if (sameVnode(oldStartVnode, newStartVnode)) {\r\n                    patchVnode(oldStartVnode, newStartVnode, insertedVnodeQueue);\r\n                    oldStartVnode = oldCh[++oldStartIdx];\r\n                    newStartVnode = newCh[++newStartIdx];\r\n                }\r\n                else if (sameVnode(oldEndVnode, newEndVnode)) {\r\n                    patchVnode(oldEndVnode, newEndVnode, insertedVnodeQueue);\r\n                    oldEndVnode = oldCh[--oldEndIdx];\r\n                    newEndVnode = newCh[--newEndIdx];\r\n                }\r\n                else if (sameVnode(oldStartVnode, newEndVnode)) {\r\n                    // Vnode moved right\r\n                    patchVnode(oldStartVnode, newEndVnode, insertedVnodeQueue);\r\n                    api.insertBefore(parentElm, oldStartVnode.elm, api.nextSibling(oldEndVnode.elm));\r\n                    oldStartVnode = oldCh[++oldStartIdx];\r\n                    newEndVnode = newCh[--newEndIdx];\r\n                }\r\n                else if (sameVnode(oldEndVnode, newStartVnode)) {\r\n                    // Vnode moved left\r\n                    patchVnode(oldEndVnode, newStartVnode, insertedVnodeQueue);\r\n                    api.insertBefore(parentElm, oldEndVnode.elm, oldStartVnode.elm);\r\n                    oldEndVnode = oldCh[--oldEndIdx];\r\n                    newStartVnode = newCh[++newStartIdx];\r\n                }\r\n                else {\r\n                    if (oldKeyToIdx === undefined) {\r\n                        oldKeyToIdx = createKeyToOldIdx(oldCh, oldStartIdx, oldEndIdx);\r\n                    }\r\n                    idxInOld = oldKeyToIdx[newStartVnode.key];\r\n                    if (isUndef(idxInOld)) {\r\n                        // New element\r\n                        api.insertBefore(parentElm, createElm(newStartVnode, insertedVnodeQueue), oldStartVnode.elm);\r\n                        newStartVnode = newCh[++newStartIdx];\r\n                    }\r\n                    else {\r\n                        elmToMove = oldCh[idxInOld];\r\n                        if (elmToMove.sel !== newStartVnode.sel) {\r\n                            api.insertBefore(parentElm, createElm(newStartVnode, insertedVnodeQueue), oldStartVnode.elm);\r\n                        }\r\n                        else {\r\n                            patchVnode(elmToMove, newStartVnode, insertedVnodeQueue);\r\n                            oldCh[idxInOld] = undefined;\r\n                            api.insertBefore(parentElm, elmToMove.elm, oldStartVnode.elm);\r\n                        }\r\n                        newStartVnode = newCh[++newStartIdx];\r\n                    }\r\n                }\r\n            }\r\n            if (oldStartIdx <= oldEndIdx || newStartIdx <= newEndIdx) {\r\n                if (oldStartIdx > oldEndIdx) {\r\n                    before = newCh[newEndIdx + 1] == null ? null : newCh[newEndIdx + 1].elm;\r\n                    addVnodes(parentElm, before, newCh, newStartIdx, newEndIdx, insertedVnodeQueue);\r\n                }\r\n                else {\r\n                    removeVnodes(parentElm, oldCh, oldStartIdx, oldEndIdx);\r\n                }\r\n            }\r\n        }\r\n        function patchVnode(oldVnode, vnode, insertedVnodeQueue) {\r\n            let i, iLen, hook;\r\n            if (isDef((i = vnode.data)) && isDef((hook = i.hook)) && isDef((i = hook.prepatch))) {\r\n                i(oldVnode, vnode);\r\n            }\r\n            const elm = (vnode.elm = oldVnode.elm);\r\n            let oldCh = oldVnode.children;\r\n            let ch = vnode.children;\r\n            if (oldVnode === vnode)\r\n                return;\r\n            if (vnode.data !== undefined) {\r\n                for (i = 0, iLen = cbs.update.length; i < iLen; ++i)\r\n                    cbs.update[i](oldVnode, vnode);\r\n                i = vnode.data.hook;\r\n                if (isDef(i) && isDef((i = i.update)))\r\n                    i(oldVnode, vnode);\r\n            }\r\n            if (isUndef(vnode.text)) {\r\n                if (isDef(oldCh) && isDef(ch)) {\r\n                    if (oldCh !== ch)\r\n                        updateChildren(elm, oldCh, ch, insertedVnodeQueue);\r\n                }\r\n                else if (isDef(ch)) {\r\n                    if (isDef(oldVnode.text))\r\n                        api.setTextContent(elm, \"\");\r\n                    addVnodes(elm, null, ch, 0, ch.length - 1, insertedVnodeQueue);\r\n                }\r\n                else if (isDef(oldCh)) {\r\n                    removeVnodes(elm, oldCh, 0, oldCh.length - 1);\r\n                }\r\n                else if (isDef(oldVnode.text)) {\r\n                    api.setTextContent(elm, \"\");\r\n                }\r\n            }\r\n            else if (oldVnode.text !== vnode.text) {\r\n                if (isDef(oldCh)) {\r\n                    removeVnodes(elm, oldCh, 0, oldCh.length - 1);\r\n                }\r\n                api.setTextContent(elm, vnode.text);\r\n            }\r\n            if (isDef(hook) && isDef((i = hook.postpatch))) {\r\n                i(oldVnode, vnode);\r\n            }\r\n        }\r\n        return function patch(oldVnode, vnode) {\r\n            let i, iLen, elm, parent;\r\n            const insertedVnodeQueue = [];\r\n            for (i = 0, iLen = cbs.pre.length; i < iLen; ++i)\r\n                cbs.pre[i]();\r\n            if (!isVnode(oldVnode)) {\r\n                oldVnode = emptyNodeAt(oldVnode);\r\n            }\r\n            if (sameVnode(oldVnode, vnode)) {\r\n                patchVnode(oldVnode, vnode, insertedVnodeQueue);\r\n            }\r\n            else {\r\n                elm = oldVnode.elm;\r\n                parent = api.parentNode(elm);\r\n                createElm(vnode, insertedVnodeQueue);\r\n                if (parent !== null) {\r\n                    api.insertBefore(parent, vnode.elm, api.nextSibling(elm));\r\n                    removeVnodes(parent, [oldVnode], 0, 0);\r\n                }\r\n            }\r\n            for (i = 0, iLen = insertedVnodeQueue.length; i < iLen; ++i) {\r\n                insertedVnodeQueue[i].data.hook.insert(insertedVnodeQueue[i]);\r\n            }\r\n            for (i = 0, iLen = cbs.post.length; i < iLen; ++i)\r\n                cbs.post[i]();\r\n            return vnode;\r\n        };\r\n    }\r\n    //------------------------------------------------------------------------------\r\n    // is.ts\r\n    //------------------------------------------------------------------------------\r\n    const array = Array.isArray;\r\n    function primitive(s) {\r\n        return typeof s === \"string\" || typeof s === \"number\";\r\n    }\r\n    function createElement(tagName) {\r\n        return document.createElement(tagName);\r\n    }\r\n    function createElementNS(namespaceURI, qualifiedName) {\r\n        return document.createElementNS(namespaceURI, qualifiedName);\r\n    }\r\n    function createTextNode(text) {\r\n        return document.createTextNode(text);\r\n    }\r\n    function createComment(text) {\r\n        return document.createComment(text);\r\n    }\r\n    function insertBefore(parentNode, newNode, referenceNode) {\r\n        parentNode.insertBefore(newNode, referenceNode);\r\n    }\r\n    function removeChild(node, child) {\r\n        node.removeChild(child);\r\n    }\r\n    function appendChild(node, child) {\r\n        node.appendChild(child);\r\n    }\r\n    function parentNode(node) {\r\n        return node.parentNode;\r\n    }\r\n    function nextSibling(node) {\r\n        return node.nextSibling;\r\n    }\r\n    function tagName(elm) {\r\n        return elm.tagName;\r\n    }\r\n    function setTextContent(node, text) {\r\n        node.textContent = text;\r\n    }\r\n    const htmlDomApi = {\r\n        createElement,\r\n        createElementNS,\r\n        createTextNode,\r\n        createComment,\r\n        insertBefore,\r\n        removeChild,\r\n        appendChild,\r\n        parentNode,\r\n        nextSibling,\r\n        tagName,\r\n        setTextContent,\r\n    };\r\n    function addNS(data, children, sel) {\r\n        if (sel === \"dummy\") {\r\n            // we do not need to add the namespace on dummy elements, they come from a\r\n            // subcomponent, which will handle the namespace itself\r\n            return;\r\n        }\r\n        data.ns = \"http://www.w3.org/2000/svg\";\r\n        if (sel !== \"foreignObject\" && children !== undefined) {\r\n            for (let i = 0, iLen = children.length; i < iLen; ++i) {\r\n                const child = children[i];\r\n                let childData = child.data;\r\n                if (childData !== undefined) {\r\n                    addNS(childData, child.children, child.sel);\r\n                }\r\n            }\r\n        }\r\n    }\r\n    function h(sel, b, c) {\r\n        var data = {}, children, text, i, iLen;\r\n        if (c !== undefined) {\r\n            data = b;\r\n            if (array(c)) {\r\n                children = c;\r\n            }\r\n            else if (primitive(c)) {\r\n                text = c;\r\n            }\r\n            else if (c && c.sel) {\r\n                children = [c];\r\n            }\r\n        }\r\n        else if (b !== undefined) {\r\n            if (array(b)) {\r\n                children = b;\r\n            }\r\n            else if (primitive(b)) {\r\n                text = b;\r\n            }\r\n            else if (b && b.sel) {\r\n                children = [b];\r\n            }\r\n            else {\r\n                data = b;\r\n            }\r\n        }\r\n        if (children !== undefined) {\r\n            for (i = 0, iLen = children.length; i < iLen; ++i) {\r\n                if (primitive(children[i]))\r\n                    children[i] = vnode(undefined, undefined, undefined, children[i], undefined);\r\n            }\r\n        }\r\n        return vnode(sel, data, children, text, undefined);\r\n    }\r\n\r\n    const patch = init([eventListenersModule, attrsModule, propsModule, classModule]);\r\n\r\n    let localStorage = null;\r\n    const browser = {\r\n        setTimeout: window.setTimeout.bind(window),\r\n        clearTimeout: window.clearTimeout.bind(window),\r\n        setInterval: window.setInterval.bind(window),\r\n        clearInterval: window.clearInterval.bind(window),\r\n        requestAnimationFrame: window.requestAnimationFrame.bind(window),\r\n        random: Math.random,\r\n        Date: window.Date,\r\n        fetch: (window.fetch || (() => { })).bind(window),\r\n        get localStorage() {\r\n            return localStorage || window.localStorage;\r\n        },\r\n        set localStorage(newLocalStorage) {\r\n            localStorage = newLocalStorage;\r\n        },\r\n    };\r\n\r\n    /**\r\n     * Owl Utils\r\n     *\r\n     * We have here a small collection of utility functions:\r\n     *\r\n     * - whenReady\r\n     * - loadJS\r\n     * - loadFile\r\n     * - escape\r\n     * - debounce\r\n     */\r\n    function whenReady(fn) {\r\n        return new Promise(function (resolve) {\r\n            if (document.readyState !== \"loading\") {\r\n                resolve();\r\n            }\r\n            else {\r\n                document.addEventListener(\"DOMContentLoaded\", resolve, false);\r\n            }\r\n        }).then(fn || function () { });\r\n    }\r\n    const loadedScripts = {};\r\n    function loadJS(url) {\r\n        if (url in loadedScripts) {\r\n            return loadedScripts[url];\r\n        }\r\n        const promise = new Promise(function (resolve, reject) {\r\n            const script = document.createElement(\"script\");\r\n            script.type = \"text/javascript\";\r\n            script.src = url;\r\n            script.onload = function () {\r\n                resolve();\r\n            };\r\n            script.onerror = function () {\r\n                reject(`Error loading file '${url}'`);\r\n            };\r\n            const head = document.head || document.getElementsByTagName(\"head\")[0];\r\n            head.appendChild(script);\r\n        });\r\n        loadedScripts[url] = promise;\r\n        return promise;\r\n    }\r\n    async function loadFile(url) {\r\n        const result = await browser.fetch(url);\r\n        if (!result.ok) {\r\n            throw new Error(\"Error while fetching xml templates\");\r\n        }\r\n        return await result.text();\r\n    }\r\n    function escape(str) {\r\n        if (str === undefined) {\r\n            return \"\";\r\n        }\r\n        if (typeof str === \"number\") {\r\n            return String(str);\r\n        }\r\n        const p = document.createElement(\"p\");\r\n        p.textContent = str;\r\n        return p.innerHTML;\r\n    }\r\n    /**\r\n     * Returns a function, that, as long as it continues to be invoked, will not\r\n     * be triggered. The function will be called after it stops being called for\r\n     * N milliseconds. If `immediate` is passed, trigger the function on the\r\n     * leading edge, instead of the trailing.\r\n     *\r\n     * Inspired by https://davidwalsh.name/javascript-debounce-function\r\n     */\r\n    function debounce(func, wait, immediate) {\r\n        let timeout;\r\n        return function () {\r\n            const context = this;\r\n            const args = arguments;\r\n            function later() {\r\n                timeout = null;\r\n                if (!immediate) {\r\n                    func.apply(context, args);\r\n                }\r\n            }\r\n            const callNow = immediate && !timeout;\r\n            browser.clearTimeout(timeout);\r\n            timeout = browser.setTimeout(later, wait);\r\n            if (callNow) {\r\n                func.apply(context, args);\r\n            }\r\n        };\r\n    }\r\n    function shallowEqual(p1, p2) {\r\n        for (let k in p1) {\r\n            if (p1[k] !== p2[k]) {\r\n                return false;\r\n            }\r\n        }\r\n        return true;\r\n    }\r\n\r\n    var _utils = /*#__PURE__*/Object.freeze({\r\n        __proto__: null,\r\n        whenReady: whenReady,\r\n        loadJS: loadJS,\r\n        loadFile: loadFile,\r\n        escape: escape,\r\n        debounce: debounce,\r\n        shallowEqual: shallowEqual\r\n    });\r\n\r\n    //------------------------------------------------------------------------------\r\n    // Const/global stuff/helpers\r\n    //------------------------------------------------------------------------------\r\n    const TRANSLATABLE_ATTRS = [\"label\", \"title\", \"placeholder\", \"alt\"];\r\n    const lineBreakRE = /[\\r\\n]/;\r\n    const whitespaceRE = /\\s+/g;\r\n    const translationRE = /^(\\s*)([\\s\\S]+?)(\\s*)$/;\r\n    const NODE_HOOKS_PARAMS = {\r\n        create: \"(_, n)\",\r\n        insert: \"vn\",\r\n        remove: \"(vn, rm)\",\r\n        destroy: \"()\",\r\n    };\r\n    function isComponent(obj) {\r\n        return obj && obj.hasOwnProperty(\"__owl__\");\r\n    }\r\n    class VDomArray extends Array {\r\n        toString() {\r\n            return vDomToString(this);\r\n        }\r\n    }\r\n    function vDomToString(vdom) {\r\n        return vdom\r\n            .map((vnode) => {\r\n            if (vnode.sel) {\r\n                const node = document.createElement(vnode.sel);\r\n                const result = patch(node, vnode);\r\n                return result.elm.outerHTML;\r\n            }\r\n            else {\r\n                return vnode.text;\r\n            }\r\n        })\r\n            .join(\"\");\r\n    }\r\n    const UTILS = {\r\n        zero: Symbol(\"zero\"),\r\n        toClassObj(expr) {\r\n            const result = {};\r\n            if (typeof expr === \"string\") {\r\n                // we transform here a list of classes into an object:\r\n                //  'hey you' becomes {hey: true, you: true}\r\n                expr = expr.trim();\r\n                if (!expr) {\r\n                    return {};\r\n                }\r\n                let words = expr.split(/\\s+/);\r\n                for (let i = 0; i < words.length; i++) {\r\n                    result[words[i]] = true;\r\n                }\r\n                return result;\r\n            }\r\n            // this is already an object, but we may need to split keys:\r\n            // {'a b': true, 'a c': false} should become {a: true, b: true, c: false}\r\n            for (let key in expr) {\r\n                const value = expr[key];\r\n                const words = key.split(/\\s+/);\r\n                for (let word of words) {\r\n                    result[word] = result[word] || value;\r\n                }\r\n            }\r\n            return result;\r\n        },\r\n        /**\r\n         * This method combines the current context with the variables defined in a\r\n         * scope for use in a slot.\r\n         *\r\n         * The implementation is kind of tricky because we want to preserve the\r\n         * prototype chain structure of the cloned result. So we need to traverse the\r\n         * prototype chain, cloning each level respectively.\r\n         */\r\n        combine(context, scope) {\r\n            let clone = context;\r\n            const scopeStack = [];\r\n            while (!isComponent(scope)) {\r\n                scopeStack.push(scope);\r\n                scope = scope.__proto__;\r\n            }\r\n            while (scopeStack.length) {\r\n                let scope = scopeStack.pop();\r\n                clone = Object.create(clone);\r\n                Object.assign(clone, scope);\r\n            }\r\n            return clone;\r\n        },\r\n        shallowEqual,\r\n        addNameSpace(vnode) {\r\n            addNS(vnode.data, vnode.children, vnode.sel);\r\n        },\r\n        VDomArray,\r\n        vDomToString,\r\n        getComponent(obj) {\r\n            while (obj && !isComponent(obj)) {\r\n                obj = obj.__proto__;\r\n            }\r\n            return obj;\r\n        },\r\n        getScope(obj, property) {\r\n            const obj0 = obj;\r\n            while (obj &&\r\n                !obj.hasOwnProperty(property) &&\r\n                !(obj.hasOwnProperty(\"__access_mode__\") && obj.__access_mode__ === \"ro\")) {\r\n                const newObj = obj.__proto__;\r\n                if (!newObj || isComponent(newObj)) {\r\n                    return obj0;\r\n                }\r\n                obj = newObj;\r\n            }\r\n            return obj;\r\n        },\r\n    };\r\n    function parseXML(xml) {\r\n        const parser = new DOMParser();\r\n        const doc = parser.parseFromString(xml, \"text/xml\");\r\n        if (doc.getElementsByTagName(\"parsererror\").length) {\r\n            let msg = \"Invalid XML in template.\";\r\n            const parsererrorText = doc.getElementsByTagName(\"parsererror\")[0].textContent;\r\n            if (parsererrorText) {\r\n                msg += \"\\nThe parser has produced the following error message:\\n\" + parsererrorText;\r\n                const re = /\\d+/g;\r\n                const firstMatch = re.exec(parsererrorText);\r\n                if (firstMatch) {\r\n                    const lineNumber = Number(firstMatch[0]);\r\n                    const line = xml.split(\"\\n\")[lineNumber - 1];\r\n                    const secondMatch = re.exec(parsererrorText);\r\n                    if (line && secondMatch) {\r\n                        const columnIndex = Number(secondMatch[0]) - 1;\r\n                        if (line[columnIndex]) {\r\n                            msg +=\r\n                                `\\nThe error might be located at xml line ${lineNumber} column ${columnIndex}\\n` +\r\n                                    `${line}\\n${\"-\".repeat(columnIndex - 1)}^`;\r\n                        }\r\n                    }\r\n                }\r\n            }\r\n            throw new Error(msg);\r\n        }\r\n        return doc;\r\n    }\r\n    function escapeQuotes(str) {\r\n        return str.replace(/\\'/g, \"\\\\'\");\r\n    }\r\n    //------------------------------------------------------------------------------\r\n    // QWeb rendering engine\r\n    //------------------------------------------------------------------------------\r\n    class QWeb extends EventBus {\r\n        constructor(config = {}) {\r\n            super();\r\n            this.h = h;\r\n            // subTemplates are stored in two objects: a (local) mapping from a name to an\r\n            // id, and a (global) mapping from an id to the compiled function.  This is\r\n            // necessary to ensure that global templates can be called with more than one\r\n            // QWeb instance.\r\n            this.subTemplates = {};\r\n            this.isUpdating = false;\r\n            this.templates = Object.create(QWeb.TEMPLATES);\r\n            if (config.templates) {\r\n                this.addTemplates(config.templates);\r\n            }\r\n            if (config.translateFn) {\r\n                this.translateFn = config.translateFn;\r\n            }\r\n        }\r\n        static addDirective(directive) {\r\n            if (directive.name in QWeb.DIRECTIVE_NAMES) {\r\n                throw new Error(`Directive \"${directive.name} already registered`);\r\n            }\r\n            QWeb.DIRECTIVES.push(directive);\r\n            QWeb.DIRECTIVE_NAMES[directive.name] = 1;\r\n            QWeb.DIRECTIVES.sort((d1, d2) => d1.priority - d2.priority);\r\n            if (directive.extraNames) {\r\n                directive.extraNames.forEach((n) => (QWeb.DIRECTIVE_NAMES[n] = 1));\r\n            }\r\n        }\r\n        static registerComponent(name, Component) {\r\n            if (QWeb.components[name]) {\r\n                throw new Error(`Component '${name}' has already been registered`);\r\n            }\r\n            QWeb.components[name] = Component;\r\n        }\r\n        /**\r\n         * Register globally a template.  All QWeb instances will obtain their\r\n         * templates from their own template map, and then, from the global static\r\n         * TEMPLATES property.\r\n         */\r\n        static registerTemplate(name, template) {\r\n            if (QWeb.TEMPLATES[name]) {\r\n                throw new Error(`Template '${name}' has already been registered`);\r\n            }\r\n            const qweb = new QWeb();\r\n            qweb.addTemplate(name, template);\r\n            QWeb.TEMPLATES[name] = qweb.templates[name];\r\n        }\r\n        /**\r\n         * Add a template to the internal template map.  Note that it is not\r\n         * immediately compiled.\r\n         */\r\n        addTemplate(name, xmlString, allowDuplicate) {\r\n            if (allowDuplicate && name in this.templates) {\r\n                return;\r\n            }\r\n            const doc = parseXML(xmlString);\r\n            if (!doc.firstChild) {\r\n                throw new Error(\"Invalid template (should not be empty)\");\r\n            }\r\n            this._addTemplate(name, doc.firstChild);\r\n        }\r\n        /**\r\n         * Load templates from a xml (as a string or xml document).  This will look up\r\n         * for the first <templates> tag, and will consider each child of this as a\r\n         * template, with the name given by the t-name attribute.\r\n         */\r\n        addTemplates(xmlstr) {\r\n            if (!xmlstr) {\r\n                return;\r\n            }\r\n            const doc = typeof xmlstr === \"string\" ? parseXML(xmlstr) : xmlstr;\r\n            const templates = doc.getElementsByTagName(\"templates\")[0];\r\n            if (!templates) {\r\n                return;\r\n            }\r\n            for (let elem of templates.children) {\r\n                const name = elem.getAttribute(\"t-name\");\r\n                this._addTemplate(name, elem);\r\n            }\r\n        }\r\n        _addTemplate(name, elem) {\r\n            if (name in this.templates) {\r\n                throw new Error(`Template ${name} already defined`);\r\n            }\r\n            this._processTemplate(elem);\r\n            const template = {\r\n                elem,\r\n                fn: function (context, extra) {\r\n                    const compiledFunction = this._compile(name);\r\n                    template.fn = compiledFunction;\r\n                    return compiledFunction.call(this, context, extra);\r\n                },\r\n            };\r\n            this.templates[name] = template;\r\n        }\r\n        _processTemplate(elem) {\r\n            let tbranch = elem.querySelectorAll(\"[t-elif], [t-else]\");\r\n            for (let i = 0, ilen = tbranch.length; i < ilen; i++) {\r\n                let node = tbranch[i];\r\n                let prevElem = node.previousElementSibling;\r\n                let pattr = function (name) {\r\n                    return prevElem.getAttribute(name);\r\n                };\r\n                let nattr = function (name) {\r\n                    return +!!node.getAttribute(name);\r\n                };\r\n                if (prevElem && (pattr(\"t-if\") || pattr(\"t-elif\"))) {\r\n                    if (pattr(\"t-foreach\")) {\r\n                        throw new Error(\"t-if cannot stay at the same level as t-foreach when using t-elif or t-else\");\r\n                    }\r\n                    if ([\"t-if\", \"t-elif\", \"t-else\"].map(nattr).reduce(function (a, b) {\r\n                        return a + b;\r\n                    }) > 1) {\r\n                        throw new Error(\"Only one conditional branching directive is allowed per node\");\r\n                    }\r\n                    // All text (with only spaces) and comment nodes (nodeType 8) between\r\n                    // branch nodes are removed\r\n                    let textNode;\r\n                    while ((textNode = node.previousSibling) !== prevElem) {\r\n                        if (textNode.nodeValue.trim().length && textNode.nodeType !== 8) {\r\n                            throw new Error(\"text is not allowed between branching directives\");\r\n                        }\r\n                        textNode.remove();\r\n                    }\r\n                }\r\n                else {\r\n                    throw new Error(\"t-elif and t-else directives must be preceded by a t-if or t-elif directive\");\r\n                }\r\n            }\r\n        }\r\n        /**\r\n         * Render a template\r\n         *\r\n         * @param {string} name the template should already have been added\r\n         */\r\n        render(name, context = {}, extra = null) {\r\n            const template = this.templates[name];\r\n            if (!template) {\r\n                throw new Error(`Template ${name} does not exist`);\r\n            }\r\n            return template.fn.call(this, context, extra);\r\n        }\r\n        /**\r\n         * Render a template to a html string.\r\n         *\r\n         * Note that this is more limited than the `render` method: it is not suitable\r\n         * to render a full component tree, since this is an asynchronous operation.\r\n         * This method can only render templates without components.\r\n         */\r\n        renderToString(name, context = {}, extra) {\r\n            const vnode = this.render(name, context, extra);\r\n            if (vnode.sel === undefined) {\r\n                return vnode.text;\r\n            }\r\n            const node = document.createElement(vnode.sel);\r\n            const result = patch(node, vnode);\r\n            return result.elm.outerHTML;\r\n        }\r\n        /**\r\n         * Force all widgets connected to this QWeb instance to rerender themselves.\r\n         *\r\n         * This method is mostly useful for external code that want to modify the\r\n         * application in some cases.  For example, a router plugin.\r\n         */\r\n        forceUpdate() {\r\n            this.isUpdating = true;\r\n            Promise.resolve().then(() => {\r\n                if (this.isUpdating) {\r\n                    this.isUpdating = false;\r\n                    this.trigger(\"update\");\r\n                }\r\n            });\r\n        }\r\n        _compile(name, options = {}) {\r\n            const elem = options.elem || this.templates[name].elem;\r\n            const isDebug = elem.attributes.hasOwnProperty(\"t-debug\");\r\n            const ctx = new CompilationContext(name);\r\n            if (elem.tagName !== \"t\") {\r\n                ctx.shouldDefineResult = false;\r\n            }\r\n            if (options.hasParent) {\r\n                ctx.variables = Object.create(null);\r\n                ctx.parentNode = ctx.generateID();\r\n                ctx.allowMultipleRoots = true;\r\n                ctx.shouldDefineParent = true;\r\n                ctx.hasParentWidget = true;\r\n                ctx.shouldDefineResult = false;\r\n                ctx.addLine(`let c${ctx.parentNode} = extra.parentNode;`);\r\n                if (options.defineKey) {\r\n                    ctx.addLine(`let key0 = extra.key || \"\";`);\r\n                    ctx.hasKey0 = true;\r\n                }\r\n            }\r\n            this._compileNode(elem, ctx);\r\n            if (!options.hasParent) {\r\n                if (ctx.shouldDefineResult) {\r\n                    ctx.addLine(`return result;`);\r\n                }\r\n                else {\r\n                    if (!ctx.rootNode) {\r\n                        throw new Error(`A template should have one root node (${ctx.templateName})`);\r\n                    }\r\n                    ctx.addLine(`return vn${ctx.rootNode};`);\r\n                }\r\n            }\r\n            let code = ctx.generateCode();\r\n            const templateName = ctx.templateName.replace(/`/g, \"'\").slice(0, 200);\r\n            code.unshift(`    // Template name: \"${templateName}\"`);\r\n            let template;\r\n            try {\r\n                template = new Function(\"context, extra\", code.join(\"\\n\"));\r\n            }\r\n            catch (e) {\r\n                console.groupCollapsed(`Invalid Code generated by ${templateName}`);\r\n                console.warn(code.join(\"\\n\"));\r\n                console.groupEnd();\r\n                throw new Error(`Invalid generated code while compiling template '${templateName}': ${e.message}`);\r\n            }\r\n            if (isDebug) {\r\n                const tpl = this.templates[name];\r\n                if (tpl) {\r\n                    const msg = `Template: ${tpl.elem.outerHTML}\\nCompiled code:\\n${template.toString()}`;\r\n                    console.log(msg);\r\n                }\r\n            }\r\n            return template;\r\n        }\r\n        /**\r\n         * Generate code from an xml node\r\n         *\r\n         */\r\n        _compileNode(node, ctx) {\r\n            if (!(node instanceof Element)) {\r\n                // this is a text node, there are no directive to apply\r\n                let text = node.textContent;\r\n                if (!ctx.inPreTag) {\r\n                    if (lineBreakRE.test(text) && !text.trim()) {\r\n                        return;\r\n                    }\r\n                    text = text.replace(whitespaceRE, \" \");\r\n                }\r\n                if (this.translateFn) {\r\n                    if (node.parentNode.getAttribute(\"t-translation\") !== \"off\") {\r\n                        const match = translationRE.exec(text);\r\n                        text = match[1] + this.translateFn(match[2]) + match[3];\r\n                    }\r\n                }\r\n                if (ctx.parentNode) {\r\n                    if (node.nodeType === 3) {\r\n                        ctx.addLine(`c${ctx.parentNode}.push({text: \\`${text}\\`});`);\r\n                    }\r\n                    else if (node.nodeType === 8) {\r\n                        ctx.addLine(`c${ctx.parentNode}.push(h('!', \\`${text}\\`));`);\r\n                    }\r\n                }\r\n                else if (ctx.parentTextNode) {\r\n                    ctx.addLine(`vn${ctx.parentTextNode}.text += \\`${text}\\`;`);\r\n                }\r\n                else {\r\n                    // this is an unusual situation: this text node is the result of the\r\n                    // template rendering.\r\n                    let nodeID = ctx.generateID();\r\n                    ctx.addLine(`let vn${nodeID} = {text: \\`${text}\\`};`);\r\n                    ctx.addLine(`result = vn${nodeID};`);\r\n                    ctx.rootContext.rootNode = nodeID;\r\n                    ctx.rootContext.parentTextNode = nodeID;\r\n                }\r\n                return;\r\n            }\r\n            if (node.tagName !== \"t\" && node.hasAttribute(\"t-call\")) {\r\n                const tCallNode = document.implementation.createDocument(\"http://www.w3.org/1999/xhtml\", \"t\", null).documentElement;\r\n                tCallNode.setAttribute(\"t-call\", node.getAttribute(\"t-call\"));\r\n                node.removeAttribute(\"t-call\");\r\n                node.prepend(tCallNode);\r\n            }\r\n            const firstLetter = node.tagName[0];\r\n            if (firstLetter === firstLetter.toUpperCase()) {\r\n                // this is a component, we modify in place the xml document to change\r\n                // <SomeComponent ... /> to <SomeComponent t-component=\"SomeComponent\" ... />\r\n                node.setAttribute(\"t-component\", node.tagName);\r\n            }\r\n            else if (node.tagName !== \"t\" && node.hasAttribute(\"t-component\")) {\r\n                throw new Error(`Directive 't-component' can only be used on <t> nodes (used on a <${node.tagName}>)`);\r\n            }\r\n            const attributes = node.attributes;\r\n            const validDirectives = [];\r\n            const finalizers = [];\r\n            // maybe this is not optimal: we iterate on all attributes here, and again\r\n            // just after for each directive.\r\n            for (let i = 0; i < attributes.length; i++) {\r\n                let attrName = attributes[i].name;\r\n                if (attrName.startsWith(\"t-\")) {\r\n                    let dName = attrName.slice(2).split(/-|\\./)[0];\r\n                    if (!(dName in QWeb.DIRECTIVE_NAMES)) {\r\n                        throw new Error(`Unknown QWeb directive: '${attrName}'`);\r\n                    }\r\n                    if (node.tagName !== \"t\" && (attrName === \"t-esc\" || attrName === \"t-raw\")) {\r\n                        const tNode = document.implementation.createDocument(\"http://www.w3.org/1999/xhtml\", \"t\", null).documentElement;\r\n                        tNode.setAttribute(attrName, node.getAttribute(attrName));\r\n                        for (let child of Array.from(node.childNodes)) {\r\n                            tNode.appendChild(child);\r\n                        }\r\n                        node.appendChild(tNode);\r\n                        node.removeAttribute(attrName);\r\n                    }\r\n                }\r\n            }\r\n            const DIR_N = QWeb.DIRECTIVES.length;\r\n            const ATTR_N = attributes.length;\r\n            let withHandlers = false;\r\n            for (let i = 0; i < DIR_N; i++) {\r\n                let directive = QWeb.DIRECTIVES[i];\r\n                let fullName;\r\n                let value;\r\n                for (let j = 0; j < ATTR_N; j++) {\r\n                    const name = attributes[j].name;\r\n                    if (name === \"t-\" + directive.name ||\r\n                        name.startsWith(\"t-\" + directive.name + \"-\") ||\r\n                        name.startsWith(\"t-\" + directive.name + \".\")) {\r\n                        fullName = name;\r\n                        value = attributes[j].textContent;\r\n                        validDirectives.push({ directive, value, fullName });\r\n                        if (directive.name === \"on\" || directive.name === \"model\") {\r\n                            withHandlers = true;\r\n                        }\r\n                    }\r\n                }\r\n            }\r\n            for (let { directive, value, fullName } of validDirectives) {\r\n                if (directive.finalize) {\r\n                    finalizers.push({ directive, value, fullName });\r\n                }\r\n                if (directive.atNodeEncounter) {\r\n                    const isDone = directive.atNodeEncounter({\r\n                        node,\r\n                        qweb: this,\r\n                        ctx,\r\n                        fullName,\r\n                        value,\r\n                    });\r\n                    if (isDone) {\r\n                        for (let { directive, value, fullName } of finalizers) {\r\n                            directive.finalize({ node, qweb: this, ctx, fullName, value });\r\n                        }\r\n                        return;\r\n                    }\r\n                }\r\n            }\r\n            if (node.nodeName !== \"t\" || node.hasAttribute(\"t-tag\")) {\r\n                let nodeHooks = {};\r\n                let addNodeHook = function (hook, handler) {\r\n                    nodeHooks[hook] = nodeHooks[hook] || [];\r\n                    nodeHooks[hook].push(handler);\r\n                };\r\n                if (node.tagName === \"select\" && node.hasAttribute(\"t-att-value\")) {\r\n                    const value = node.getAttribute(\"t-att-value\");\r\n                    let exprId = ctx.generateID();\r\n                    ctx.addLine(`let expr${exprId} = ${ctx.formatExpression(value)};`);\r\n                    let expr = `expr${exprId}`;\r\n                    node.setAttribute(\"t-att-value\", expr);\r\n                    addNodeHook(\"create\", `n.elm.value=${expr};`);\r\n                }\r\n                let nodeID = this._compileGenericNode(node, ctx, withHandlers);\r\n                ctx = ctx.withParent(nodeID);\r\n                for (let { directive, value, fullName } of validDirectives) {\r\n                    if (directive.atNodeCreation) {\r\n                        directive.atNodeCreation({\r\n                            node,\r\n                            qweb: this,\r\n                            ctx,\r\n                            fullName,\r\n                            value,\r\n                            nodeID,\r\n                            addNodeHook,\r\n                        });\r\n                    }\r\n                }\r\n                if (Object.keys(nodeHooks).length) {\r\n                    ctx.addLine(`p${nodeID}.hook = {`);\r\n                    for (let hook in nodeHooks) {\r\n                        ctx.addLine(`  ${hook}: ${NODE_HOOKS_PARAMS[hook]} => {`);\r\n                        for (let handler of nodeHooks[hook]) {\r\n                            ctx.addLine(`    ${handler}`);\r\n                        }\r\n                        ctx.addLine(`  },`);\r\n                    }\r\n                    ctx.addLine(`};`);\r\n                }\r\n            }\r\n            if (node.nodeName === \"pre\") {\r\n                ctx = ctx.subContext(\"inPreTag\", true);\r\n            }\r\n            this._compileChildren(node, ctx);\r\n            // svg support\r\n            // we hadd svg namespace if it is a svg or if it is a g, but only if it is\r\n            // the root node.  This is the easiest way to support svg sub components:\r\n            // they need to have a g tag as root. Otherwise, we would need a complete\r\n            // list of allowed svg tags.\r\n            const shouldAddNS = node.nodeName === \"svg\" || (node.nodeName === \"g\" && ctx.rootNode === ctx.parentNode);\r\n            if (shouldAddNS) {\r\n                ctx.rootContext.shouldDefineUtils = true;\r\n                ctx.addLine(`utils.addNameSpace(vn${ctx.parentNode});`);\r\n            }\r\n            for (let { directive, value, fullName } of finalizers) {\r\n                directive.finalize({ node, qweb: this, ctx, fullName, value });\r\n            }\r\n        }\r\n        _compileGenericNode(node, ctx, withHandlers = true) {\r\n            // nodeType 1 is generic tag\r\n            if (node.nodeType !== 1) {\r\n                throw new Error(\"unsupported node type\");\r\n            }\r\n            const attributes = node.attributes;\r\n            const attrs = [];\r\n            const props = [];\r\n            const tattrs = [];\r\n            function handleProperties(key, val) {\r\n                let isProp = false;\r\n                switch (node.nodeName) {\r\n                    case \"input\":\r\n                        let type = node.getAttribute(\"type\");\r\n                        if (type === \"checkbox\" || type === \"radio\") {\r\n                            if (key === \"checked\" || key === \"indeterminate\") {\r\n                                isProp = true;\r\n                            }\r\n                        }\r\n                        if (key === \"value\" || key === \"readonly\" || key === \"disabled\") {\r\n                            isProp = true;\r\n                        }\r\n                        break;\r\n                    case \"option\":\r\n                        isProp = key === \"selected\" || key === \"disabled\";\r\n                        break;\r\n                    case \"textarea\":\r\n                        isProp = key === \"readonly\" || key === \"disabled\" || key === \"value\";\r\n                        break;\r\n                    case \"select\":\r\n                        isProp = key === \"disabled\" || key === \"value\";\r\n                        break;\r\n                    case \"button\":\r\n                    case \"optgroup\":\r\n                        isProp = key === \"disabled\";\r\n                        break;\r\n                }\r\n                if (isProp) {\r\n                    props.push(`${key}: ${val}`);\r\n                }\r\n            }\r\n            let classObj = \"\";\r\n            for (let i = 0; i < attributes.length; i++) {\r\n                let name = attributes[i].name;\r\n                let value = attributes[i].textContent;\r\n                if (this.translateFn && TRANSLATABLE_ATTRS.includes(name)) {\r\n                    value = this.translateFn(value);\r\n                }\r\n                // regular attributes\r\n                if (!name.startsWith(\"t-\") && !node.getAttribute(\"t-attf-\" + name)) {\r\n                    const attID = ctx.generateID();\r\n                    if (name === \"class\") {\r\n                        if ((value = value.trim())) {\r\n                            let classDef = value\r\n                                .split(/\\s+/)\r\n                                .map((a) => `'${escapeQuotes(a)}':true`)\r\n                                .join(\",\");\r\n                            if (classObj) {\r\n                                ctx.addLine(`Object.assign(${classObj}, {${classDef}})`);\r\n                            }\r\n                            else {\r\n                                classObj = `_${ctx.generateID()}`;\r\n                                ctx.addLine(`let ${classObj} = {${classDef}};`);\r\n                            }\r\n                        }\r\n                    }\r\n                    else {\r\n                        ctx.addLine(`let _${attID} = '${escapeQuotes(value)}';`);\r\n                        if (!name.match(/^[a-zA-Z]+$/)) {\r\n                            // attribute contains 'non letters' => we want to quote it\r\n                            name = '\"' + name + '\"';\r\n                        }\r\n                        attrs.push(`${name}: _${attID}`);\r\n                        handleProperties(name, `_${attID}`);\r\n                    }\r\n                }\r\n                // dynamic attributes\r\n                if (name.startsWith(\"t-att-\")) {\r\n                    let attName = name.slice(6);\r\n                    const v = ctx.getValue(value);\r\n                    let formattedValue = typeof v === \"string\" ? ctx.formatExpression(v) : `scope.${v.id}`;\r\n                    if (attName === \"class\") {\r\n                        ctx.rootContext.shouldDefineUtils = true;\r\n                        formattedValue = `utils.toClassObj(${formattedValue})`;\r\n                        if (classObj) {\r\n                            ctx.addLine(`Object.assign(${classObj}, ${formattedValue})`);\r\n                        }\r\n                        else {\r\n                            classObj = `_${ctx.generateID()}`;\r\n                            ctx.addLine(`let ${classObj} = ${formattedValue};`);\r\n                        }\r\n                    }\r\n                    else {\r\n                        const attID = ctx.generateID();\r\n                        if (!attName.match(/^[a-zA-Z]+$/)) {\r\n                            // attribute contains 'non letters' => we want to quote it\r\n                            attName = '\"' + attName + '\"';\r\n                        }\r\n                        // we need to combine dynamic with non dynamic attributes:\r\n                        // class=\"a\" t-att-class=\"'yop'\" should be rendered as class=\"a yop\"\r\n                        const attValue = node.getAttribute(attName);\r\n                        if (attValue) {\r\n                            const attValueID = ctx.generateID();\r\n                            ctx.addLine(`let _${attValueID} = ${formattedValue};`);\r\n                            formattedValue = `'${attValue}' + (_${attValueID} ? ' ' + _${attValueID} : '')`;\r\n                            const attrIndex = attrs.findIndex((att) => att.startsWith(attName + \":\"));\r\n                            attrs.splice(attrIndex, 1);\r\n                        }\r\n                        if (node.nodeName === \"select\" && attName === \"value\") {\r\n                            attrs.push(`${attName}: ${v}`);\r\n                            handleProperties(attName, v);\r\n                        }\r\n                        else {\r\n                            ctx.addLine(`let _${attID} = ${formattedValue};`);\r\n                            attrs.push(`${attName}: _${attID}`);\r\n                            handleProperties(attName, \"_\" + attID);\r\n                        }\r\n                    }\r\n                }\r\n                if (name.startsWith(\"t-attf-\")) {\r\n                    let attName = name.slice(7);\r\n                    if (!attName.match(/^[a-zA-Z]+$/)) {\r\n                        // attribute contains 'non letters' => we want to quote it\r\n                        attName = '\"' + attName + '\"';\r\n                    }\r\n                    const formattedExpr = ctx.interpolate(value);\r\n                    const attID = ctx.generateID();\r\n                    let staticVal = node.getAttribute(attName);\r\n                    if (staticVal) {\r\n                        ctx.addLine(`let _${attID} = '${staticVal} ' + ${formattedExpr};`);\r\n                    }\r\n                    else {\r\n                        ctx.addLine(`let _${attID} = ${formattedExpr};`);\r\n                    }\r\n                    attrs.push(`${attName}: _${attID}`);\r\n                }\r\n                // t-att= attributes\r\n                if (name === \"t-att\") {\r\n                    let id = ctx.generateID();\r\n                    ctx.addLine(`let _${id} = ${ctx.formatExpression(value)};`);\r\n                    tattrs.push(id);\r\n                }\r\n            }\r\n            let nodeID = ctx.generateID();\r\n            let key = ctx.loopNumber || ctx.hasKey0 ? `\\`\\${key${ctx.loopNumber}}_${nodeID}\\`` : nodeID;\r\n            const parts = [`key:${key}`];\r\n            if (attrs.length + tattrs.length > 0) {\r\n                parts.push(`attrs:{${attrs.join(\",\")}}`);\r\n            }\r\n            if (props.length > 0) {\r\n                parts.push(`props:{${props.join(\",\")}}`);\r\n            }\r\n            if (classObj) {\r\n                parts.push(`class:${classObj}`);\r\n            }\r\n            if (withHandlers) {\r\n                parts.push(`on:{}`);\r\n            }\r\n            ctx.addLine(`let c${nodeID} = [], p${nodeID} = {${parts.join(\",\")}};`);\r\n            for (let id of tattrs) {\r\n                ctx.addIf(`_${id} instanceof Array`);\r\n                ctx.addLine(`p${nodeID}.attrs[_${id}[0]] = _${id}[1];`);\r\n                ctx.addElse();\r\n                ctx.addLine(`for (let key in _${id}) {`);\r\n                ctx.indent();\r\n                ctx.addLine(`p${nodeID}.attrs[key] = _${id}[key];`);\r\n                ctx.dedent();\r\n                ctx.addLine(`}`);\r\n                ctx.closeIf();\r\n            }\r\n            let nodeName = `'${node.nodeName}'`;\r\n            if (node.hasAttribute(\"t-tag\")) {\r\n                const tagExpr = node.getAttribute(\"t-tag\");\r\n                node.removeAttribute(\"t-tag\");\r\n                nodeName = `tag${ctx.generateID()}`;\r\n                ctx.addLine(`let ${nodeName} = ${ctx.formatExpression(tagExpr)};`);\r\n            }\r\n            ctx.addLine(`let vn${nodeID} = h(${nodeName}, p${nodeID}, c${nodeID});`);\r\n            if (ctx.parentNode) {\r\n                ctx.addLine(`c${ctx.parentNode}.push(vn${nodeID});`);\r\n            }\r\n            else if (ctx.loopNumber || ctx.hasKey0) {\r\n                ctx.rootContext.shouldDefineResult = true;\r\n                ctx.addLine(`result = vn${nodeID};`);\r\n            }\r\n            return nodeID;\r\n        }\r\n        _compileChildren(node, ctx) {\r\n            if (node.childNodes.length > 0) {\r\n                for (let child of Array.from(node.childNodes)) {\r\n                    this._compileNode(child, ctx);\r\n                }\r\n            }\r\n        }\r\n    }\r\n    QWeb.utils = UTILS;\r\n    QWeb.components = Object.create(null);\r\n    QWeb.DIRECTIVE_NAMES = {\r\n        name: 1,\r\n        att: 1,\r\n        attf: 1,\r\n        translation: 1,\r\n        tag: 1,\r\n    };\r\n    QWeb.DIRECTIVES = [];\r\n    QWeb.TEMPLATES = {};\r\n    QWeb.nextId = 1;\r\n    // dev mode enables better error messages or more costly validations\r\n    QWeb.dev = false;\r\n    QWeb.enableTransitions = true;\r\n    // slots contains sub templates defined with t-set inside t-component nodes, and\r\n    // are meant to be used by the t-slot directive.\r\n    QWeb.slots = {};\r\n    QWeb.nextSlotId = 1;\r\n    QWeb.subTemplates = {};\r\n\r\n    const parser = new DOMParser();\r\n    function htmlToVDOM(html) {\r\n        const doc = parser.parseFromString(html, \"text/html\");\r\n        const result = [];\r\n        for (let child of doc.body.childNodes) {\r\n            result.push(htmlToVNode(child));\r\n        }\r\n        return result;\r\n    }\r\n    function htmlToVNode(node) {\r\n        if (!(node instanceof Element)) {\r\n            if (node instanceof Comment) {\r\n                return h(\"!\", node.textContent);\r\n            }\r\n            return { text: node.textContent };\r\n        }\r\n        const attrs = {};\r\n        for (let attr of node.attributes) {\r\n            attrs[attr.name] = attr.textContent;\r\n        }\r\n        const children = [];\r\n        for (let c of node.childNodes) {\r\n            children.push(htmlToVNode(c));\r\n        }\r\n        const vnode = h(node.tagName, { attrs }, children);\r\n        if (vnode.sel === \"svg\") {\r\n            addNS(vnode.data, vnode.children, vnode.sel);\r\n        }\r\n        return vnode;\r\n    }\r\n\r\n    /**\r\n     * Owl QWeb Directives\r\n     *\r\n     * This file contains the implementation of most standard QWeb directives:\r\n     * - t-esc\r\n     * - t-raw\r\n     * - t-set/t-value\r\n     * - t-if/t-elif/t-else\r\n     * - t-call\r\n     * - t-foreach/t-as\r\n     * - t-debug\r\n     * - t-log\r\n     */\r\n    //------------------------------------------------------------------------------\r\n    // t-esc and t-raw\r\n    //------------------------------------------------------------------------------\r\n    QWeb.utils.htmlToVDOM = htmlToVDOM;\r\n    function compileValueNode(value, node, qweb, ctx) {\r\n        ctx.rootContext.shouldDefineScope = true;\r\n        if (value === \"0\") {\r\n            if (ctx.parentNode) {\r\n                // the 'zero' magical symbol is where we can find the result of the rendering\r\n                // of  the body of the t-call.\r\n                ctx.rootContext.shouldDefineUtils = true;\r\n                const zeroArgs = ctx.escaping\r\n                    ? `{text: utils.vDomToString(scope[utils.zero])}`\r\n                    : `...scope[utils.zero]`;\r\n                ctx.addLine(`c${ctx.parentNode}.push(${zeroArgs});`);\r\n            }\r\n            return;\r\n        }\r\n        let exprID;\r\n        if (typeof value === \"string\") {\r\n            exprID = `_${ctx.generateID()}`;\r\n            ctx.addLine(`let ${exprID} = ${ctx.formatExpression(value)};`);\r\n        }\r\n        else {\r\n            exprID = `scope.${value.id}`;\r\n        }\r\n        ctx.addIf(`${exprID} != null`);\r\n        if (ctx.escaping) {\r\n            let protectID;\r\n            if (value.hasBody) {\r\n                ctx.rootContext.shouldDefineUtils = true;\r\n                protectID = ctx.startProtectScope();\r\n                ctx.addLine(`${exprID} = ${exprID} instanceof utils.VDomArray ? utils.vDomToString(${exprID}) : ${exprID};`);\r\n            }\r\n            if (ctx.parentTextNode) {\r\n                ctx.addLine(`vn${ctx.parentTextNode}.text += ${exprID};`);\r\n            }\r\n            else if (ctx.parentNode) {\r\n                ctx.addLine(`c${ctx.parentNode}.push({text: ${exprID}});`);\r\n            }\r\n            else {\r\n                let nodeID = ctx.generateID();\r\n                ctx.rootContext.rootNode = nodeID;\r\n                ctx.rootContext.parentTextNode = nodeID;\r\n                ctx.addLine(`let vn${nodeID} = {text: ${exprID}};`);\r\n                if (ctx.rootContext.shouldDefineResult) {\r\n                    ctx.addLine(`result = vn${nodeID}`);\r\n                }\r\n            }\r\n            if (value.hasBody) {\r\n                ctx.stopProtectScope(protectID);\r\n            }\r\n        }\r\n        else {\r\n            ctx.rootContext.shouldDefineUtils = true;\r\n            if (value.hasBody) {\r\n                ctx.addLine(`const vnodeArray = ${exprID} instanceof utils.VDomArray ? ${exprID} : utils.htmlToVDOM(${exprID});`);\r\n                ctx.addLine(`c${ctx.parentNode}.push(...vnodeArray);`);\r\n            }\r\n            else {\r\n                ctx.addLine(`c${ctx.parentNode}.push(...utils.htmlToVDOM(${exprID}));`);\r\n            }\r\n        }\r\n        if (node.childNodes.length) {\r\n            ctx.addElse();\r\n            qweb._compileChildren(node, ctx);\r\n        }\r\n        ctx.closeIf();\r\n    }\r\n    QWeb.addDirective({\r\n        name: \"esc\",\r\n        priority: 70,\r\n        atNodeEncounter({ node, qweb, ctx }) {\r\n            let value = ctx.getValue(node.getAttribute(\"t-esc\"));\r\n            compileValueNode(value, node, qweb, ctx.subContext(\"escaping\", true));\r\n            return true;\r\n        },\r\n    });\r\n    QWeb.addDirective({\r\n        name: \"raw\",\r\n        priority: 80,\r\n        atNodeEncounter({ node, qweb, ctx }) {\r\n            let value = ctx.getValue(node.getAttribute(\"t-raw\"));\r\n            compileValueNode(value, node, qweb, ctx);\r\n            return true;\r\n        },\r\n    });\r\n    //------------------------------------------------------------------------------\r\n    // t-set\r\n    //------------------------------------------------------------------------------\r\n    QWeb.addDirective({\r\n        name: \"set\",\r\n        extraNames: [\"value\"],\r\n        priority: 60,\r\n        atNodeEncounter({ node, qweb, ctx }) {\r\n            ctx.rootContext.shouldDefineScope = true;\r\n            const variable = node.getAttribute(\"t-set\");\r\n            let value = node.getAttribute(\"t-value\");\r\n            ctx.variables[variable] = ctx.variables[variable] || {};\r\n            let qwebvar = ctx.variables[variable];\r\n            const hasBody = node.hasChildNodes();\r\n            qwebvar.id = variable;\r\n            qwebvar.expr = `scope.${variable}`;\r\n            if (value) {\r\n                const formattedValue = ctx.formatExpression(value);\r\n                let scopeExpr = `scope`;\r\n                if (ctx.protectedScopeNumber) {\r\n                    ctx.rootContext.shouldDefineUtils = true;\r\n                    scopeExpr = `utils.getScope(scope, '${variable}')`;\r\n                }\r\n                ctx.addLine(`${scopeExpr}.${variable} = ${formattedValue};`);\r\n                qwebvar.value = formattedValue;\r\n            }\r\n            if (hasBody) {\r\n                ctx.rootContext.shouldDefineUtils = true;\r\n                if (value) {\r\n                    ctx.addIf(`!(${qwebvar.expr})`);\r\n                }\r\n                const tempParentNodeID = ctx.generateID();\r\n                const _parentNode = ctx.parentNode;\r\n                ctx.parentNode = tempParentNodeID;\r\n                ctx.addLine(`let c${tempParentNodeID} = new utils.VDomArray();`);\r\n                const nodeCopy = node.cloneNode(true);\r\n                for (let attr of [\"t-set\", \"t-value\", \"t-if\", \"t-else\", \"t-elif\"]) {\r\n                    nodeCopy.removeAttribute(attr);\r\n                }\r\n                qweb._compileNode(nodeCopy, ctx);\r\n                ctx.addLine(`${qwebvar.expr} = c${tempParentNodeID}`);\r\n                qwebvar.value = `c${tempParentNodeID}`;\r\n                qwebvar.hasBody = true;\r\n                ctx.parentNode = _parentNode;\r\n                if (value) {\r\n                    ctx.closeIf();\r\n                }\r\n            }\r\n            return true;\r\n        },\r\n    });\r\n    //------------------------------------------------------------------------------\r\n    // t-if, t-elif, t-else\r\n    //------------------------------------------------------------------------------\r\n    QWeb.addDirective({\r\n        name: \"if\",\r\n        priority: 20,\r\n        atNodeEncounter({ node, ctx }) {\r\n            let cond = ctx.getValue(node.getAttribute(\"t-if\"));\r\n            ctx.addIf(typeof cond === \"string\" ? ctx.formatExpression(cond) : `scope.${cond.id}`);\r\n            return false;\r\n        },\r\n        finalize({ ctx }) {\r\n            ctx.closeIf();\r\n        },\r\n    });\r\n    QWeb.addDirective({\r\n        name: \"elif\",\r\n        priority: 30,\r\n        atNodeEncounter({ node, ctx }) {\r\n            let cond = ctx.getValue(node.getAttribute(\"t-elif\"));\r\n            ctx.addLine(`else if (${typeof cond === \"string\" ? ctx.formatExpression(cond) : `scope.${cond.id}`}) {`);\r\n            ctx.indent();\r\n            return false;\r\n        },\r\n        finalize({ ctx }) {\r\n            ctx.closeIf();\r\n        },\r\n    });\r\n    QWeb.addDirective({\r\n        name: \"else\",\r\n        priority: 40,\r\n        atNodeEncounter({ ctx }) {\r\n            ctx.addLine(`else {`);\r\n            ctx.indent();\r\n            return false;\r\n        },\r\n        finalize({ ctx }) {\r\n            ctx.closeIf();\r\n        },\r\n    });\r\n    //------------------------------------------------------------------------------\r\n    // t-call\r\n    //------------------------------------------------------------------------------\r\n    QWeb.addDirective({\r\n        name: \"call\",\r\n        priority: 50,\r\n        atNodeEncounter({ node, qweb, ctx }) {\r\n            // Step 1: sanity checks\r\n            // ------------------------------------------------\r\n            ctx.rootContext.shouldDefineScope = true;\r\n            ctx.rootContext.shouldDefineUtils = true;\r\n            const subTemplate = node.getAttribute(\"t-call\");\r\n            const isDynamic = INTERP_REGEXP.test(subTemplate);\r\n            const nodeTemplate = qweb.templates[subTemplate];\r\n            if (!isDynamic && !nodeTemplate) {\r\n                throw new Error(`Cannot find template \"${subTemplate}\" (t-call)`);\r\n            }\r\n            // Step 2: compile target template in sub templates\r\n            // ------------------------------------------------\r\n            let subIdstr;\r\n            if (isDynamic) {\r\n                const _id = ctx.generateID();\r\n                ctx.addLine(`let tname${_id} = ${ctx.interpolate(subTemplate)};`);\r\n                ctx.addLine(`let tid${_id} = this.subTemplates[tname${_id}];`);\r\n                ctx.addIf(`!tid${_id}`);\r\n                ctx.addLine(`tid${_id} = this.constructor.nextId++;`);\r\n                ctx.addLine(`this.subTemplates[tname${_id}] = tid${_id};`);\r\n                ctx.addLine(`this.constructor.subTemplates[tid${_id}] = this._compile(tname${_id}, {hasParent: true, defineKey: true});`);\r\n                ctx.closeIf();\r\n                subIdstr = `tid${_id}`;\r\n            }\r\n            else {\r\n                let subId = qweb.subTemplates[subTemplate];\r\n                if (!subId) {\r\n                    subId = QWeb.nextId++;\r\n                    qweb.subTemplates[subTemplate] = subId;\r\n                    const subTemplateFn = qweb._compile(subTemplate, { hasParent: true, defineKey: true });\r\n                    QWeb.subTemplates[subId] = subTemplateFn;\r\n                }\r\n                subIdstr = `'${subId}'`;\r\n            }\r\n            // Step 3: compile t-call body if necessary\r\n            // ------------------------------------------------\r\n            let hasBody = node.hasChildNodes();\r\n            const protectID = ctx.startProtectScope();\r\n            if (hasBody) {\r\n                // we add a sub scope to protect the ambient scope\r\n                ctx.addLine(`{`);\r\n                ctx.indent();\r\n                const nodeCopy = node.cloneNode(true);\r\n                for (let attr of [\"t-if\", \"t-else\", \"t-elif\", \"t-call\"]) {\r\n                    nodeCopy.removeAttribute(attr);\r\n                }\r\n                // this local scope is intended to trap c__0\r\n                ctx.addLine(`{`);\r\n                ctx.indent();\r\n                ctx.addLine(\"let c__0 = [];\");\r\n                qweb._compileNode(nodeCopy, ctx.subContext(\"parentNode\", \"__0\"));\r\n                ctx.rootContext.shouldDefineUtils = true;\r\n                ctx.addLine(\"scope[utils.zero] = c__0;\");\r\n                ctx.dedent();\r\n                ctx.addLine(`}`);\r\n            }\r\n            // Step 4: add the appropriate function call to current component\r\n            // ------------------------------------------------\r\n            const parentComponent = ctx.rootContext.shouldDefineParent\r\n                ? `parent`\r\n                : `utils.getComponent(context)`;\r\n            const key = ctx.generateTemplateKey();\r\n            const parentNode = ctx.parentNode ? `c${ctx.parentNode}` : \"result\";\r\n            const extra = `Object.assign({}, extra, {parentNode: ${parentNode}, parent: ${parentComponent}, key: ${key}})`;\r\n            if (ctx.parentNode) {\r\n                ctx.addLine(`this.constructor.subTemplates[${subIdstr}].call(this, scope, ${extra});`);\r\n            }\r\n            else {\r\n                // this is a t-call with no parentnode, we need to extract the result\r\n                ctx.rootContext.shouldDefineResult = true;\r\n                ctx.addLine(`result = []`);\r\n                ctx.addLine(`this.constructor.subTemplates[${subIdstr}].call(this, scope, ${extra});`);\r\n                ctx.addLine(`result = result[0]`);\r\n            }\r\n            // Step 5: restore previous scope\r\n            // ------------------------------------------------\r\n            if (hasBody) {\r\n                ctx.dedent();\r\n                ctx.addLine(`}`);\r\n            }\r\n            ctx.stopProtectScope(protectID);\r\n            return true;\r\n        },\r\n    });\r\n    //------------------------------------------------------------------------------\r\n    // t-foreach\r\n    //------------------------------------------------------------------------------\r\n    QWeb.addDirective({\r\n        name: \"foreach\",\r\n        extraNames: [\"as\"],\r\n        priority: 10,\r\n        atNodeEncounter({ node, qweb, ctx }) {\r\n            ctx.rootContext.shouldDefineScope = true;\r\n            ctx = ctx.subContext(\"loopNumber\", ctx.loopNumber + 1);\r\n            const elems = node.getAttribute(\"t-foreach\");\r\n            const name = node.getAttribute(\"t-as\");\r\n            let arrayID = ctx.generateID();\r\n            ctx.addLine(`let _${arrayID} = ${ctx.formatExpression(elems)};`);\r\n            ctx.addLine(`if (!_${arrayID}) { throw new Error('QWeb error: Invalid loop expression')}`);\r\n            let keysID = ctx.generateID();\r\n            let valuesID = ctx.generateID();\r\n            ctx.addLine(`let _${keysID} = _${arrayID};`);\r\n            ctx.addLine(`let _${valuesID} = _${arrayID};`);\r\n            ctx.addIf(`!(_${arrayID} instanceof Array)`);\r\n            ctx.addLine(`_${keysID} = Object.keys(_${arrayID});`);\r\n            ctx.addLine(`_${valuesID} = Object.values(_${arrayID});`);\r\n            ctx.closeIf();\r\n            ctx.addLine(`let _length${keysID} = _${keysID}.length;`);\r\n            let varsID = ctx.startProtectScope(true);\r\n            const loopVar = `i${ctx.loopNumber}`;\r\n            ctx.addLine(`for (let ${loopVar} = 0; ${loopVar} < _length${keysID}; ${loopVar}++) {`);\r\n            ctx.indent();\r\n            ctx.addLine(`scope.${name}_first = ${loopVar} === 0`);\r\n            ctx.addLine(`scope.${name}_last = ${loopVar} === _length${keysID} - 1`);\r\n            ctx.addLine(`scope.${name}_index = ${loopVar}`);\r\n            ctx.addLine(`scope.${name} = _${keysID}[${loopVar}]`);\r\n            ctx.addLine(`scope.${name}_value = _${valuesID}[${loopVar}]`);\r\n            const nodeCopy = node.cloneNode(true);\r\n            let shouldWarn = !nodeCopy.hasAttribute(\"t-key\") &&\r\n                node.children.length === 1 &&\r\n                node.children[0].tagName !== \"t\" &&\r\n                !node.children[0].hasAttribute(\"t-key\");\r\n            if (shouldWarn) {\r\n                console.warn(`Directive t-foreach should always be used with a t-key! (in template: '${ctx.templateName}')`);\r\n            }\r\n            if (nodeCopy.hasAttribute(\"t-key\")) {\r\n                const expr = ctx.formatExpression(nodeCopy.getAttribute(\"t-key\"));\r\n                ctx.addLine(`let key${ctx.loopNumber} = ${expr};`);\r\n                nodeCopy.removeAttribute(\"t-key\");\r\n            }\r\n            else {\r\n                ctx.addLine(`let key${ctx.loopNumber} = i${ctx.loopNumber};`);\r\n            }\r\n            nodeCopy.removeAttribute(\"t-foreach\");\r\n            qweb._compileNode(nodeCopy, ctx);\r\n            ctx.dedent();\r\n            ctx.addLine(\"}\");\r\n            ctx.stopProtectScope(varsID);\r\n            return true;\r\n        },\r\n    });\r\n    //------------------------------------------------------------------------------\r\n    // t-debug\r\n    //------------------------------------------------------------------------------\r\n    QWeb.addDirective({\r\n        name: \"debug\",\r\n        priority: 1,\r\n        atNodeEncounter({ ctx }) {\r\n            ctx.addLine(\"debugger;\");\r\n        },\r\n    });\r\n    //------------------------------------------------------------------------------\r\n    // t-log\r\n    //------------------------------------------------------------------------------\r\n    QWeb.addDirective({\r\n        name: \"log\",\r\n        priority: 1,\r\n        atNodeEncounter({ ctx, value }) {\r\n            const expr = ctx.formatExpression(value);\r\n            ctx.addLine(`console.log(${expr})`);\r\n        },\r\n    });\r\n\r\n    /**\r\n     * Owl QWeb Extensions\r\n     *\r\n     * This file contains the implementation of non standard QWeb directives, added\r\n     * by Owl and that will only work on Owl projects:\r\n     *\r\n     * - t-on\r\n     * - t-ref\r\n     * - t-transition\r\n     * - t-mounted\r\n     * - t-slot\r\n     * - t-model\r\n     */\r\n    //------------------------------------------------------------------------------\r\n    // t-on\r\n    //------------------------------------------------------------------------------\r\n    // these are pieces of code that will be injected into the event handler if\r\n    // modifiers are specified\r\n    const MODS_CODE = {\r\n        prevent: \"e.preventDefault();\",\r\n        self: \"if (e.target !== this.elm) {return}\",\r\n        stop: \"e.stopPropagation();\",\r\n    };\r\n    const FNAMEREGEXP = /^[$A-Z_][0-9A-Z_$]*$/i;\r\n    function makeHandlerCode(ctx, fullName, value, putInCache, modcodes = MODS_CODE) {\r\n        let [event, ...mods] = fullName.slice(5).split(\".\");\r\n        if (mods.includes(\"capture\")) {\r\n            event = \"!\" + event;\r\n        }\r\n        if (!event) {\r\n            throw new Error(\"Missing event name with t-on directive\");\r\n        }\r\n        let code;\r\n        // check if it is a method with no args, a method with args or an expression\r\n        let args = \"\";\r\n        const name = value.replace(/\\(.*\\)/, function (_args) {\r\n            args = _args.slice(1, -1);\r\n            return \"\";\r\n        });\r\n        const isMethodCall = name.match(FNAMEREGEXP);\r\n        // then generate code\r\n        if (isMethodCall) {\r\n            ctx.rootContext.shouldDefineUtils = true;\r\n            const comp = `utils.getComponent(context)`;\r\n            if (args) {\r\n                const argId = ctx.generateID();\r\n                ctx.addLine(`let args${argId} = [${ctx.formatExpression(args)}];`);\r\n                code = `${comp}['${name}'](...args${argId}, e);`;\r\n                putInCache = false;\r\n            }\r\n            else {\r\n                code = `${comp}['${name}'](e);`;\r\n            }\r\n        }\r\n        else {\r\n            // if we get here, then it is an expression\r\n            // we need to capture every variable in it\r\n            putInCache = false;\r\n            code = ctx.captureExpression(value);\r\n            code = `const res = (() => { return ${code} })(); if (typeof res === 'function') { res(e) }`;\r\n        }\r\n        const modCode = mods.map((mod) => modcodes[mod]).join(\"\");\r\n        let handler = `function (e) {if (context.__owl__.status === ${5 /* DESTROYED */}){return}${modCode}${code}}`;\r\n        if (putInCache) {\r\n            const key = ctx.generateTemplateKey(event);\r\n            ctx.addLine(`extra.handlers[${key}] = extra.handlers[${key}] || ${handler};`);\r\n            handler = `extra.handlers[${key}]`;\r\n        }\r\n        return { event, handler };\r\n    }\r\n    QWeb.addDirective({\r\n        name: \"on\",\r\n        priority: 90,\r\n        atNodeCreation({ ctx, fullName, value, nodeID }) {\r\n            const { event, handler } = makeHandlerCode(ctx, fullName, value, true);\r\n            ctx.addLine(`p${nodeID}.on['${event}'] = ${handler};`);\r\n        },\r\n    });\r\n    //------------------------------------------------------------------------------\r\n    // t-ref\r\n    //------------------------------------------------------------------------------\r\n    QWeb.addDirective({\r\n        name: \"ref\",\r\n        priority: 95,\r\n        atNodeCreation({ ctx, value, addNodeHook }) {\r\n            ctx.rootContext.shouldDefineRefs = true;\r\n            const refKey = `ref${ctx.generateID()}`;\r\n            ctx.addLine(`const ${refKey} = ${ctx.interpolate(value)};`);\r\n            addNodeHook(\"create\", `context.__owl__.refs[${refKey}] = n.elm;`);\r\n            addNodeHook(\"destroy\", `delete context.__owl__.refs[${refKey}];`);\r\n        },\r\n    });\r\n    //------------------------------------------------------------------------------\r\n    // t-transition\r\n    //------------------------------------------------------------------------------\r\n    QWeb.utils.nextFrame = function (cb) {\r\n        requestAnimationFrame(() => requestAnimationFrame(cb));\r\n    };\r\n    QWeb.utils.transitionInsert = function (vn, name) {\r\n        const elm = vn.elm;\r\n        // remove potential duplicated vnode that is currently being removed, to\r\n        // prevent from having twice the same node in the DOM during an animation\r\n        const dup = elm.parentElement && elm.parentElement.querySelector(`*[data-owl-key='${vn.key}']`);\r\n        if (dup) {\r\n            dup.remove();\r\n        }\r\n        elm.classList.add(name + \"-enter\");\r\n        elm.classList.add(name + \"-enter-active\");\r\n        elm.classList.remove(name + \"-leave-active\");\r\n        elm.classList.remove(name + \"-leave-to\");\r\n        const finalize = () => {\r\n            elm.classList.remove(name + \"-enter-active\");\r\n            elm.classList.remove(name + \"-enter-to\");\r\n        };\r\n        this.nextFrame(() => {\r\n            elm.classList.remove(name + \"-enter\");\r\n            elm.classList.add(name + \"-enter-to\");\r\n            whenTransitionEnd(elm, finalize);\r\n        });\r\n    };\r\n    QWeb.utils.transitionRemove = function (vn, name, rm) {\r\n        const elm = vn.elm;\r\n        elm.setAttribute(\"data-owl-key\", vn.key);\r\n        elm.classList.add(name + \"-leave\");\r\n        elm.classList.add(name + \"-leave-active\");\r\n        const finalize = () => {\r\n            if (!elm.classList.contains(name + \"-leave-active\")) {\r\n                return;\r\n            }\r\n            elm.classList.remove(name + \"-leave-active\");\r\n            elm.classList.remove(name + \"-leave-to\");\r\n            rm();\r\n        };\r\n        this.nextFrame(() => {\r\n            elm.classList.remove(name + \"-leave\");\r\n            elm.classList.add(name + \"-leave-to\");\r\n            whenTransitionEnd(elm, finalize);\r\n        });\r\n    };\r\n    function getTimeout(delays, durations) {\r\n        /* istanbul ignore next */\r\n        while (delays.length < durations.length) {\r\n            delays = delays.concat(delays);\r\n        }\r\n        return Math.max.apply(null, durations.map((d, i) => {\r\n            return toMs(d) + toMs(delays[i]);\r\n        }));\r\n    }\r\n    // Old versions of Chromium (below 61.0.3163.100) formats floating pointer numbers\r\n    // in a locale-dependent way, using a comma instead of a dot.\r\n    // If comma is not replaced with a dot, the input will be rounded down (i.e. acting\r\n    // as a floor function) causing unexpected behaviors\r\n    function toMs(s) {\r\n        return Number(s.slice(0, -1).replace(\",\", \".\")) * 1000;\r\n    }\r\n    function whenTransitionEnd(elm, cb) {\r\n        if (!elm.parentNode) {\r\n            // if we get here, this means that the element was removed for some other\r\n            // reasons, and in that case, we don't want to work on animation since nothing\r\n            // will be displayed anyway.\r\n            return;\r\n        }\r\n        const styles = window.getComputedStyle(elm);\r\n        const delays = (styles.transitionDelay || \"\").split(\", \");\r\n        const durations = (styles.transitionDuration || \"\").split(\", \");\r\n        const timeout = getTimeout(delays, durations);\r\n        if (timeout > 0) {\r\n            const transitionEndCB = () => {\r\n                if (!elm.parentNode)\r\n                    return;\r\n                cb();\r\n                browser.clearTimeout(fallbackTimeout);\r\n                elm.removeEventListener(\"transitionend\", transitionEndCB);\r\n            };\r\n            elm.addEventListener(\"transitionend\", transitionEndCB, { once: true });\r\n            const fallbackTimeout = browser.setTimeout(transitionEndCB, timeout + 1);\r\n        }\r\n        else {\r\n            cb();\r\n        }\r\n    }\r\n    QWeb.addDirective({\r\n        name: \"transition\",\r\n        priority: 96,\r\n        atNodeCreation({ ctx, value, addNodeHook }) {\r\n            if (!QWeb.enableTransitions) {\r\n                return;\r\n            }\r\n            ctx.rootContext.shouldDefineUtils = true;\r\n            let name = value;\r\n            const hooks = {\r\n                insert: `utils.transitionInsert(vn, '${name}');`,\r\n                remove: `utils.transitionRemove(vn, '${name}', rm);`,\r\n            };\r\n            for (let hookName in hooks) {\r\n                addNodeHook(hookName, hooks[hookName]);\r\n            }\r\n        },\r\n    });\r\n    //------------------------------------------------------------------------------\r\n    // t-slot\r\n    //------------------------------------------------------------------------------\r\n    QWeb.addDirective({\r\n        name: \"slot\",\r\n        priority: 80,\r\n        atNodeEncounter({ ctx, value, node, qweb }) {\r\n            const slotKey = ctx.generateID();\r\n            const valueExpr = value.match(INTERP_REGEXP) ? ctx.interpolate(value) : `'${value}'`;\r\n            ctx.addLine(`const slot${slotKey} = this.constructor.slots[context.__owl__.slotId + '_' + ${valueExpr}];`);\r\n            ctx.addIf(`slot${slotKey}`);\r\n            let parentNode = `c${ctx.parentNode}`;\r\n            if (!ctx.parentNode) {\r\n                ctx.rootContext.shouldDefineResult = true;\r\n                ctx.rootContext.shouldDefineUtils = true;\r\n                parentNode = `children${ctx.generateID()}`;\r\n                ctx.addLine(`let ${parentNode}= []`);\r\n                ctx.addLine(`result = {}`);\r\n            }\r\n            ctx.addLine(`slot${slotKey}.call(this, context.__owl__.scope, Object.assign({}, extra, {parentNode: ${parentNode}, parent: extra.parent || context}));`);\r\n            if (!ctx.parentNode) {\r\n                ctx.addLine(`utils.defineProxy(result, ${parentNode}[0]);`);\r\n            }\r\n            if (node.hasChildNodes()) {\r\n                ctx.addElse();\r\n                const nodeCopy = node.cloneNode(true);\r\n                nodeCopy.removeAttribute(\"t-slot\");\r\n                qweb._compileNode(nodeCopy, ctx);\r\n            }\r\n            ctx.closeIf();\r\n            return true;\r\n        },\r\n    });\r\n    //------------------------------------------------------------------------------\r\n    // t-model\r\n    //------------------------------------------------------------------------------\r\n    QWeb.utils.toNumber = function (val) {\r\n        const n = parseFloat(val);\r\n        return isNaN(n) ? val : n;\r\n    };\r\n    const hasDotAtTheEnd = /\\.[\\w_]+\\s*$/;\r\n    const hasBracketsAtTheEnd = /\\[[^\\[]+\\]\\s*$/;\r\n    QWeb.addDirective({\r\n        name: \"model\",\r\n        priority: 42,\r\n        atNodeCreation({ ctx, nodeID, value, node, fullName, addNodeHook }) {\r\n            const type = node.getAttribute(\"type\");\r\n            let handler;\r\n            let event = fullName.includes(\".lazy\") ? \"change\" : \"input\";\r\n            // First step: we need to understand the structure of the expression, and\r\n            // from it, extract a base expression (that we can capture, which is\r\n            // important because it will be used in a handler later) and a formatted\r\n            // expression (which uses the captured base expression)\r\n            //\r\n            // Also, we support 2 kinds of values: some.expr.value or some.expr[value]\r\n            // For the first one, we have:\r\n            // - base expression = scope[some].expr\r\n            // - expression = exprX.value (where exprX is the var that captures the base expr)\r\n            // and for the expression with brackets:\r\n            // - base expression = scope[some].expr\r\n            // - expression = exprX[keyX] (where exprX is the var that captures the base expr\r\n            //        and keyX captures scope[value])\r\n            let expr;\r\n            let baseExpr;\r\n            if (hasDotAtTheEnd.test(value)) {\r\n                // we manage the case where the expr has a dot: some.expr.value\r\n                const index = value.lastIndexOf(\".\");\r\n                baseExpr = value.slice(0, index);\r\n                ctx.addLine(`let expr${nodeID} = ${ctx.formatExpression(baseExpr)};`);\r\n                expr = `expr${nodeID}${value.slice(index)}`;\r\n            }\r\n            else if (hasBracketsAtTheEnd.test(value)) {\r\n                // we manage here the case where the expr ends in a bracket expression:\r\n                //    some.expr[value]\r\n                const index = value.lastIndexOf(\"[\");\r\n                baseExpr = value.slice(0, index);\r\n                ctx.addLine(`let expr${nodeID} = ${ctx.formatExpression(baseExpr)};`);\r\n                let exprKey = value.trimRight().slice(index + 1, -1);\r\n                ctx.addLine(`let exprKey${nodeID} = ${ctx.formatExpression(exprKey)};`);\r\n                expr = `expr${nodeID}[exprKey${nodeID}]`;\r\n            }\r\n            else {\r\n                throw new Error(`Invalid t-model expression: \"${value}\" (it should be assignable)`);\r\n            }\r\n            const key = ctx.generateTemplateKey();\r\n            if (node.tagName === \"select\") {\r\n                ctx.addLine(`p${nodeID}.props = {value: ${expr}};`);\r\n                addNodeHook(\"create\", `n.elm.value=${expr};`);\r\n                event = \"change\";\r\n                handler = `(ev) => {${expr} = ev.target.value}`;\r\n            }\r\n            else if (type === \"checkbox\") {\r\n                ctx.addLine(`p${nodeID}.props = {checked: ${expr}};`);\r\n                handler = `(ev) => {${expr} = ev.target.checked}`;\r\n            }\r\n            else if (type === \"radio\") {\r\n                const nodeValue = node.getAttribute(\"value\");\r\n                ctx.addLine(`p${nodeID}.props = {checked:${expr} === '${nodeValue}'};`);\r\n                handler = `(ev) => {${expr} = ev.target.value}`;\r\n                event = \"click\";\r\n            }\r\n            else {\r\n                ctx.addLine(`p${nodeID}.props = {value: ${expr}};`);\r\n                const trimCode = fullName.includes(\".trim\") ? \".trim()\" : \"\";\r\n                let valueCode = `ev.target.value${trimCode}`;\r\n                if (fullName.includes(\".number\")) {\r\n                    ctx.rootContext.shouldDefineUtils = true;\r\n                    valueCode = `utils.toNumber(${valueCode})`;\r\n                }\r\n                handler = `(ev) => {${expr} = ${valueCode}}`;\r\n            }\r\n            ctx.addLine(`extra.handlers[${key}] = extra.handlers[${key}] || (${handler});`);\r\n            ctx.addLine(`p${nodeID}.on['${event}'] = extra.handlers[${key}];`);\r\n        },\r\n    });\r\n    //------------------------------------------------------------------------------\r\n    // t-key\r\n    //------------------------------------------------------------------------------\r\n    QWeb.addDirective({\r\n        name: \"key\",\r\n        priority: 45,\r\n        atNodeEncounter({ ctx, value, node }) {\r\n            if (ctx.loopNumber === 0) {\r\n                ctx.keyStack.push(ctx.rootContext.hasKey0);\r\n                ctx.rootContext.hasKey0 = true;\r\n            }\r\n            ctx.addLine(\"{\");\r\n            ctx.indent();\r\n            ctx.addLine(`let key${ctx.loopNumber} = ${ctx.formatExpression(value)};`);\r\n        },\r\n        finalize({ ctx }) {\r\n            ctx.dedent();\r\n            ctx.addLine(\"}\");\r\n            if (ctx.loopNumber === 0) {\r\n                ctx.rootContext.hasKey0 = ctx.keyStack.pop();\r\n            }\r\n        },\r\n    });\r\n\r\n    const config = {\r\n        translatableAttributes: TRANSLATABLE_ATTRS,\r\n    };\r\n    Object.defineProperty(config, \"mode\", {\r\n        get() {\r\n            return QWeb.dev ? \"dev\" : \"prod\";\r\n        },\r\n        set(mode) {\r\n            QWeb.dev = mode === \"dev\";\r\n            if (QWeb.dev) {\r\n                console.info(`Owl is running in 'dev' mode.\r\n\r\nThis is not suitable for production use.\r\nSee https://github.com/odoo/owl/blob/owl-1.x/doc/reference/config.md#mode for more information.`);\r\n            }\r\n        },\r\n    });\r\n    Object.defineProperty(config, \"enableTransitions\", {\r\n        get() {\r\n            return QWeb.enableTransitions;\r\n        },\r\n        set(value) {\r\n            QWeb.enableTransitions = value;\r\n        },\r\n    });\r\n\r\n    /**\r\n     * We define here OwlEvent, a subclass of CustomEvent, with an additional\r\n     * attribute:\r\n     *  - originalComponent: the component that triggered the event\r\n     */\r\n    class OwlEvent extends CustomEvent {\r\n        constructor(component, eventType, options) {\r\n            super(eventType, options);\r\n            this.originalComponent = component;\r\n        }\r\n    }\r\n\r\n    //------------------------------------------------------------------------------\r\n    // t-component\r\n    //------------------------------------------------------------------------------\r\n    const T_COMPONENT_MODS_CODE = Object.assign({}, MODS_CODE, {\r\n        self: \"if (e.target !== vn.elm) {return}\",\r\n    });\r\n    QWeb.utils.defineProxy = function defineProxy(target, source) {\r\n        for (let k in source) {\r\n            Object.defineProperty(target, k, {\r\n                get() {\r\n                    return source[k];\r\n                },\r\n                set(val) {\r\n                    source[k] = val;\r\n                },\r\n            });\r\n        }\r\n    };\r\n    QWeb.utils.assignHooks = function assignHooks(dataObj, hooks) {\r\n        if (\"hook\" in dataObj) {\r\n            const hookObject = dataObj.hook;\r\n            for (let name in hooks) {\r\n                const current = hookObject[name];\r\n                const fn = hooks[name];\r\n                if (current) {\r\n                    hookObject[name] = (...args) => {\r\n                        current(...args);\r\n                        fn(...args);\r\n                    };\r\n                }\r\n                else {\r\n                    hookObject[name] = fn;\r\n                }\r\n            }\r\n        }\r\n        else {\r\n            dataObj.hook = hooks;\r\n        }\r\n    };\r\n    /**\r\n     * The t-component directive is certainly a complicated and hard to maintain piece\r\n     * of code.  To help you, fellow developer, if you have to maintain it, I offer\r\n     * you this advice: Good luck...\r\n     *\r\n     * Since it is not 'direct' code, but rather code that generates other code, it\r\n     * is not easy to understand.  To help you, here  is a detailed and commented\r\n     * explanation of the code generated by the t-component directive for the following\r\n     * situation:\r\n     * ```xml\r\n     *   <Child\r\n     *      t-key=\"'somestring'\"\r\n     *      flag=\"state.flag\"\r\n     *      t-transition=\"fade\"/>\r\n     * ```\r\n     *\r\n     * ```js\r\n     * // we assign utils on top of the function because it will be useful for\r\n     * // each components\r\n     * let utils = this.utils;\r\n     *\r\n     * // this is the virtual node representing the parent div\r\n     * let c1 = [], p1 = { key: 1 };\r\n     * var vn1 = h(\"div\", p1, c1);\r\n     *\r\n     * // t-component directive: we start by evaluating the expression given by t-key:\r\n     * let key5 = \"somestring\";\r\n     *\r\n     * // def3 is the promise that will contain later either the new component\r\n     * // creation, or the props update...\r\n     * let def3;\r\n     *\r\n     * // this is kind of tricky: we need here to find if the component was already\r\n     * // created by a previous rendering.  This is done by checking the internal\r\n     * // `cmap` (children map) of the parent component: it maps keys to component ids,\r\n     * // and, then, if there is an id, we look into the children list to get the\r\n     * // instance\r\n     * let w4 =\r\n     *   key5 in context.__owl__.cmap\r\n     *   ? context.__owl__.children[context.__owl__.cmap[key5]]\r\n     *   : false;\r\n     *\r\n     * // We keep the index of the position of the component in the closure.  We push\r\n     * // null to reserve the slot, and will replace it later by the component vnode,\r\n     * // when it will be ready (do not forget that preparing/rendering a component is\r\n     * // asynchronous)\r\n     * let _2_index = c1.length;\r\n     * c1.push(null);\r\n     *\r\n     * // we evaluate here the props given to the component. It is done here to be\r\n     * // able to easily reference it later, and also, it might be an expensive\r\n     * // computation, so it is certainly better to do it only once\r\n     * let props4 = { flag: context[\"state\"].flag };\r\n     *\r\n     * // If we have a component, currently rendering, but not ready yet, we do not want\r\n     * // to wait for it to be ready if we can avoid it\r\n     * if (w4 && w4.__owl__.renderPromise && !w4.__owl__.vnode) {\r\n     *   // we check if the props are the same.  In that case, we can simply reuse\r\n     *   // the previous rendering and skip all useless work\r\n     *   if (utils.shallowEqual(props4, w4.__owl__.renderProps)) {\r\n     *     def3 = w4.__owl__.renderPromise;\r\n     *   } else {\r\n     *     // if the props are not the same, we destroy the component and starts anew.\r\n     *     // this will be faster than waiting for its rendering, then updating it\r\n     *     w4.destroy();\r\n     *     w4 = false;\r\n     *   }\r\n     * }\r\n     *\r\n     * if (!w4) {\r\n     *   // in this situation, we need to create a new component.  First step is\r\n     *   // to get a reference to the class, then create an instance with\r\n     *   // current context as parent, and the props.\r\n     *   let W4 = context.component && context.components[componentKey4] || QWeb.component[componentKey4];\r\n\r\n     *   if (!W4) {\r\n     *     throw new Error(\"Cannot find the definition of component 'child'\");\r\n     *   }\r\n     *   w4 = new W4(owner, props4);\r\n     *\r\n     *   // Whenever we rerender the parent component, we need to be sure that we\r\n     *   // are able to find the component instance. To do that, we register it to\r\n     *   // the parent cmap (children map).  Note that the 'template' key is\r\n     *   // used here, since this is what identify the component from the template\r\n     *   // perspective.\r\n     *   context.__owl__.cmap[key5] = w4.__owl__.id;\r\n     *\r\n     *   // __prepare is called, to basically call willStart, then render the\r\n     *   // component\r\n     *   def3 = w4.__prepare();\r\n     *\r\n     *   def3 = def3.then(vnode => {\r\n     *     // we create here a virtual node for the parent (NOT the component). This\r\n     *     // means that the vdom of the parent will be stopped here, and from\r\n     *     // the parent's perspective, it simply is a vnode with no children.\r\n     *     // However, it shares the same dom element with the component root\r\n     *     // vnode.\r\n     *     let pvnode = h(vnode.sel, { key: key5 });\r\n     *\r\n     *     // we add hooks to the parent vnode so we can interact with the new\r\n     *     // component at the proper time\r\n     *     pvnode.data.hook = {\r\n     *       insert(vn) {\r\n     *         // the __mount method will patch the component vdom into the elm vn.elm,\r\n     *         // then call the mounted hooks. However, suprisingly, the snabbdom\r\n     *         // patch method actually replace the elm by a new elm, so we need\r\n     *         // to synchronise the pvnode elm with the resulting elm\r\n     *         let nvn = w4.__mount(vnode, vn.elm);\r\n     *         pvnode.elm = nvn.elm;\r\n     *         // what follows is only present if there are animations on the component\r\n     *         utils.transitionInsert(vn, \"fade\");\r\n     *       },\r\n     *       remove() {\r\n     *         // override with empty function to prevent from removing the node\r\n     *         // directly. It will be removed when destroy is called anyway, which\r\n     *         // delays the removal if there are animations.\r\n     *       },\r\n     *       destroy() {\r\n     *         // if there are animations, we delay the call to destroy on the\r\n     *         // component, if not, we call it directly.\r\n     *         let finalize = () => {\r\n     *           w4.destroy();\r\n     *         };\r\n     *         utils.transitionRemove(vn, \"fade\", finalize);\r\n     *       }\r\n     *     };\r\n     *     // the pvnode is inserted at the correct position in the div's children\r\n     *     c1[_2_index] = pvnode;\r\n     *\r\n     *     // we keep here a reference to the parent vnode (representing the\r\n     *     // component, so we can reuse it later whenever we update the component\r\n     *     w4.__owl__.pvnode = pvnode;\r\n     *   });\r\n     * } else {\r\n     *   // this is the 'update' path of the directive.\r\n     *   // the call to __updateProps is the actual component update\r\n     *   // Note that we only update the props if we cannot reuse the previous\r\n     *   // rendering work (in the case it was rendered with the same props)\r\n     *   def3 = def3 || w4.__updateProps(props4, extra.forceUpdate, extra.patchQueue);\r\n     *   def3 = def3.then(() => {\r\n     *     // if component was destroyed in the meantime, we do nothing (so, this\r\n     *     // means that the parent's element children list will have a null in\r\n     *     // the component's position, which will cause the pvnode to be removed\r\n     *     // when it is patched.\r\n     *     if (w4.__owl__.isDestroyed) {\r\n     *       return;\r\n     *     }\r\n     *     // like above, we register the pvnode to the children list, so it\r\n     *     // will not be patched out of the dom.\r\n     *     let pvnode = w4.__owl__.pvnode;\r\n     *     c1[_2_index] = pvnode;\r\n     *   });\r\n     * }\r\n     *\r\n     * // we register the deferred here so the parent can coordinate its patch operation\r\n     * // with all the children.\r\n     * extra.promises.push(def3);\r\n     * return vn1;\r\n     * ```\r\n     */\r\n    QWeb.addDirective({\r\n        name: \"component\",\r\n        extraNames: [\"props\"],\r\n        priority: 100,\r\n        atNodeEncounter({ ctx, value, node, qweb }) {\r\n            ctx.addLine(`// Component '${value}'`);\r\n            ctx.rootContext.shouldDefineQWeb = true;\r\n            ctx.rootContext.shouldDefineParent = true;\r\n            ctx.rootContext.shouldDefineUtils = true;\r\n            ctx.rootContext.shouldDefineScope = true;\r\n            let hasDynamicProps = node.getAttribute(\"t-props\") ? true : false;\r\n            // t-on- events and t-transition\r\n            const events = [];\r\n            let transition = \"\";\r\n            const attributes = node.attributes;\r\n            const props = {};\r\n            for (let i = 0; i < attributes.length; i++) {\r\n                const name = attributes[i].name;\r\n                const value = attributes[i].textContent;\r\n                if (name.startsWith(\"t-on-\")) {\r\n                    events.push([name, value]);\r\n                }\r\n                else if (name === \"t-transition\") {\r\n                    if (QWeb.enableTransitions) {\r\n                        transition = value;\r\n                    }\r\n                }\r\n                else if (!name.startsWith(\"t-\")) {\r\n                    if (name !== \"class\" && name !== \"style\") {\r\n                        // this is a prop!\r\n                        if (value.includes(\"=>\")) {\r\n                            props[name] = ctx.captureExpression(value);\r\n                        }\r\n                        else {\r\n                            props[name] = ctx.formatExpression(value) || \"undefined\";\r\n                        }\r\n                    }\r\n                }\r\n            }\r\n            // computing the props string representing the props object\r\n            let propStr = Object.keys(props)\r\n                .map((k) => k + \":\" + props[k])\r\n                .join(\",\");\r\n            let componentID = ctx.generateID();\r\n            let hasDefinedKey = false;\r\n            let templateKey;\r\n            if (node.tagName === \"t\" && !node.hasAttribute(\"t-key\") && value.match(INTERP_REGEXP)) {\r\n                defineComponentKey();\r\n                const id = ctx.generateID();\r\n                // the ___ is to make sure we have no possible conflict with normal\r\n                // template keys\r\n                ctx.addLine(`let k${id} = '___' + componentKey${componentID}`);\r\n                templateKey = `k${id}`;\r\n            }\r\n            else {\r\n                templateKey = ctx.generateTemplateKey();\r\n            }\r\n            let ref = node.getAttribute(\"t-ref\");\r\n            let refExpr = \"\";\r\n            let refKey = \"\";\r\n            if (ref) {\r\n                ctx.rootContext.shouldDefineRefs = true;\r\n                refKey = `ref${ctx.generateID()}`;\r\n                ctx.addLine(`const ${refKey} = ${ctx.interpolate(ref)};`);\r\n                refExpr = `context.__owl__.refs[${refKey}] = w${componentID};`;\r\n            }\r\n            let finalizeComponentCode = `w${componentID}.destroy();`;\r\n            if (ref) {\r\n                finalizeComponentCode += `delete context.__owl__.refs[${refKey}];`;\r\n            }\r\n            if (transition) {\r\n                finalizeComponentCode = `let finalize = () => {\r\n          ${finalizeComponentCode}\r\n        };\r\n        delete w${componentID}.__owl__.transitionInserted;\r\n        utils.transitionRemove(vn, '${transition}', finalize);`;\r\n            }\r\n            let createHook = \"\";\r\n            let classAttr = node.getAttribute(\"class\");\r\n            let tattClass = node.getAttribute(\"t-att-class\");\r\n            let styleAttr = node.getAttribute(\"style\");\r\n            let tattStyle = node.getAttribute(\"t-att-style\");\r\n            if (tattStyle) {\r\n                const attVar = `_${ctx.generateID()}`;\r\n                ctx.addLine(`const ${attVar} = ${ctx.formatExpression(tattStyle)};`);\r\n                tattStyle = attVar;\r\n            }\r\n            let classObj = \"\";\r\n            if (classAttr || tattClass || styleAttr || tattStyle || events.length) {\r\n                if (classAttr) {\r\n                    let classDef = classAttr\r\n                        .trim()\r\n                        .split(/\\s+/)\r\n                        .map((a) => `'${a}':true`)\r\n                        .join(\",\");\r\n                    classObj = `_${ctx.generateID()}`;\r\n                    ctx.addLine(`let ${classObj} = {${classDef}};`);\r\n                }\r\n                if (tattClass) {\r\n                    let tattExpr = ctx.formatExpression(tattClass);\r\n                    if (tattExpr[0] !== \"{\" || tattExpr[tattExpr.length - 1] !== \"}\") {\r\n                        tattExpr = `utils.toClassObj(${tattExpr})`;\r\n                    }\r\n                    if (classAttr) {\r\n                        ctx.addLine(`Object.assign(${classObj}, ${tattExpr})`);\r\n                    }\r\n                    else {\r\n                        classObj = `_${ctx.generateID()}`;\r\n                        ctx.addLine(`let ${classObj} = ${tattExpr};`);\r\n                    }\r\n                }\r\n                let eventsCode = events\r\n                    .map(function ([name, value]) {\r\n                    const capture = name.match(/\\.capture/);\r\n                    name = capture ? name.replace(/\\.capture/, \"\") : name;\r\n                    const { event, handler } = makeHandlerCode(ctx, name, value, false, T_COMPONENT_MODS_CODE);\r\n                    if (capture) {\r\n                        return `vn.elm.addEventListener('${event}', ${handler}, true);`;\r\n                    }\r\n                    return `vn.elm.addEventListener('${event}', ${handler});`;\r\n                })\r\n                    .join(\"\");\r\n                const styleExpr = tattStyle || (styleAttr ? `'${styleAttr}'` : false);\r\n                const styleCode = styleExpr ? `vn.elm.style = ${styleExpr};` : \"\";\r\n                createHook = `utils.assignHooks(vnode.data, {create(_, vn){${styleCode}${eventsCode}}});`;\r\n            }\r\n            ctx.addLine(`let w${componentID} = ${templateKey} in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[${templateKey}]] : false;`);\r\n            let shouldProxy = !ctx.parentNode;\r\n            if (shouldProxy) {\r\n                let id = ctx.generateID();\r\n                ctx.rootContext.rootNode = id;\r\n                shouldProxy = true;\r\n                ctx.rootContext.shouldDefineResult = true;\r\n                ctx.addLine(`let vn${id} = {};`);\r\n                ctx.addLine(`result = vn${id};`);\r\n            }\r\n            if (hasDynamicProps) {\r\n                const dynamicProp = ctx.formatExpression(node.getAttribute(\"t-props\"));\r\n                ctx.addLine(`let props${componentID} = Object.assign({}, ${dynamicProp}, {${propStr}});`);\r\n            }\r\n            else {\r\n                ctx.addLine(`let props${componentID} = {${propStr}};`);\r\n            }\r\n            ctx.addIf(`w${componentID} && w${componentID}.__owl__.currentFiber && !w${componentID}.__owl__.vnode`);\r\n            ctx.addLine(`w${componentID}.destroy();`);\r\n            ctx.addLine(`w${componentID} = false;`);\r\n            ctx.closeIf();\r\n            let registerCode = \"\";\r\n            if (shouldProxy) {\r\n                registerCode = `utils.defineProxy(vn${ctx.rootNode}, pvnode);`;\r\n            }\r\n            // SLOTS\r\n            const hasSlots = node.childNodes.length;\r\n            let scope = hasSlots ? `utils.combine(context, scope)` : \"undefined\";\r\n            ctx.addIf(`w${componentID}`);\r\n            // need to update component\r\n            let styleCode = \"\";\r\n            if (tattStyle) {\r\n                styleCode = `.then(()=>{if (w${componentID}.__owl__.status === ${5 /* DESTROYED */}) {return};w${componentID}.el.style=${tattStyle};});`;\r\n            }\r\n            ctx.addLine(`w${componentID}.__updateProps(props${componentID}, extra.fiber, ${scope})${styleCode};`);\r\n            ctx.addLine(`let pvnode = w${componentID}.__owl__.pvnode;`);\r\n            if (registerCode) {\r\n                ctx.addLine(registerCode);\r\n            }\r\n            if (ctx.parentNode) {\r\n                ctx.addLine(`c${ctx.parentNode}.push(pvnode);`);\r\n            }\r\n            ctx.addElse();\r\n            // new component\r\n            function defineComponentKey() {\r\n                if (!hasDefinedKey) {\r\n                    const interpValue = ctx.interpolate(value);\r\n                    ctx.addLine(`let componentKey${componentID} = ${interpValue};`);\r\n                    hasDefinedKey = true;\r\n                }\r\n            }\r\n            defineComponentKey();\r\n            const contextualValue = value.match(INTERP_REGEXP) ? \"false\" : ctx.formatExpression(value);\r\n            ctx.addLine(`let W${componentID} = ${contextualValue} || context.constructor.components[componentKey${componentID}] || QWeb.components[componentKey${componentID}];`);\r\n            // maybe only do this in dev mode...\r\n            ctx.addLine(`if (!W${componentID}) {throw new Error('Cannot find the definition of component \"' + componentKey${componentID} + '\"')}`);\r\n            ctx.addLine(`w${componentID} = new W${componentID}(parent, props${componentID});`);\r\n            if (transition) {\r\n                ctx.addLine(`const __patch${componentID} = w${componentID}.__patch;`);\r\n                ctx.addLine(`w${componentID}.__patch = (t, vn) => {__patch${componentID}.call(w${componentID}, t, vn); if(!w${componentID}.__owl__.transitionInserted){w${componentID}.__owl__.transitionInserted = true;utils.transitionInsert(w${componentID}.__owl__.vnode, '${transition}');}};`);\r\n            }\r\n            ctx.addLine(`parent.__owl__.cmap[${templateKey}] = w${componentID}.__owl__.id;`);\r\n            if (hasSlots) {\r\n                const clone = node.cloneNode(true);\r\n                // The next code is a fallback for compatibility reason. It accepts t-set\r\n                // elements that are direct children with a non empty body as nodes defining\r\n                // the content of a slot.\r\n                //\r\n                // This is wrong, but is necessary to prevent breaking all existing Owl\r\n                // code using slots. This will be removed in v2.0 someday. Meanwhile,\r\n                // please use t-set-slot everywhere you need to set the content of a\r\n                // slot.\r\n                for (let node of clone.children) {\r\n                    if (node.hasAttribute(\"t-set\") && node.hasChildNodes()) {\r\n                        node.setAttribute(\"t-set-slot\", node.getAttribute(\"t-set\"));\r\n                        node.removeAttribute(\"t-set\");\r\n                    }\r\n                }\r\n                const slotNodes = Array.from(clone.querySelectorAll(\"[t-set-slot]\"));\r\n                const slotNames = new Set();\r\n                const slotId = QWeb.nextSlotId++;\r\n                ctx.addLine(`w${componentID}.__owl__.slotId = ${slotId};`);\r\n                if (slotNodes.length) {\r\n                    for (let i = 0, length = slotNodes.length; i < length; i++) {\r\n                        const slotNode = slotNodes[i];\r\n                        // check if this is defined in a sub component (in which case it should\r\n                        // be ignored)\r\n                        let el = slotNode.parentElement;\r\n                        let isInSubComponent = false;\r\n                        while (el !== clone) {\r\n                            if (el.hasAttribute(\"t-component\") ||\r\n                                el.tagName[0] === el.tagName[0].toUpperCase()) {\r\n                                isInSubComponent = true;\r\n                                break;\r\n                            }\r\n                            el = el.parentElement;\r\n                        }\r\n                        if (isInSubComponent) {\r\n                            continue;\r\n                        }\r\n                        let key = slotNode.getAttribute(\"t-set-slot\");\r\n                        if (slotNames.has(key)) {\r\n                            continue;\r\n                        }\r\n                        slotNames.add(key);\r\n                        slotNode.removeAttribute(\"t-set-slot\");\r\n                        slotNode.parentElement.removeChild(slotNode);\r\n                        const slotFn = qweb._compile(`slot_${key}_template`, { elem: slotNode, hasParent: true });\r\n                        QWeb.slots[`${slotId}_${key}`] = slotFn;\r\n                    }\r\n                }\r\n                if (clone.childNodes.length) {\r\n                    let hasContent = false;\r\n                    const t = clone.ownerDocument.createElement(\"t\");\r\n                    for (let child of Object.values(clone.childNodes)) {\r\n                        hasContent =\r\n                            hasContent || (child instanceof Text ? Boolean(child.textContent.trim().length) : true);\r\n                        t.appendChild(child);\r\n                    }\r\n                    if (hasContent) {\r\n                        const slotFn = qweb._compile(`slot_default_template`, { elem: t, hasParent: true });\r\n                        QWeb.slots[`${slotId}_default`] = slotFn;\r\n                    }\r\n                }\r\n            }\r\n            ctx.addLine(`let fiber = w${componentID}.__prepare(extra.fiber, ${scope}, () => { const vnode = fiber.vnode; pvnode.sel = vnode.sel; ${createHook}});`);\r\n            // hack: specify empty remove hook to prevent the node from being removed from the DOM\r\n            const insertHook = refExpr ? `insert(vn) {${refExpr}},` : \"\";\r\n            ctx.addLine(`let pvnode = h('dummy', {key: ${templateKey}, hook: {${insertHook}remove() {},destroy(vn) {${finalizeComponentCode}}}});`);\r\n            if (registerCode) {\r\n                ctx.addLine(registerCode);\r\n            }\r\n            if (ctx.parentNode) {\r\n                ctx.addLine(`c${ctx.parentNode}.push(pvnode);`);\r\n            }\r\n            ctx.addLine(`w${componentID}.__owl__.pvnode = pvnode;`);\r\n            ctx.closeIf();\r\n            if (classObj) {\r\n                ctx.addLine(`w${componentID}.__owl__.classObj=${classObj};`);\r\n            }\r\n            ctx.addLine(`w${componentID}.__owl__.parentLastFiberId = extra.fiber.id;`);\r\n            return true;\r\n        },\r\n    });\r\n\r\n    class Scheduler {\r\n        constructor(requestAnimationFrame) {\r\n            this.tasks = [];\r\n            this.isRunning = false;\r\n            this.requestAnimationFrame = requestAnimationFrame;\r\n        }\r\n        start() {\r\n            this.isRunning = true;\r\n            this.scheduleTasks();\r\n        }\r\n        stop() {\r\n            this.isRunning = false;\r\n        }\r\n        addFiber(fiber) {\r\n            // if the fiber was remapped into a larger rendering fiber, it may not be a\r\n            // root fiber.  But we only want to register root fibers\r\n            fiber = fiber.root;\r\n            return new Promise((resolve, reject) => {\r\n                if (fiber.error) {\r\n                    return reject(fiber.error);\r\n                }\r\n                this.tasks.push({\r\n                    fiber,\r\n                    callback: () => {\r\n                        if (fiber.error) {\r\n                            return reject(fiber.error);\r\n                        }\r\n                        resolve();\r\n                    },\r\n                });\r\n                if (!this.isRunning) {\r\n                    this.start();\r\n                }\r\n            });\r\n        }\r\n        rejectFiber(fiber, reason) {\r\n            fiber = fiber.root;\r\n            const index = this.tasks.findIndex((t) => t.fiber === fiber);\r\n            if (index >= 0) {\r\n                const [task] = this.tasks.splice(index, 1);\r\n                fiber.cancel();\r\n                fiber.error = new Error(reason);\r\n                task.callback();\r\n            }\r\n        }\r\n        /**\r\n         * Process all current tasks. This only applies to the fibers that are ready.\r\n         * Other tasks are left unchanged.\r\n         */\r\n        flush() {\r\n            let tasks = this.tasks;\r\n            this.tasks = [];\r\n            tasks = tasks.filter((task) => {\r\n                if (task.fiber.isCompleted) {\r\n                    task.callback();\r\n                    return false;\r\n                }\r\n                if (task.fiber.counter === 0) {\r\n                    if (!task.fiber.error) {\r\n                        try {\r\n                            task.fiber.complete();\r\n                        }\r\n                        catch (e) {\r\n                            task.fiber.handleError(e);\r\n                        }\r\n                    }\r\n                    task.callback();\r\n                    return false;\r\n                }\r\n                return true;\r\n            });\r\n            this.tasks = tasks.concat(this.tasks);\r\n            if (this.tasks.length === 0) {\r\n                this.stop();\r\n            }\r\n        }\r\n        scheduleTasks() {\r\n            this.requestAnimationFrame(() => {\r\n                this.flush();\r\n                if (this.isRunning) {\r\n                    this.scheduleTasks();\r\n                }\r\n            });\r\n        }\r\n    }\r\n    const scheduler = new Scheduler(browser.requestAnimationFrame);\r\n\r\n    /**\r\n     * Owl Fiber Class\r\n     *\r\n     * Fibers are small abstractions designed to contain all the internal state\r\n     * associated with a \"rendering work unit\", relative to a specific component.\r\n     *\r\n     * A rendering will cause the creation of a fiber for each impacted components.\r\n     *\r\n     * Fibers capture all that necessary information, which is critical to owl\r\n     * asynchronous rendering pipeline. Fibers can be cancelled, can be in different\r\n     * states and in general determine the state of the rendering.\r\n     */\r\n    class Fiber {\r\n        constructor(parent, component, force, target, position) {\r\n            this.id = Fiber.nextId++;\r\n            // isCompleted means that the rendering corresponding to this fiber's work is\r\n            // done, either because the component has been mounted or patched, or because\r\n            // fiber has been cancelled.\r\n            this.isCompleted = false;\r\n            // the fibers corresponding to component updates (updateProps) need to call\r\n            // the willPatch and patched hooks from the corresponding component. However,\r\n            // fibers corresponding to a new component do not need to do that. So, the\r\n            // shouldPatch hook is the boolean that we check whenever we need to apply\r\n            // a patch.\r\n            this.shouldPatch = true;\r\n            // isRendered is the last state of a fiber. If true, this means that it has\r\n            // been rendered and is inert (so, it should not be taken into account when\r\n            // counting the number of active fibers).\r\n            this.isRendered = false;\r\n            // the counter number is a critical information. It is only necessary for a\r\n            // root fiber.  For that fiber, this number counts the number of active sub\r\n            // fibers.  When that number reaches 0, the fiber can be applied by the\r\n            // scheduler.\r\n            this.counter = 0;\r\n            this.vnode = null;\r\n            this.child = null;\r\n            this.sibling = null;\r\n            this.lastChild = null;\r\n            this.parent = null;\r\n            this.component = component;\r\n            this.force = force;\r\n            this.target = target;\r\n            this.position = position;\r\n            const __owl__ = component.__owl__;\r\n            this.scope = __owl__.scope;\r\n            this.root = parent ? parent.root : this;\r\n            this.parent = parent;\r\n            let oldFiber = __owl__.currentFiber;\r\n            if (oldFiber && !oldFiber.isCompleted) {\r\n                this.force = true;\r\n                if (oldFiber.root === oldFiber && !parent) {\r\n                    // both oldFiber and this fiber are root fibers\r\n                    this._reuseFiber(oldFiber);\r\n                    return oldFiber;\r\n                }\r\n                else {\r\n                    this._remapFiber(oldFiber);\r\n                }\r\n            }\r\n            this.root.counter++;\r\n            __owl__.currentFiber = this;\r\n        }\r\n        /**\r\n         * When the oldFiber is not completed yet, and both oldFiber and this fiber\r\n         * are root fibers, we want to reuse the oldFiber instead of creating a new\r\n         * one. Doing so will guarantee that the initiator(s) of those renderings will\r\n         * be notified (the promise will resolve) when the last rendering will be done.\r\n         *\r\n         * This function thus assumes that oldFiber is a root fiber.\r\n         */\r\n        _reuseFiber(oldFiber) {\r\n            oldFiber.cancel(); // cancel children fibers\r\n            oldFiber.target = this.target || oldFiber.target;\r\n            oldFiber.position = this.position || oldFiber.position;\r\n            oldFiber.isCompleted = false; // keep the root fiber alive\r\n            oldFiber.isRendered = false; // the fiber has to be re-rendered\r\n            if (oldFiber.child) {\r\n                // remove relation to children\r\n                oldFiber.child.parent = null;\r\n                oldFiber.child = null;\r\n                oldFiber.lastChild = null;\r\n            }\r\n            oldFiber.counter = 1; // re-initialize counter\r\n            oldFiber.id = Fiber.nextId++;\r\n        }\r\n        /**\r\n         * In some cases, a rendering initiated at some component can detect that it\r\n         * should be part of a larger rendering initiated somewhere up the component\r\n         * tree.  In that case, it needs to cancel the previous rendering and\r\n         * remap itself as a part of the current parent rendering.\r\n         */\r\n        _remapFiber(oldFiber) {\r\n            oldFiber.cancel();\r\n            this.shouldPatch = oldFiber.shouldPatch;\r\n            if (oldFiber === oldFiber.root) {\r\n                oldFiber.counter++;\r\n            }\r\n            if (oldFiber.parent && !this.parent) {\r\n                // re-map links\r\n                this.parent = oldFiber.parent;\r\n                this.root = this.parent.root;\r\n                this.sibling = oldFiber.sibling;\r\n                if (this.parent.lastChild === oldFiber) {\r\n                    this.parent.lastChild = this;\r\n                }\r\n                if (this.parent.child === oldFiber) {\r\n                    this.parent.child = this;\r\n                }\r\n                else {\r\n                    let current = this.parent.child;\r\n                    while (true) {\r\n                        if (current.sibling === oldFiber) {\r\n                            current.sibling = this;\r\n                            break;\r\n                        }\r\n                        current = current.sibling;\r\n                    }\r\n                }\r\n            }\r\n        }\r\n        /**\r\n         * This function has been taken from\r\n         * https://medium.com/react-in-depth/the-how-and-why-on-reacts-usage-of-linked-list-in-fiber-67f1014d0eb7\r\n         */\r\n        _walk(doWork) {\r\n            let root = this;\r\n            let current = this;\r\n            while (true) {\r\n                const child = doWork(current);\r\n                if (child) {\r\n                    current = child;\r\n                    continue;\r\n                }\r\n                if (current === root) {\r\n                    return;\r\n                }\r\n                while (!current.sibling) {\r\n                    if (!current.parent || current.parent === root) {\r\n                        return;\r\n                    }\r\n                    current = current.parent;\r\n                }\r\n                current = current.sibling;\r\n            }\r\n        }\r\n        /**\r\n         * Successfully complete the work of the fiber: call the mount or patch hooks\r\n         * and patch the DOM. This function is called once the fiber and its children\r\n         * are ready, and the scheduler decides to process it.\r\n         */\r\n        complete() {\r\n            let component = this.component;\r\n            this.isCompleted = true;\r\n            const status = component.__owl__.status;\r\n            if (status === 5 /* DESTROYED */) {\r\n                return;\r\n            }\r\n            // build patchQueue\r\n            const patchQueue = [];\r\n            const doWork = function (f) {\r\n                f.component.__owl__.currentFiber = null;\r\n                patchQueue.push(f);\r\n                return f.child;\r\n            };\r\n            this._walk(doWork);\r\n            const patchLen = patchQueue.length;\r\n            // call willPatch hook on each fiber of patchQueue\r\n            if (status === 3 /* MOUNTED */) {\r\n                for (let i = 0; i < patchLen; i++) {\r\n                    const fiber = patchQueue[i];\r\n                    if (fiber.shouldPatch) {\r\n                        component = fiber.component;\r\n                        if (component.__owl__.willPatchCB) {\r\n                            component.__owl__.willPatchCB();\r\n                        }\r\n                        component.willPatch();\r\n                    }\r\n                }\r\n            }\r\n            // call __patch on each fiber of (reversed) patchQueue\r\n            for (let i = patchLen - 1; i >= 0; i--) {\r\n                const fiber = patchQueue[i];\r\n                component = fiber.component;\r\n                if (fiber.target && i === 0) {\r\n                    let target;\r\n                    if (fiber.position === \"self\") {\r\n                        target = fiber.target;\r\n                        if (target.tagName.toLowerCase() !== fiber.vnode.sel) {\r\n                            throw new Error(`Cannot attach '${component.constructor.name}' to target node (not same tag name)`);\r\n                        }\r\n                        // In self mode, we *know* we are to take possession of the target\r\n                        // Hence we manually create the corresponding VNode and copy the \"key\" in data\r\n                        const selfVnodeData = fiber.vnode.data ? { key: fiber.vnode.data.key } : {};\r\n                        const selfVnode = h(fiber.vnode.sel, selfVnodeData);\r\n                        selfVnode.elm = target;\r\n                        target = selfVnode;\r\n                    }\r\n                    else {\r\n                        target = component.__owl__.vnode || document.createElement(fiber.vnode.sel);\r\n                    }\r\n                    component.__patch(target, fiber.vnode);\r\n                }\r\n                else {\r\n                    const vnode = component.__owl__.vnode;\r\n                    if (fiber.shouldPatch && vnode) {\r\n                        component.__patch(vnode, fiber.vnode);\r\n                        // When updating a Component's props (in directive),\r\n                        // the component has a pvnode AND should be patched.\r\n                        // However, its pvnode.elm may have changed if it is a High Order Component\r\n                        if (component.__owl__.pvnode) {\r\n                            component.__owl__.pvnode.elm = component.__owl__.vnode.elm;\r\n                        }\r\n                    }\r\n                    else {\r\n                        component.__patch(document.createElement(fiber.vnode.sel), fiber.vnode);\r\n                        component.__owl__.pvnode.elm = component.__owl__.vnode.elm;\r\n                    }\r\n                }\r\n            }\r\n            // insert into the DOM (mount case)\r\n            let inDOM = false;\r\n            if (this.target) {\r\n                switch (this.position) {\r\n                    case \"first-child\":\r\n                        this.target.prepend(this.component.el);\r\n                        break;\r\n                    case \"last-child\":\r\n                        this.target.appendChild(this.component.el);\r\n                        break;\r\n                }\r\n                inDOM = document.body.contains(this.component.el);\r\n                this.component.env.qweb.trigger(\"dom-appended\");\r\n            }\r\n            // call patched/mounted hook on each fiber of (reversed) patchQueue\r\n            if (status === 3 /* MOUNTED */ || inDOM) {\r\n                for (let i = patchLen - 1; i >= 0; i--) {\r\n                    const fiber = patchQueue[i];\r\n                    component = fiber.component;\r\n                    if (fiber.shouldPatch && !this.target) {\r\n                        component.patched();\r\n                        if (component.__owl__.patchedCB) {\r\n                            component.__owl__.patchedCB();\r\n                        }\r\n                    }\r\n                    else {\r\n                        component.__callMounted();\r\n                    }\r\n                }\r\n            }\r\n            else {\r\n                for (let i = patchLen - 1; i >= 0; i--) {\r\n                    const fiber = patchQueue[i];\r\n                    component = fiber.component;\r\n                    component.__owl__.status = 4 /* UNMOUNTED */;\r\n                }\r\n            }\r\n        }\r\n        /**\r\n         * Cancel a fiber and all its children.\r\n         */\r\n        cancel() {\r\n            this._walk((f) => {\r\n                if (!f.isRendered) {\r\n                    f.root.counter--;\r\n                }\r\n                f.isCompleted = true;\r\n                return f.child;\r\n            });\r\n        }\r\n        /**\r\n         * This is the global error handler for errors occurring in Owl main lifecycle\r\n         * methods.  Caught errors are triggered on the QWeb instance, and are\r\n         * potentially given to some parent component which implements `catchError`.\r\n         *\r\n         * If there are no such component, we destroy everything. This is better than\r\n         * being in a corrupted state.\r\n         */\r\n        handleError(error) {\r\n            let component = this.component;\r\n            this.vnode = component.__owl__.vnode || h(\"div\");\r\n            const qweb = component.env.qweb;\r\n            let root = component;\r\n            function handle(error) {\r\n                let canCatch = false;\r\n                qweb.trigger(\"error\", error);\r\n                while (component && !(canCatch = !!component.catchError)) {\r\n                    root = component;\r\n                    component = component.__owl__.parent;\r\n                }\r\n                if (canCatch) {\r\n                    try {\r\n                        component.catchError(error);\r\n                    }\r\n                    catch (e) {\r\n                        root = component;\r\n                        component = component.__owl__.parent;\r\n                        return handle(e);\r\n                    }\r\n                    return true;\r\n                }\r\n                return false;\r\n            }\r\n            let isHandled = handle(error);\r\n            if (!isHandled) {\r\n                // the 3 next lines aim to mark the root fiber as being in error, and\r\n                // to force it to end, without waiting for its children\r\n                this.root.counter = 0;\r\n                this.root.error = error;\r\n                scheduler.flush();\r\n                // at this point, the state of the application is corrupted and we could\r\n                // have a lot of issues or crashes. So we destroy the application in a try\r\n                // catch and swallow these errors because the fiber is already in error,\r\n                // and this is the actual issue that needs to be solved, not those followup\r\n                // errors.\r\n                try {\r\n                    root.destroy();\r\n                }\r\n                catch (e) { }\r\n            }\r\n        }\r\n    }\r\n    Fiber.nextId = 1;\r\n\r\n    //------------------------------------------------------------------------------\r\n    // Prop validation helper\r\n    //------------------------------------------------------------------------------\r\n    /**\r\n     * Validate the component props (or next props) against the (static) props\r\n     * description.  This is potentially an expensive operation: it may needs to\r\n     * visit recursively the props and all the children to check if they are valid.\r\n     * This is why it is only done in 'dev' mode.\r\n     */\r\n    QWeb.utils.validateProps = function (Widget, props) {\r\n        const propsDef = Widget.props;\r\n        if (propsDef instanceof Array) {\r\n            // list of strings (prop names)\r\n            for (let i = 0, l = propsDef.length; i < l; i++) {\r\n                const propName = propsDef[i];\r\n                if (propName[propName.length - 1] === \"?\") {\r\n                    // optional prop\r\n                    break;\r\n                }\r\n                if (!(propName in props)) {\r\n                    throw new Error(`Missing props '${propsDef[i]}' (component '${Widget.name}')`);\r\n                }\r\n            }\r\n            for (let key in props) {\r\n                if (!propsDef.includes(key) && !propsDef.includes(key + \"?\")) {\r\n                    throw new Error(`Unknown prop '${key}' given to component '${Widget.name}'`);\r\n                }\r\n            }\r\n        }\r\n        else if (propsDef) {\r\n            // propsDef is an object now\r\n            for (let propName in propsDef) {\r\n                if (props[propName] === undefined) {\r\n                    if (propsDef[propName] && !propsDef[propName].optional) {\r\n                        throw new Error(`Missing props '${propName}' (component '${Widget.name}')`);\r\n                    }\r\n                    else {\r\n                        continue;\r\n                    }\r\n                }\r\n                let whyInvalid;\r\n                try {\r\n                    whyInvalid = whyInvalidProp(props[propName], propsDef[propName]);\r\n                }\r\n                catch (e) {\r\n                    e.message = `Invalid prop '${propName}' in component ${Widget.name} (${e.message})`;\r\n                    throw e;\r\n                }\r\n                if (whyInvalid !== null) {\r\n                    whyInvalid = whyInvalid.replace(/\\${propName}/g, propName);\r\n                    throw new Error(`Invalid Prop '${propName}' in component '${Widget.name}': ${whyInvalid}`);\r\n                }\r\n            }\r\n            for (let propName in props) {\r\n                if (!(propName in propsDef)) {\r\n                    throw new Error(`Unknown prop '${propName}' given to component '${Widget.name}'`);\r\n                }\r\n            }\r\n        }\r\n    };\r\n    /**\r\n     * Check why an invidual prop value doesn't match its (static) prop definition\r\n     */\r\n    function whyInvalidProp(prop, propDef) {\r\n        if (propDef === true) {\r\n            return null;\r\n        }\r\n        if (typeof propDef === \"function\") {\r\n            // Check if a value is constructed by some Constructor.  Note that there is a\r\n            // slight abuse of language: we want to consider primitive values as well.\r\n            //\r\n            // So, even though 1 is not an instance of Number, we want to consider that\r\n            // it is valid.\r\n            if (typeof prop === \"object\") {\r\n                if (prop instanceof propDef) {\r\n                    return null;\r\n                }\r\n                return `\\${propName} is not an instance of ${propDef.name}`;\r\n            }\r\n            if (typeof prop === propDef.name.toLowerCase()) {\r\n                return null;\r\n            }\r\n            return `type of \\${propName} is not ${propDef.name}`;\r\n        }\r\n        else if (propDef instanceof Array) {\r\n            // If this code is executed, this means that we want to check if a prop\r\n            // matches at least one of its descriptor.\r\n            let reasons = [];\r\n            for (let i = 0, iLen = propDef.length; i < iLen; i++) {\r\n                const why = whyInvalidProp(prop, propDef[i]);\r\n                if (why === null) {\r\n                    return null;\r\n                }\r\n                reasons.push(why);\r\n            }\r\n            if (reasons.length > 1) {\r\n                return reasons.slice(0, -1).join(\", \") + \" and \" + reasons[reasons.length - 1];\r\n            }\r\n            else {\r\n                return reasons[0];\r\n            }\r\n        }\r\n        // propsDef is an object\r\n        if (propDef.optional && prop === undefined) {\r\n            return null;\r\n        }\r\n        if (propDef.type) {\r\n            const why = whyInvalidProp(prop, propDef.type);\r\n            if (why !== null) {\r\n                return why;\r\n            }\r\n        }\r\n        if (propDef.validate && !propDef.validate(prop)) {\r\n            return \"${propName} could not be validated by `validate` function\";\r\n        }\r\n        if (propDef.type === Array && propDef.element) {\r\n            for (let i = 0, iLen = prop.length; i < iLen; i++) {\r\n                const why = whyInvalidProp(prop[i], propDef.element);\r\n                if (why !== null) {\r\n                    return why.replace(/\\${propName}/g, `\\${propName}[${i}]`);\r\n                }\r\n            }\r\n        }\r\n        if (propDef.type === Object && propDef.shape) {\r\n            const shape = propDef.shape;\r\n            for (let key in shape) {\r\n                const why = whyInvalidProp(prop[key], shape[key]);\r\n                if (why !== null) {\r\n                    return why.replace(/\\${propName}/g, `\\${propName}['${key}']`);\r\n                }\r\n            }\r\n            for (let propName in prop) {\r\n                if (!(propName in shape)) {\r\n                    return `unknown prop \\${propName}['${propName}']`;\r\n                }\r\n            }\r\n        }\r\n        return null;\r\n    }\r\n\r\n    /**\r\n     * Owl Style System\r\n     *\r\n     * This files contains the Owl code related to processing (extended) css strings\r\n     * and creating/adding <style> tags to the document head.\r\n     */\r\n    const STYLESHEETS = {};\r\n    function processSheet(str) {\r\n        const tokens = str.split(/(\\{|\\}|;)/).map((s) => s.trim());\r\n        const selectorStack = [];\r\n        const parts = [];\r\n        let rules = [];\r\n        function generateSelector(stackIndex, parentSelector) {\r\n            const parts = [];\r\n            for (const selector of selectorStack[stackIndex]) {\r\n                let part = (parentSelector && parentSelector + \" \" + selector) || selector;\r\n                if (part.includes(\"&\")) {\r\n                    part = selector.replace(/&/g, parentSelector || \"\");\r\n                }\r\n                if (stackIndex < selectorStack.length - 1) {\r\n                    part = generateSelector(stackIndex + 1, part);\r\n                }\r\n                parts.push(part);\r\n            }\r\n            return parts.join(\", \");\r\n        }\r\n        function generateRules() {\r\n            if (rules.length) {\r\n                parts.push(generateSelector(0) + \" {\");\r\n                parts.push(...rules);\r\n                parts.push(\"}\");\r\n                rules = [];\r\n            }\r\n        }\r\n        while (tokens.length) {\r\n            let token = tokens.shift();\r\n            if (token === \"}\") {\r\n                generateRules();\r\n                selectorStack.pop();\r\n            }\r\n            else {\r\n                if (tokens[0] === \"{\") {\r\n                    generateRules();\r\n                    selectorStack.push(token.split(/\\s*,\\s*/));\r\n                    tokens.shift();\r\n                }\r\n                if (tokens[0] === \";\") {\r\n                    rules.push(\"  \" + token + \";\");\r\n                }\r\n            }\r\n        }\r\n        return parts.join(\"\\n\");\r\n    }\r\n    function registerSheet(id, css) {\r\n        const sheet = document.createElement(\"style\");\r\n        sheet.innerHTML = processSheet(css);\r\n        STYLESHEETS[id] = sheet;\r\n    }\r\n    function activateSheet(id, name) {\r\n        const sheet = STYLESHEETS[id];\r\n        if (!sheet) {\r\n            throw new Error(`Invalid css stylesheet for component '${name}'. Did you forget to use the 'css' tag helper?`);\r\n        }\r\n        sheet.setAttribute(\"component\", name);\r\n        document.head.appendChild(sheet);\r\n    }\r\n\r\n    var STATUS;\r\n    (function (STATUS) {\r\n        STATUS[STATUS[\"CREATED\"] = 0] = \"CREATED\";\r\n        STATUS[STATUS[\"WILLSTARTED\"] = 1] = \"WILLSTARTED\";\r\n        STATUS[STATUS[\"RENDERED\"] = 2] = \"RENDERED\";\r\n        STATUS[STATUS[\"MOUNTED\"] = 3] = \"MOUNTED\";\r\n        STATUS[STATUS[\"UNMOUNTED\"] = 4] = \"UNMOUNTED\";\r\n        STATUS[STATUS[\"DESTROYED\"] = 5] = \"DESTROYED\";\r\n    })(STATUS || (STATUS = {}));\r\n    const portalSymbol = Symbol(\"portal\"); // FIXME\r\n    //------------------------------------------------------------------------------\r\n    // Component\r\n    //------------------------------------------------------------------------------\r\n    let nextId = 1;\r\n    class Component {\r\n        //--------------------------------------------------------------------------\r\n        // Lifecycle\r\n        //--------------------------------------------------------------------------\r\n        /**\r\n         * Creates an instance of Component.\r\n         *\r\n         * Note that most of the time, only the root component needs to be created by\r\n         * hand.  Other components should be created automatically by the framework (with\r\n         * the t-component directive in a template)\r\n         */\r\n        constructor(parent, props) {\r\n            Component.current = this;\r\n            let constr = this.constructor;\r\n            const defaultProps = constr.defaultProps;\r\n            if (defaultProps) {\r\n                props = props || {};\r\n                this.__applyDefaultProps(props, defaultProps);\r\n            }\r\n            this.props = props;\r\n            if (QWeb.dev) {\r\n                QWeb.utils.validateProps(constr, this.props);\r\n            }\r\n            const id = nextId++;\r\n            let depth;\r\n            if (parent) {\r\n                this.env = parent.env;\r\n                const __powl__ = parent.__owl__;\r\n                __powl__.children[id] = this;\r\n                depth = __powl__.depth + 1;\r\n            }\r\n            else {\r\n                // we are the root component\r\n                this.env = this.constructor.env;\r\n                if (!this.env.qweb) {\r\n                    this.env.qweb = new QWeb();\r\n                }\r\n                // TODO: remove this in owl 2.0\r\n                if (!this.env.browser) {\r\n                    this.env.browser = browser;\r\n                }\r\n                this.env.qweb.on(\"update\", this, () => {\r\n                    switch (this.__owl__.status) {\r\n                        case 3 /* MOUNTED */:\r\n                            this.render(true);\r\n                            break;\r\n                        case 5 /* DESTROYED */:\r\n                            // this is unlikely to happen, but if a root widget is destroyed,\r\n                            // we want to remove our subscription.  The usual way to do that\r\n                            // would be to perform some check in the destroy method, but since\r\n                            // it is very performance sensitive, and since this is a rare event,\r\n                            // we simply do it lazily\r\n                            this.env.qweb.off(\"update\", this);\r\n                            break;\r\n                    }\r\n                });\r\n                depth = 0;\r\n            }\r\n            const qweb = this.env.qweb;\r\n            const template = constr.template || this.__getTemplate(qweb);\r\n            this.__owl__ = {\r\n                id: id,\r\n                depth: depth,\r\n                vnode: null,\r\n                pvnode: null,\r\n                status: 0 /* CREATED */,\r\n                parent: parent || null,\r\n                children: {},\r\n                cmap: {},\r\n                currentFiber: null,\r\n                parentLastFiberId: 0,\r\n                boundHandlers: {},\r\n                mountedCB: null,\r\n                willUnmountCB: null,\r\n                willPatchCB: null,\r\n                patchedCB: null,\r\n                willStartCB: null,\r\n                willUpdatePropsCB: null,\r\n                observer: null,\r\n                renderFn: qweb.render.bind(qweb, template),\r\n                classObj: null,\r\n                refs: null,\r\n                scope: null,\r\n            };\r\n            if (constr.style) {\r\n                this.__applyStyles(constr);\r\n            }\r\n            this.setup();\r\n        }\r\n        /**\r\n         * The `el` is the root element of the component.  Note that it could be null:\r\n         * this is the case if the component is not mounted yet, or is destroyed.\r\n         */\r\n        get el() {\r\n            return this.__owl__.vnode ? this.__owl__.vnode.elm : null;\r\n        }\r\n        /**\r\n         * setup is run just after the component is constructed. This is the standard\r\n         * location where the component can setup its hooks. It has some advantages\r\n         * over the constructor:\r\n         *  - it can be patched (useful in odoo ecosystem)\r\n         *  - it does not need to propagate the arguments to the super call\r\n         *\r\n         * Note: this method should not be called manually.\r\n         */\r\n        setup() { }\r\n        /**\r\n         * willStart is an asynchronous hook that can be implemented to perform some\r\n         * action before the initial rendering of a component.\r\n         *\r\n         * It will be called exactly once before the initial rendering. It is useful\r\n         * in some cases, for example, to load external assets (such as a JS library)\r\n         * before the component is rendered.\r\n         *\r\n         * Note that a slow willStart method will slow down the rendering of the user\r\n         * interface.  Therefore, some effort should be made to make this method as\r\n         * fast as possible.\r\n         *\r\n         * Note: this method should not be called manually.\r\n         */\r\n        async willStart() { }\r\n        /**\r\n         * mounted is a hook that is called each time a component is attached to the\r\n         * DOM. This is a good place to add some listeners, or to interact with the\r\n         * DOM, if the component needs to perform some measure for example.\r\n         *\r\n         * Note: this method should not be called manually.\r\n         *\r\n         * @see willUnmount\r\n         */\r\n        mounted() { }\r\n        /**\r\n         * The willUpdateProps is an asynchronous hook, called just before new props\r\n         * are set. This is useful if the component needs some asynchronous task\r\n         * performed, depending on the props (for example, assuming that the props are\r\n         * some record Id, fetching the record data).\r\n         *\r\n         * This hook is not called during the first render (but willStart is called\r\n         * and performs a similar job).\r\n         */\r\n        async willUpdateProps(nextProps) { }\r\n        /**\r\n         * The willPatch hook is called just before the DOM patching process starts.\r\n         * It is not called on the initial render.  This is useful to get some\r\n         * information which are in the DOM.  For example, the current position of the\r\n         * scrollbar\r\n         */\r\n        willPatch() { }\r\n        /**\r\n         * This hook is called whenever a component did actually update its props,\r\n         * state or env.\r\n         *\r\n         * This method is not called on the initial render. It is useful to interact\r\n         * with the DOM (for example, through an external library) whenever the\r\n         * component was updated.\r\n         *\r\n         * Updating the component state in this hook is possible, but not encouraged.\r\n         * One need to be careful, because updates here will cause rerender, which in\r\n         * turn will cause other calls to updated. So, we need to be particularly\r\n         * careful at avoiding endless cycles.\r\n         */\r\n        patched() { }\r\n        /**\r\n         * willUnmount is a hook that is called each time just before a component is\r\n         * unmounted from the DOM. This is a good place to remove some listeners, for\r\n         * example.\r\n         *\r\n         * Note: this method should not be called manually.\r\n         *\r\n         * @see mounted\r\n         */\r\n        willUnmount() { }\r\n        //--------------------------------------------------------------------------\r\n        // Public\r\n        //--------------------------------------------------------------------------\r\n        /**\r\n         * Mount the component to a target element.\r\n         *\r\n         * This should only be done if the component was created manually. Components\r\n         * created declaratively in templates are managed by the Owl system.\r\n         *\r\n         * Note that a component can be mounted an unmounted several times\r\n         */\r\n        async mount(target, options = {}) {\r\n            if (!(target instanceof HTMLElement || target instanceof DocumentFragment)) {\r\n                let message = `Component '${this.constructor.name}' cannot be mounted: the target is not a valid DOM node.`;\r\n                message += `\\nMaybe the DOM is not ready yet? (in that case, you can use owl.utils.whenReady)`;\r\n                throw new Error(message);\r\n            }\r\n            const position = options.position || \"last-child\";\r\n            const __owl__ = this.__owl__;\r\n            const currentFiber = __owl__.currentFiber;\r\n            switch (__owl__.status) {\r\n                case 0 /* CREATED */: {\r\n                    const fiber = new Fiber(null, this, true, target, position);\r\n                    fiber.shouldPatch = false;\r\n                    this.__prepareAndRender(fiber, () => { });\r\n                    return scheduler.addFiber(fiber);\r\n                }\r\n                case 1 /* WILLSTARTED */:\r\n                case 2 /* RENDERED */:\r\n                    currentFiber.target = target;\r\n                    currentFiber.position = position;\r\n                    return scheduler.addFiber(currentFiber);\r\n                case 4 /* UNMOUNTED */: {\r\n                    const fiber = new Fiber(null, this, true, target, position);\r\n                    fiber.shouldPatch = false;\r\n                    this.__render(fiber);\r\n                    return scheduler.addFiber(fiber);\r\n                }\r\n                case 3 /* MOUNTED */: {\r\n                    if (position !== \"self\" && this.el.parentNode !== target) {\r\n                        const fiber = new Fiber(null, this, true, target, position);\r\n                        fiber.shouldPatch = false;\r\n                        this.__render(fiber);\r\n                        return scheduler.addFiber(fiber);\r\n                    }\r\n                    else {\r\n                        return Promise.resolve();\r\n                    }\r\n                }\r\n                case 5 /* DESTROYED */:\r\n                    throw new Error(\"Cannot mount a destroyed component\");\r\n            }\r\n        }\r\n        /**\r\n         * The unmount method is the opposite of the mount method.  It is useful\r\n         * to call willUnmount calls and remove the component from the DOM.\r\n         */\r\n        unmount() {\r\n            if (this.__owl__.status === 3 /* MOUNTED */) {\r\n                this.__callWillUnmount();\r\n                this.el.remove();\r\n            }\r\n        }\r\n        /**\r\n         * The render method is the main entry point to render a component (once it\r\n         * is ready. This method is not initially called when the component is\r\n         * rendered the first time).\r\n         *\r\n         * This method will cause all its sub components to potentially rerender\r\n         * themselves.  Note that `render` is not called if a component is updated via\r\n         * its props.\r\n         */\r\n        async render(force = false) {\r\n            const __owl__ = this.__owl__;\r\n            const currentFiber = __owl__.currentFiber;\r\n            if (!__owl__.vnode && !currentFiber) {\r\n                return;\r\n            }\r\n            if (currentFiber && !currentFiber.isRendered && !currentFiber.isCompleted) {\r\n                return scheduler.addFiber(currentFiber.root);\r\n            }\r\n            // if we aren't mounted at this point, it implies that there is a\r\n            // currentFiber that is already rendered (isRendered is true), so we are\r\n            // about to be mounted\r\n            const status = __owl__.status;\r\n            const fiber = new Fiber(null, this, force, null, null);\r\n            Promise.resolve().then(() => {\r\n                if (__owl__.status === 3 /* MOUNTED */ || status !== 3 /* MOUNTED */) {\r\n                    if (fiber.isCompleted || fiber.isRendered) {\r\n                        return;\r\n                    }\r\n                    this.__render(fiber);\r\n                }\r\n                else {\r\n                    // we were mounted when render was called, but we aren't anymore, so we\r\n                    // were actually about to be unmounted ; we can thus forget about this\r\n                    // fiber\r\n                    fiber.isCompleted = true;\r\n                    __owl__.currentFiber = null;\r\n                }\r\n            });\r\n            return scheduler.addFiber(fiber);\r\n        }\r\n        /**\r\n         * Destroy the component.  This operation is quite complex:\r\n         *  - it recursively destroy all children\r\n         *  - call the willUnmount hooks if necessary\r\n         *  - remove the dom node from the dom\r\n         *\r\n         * This should only be called manually if you created the component.  Most\r\n         * components will be automatically destroyed.\r\n         */\r\n        destroy() {\r\n            const __owl__ = this.__owl__;\r\n            if (__owl__.status !== 5 /* DESTROYED */) {\r\n                const el = this.el;\r\n                this.__destroy(__owl__.parent);\r\n                if (el) {\r\n                    el.remove();\r\n                }\r\n            }\r\n        }\r\n        /**\r\n         * This method is called by the component system whenever its props are\r\n         * updated. If it returns true, then the component will be rendered.\r\n         * Otherwise, it will skip the rendering (also, its props will not be updated)\r\n         */\r\n        shouldUpdate(nextProps) {\r\n            return true;\r\n        }\r\n        /**\r\n         * Emit a custom event of type 'eventType' with the given 'payload' on the\r\n         * component's el, if it exists. However, note that the event will only bubble\r\n         * up to the parent DOM nodes. Thus, it must be called between mounted() and\r\n         * willUnmount().\r\n         */\r\n        trigger(eventType, payload) {\r\n            this.__trigger(this, eventType, payload);\r\n        }\r\n        //--------------------------------------------------------------------------\r\n        // Private\r\n        //--------------------------------------------------------------------------\r\n        /**\r\n         * Private helper to perform a full destroy, from the point of view of an Owl\r\n         * component. It does not remove the el (this is done only once on the top\r\n         * level destroyed component, for performance reasons).\r\n         *\r\n         * The job of this method is mostly to call willUnmount hooks, and to perform\r\n         * all necessary internal cleanup.\r\n         *\r\n         * Note that it does not call the __callWillUnmount method to avoid visiting\r\n         * all children many times.\r\n         */\r\n        __destroy(parent) {\r\n            const __owl__ = this.__owl__;\r\n            if (__owl__.status === 3 /* MOUNTED */) {\r\n                if (__owl__.willUnmountCB) {\r\n                    __owl__.willUnmountCB();\r\n                }\r\n                this.willUnmount();\r\n                __owl__.status = 4 /* UNMOUNTED */;\r\n            }\r\n            const children = __owl__.children;\r\n            for (let key in children) {\r\n                children[key].__destroy(this);\r\n            }\r\n            if (parent) {\r\n                let id = __owl__.id;\r\n                delete parent.__owl__.children[id];\r\n                __owl__.parent = null;\r\n            }\r\n            __owl__.status = 5 /* DESTROYED */;\r\n            delete __owl__.vnode;\r\n            if (__owl__.currentFiber) {\r\n                __owl__.currentFiber.isCompleted = true;\r\n            }\r\n        }\r\n        __callMounted() {\r\n            const __owl__ = this.__owl__;\r\n            __owl__.status = 3 /* MOUNTED */;\r\n            this.mounted();\r\n            if (__owl__.mountedCB) {\r\n                __owl__.mountedCB();\r\n            }\r\n        }\r\n        __callWillUnmount() {\r\n            const __owl__ = this.__owl__;\r\n            if (__owl__.willUnmountCB) {\r\n                __owl__.willUnmountCB();\r\n            }\r\n            this.willUnmount();\r\n            __owl__.status = 4 /* UNMOUNTED */;\r\n            if (__owl__.currentFiber) {\r\n                __owl__.currentFiber.isCompleted = true;\r\n                __owl__.currentFiber.root.counter = 0;\r\n            }\r\n            const children = __owl__.children;\r\n            for (let id in children) {\r\n                const comp = children[id];\r\n                if (comp.__owl__.status === 3 /* MOUNTED */) {\r\n                    comp.__callWillUnmount();\r\n                }\r\n            }\r\n        }\r\n        /**\r\n         * Private trigger method, allows to choose the component which triggered\r\n         * the event in the first place\r\n         */\r\n        __trigger(component, eventType, payload) {\r\n            if (this.el) {\r\n                const ev = new OwlEvent(component, eventType, {\r\n                    bubbles: true,\r\n                    cancelable: true,\r\n                    detail: payload,\r\n                });\r\n                const triggerHook = this.env[portalSymbol];\r\n                if (triggerHook) {\r\n                    triggerHook(ev);\r\n                }\r\n                this.el.dispatchEvent(ev);\r\n            }\r\n        }\r\n        /**\r\n         * The __updateProps method is called by the t-component directive whenever\r\n         * it updates a component (so, when the parent template is rerendered).\r\n         */\r\n        async __updateProps(nextProps, parentFiber, scope) {\r\n            this.__owl__.scope = scope;\r\n            const shouldUpdate = parentFiber.force || this.shouldUpdate(nextProps);\r\n            if (shouldUpdate) {\r\n                const __owl__ = this.__owl__;\r\n                const fiber = new Fiber(parentFiber, this, parentFiber.force, null, null);\r\n                if (!parentFiber.child) {\r\n                    parentFiber.child = fiber;\r\n                }\r\n                else {\r\n                    parentFiber.lastChild.sibling = fiber;\r\n                }\r\n                parentFiber.lastChild = fiber;\r\n                const defaultProps = this.constructor.defaultProps;\r\n                if (defaultProps) {\r\n                    this.__applyDefaultProps(nextProps, defaultProps);\r\n                }\r\n                if (QWeb.dev) {\r\n                    QWeb.utils.validateProps(this.constructor, nextProps);\r\n                }\r\n                await Promise.all([\r\n                    this.willUpdateProps(nextProps),\r\n                    __owl__.willUpdatePropsCB && __owl__.willUpdatePropsCB(nextProps),\r\n                ]);\r\n                if (fiber.isCompleted) {\r\n                    return;\r\n                }\r\n                this.props = nextProps;\r\n                this.__render(fiber);\r\n            }\r\n        }\r\n        /**\r\n         * Main patching method. We call the virtual dom patch method here to convert\r\n         * a virtual dom vnode into some actual dom.\r\n         */\r\n        __patch(target, vnode) {\r\n            this.__owl__.vnode = patch(target, vnode);\r\n        }\r\n        /**\r\n         * The __prepare method is only called by the t-component directive, when a\r\n         * subcomponent is created. It gets its scope, if any, from the\r\n         * parent template.\r\n         */\r\n        __prepare(parentFiber, scope, cb) {\r\n            this.__owl__.scope = scope;\r\n            const fiber = new Fiber(parentFiber, this, parentFiber.force, null, null);\r\n            fiber.shouldPatch = false;\r\n            if (!parentFiber.child) {\r\n                parentFiber.child = fiber;\r\n            }\r\n            else {\r\n                parentFiber.lastChild.sibling = fiber;\r\n            }\r\n            parentFiber.lastChild = fiber;\r\n            this.__prepareAndRender(fiber, cb);\r\n            return fiber;\r\n        }\r\n        /**\r\n         * Apply the stylesheets defined by the component. Note that we need to make\r\n         * sure all inherited stylesheets are applied as well.  We then delete the\r\n         * `style` key from the constructor to make sure we do not apply it again.\r\n         */\r\n        __applyStyles(constr) {\r\n            while (constr && constr.style) {\r\n                if (constr.hasOwnProperty(\"style\")) {\r\n                    activateSheet(constr.style, constr.name);\r\n                    delete constr.style;\r\n                }\r\n                constr = constr.__proto__;\r\n            }\r\n        }\r\n        __getTemplate(qweb) {\r\n            let p = this.constructor;\r\n            if (!p.hasOwnProperty(\"_template\")) {\r\n                // here, the component and none of its superclasses defines a static `template`\r\n                // key. So we fall back on looking for a template matching its name (or\r\n                // one of its subclass).\r\n                let template = p.name;\r\n                while (!(template in qweb.templates) && p !== Component) {\r\n                    p = p.__proto__;\r\n                    template = p.name;\r\n                }\r\n                if (p === Component) {\r\n                    throw new Error(`Could not find template for component \"${this.constructor.name}\"`);\r\n                }\r\n                else {\r\n                    p._template = template;\r\n                }\r\n            }\r\n            return p._template;\r\n        }\r\n        async __prepareAndRender(fiber, cb) {\r\n            try {\r\n                const proms = Promise.all([\r\n                    this.willStart(),\r\n                    this.__owl__.willStartCB && this.__owl__.willStartCB(),\r\n                ]);\r\n                this.__owl__.status = 1 /* WILLSTARTED */;\r\n                await proms;\r\n                if (this.__owl__.status === 5 /* DESTROYED */) {\r\n                    return Promise.resolve();\r\n                }\r\n            }\r\n            catch (e) {\r\n                fiber.handleError(e);\r\n                return Promise.resolve();\r\n            }\r\n            if (!fiber.isCompleted) {\r\n                this.__render(fiber);\r\n                this.__owl__.status = 2 /* RENDERED */;\r\n                cb();\r\n            }\r\n        }\r\n        __render(fiber) {\r\n            const __owl__ = this.__owl__;\r\n            if (__owl__.observer) {\r\n                __owl__.observer.allowMutations = false;\r\n            }\r\n            let error;\r\n            try {\r\n                let vnode = __owl__.renderFn(this, {\r\n                    handlers: __owl__.boundHandlers,\r\n                    fiber: fiber,\r\n                });\r\n                // we iterate over the children to detect those that no longer belong to the\r\n                // current rendering: those ones, if not mounted yet, can (and have to) be\r\n                // destroyed right now, because they are not in the DOM, and thus we won't\r\n                // be notified later on (when patching), that they are removed from the DOM\r\n                for (let childKey in __owl__.children) {\r\n                    const child = __owl__.children[childKey];\r\n                    const childOwl = child.__owl__;\r\n                    if (childOwl.status !== 3 /* MOUNTED */ && childOwl.parentLastFiberId < fiber.id) {\r\n                        // we only do here a \"soft\" destroy, meaning that we leave the child\r\n                        // dom node alone, without removing it.  Most of the time, it does not\r\n                        // matter, because the child component is already unmounted.  However,\r\n                        // if some of its parent have been unmounted, the child could actually\r\n                        // still be attached to its parent, and this may be important if we\r\n                        // want to remount the parent, because the vdom need to match the\r\n                        // actual DOM\r\n                        child.__destroy(childOwl.parent);\r\n                        if (childOwl.pvnode) {\r\n                            // we remove the key here to make sure that the patching algorithm\r\n                            // is able to make the difference between this pvnode and an eventual\r\n                            // other instance of the same component\r\n                            delete childOwl.pvnode.key;\r\n                            // Since the component has been unmounted, we do not want to actually\r\n                            // call a remove hook.  This is pretty important, since the t-component\r\n                            // directive actually disabled it, so the vdom algorithm will just\r\n                            // not remove the child elm if we don't remove the hook.\r\n                            delete childOwl.pvnode.data.hook.remove;\r\n                        }\r\n                    }\r\n                }\r\n                if (!vnode) {\r\n                    throw new Error(`Rendering '${this.constructor.name}' did not return anything`);\r\n                }\r\n                fiber.vnode = vnode;\r\n                // we apply here the class information described on the component by the\r\n                // template (so, something like <MyComponent class=\"...\"/>) to the actual\r\n                // root vnode\r\n                if (__owl__.classObj) {\r\n                    const data = vnode.data;\r\n                    data.class = Object.assign(data.class || {}, __owl__.classObj);\r\n                }\r\n            }\r\n            catch (e) {\r\n                error = e;\r\n            }\r\n            if (__owl__.observer) {\r\n                __owl__.observer.allowMutations = true;\r\n            }\r\n            fiber.root.counter--;\r\n            fiber.isRendered = true;\r\n            if (error) {\r\n                fiber.handleError(error);\r\n            }\r\n        }\r\n        /**\r\n         * Apply default props (only top level).\r\n         *\r\n         * Note that this method does modify in place the props\r\n         */\r\n        __applyDefaultProps(props, defaultProps) {\r\n            for (let propName in defaultProps) {\r\n                if (props[propName] === undefined) {\r\n                    props[propName] = defaultProps[propName];\r\n                }\r\n            }\r\n        }\r\n    }\r\n    Component.template = null;\r\n    Component._template = null;\r\n    Component.current = null;\r\n    Component.components = {};\r\n    Component.env = {};\r\n    // expose scheduler s.t. it can be mocked for testing purposes\r\n    Component.scheduler = scheduler;\r\n    async function mount(C, params) {\r\n        const { env, props, target } = params;\r\n        let origEnv = C.hasOwnProperty(\"env\") ? C.env : null;\r\n        if (env) {\r\n            C.env = env;\r\n        }\r\n        const component = new C(null, props);\r\n        if (origEnv) {\r\n            C.env = origEnv;\r\n        }\r\n        else {\r\n            delete C.env;\r\n        }\r\n        const position = params.position || \"last-child\";\r\n        await component.mount(target, { position });\r\n        return component;\r\n    }\r\n\r\n    /**\r\n     * The `Context` object provides a way to share data between an arbitrary number\r\n     * of component. Usually, data is passed from a parent to its children component,\r\n     * but when we have to deal with some mostly global information, this can be\r\n     * annoying, since each component will need to pass the information to each\r\n     * children, even though some or most of them will not use the information.\r\n     *\r\n     * With a `Context` object, each component can subscribe (with the `useContext`\r\n     * hook) to its state, and will be updated whenever the context state is updated.\r\n     */\r\n    function partitionBy(arr, fn) {\r\n        let lastGroup = false;\r\n        let lastValue;\r\n        return arr.reduce((acc, cur) => {\r\n            let curVal = fn(cur);\r\n            if (lastGroup) {\r\n                if (curVal === lastValue) {\r\n                    lastGroup.push(cur);\r\n                }\r\n                else {\r\n                    lastGroup = false;\r\n                }\r\n            }\r\n            if (!lastGroup) {\r\n                lastGroup = [cur];\r\n                acc.push(lastGroup);\r\n            }\r\n            lastValue = curVal;\r\n            return acc;\r\n        }, []);\r\n    }\r\n    class Context$1 extends EventBus {\r\n        constructor(state = {}) {\r\n            super();\r\n            this.rev = 1;\r\n            // mapping from component id to last observed context id\r\n            this.mapping = {};\r\n            this.observer = new Observer();\r\n            this.observer.notifyCB = () => {\r\n                // notify components in the next microtask tick to ensure that subscribers\r\n                // are notified only once for all changes that occur in the same micro tick\r\n                let rev = this.rev;\r\n                return Promise.resolve().then(() => {\r\n                    if (rev === this.rev) {\r\n                        this.__notifyComponents();\r\n                    }\r\n                });\r\n            };\r\n            this.state = this.observer.observe(state);\r\n            this.subscriptions.update = [];\r\n        }\r\n        /**\r\n         * Instead of using trigger to emit an update event, we actually implement\r\n         * our own function to do that.  The reason is that we need to be smarter than\r\n         * a simple trigger function: we need to wait for parent components to be\r\n         * done before doing children components.  More precisely, if an update\r\n         * as an effect of destroying a children, we do not want to call any code\r\n         * from the child, and certainly not render it.\r\n         *\r\n         * This method implements a simple grouping algorithm by depth. If we have\r\n         * connected components of depths [2, 4,4,4,4, 3,8,8], the Context will notify\r\n         * them in the following groups: [2], [4,4,4,4], [3], [8,8]. Each group will\r\n         * be updated sequentially, but each components in a given group will be done in\r\n         * parallel.\r\n         *\r\n         * This is a very simple algorithm, but it avoids checking if a given\r\n         * component is a child of another.\r\n         */\r\n        async __notifyComponents() {\r\n            const rev = ++this.rev;\r\n            const subscriptions = this.subscriptions.update;\r\n            const groups = partitionBy(subscriptions, (s) => (s.owner ? s.owner.__owl__.depth : -1));\r\n            for (let group of groups) {\r\n                const proms = group.map((sub) => sub.callback.call(sub.owner, rev));\r\n                // at this point, each component in the current group has registered a\r\n                // top level fiber in the scheduler. It could happen that rendering these\r\n                // components is done (if they have no children).  This is why we manually\r\n                // flush the scheduler.  This will force the scheduler to check\r\n                // immediately if they are done, which will cause their rendering\r\n                // promise to resolve earlier, which means that there is a chance of\r\n                // processing the next group in the same frame.\r\n                scheduler.flush();\r\n                await Promise.all(proms);\r\n            }\r\n        }\r\n    }\r\n    /**\r\n     * The`useContext` hook is the normal way for a component to register themselve\r\n     * to context state changes. The `useContext` method returns the context state\r\n     */\r\n    function useContext(ctx) {\r\n        const component = Component.current;\r\n        return useContextWithCB(ctx, component, component.render.bind(component));\r\n    }\r\n    function useContextWithCB(ctx, component, method) {\r\n        const __owl__ = component.__owl__;\r\n        const id = __owl__.id;\r\n        const mapping = ctx.mapping;\r\n        if (id in mapping) {\r\n            return ctx.state;\r\n        }\r\n        if (!__owl__.observer) {\r\n            __owl__.observer = new Observer();\r\n            __owl__.observer.notifyCB = component.render.bind(component);\r\n        }\r\n        mapping[id] = 0;\r\n        const renderFn = __owl__.renderFn;\r\n        __owl__.renderFn = function (comp, params) {\r\n            mapping[id] = ctx.rev;\r\n            return renderFn(comp, params);\r\n        };\r\n        ctx.on(\"update\", component, async (contextRev) => {\r\n            if (mapping[id] < contextRev) {\r\n                mapping[id] = contextRev;\r\n                await method();\r\n            }\r\n        });\r\n        const __destroy = component.__destroy;\r\n        component.__destroy = (parent) => {\r\n            ctx.off(\"update\", component);\r\n            delete mapping[id];\r\n            __destroy.call(component, parent);\r\n        };\r\n        return ctx.state;\r\n    }\r\n\r\n    /**\r\n     * Owl Hook System\r\n     *\r\n     * This file introduces the concept of hooks, similar to React or Vue hooks.\r\n     * We have currently an implementation of:\r\n     * - useState (reactive state)\r\n     * - onMounted\r\n     * - onWillUnmount\r\n     * - useRef\r\n     */\r\n    // -----------------------------------------------------------------------------\r\n    // useState\r\n    // -----------------------------------------------------------------------------\r\n    /**\r\n     * This is the main way a component can be made reactive.  The useState hook\r\n     * will return an observed object (or array).  Changes to that value will then\r\n     * trigger a rerendering of the current component.\r\n     */\r\n    function useState$1(state) {\r\n        const component = Component.current;\r\n        const __owl__ = component.__owl__;\r\n        if (!__owl__.observer) {\r\n            __owl__.observer = new Observer();\r\n            __owl__.observer.notifyCB = component.render.bind(component);\r\n        }\r\n        return __owl__.observer.observe(state);\r\n    }\r\n    // -----------------------------------------------------------------------------\r\n    // Life cycle hooks\r\n    // -----------------------------------------------------------------------------\r\n    function makeLifecycleHook(method, reverse = false) {\r\n        if (reverse) {\r\n            return function (cb) {\r\n                const component = Component.current;\r\n                if (component.__owl__[method]) {\r\n                    const current = component.__owl__[method];\r\n                    component.__owl__[method] = function () {\r\n                        current.call(component);\r\n                        cb.call(component);\r\n                    };\r\n                }\r\n                else {\r\n                    component.__owl__[method] = cb;\r\n                }\r\n            };\r\n        }\r\n        else {\r\n            return function (cb) {\r\n                const component = Component.current;\r\n                if (component.__owl__[method]) {\r\n                    const current = component.__owl__[method];\r\n                    component.__owl__[method] = function () {\r\n                        cb.call(component);\r\n                        current.call(component);\r\n                    };\r\n                }\r\n                else {\r\n                    component.__owl__[method] = cb;\r\n                }\r\n            };\r\n        }\r\n    }\r\n    function makeAsyncHook(method) {\r\n        return function (cb) {\r\n            const component = Component.current;\r\n            if (component.__owl__[method]) {\r\n                const current = component.__owl__[method];\r\n                component.__owl__[method] = function (...args) {\r\n                    return Promise.all([current.call(component, ...args), cb.call(component, ...args)]);\r\n                };\r\n            }\r\n            else {\r\n                component.__owl__[method] = cb;\r\n            }\r\n        };\r\n    }\r\n    const onMounted = makeLifecycleHook(\"mountedCB\", true);\r\n    const onWillUnmount = makeLifecycleHook(\"willUnmountCB\");\r\n    const onWillPatch = makeLifecycleHook(\"willPatchCB\");\r\n    const onPatched = makeLifecycleHook(\"patchedCB\", true);\r\n    const onWillStart = makeAsyncHook(\"willStartCB\");\r\n    const onWillUpdateProps = makeAsyncHook(\"willUpdatePropsCB\");\r\n    function useRef(name) {\r\n        const __owl__ = Component.current.__owl__;\r\n        return {\r\n            get el() {\r\n                var _a, _b;\r\n                const val = __owl__.refs && __owl__.refs[name];\r\n                if (val instanceof Component) {\r\n                    return val.el;\r\n                }\r\n                if (val instanceof HTMLElement) {\r\n                    return val;\r\n                }\r\n                // Extra check in case the app was created outside an iframe but mounted into one\r\n                // on Firefox 109+, the prototype of the element changes to use the iframe window's HTMLElement\r\n                // see https://bugzilla.mozilla.org/show_bug.cgi?id=1813499\r\n                const ownerWindow = (_b = (_a = val) === null || _a === void 0 ? void 0 : _a.ownerDocument) === null || _b === void 0 ? void 0 : _b.defaultView;\r\n                if (ownerWindow && val instanceof ownerWindow.HTMLElement) {\r\n                    return val;\r\n                }\r\n                return null;\r\n            },\r\n            get comp() {\r\n                const val = __owl__.refs && __owl__.refs[name];\r\n                return val instanceof Component ? val : null;\r\n            },\r\n        };\r\n    }\r\n    // -----------------------------------------------------------------------------\r\n    // \"Builder\" hooks\r\n    // -----------------------------------------------------------------------------\r\n    /**\r\n     * This hook is useful as a building block for some customized hooks, that may\r\n     * need a reference to the component calling them.\r\n     */\r\n    function useComponent() {\r\n        return Component.current;\r\n    }\r\n    /**\r\n     * This hook is useful as a building block for some customized hooks, that may\r\n     * need a reference to the env of the component calling them.\r\n     */\r\n    function useEnv() {\r\n        return Component.current.env;\r\n    }\r\n    // -----------------------------------------------------------------------------\r\n    // useSubEnv\r\n    // -----------------------------------------------------------------------------\r\n    /**\r\n     * This hook is a simple way to let components use a sub environment.  Note that\r\n     * like for all hooks, it is important that this is only called in the\r\n     * constructor method.\r\n     */\r\n    function useSubEnv(nextEnv) {\r\n        const component = Component.current;\r\n        component.env = Object.assign(Object.create(component.env), nextEnv);\r\n    }\r\n    // -----------------------------------------------------------------------------\r\n    // useExternalListener\r\n    // -----------------------------------------------------------------------------\r\n    /**\r\n     * When a component needs to listen to DOM Events on element(s) that are not\r\n     * part of his hierarchy, we can use the `useExternalListener` hook.\r\n     * It will correctly add and remove the event listener, whenever the\r\n     * component is mounted and unmounted.\r\n     *\r\n     * Example:\r\n     *  a menu needs to listen to the click on window to be closed automatically\r\n     *\r\n     * Usage:\r\n     *  in the constructor of the OWL component that needs to be notified,\r\n     *  `useExternalListener(window, 'click', this._doSomething);`\r\n     * */\r\n    function useExternalListener(target, eventName, handler, eventParams) {\r\n        const boundHandler = handler.bind(Component.current);\r\n        onMounted(() => target.addEventListener(eventName, boundHandler, eventParams));\r\n        onWillUnmount(() => target.removeEventListener(eventName, boundHandler, eventParams));\r\n    }\r\n\r\n    var _hooks = /*#__PURE__*/Object.freeze({\r\n        __proto__: null,\r\n        useState: useState$1,\r\n        onMounted: onMounted,\r\n        onWillUnmount: onWillUnmount,\r\n        onWillPatch: onWillPatch,\r\n        onPatched: onPatched,\r\n        onWillStart: onWillStart,\r\n        onWillUpdateProps: onWillUpdateProps,\r\n        useRef: useRef,\r\n        useComponent: useComponent,\r\n        useEnv: useEnv,\r\n        useSubEnv: useSubEnv,\r\n        useExternalListener: useExternalListener\r\n    });\r\n\r\n    class Store$1 extends Context$1 {\r\n        constructor(config) {\r\n            super(config.state);\r\n            this.actions = config.actions;\r\n            this.env = config.env;\r\n            this.getters = {};\r\n            this.updateFunctions = [];\r\n            if (config.getters) {\r\n                const firstArg = {\r\n                    state: this.state,\r\n                    getters: this.getters,\r\n                };\r\n                for (let g in config.getters) {\r\n                    this.getters[g] = config.getters[g].bind(this, firstArg);\r\n                }\r\n            }\r\n        }\r\n        dispatch(action, ...payload) {\r\n            if (!this.actions[action]) {\r\n                throw new Error(`[Error] action ${action} is undefined`);\r\n            }\r\n            const result = this.actions[action]({\r\n                dispatch: this.dispatch.bind(this),\r\n                env: this.env,\r\n                state: this.state,\r\n                getters: this.getters,\r\n            }, ...payload);\r\n            return result;\r\n        }\r\n        __notifyComponents() {\r\n            this.trigger(\"before-update\");\r\n            return super.__notifyComponents();\r\n        }\r\n    }\r\n    const isStrictEqual = (a, b) => a === b;\r\n    function useStore(selector, options = {}) {\r\n        const component = Component.current;\r\n        const componentId = component.__owl__.id;\r\n        const store = options.store || component.env.store;\r\n        if (!(store instanceof Store$1)) {\r\n            throw new Error(`No store found when connecting '${component.constructor.name}'`);\r\n        }\r\n        let result = selector(store.state, component.props);\r\n        const hashFn = store.observer.revNumber.bind(store.observer);\r\n        let revNumber = hashFn(result);\r\n        const isEqual = options.isEqual || isStrictEqual;\r\n        if (!store.updateFunctions[componentId]) {\r\n            store.updateFunctions[componentId] = [];\r\n        }\r\n        function selectCompareUpdate(state, props) {\r\n            const oldResult = result;\r\n            result = selector(state, props);\r\n            const newRevNumber = hashFn(result);\r\n            if ((newRevNumber > 0 && revNumber !== newRevNumber) || !isEqual(oldResult, result)) {\r\n                revNumber = newRevNumber;\r\n                return true;\r\n            }\r\n            return false;\r\n        }\r\n        if (options.onUpdate) {\r\n            store.on(\"before-update\", component, () => {\r\n                const newValue = selector(store.state, component.props);\r\n                options.onUpdate(newValue);\r\n            });\r\n        }\r\n        store.updateFunctions[componentId].push(function () {\r\n            return selectCompareUpdate(store.state, component.props);\r\n        });\r\n        useContextWithCB(store, component, function () {\r\n            let shouldRender = false;\r\n            for (let fn of store.updateFunctions[componentId]) {\r\n                shouldRender = fn() || shouldRender;\r\n            }\r\n            if (shouldRender) {\r\n                return component.render();\r\n            }\r\n        });\r\n        onWillUpdateProps((props) => {\r\n            selectCompareUpdate(store.state, props);\r\n        });\r\n        const __destroy = component.__destroy;\r\n        component.__destroy = (parent) => {\r\n            delete store.updateFunctions[componentId];\r\n            if (options.onUpdate) {\r\n                store.off(\"before-update\", component);\r\n            }\r\n            __destroy.call(component, parent);\r\n        };\r\n        if (typeof result !== \"object\" || result === null) {\r\n            return result;\r\n        }\r\n        return new Proxy(result, {\r\n            get(target, k) {\r\n                return result[k];\r\n            },\r\n            set(target, k, v) {\r\n                throw new Error(\"Store state should only be modified through actions\");\r\n            },\r\n            has(target, k) {\r\n                return k in result;\r\n            },\r\n        });\r\n    }\r\n    function useDispatch(store) {\r\n        store = store || Component.current.env.store;\r\n        return store.dispatch.bind(store);\r\n    }\r\n    function useGetters(store) {\r\n        store = store || Component.current.env.store;\r\n        return store.getters;\r\n    }\r\n\r\n    /**\r\n     * Owl Tags\r\n     *\r\n     * We have here a (very) small collection of tag functions:\r\n     *\r\n     * - xml\r\n     *\r\n     * The plan is to add a few other tags such as css, globalcss.\r\n     */\r\n    /**\r\n     * XML tag helper for defining templates.  With this, one can simply define\r\n     * an inline template with just the template xml:\r\n     * ```js\r\n     *   class A extends Component {\r\n     *     static template = xml`<div>some template</div>`;\r\n     *   }\r\n     * ```\r\n     */\r\n    function xml(strings, ...args) {\r\n        const name = `__template__${QWeb.nextId++}`;\r\n        const value = String.raw(strings, ...args);\r\n        QWeb.registerTemplate(name, value);\r\n        return name;\r\n    }\r\n    /**\r\n     * CSS tag helper for defining inline stylesheets.  With this, one can simply define\r\n     * an inline stylesheet with just the following code:\r\n     * ```js\r\n     *   class A extends Component {\r\n     *     static style = css`.component-a { color: red; }`;\r\n     *   }\r\n     * ```\r\n     */\r\n    function css(strings, ...args) {\r\n        const name = `__sheet__${QWeb.nextId++}`;\r\n        const value = String.raw(strings, ...args);\r\n        registerSheet(name, value);\r\n        return name;\r\n    }\r\n\r\n    var _tags = /*#__PURE__*/Object.freeze({\r\n        __proto__: null,\r\n        xml: xml,\r\n        css: css\r\n    });\r\n\r\n    /**\r\n     * AsyncRoot\r\n     *\r\n     * Owl is by default asynchronous, and the user interface will wait for all its\r\n     * subcomponents to be rendered before updating the DOM. This is most of the\r\n     * time what we want, but in some cases, it makes sense to \"detach\" a component\r\n     * from this coordination.  This is the goal of the AsyncRoot component.\r\n     */\r\n    class AsyncRoot extends Component {\r\n        async __updateProps(nextProps, parentFiber) {\r\n            this.render(parentFiber.force);\r\n        }\r\n    }\r\n    AsyncRoot.template = xml `<t t-slot=\"default\"/>`;\r\n\r\n    class Portal extends Component {\r\n        constructor(parent, props) {\r\n            super(parent, props);\r\n            // boolean to indicate whether or not we must listen to 'dom-appended' event\r\n            // to hook on the moment when the target is inserted into the DOM (because it\r\n            // is not when the portal is rendered)\r\n            this.doTargetLookUp = true;\r\n            // set of encountered events that need to be redirected\r\n            this._handledEvents = new Set();\r\n            // function that will be the event's tunnel (needs to be an arrow function to\r\n            // avoid having to rebind `this`)\r\n            this._handlerTunnel = (ev) => {\r\n                ev.stopPropagation();\r\n                this.__trigger(ev.originalComponent, ev.type, ev.detail);\r\n            };\r\n            // Storing the parent's env\r\n            this.parentEnv = null;\r\n            // represents the element that is moved somewhere else\r\n            this.portal = null;\r\n            // the target where we will move `portal`\r\n            this.target = null;\r\n            this.parentEnv = parent ? parent.env : {};\r\n            // put a callback in the env that is propagated to children s.t. portal can\r\n            // register an handler to those events just before children will trigger them\r\n            useSubEnv({\r\n                [portalSymbol]: (ev) => {\r\n                    if (!this._handledEvents.has(ev.type)) {\r\n                        this.portal.elm.addEventListener(ev.type, this._handlerTunnel);\r\n                        this._handledEvents.add(ev.type);\r\n                    }\r\n                },\r\n            });\r\n        }\r\n        /**\r\n         * Override to revert back to a classic Component's structure\r\n         *\r\n         * @override\r\n         */\r\n        __callWillUnmount() {\r\n            super.__callWillUnmount();\r\n            this.el.appendChild(this.portal.elm);\r\n            this.doTargetLookUp = true;\r\n        }\r\n        /**\r\n         * At each DOM change, we must ensure that the portal contains exactly one\r\n         * child\r\n         */\r\n        __checkVNodeStructure(vnode) {\r\n            const children = vnode.children;\r\n            let countRealNodes = 0;\r\n            for (let child of children) {\r\n                if (child.sel) {\r\n                    countRealNodes++;\r\n                }\r\n            }\r\n            if (countRealNodes !== 1) {\r\n                throw new Error(`Portal must have exactly one non-text child (has ${countRealNodes})`);\r\n            }\r\n        }\r\n        /**\r\n         * Ensure the target is still there at whichever time we render\r\n         */\r\n        __checkTargetPresence() {\r\n            if (!this.target || !document.contains(this.target)) {\r\n                throw new Error(`Could not find any match for \"${this.props.target}\"`);\r\n            }\r\n        }\r\n        /**\r\n         * Move the portal's element to the target\r\n         */\r\n        __deployPortal() {\r\n            this.__checkTargetPresence();\r\n            this.target.appendChild(this.portal.elm);\r\n        }\r\n        /**\r\n         * Override to remove from the DOM the element we have teleported\r\n         *\r\n         * @override\r\n         */\r\n        __destroy(parent) {\r\n            if (this.portal && this.portal.elm) {\r\n                const displacedElm = this.portal.elm;\r\n                const parent = displacedElm.parentNode;\r\n                if (parent) {\r\n                    parent.removeChild(displacedElm);\r\n                }\r\n            }\r\n            super.__destroy(parent);\r\n        }\r\n        /**\r\n         * Override to patch the element that has been teleported\r\n         *\r\n         * @override\r\n         */\r\n        __patch(target, vnode) {\r\n            if (this.doTargetLookUp) {\r\n                const target = document.querySelector(this.props.target);\r\n                if (!target) {\r\n                    this.env.qweb.on(\"dom-appended\", this, () => {\r\n                        this.doTargetLookUp = false;\r\n                        this.env.qweb.off(\"dom-appended\", this);\r\n                        this.target = document.querySelector(this.props.target);\r\n                        this.__deployPortal();\r\n                    });\r\n                }\r\n                else {\r\n                    this.doTargetLookUp = false;\r\n                    this.target = target;\r\n                }\r\n            }\r\n            this.__checkVNodeStructure(vnode);\r\n            const shouldDeploy = (!this.portal || this.el.contains(this.portal.elm)) && !this.doTargetLookUp;\r\n            if (!this.doTargetLookUp && !shouldDeploy) {\r\n                // Only on pure patching, provided the\r\n                // this.target's parent has not been unmounted\r\n                this.__checkTargetPresence();\r\n            }\r\n            const portalPatch = this.portal ? this.portal : document.createElement(vnode.children[0].sel);\r\n            this.portal = patch(portalPatch, vnode.children[0]);\r\n            vnode.children = [];\r\n            super.__patch(target, vnode);\r\n            if (shouldDeploy) {\r\n                this.__deployPortal();\r\n            }\r\n        }\r\n        /**\r\n         * Override to set the env\r\n         */\r\n        __trigger(component, eventType, payload) {\r\n            const env = this.env;\r\n            this.env = this.parentEnv;\r\n            super.__trigger(component, eventType, payload);\r\n            this.env = env;\r\n        }\r\n    }\r\n    Portal.template = xml `<portal><t t-slot=\"default\"/></portal>`;\r\n    Portal.props = {\r\n        target: {\r\n            type: String,\r\n        },\r\n    };\r\n\r\n    class Link extends Component {\r\n        constructor() {\r\n            super(...arguments);\r\n            this.href = this.env.router.destToPath(this.props);\r\n        }\r\n        async willUpdateProps(nextProps) {\r\n            this.href = this.env.router.destToPath(nextProps);\r\n        }\r\n        get isActive() {\r\n            if (this.env.router.mode === \"hash\") {\r\n                return document.location.hash === this.href;\r\n            }\r\n            return document.location.pathname === this.href;\r\n        }\r\n        navigate(ev) {\r\n            // don't redirect with control keys\r\n            if (ev.metaKey || ev.altKey || ev.ctrlKey || ev.shiftKey) {\r\n                return;\r\n            }\r\n            // don't redirect on right click\r\n            if (ev.button !== undefined && ev.button !== 0) {\r\n                return;\r\n            }\r\n            // don't redirect if `target=\"_blank\"`\r\n            if (ev.currentTarget && ev.currentTarget.getAttribute) {\r\n                const target = ev.currentTarget.getAttribute(\"target\");\r\n                if (/\\b_blank\\b/i.test(target)) {\r\n                    return;\r\n                }\r\n            }\r\n            ev.preventDefault();\r\n            this.env.router.navigate(this.props);\r\n        }\r\n    }\r\n    Link.template = xml `\r\n    <a  t-att-class=\"{'router-link-active': isActive }\"\r\n        t-att-href=\"href\"\r\n        t-on-click=\"navigate\">\r\n        <t t-slot=\"default\"/>\r\n    </a>\r\n  `;\r\n\r\n    class RouteComponent extends Component {\r\n        get routeComponent() {\r\n            return this.env.router.currentRoute && this.env.router.currentRoute.component;\r\n        }\r\n    }\r\n    RouteComponent.template = xml `\r\n    <t>\r\n        <t\r\n            t-if=\"routeComponent\"\r\n            t-component=\"routeComponent\"\r\n            t-key=\"env.router.currentRouteName\"\r\n            t-props=\"env.router.currentParams\" />\r\n    </t>\r\n  `;\r\n\r\n    const paramRegexp = /\\{\\{(.*?)\\}\\}/;\r\n    const globalParamRegexp = new RegExp(paramRegexp.source, \"g\");\r\n    class Router {\r\n        constructor(env, routes, options = { mode: \"history\" }) {\r\n            this.currentRoute = null;\r\n            this.currentParams = null;\r\n            env.router = this;\r\n            this.mode = options.mode;\r\n            this.env = env;\r\n            this.routes = {};\r\n            this.routeIds = [];\r\n            let nextId = 1;\r\n            for (let partialRoute of routes) {\r\n                if (!partialRoute.name) {\r\n                    partialRoute.name = \"__route__\" + nextId++;\r\n                }\r\n                if (partialRoute.component) {\r\n                    QWeb.registerComponent(\"__component__\" + partialRoute.name, partialRoute.component);\r\n                }\r\n                if (partialRoute.redirect) {\r\n                    this.validateDestination(partialRoute.redirect);\r\n                }\r\n                partialRoute.params = partialRoute.path ? findParams(partialRoute.path) : [];\r\n                partialRoute.extractionRegExp = makeExtractionRegExp(partialRoute.path);\r\n                this.routes[partialRoute.name] = partialRoute;\r\n                this.routeIds.push(partialRoute.name);\r\n            }\r\n        }\r\n        //--------------------------------------------------------------------------\r\n        // Public API\r\n        //--------------------------------------------------------------------------\r\n        async start() {\r\n            this._listener = (ev) => this._navigate(this.currentPath(), ev);\r\n            window.addEventListener(\"popstate\", this._listener);\r\n            if (this.mode === \"hash\") {\r\n                window.addEventListener(\"hashchange\", this._listener);\r\n            }\r\n            const result = await this.matchAndApplyRules(this.currentPath());\r\n            if (result.type === \"match\") {\r\n                this.currentRoute = result.route;\r\n                this.currentParams = result.params;\r\n                const currentPath = this.routeToPath(result.route, result.params);\r\n                if (currentPath !== this.currentPath()) {\r\n                    this.setUrlFromPath(currentPath);\r\n                }\r\n            }\r\n        }\r\n        async navigate(to) {\r\n            const path = this.destToPath(to);\r\n            return this._navigate(path);\r\n        }\r\n        async _navigate(path, ev) {\r\n            const initialName = this.currentRouteName;\r\n            const initialParams = this.currentParams;\r\n            const result = await this.matchAndApplyRules(path);\r\n            if (result.type === \"match\") {\r\n                let finalPath = this.routeToPath(result.route, result.params);\r\n                if (path.indexOf(\"?\") > -1) {\r\n                    finalPath += \"?\" + path.split(\"?\")[1];\r\n                }\r\n                const isPopStateEvent = ev && ev instanceof PopStateEvent;\r\n                if (!isPopStateEvent) {\r\n                    this.setUrlFromPath(finalPath);\r\n                }\r\n                this.currentRoute = result.route;\r\n                this.currentParams = result.params;\r\n            }\r\n            else if (result.type === \"nomatch\") {\r\n                this.currentRoute = null;\r\n                this.currentParams = null;\r\n            }\r\n            const didChange = this.currentRouteName !== initialName || !shallowEqual(this.currentParams, initialParams);\r\n            if (didChange) {\r\n                this.env.qweb.forceUpdate();\r\n                return true;\r\n            }\r\n            return false;\r\n        }\r\n        destToPath(dest) {\r\n            this.validateDestination(dest);\r\n            return dest.path || this.routeToPath(this.routes[dest.to], dest.params);\r\n        }\r\n        get currentRouteName() {\r\n            return this.currentRoute && this.currentRoute.name;\r\n        }\r\n        //--------------------------------------------------------------------------\r\n        // Private helpers\r\n        //--------------------------------------------------------------------------\r\n        setUrlFromPath(path) {\r\n            const separator = this.mode === \"hash\" ? location.pathname : \"\";\r\n            const url = location.origin + separator + path;\r\n            if (url !== window.location.href) {\r\n                window.history.pushState({}, path, url);\r\n            }\r\n        }\r\n        validateDestination(dest) {\r\n            if ((!dest.path && !dest.to) || (dest.path && dest.to)) {\r\n                throw new Error(`Invalid destination: ${JSON.stringify(dest)}`);\r\n            }\r\n        }\r\n        routeToPath(route, params) {\r\n            const prefix = this.mode === \"hash\" ? \"#\" : \"\";\r\n            return (prefix +\r\n                route.path.replace(globalParamRegexp, (match, param) => {\r\n                    const [key] = param.split(\".\");\r\n                    return params[key];\r\n                }));\r\n        }\r\n        currentPath() {\r\n            let result = this.mode === \"history\" ? window.location.pathname : window.location.hash.slice(1);\r\n            return result || \"/\";\r\n        }\r\n        match(path) {\r\n            for (let routeId of this.routeIds) {\r\n                let route = this.routes[routeId];\r\n                let params = this.getRouteParams(route, path);\r\n                if (params) {\r\n                    return {\r\n                        type: \"match\",\r\n                        route: route,\r\n                        params: params,\r\n                    };\r\n                }\r\n            }\r\n            return { type: \"nomatch\" };\r\n        }\r\n        async matchAndApplyRules(path) {\r\n            const result = this.match(path);\r\n            if (result.type === \"match\") {\r\n                return this.applyRules(result);\r\n            }\r\n            return result;\r\n        }\r\n        async applyRules(matchResult) {\r\n            const route = matchResult.route;\r\n            if (route.redirect) {\r\n                const path = this.destToPath(route.redirect);\r\n                return this.matchAndApplyRules(path);\r\n            }\r\n            if (route.beforeRouteEnter) {\r\n                const result = await route.beforeRouteEnter({\r\n                    env: this.env,\r\n                    from: this.currentRoute,\r\n                    to: route,\r\n                });\r\n                if (result === false) {\r\n                    return { type: \"cancelled\" };\r\n                }\r\n                else if (result !== true) {\r\n                    // we want to navigate to another destination\r\n                    const path = this.destToPath(result);\r\n                    return this.matchAndApplyRules(path);\r\n                }\r\n            }\r\n            return matchResult;\r\n        }\r\n        getRouteParams(route, path) {\r\n            if (route.path === \"*\") {\r\n                return {};\r\n            }\r\n            if (path.indexOf(\"?\") > -1) {\r\n                path = path.split(\"?\")[0];\r\n            }\r\n            if (path.startsWith(\"#\")) {\r\n                path = path.slice(1);\r\n            }\r\n            const paramsMatch = path.match(route.extractionRegExp);\r\n            if (!paramsMatch) {\r\n                return false;\r\n            }\r\n            const result = {};\r\n            route.params.forEach((param, index) => {\r\n                const [key, suffix] = param.split(\".\");\r\n                const paramValue = paramsMatch[index + 1];\r\n                if (suffix === \"number\") {\r\n                    return (result[key] = parseInt(paramValue, 10));\r\n                }\r\n                return (result[key] = paramValue);\r\n            });\r\n            return result;\r\n        }\r\n    }\r\n    function findParams(str) {\r\n        const result = [];\r\n        let m;\r\n        do {\r\n            m = globalParamRegexp.exec(str);\r\n            if (m) {\r\n                result.push(m[1]);\r\n            }\r\n        } while (m);\r\n        return result;\r\n    }\r\n    function escapeRegExp(str) {\r\n        return str.replace(/[-[\\]{}()*+?.,\\\\^$|#\\s]/g, \"\\\\$&\");\r\n    }\r\n    function makeExtractionRegExp(path) {\r\n        // replace param strings with capture groups so that we can build a regex to match over the path\r\n        const extractionString = path\r\n            .split(paramRegexp)\r\n            .map((part, index) => {\r\n            return index % 2 ? \"(.*)\" : escapeRegExp(part);\r\n        })\r\n            .join(\"\");\r\n        // Example: /home/{{param1}}/{{param2}} => ^\\/home\\/(.*)\\/(.*)$\r\n        return new RegExp(`^${extractionString}$`);\r\n    }\r\n\r\n    /**\r\n     * This file is the main file packaged by rollup (see rollup.config.js).  From\r\n     * this file, we export all public owl elements.\r\n     *\r\n     * Note that dynamic values, such as a date or a commit hash are added by rollup\r\n     */\r\n    const Context = Context$1;\r\n    const useState = useState$1;\r\n    const core = { EventBus, Observer };\r\n    const router = { Router, RouteComponent, Link };\r\n    const Store = Store$1;\r\n    const utils = _utils;\r\n    const tags = _tags;\r\n    const misc = { AsyncRoot, Portal };\r\n    const hooks = Object.assign({}, _hooks, {\r\n        useContext: useContext,\r\n        useDispatch: useDispatch,\r\n        useGetters: useGetters,\r\n        useStore: useStore,\r\n    });\r\n    const __info__ = {};\r\n\r\n    exports.Component = Component;\r\n    exports.Context = Context;\r\n    exports.QWeb = QWeb;\r\n    exports.Store = Store;\r\n    exports.__info__ = __info__;\r\n    exports.browser = browser;\r\n    exports.config = config;\r\n    exports.core = core;\r\n    exports.hooks = hooks;\r\n    exports.misc = misc;\r\n    exports.mount = mount;\r\n    exports.router = router;\r\n    exports.tags = tags;\r\n    exports.useState = useState;\r\n    exports.utils = utils;\r\n\r\n    Object.defineProperty(exports, '__esModule', { value: true });\r\n\r\n\r\n    __info__.version = '1.4.11';\r\n    __info__.date = '2023-01-30T13:09:39.141Z';\r\n    __info__.hash = 'a38c534';\r\n    __info__.url = 'https://github.com/odoo/owl';\r\n\r\n\r\n}(this.owl = this.owl || {}));\r\n", "(function () {\n    /**\n     * Symbol used in ComponentWrapper to redirect Owl events to Odoo legacy\n     * events.\n     */\n    odoo.widgetSymbol = Symbol('widget');\n\n    /**\n     * Add a new method to owl Components to ensure that no performed RPC is\n     * resolved/rejected when the component is destroyed.\n     */\n    owl.Component.prototype.rpc = function () {\n        return new Promise((resolve, reject) => {\n            return this.env.services.rpc(...arguments)\n                .then(result => {\n                    if (this.__owl__.status !== 5 /* not destroyed */) {\n                        resolve(result);\n                    }\n                })\n                .catch(reason => {\n                    if (this.__owl__.status !== 5) /* not destroyed */ {\n                        reject(reason);\n                    }\n                });\n        });\n    };\n\n    /**\n     * Patch owl.Component.__trigger method to call a hook that adds a listener\n     * for the triggered event just before triggering it. This is useful if\n     * there are legacy widgets in the ancestors. In that case, there would be\n     * a widgetSymbol key in the environment, corresponding to the hook to call\n     * (see ComponentWrapper).\n     */\n    const originalTrigger = owl.Component.prototype.__trigger;\n    owl.Component.prototype.__trigger = function (component, evType, payload) {\n        if (this.env[odoo.widgetSymbol]) {\n            this.env[odoo.widgetSymbol](evType);\n        }\n        originalTrigger.call(this, component, evType, payload);\n    };\n})();\n", "/*!\n * jQuery JavaScript Library v3.3.1\n * https://jquery.com/\n *\n * Includes Sizzle.js\n * https://sizzlejs.com/\n *\n * Copyright JS Foundation and other contributors\n * Released under the MIT license\n * https://jquery.org/license\n *\n * Date: 2018-01-20T17:24Z\n */\n( function( global, factory ) {\n\n\t\"use strict\";\n\n\tif ( typeof module === \"object\" && typeof module.exports === \"object\" ) {\n\n\t\t// For CommonJS and CommonJS-like environments where a proper `window`\n\t\t// is present, execute the factory and get jQuery.\n\t\t// For environments that do not have a `window` with a `document`\n\t\t// (such as Node.js), expose a factory as module.exports.\n\t\t// This accentuates the need for the creation of a real `window`.\n\t\t// e.g. var jQuery = require(\"jquery\")(window);\n\t\t// See ticket #14549 for more info.\n\t\tmodule.exports = global.document ?\n\t\t\tfactory( global, true ) :\n\t\t\tfunction( w ) {\n\t\t\t\tif ( !w.document ) {\n\t\t\t\t\tthrow new Error( \"jQuery requires a window with a document\" );\n\t\t\t\t}\n\t\t\t\treturn factory( w );\n\t\t\t};\n\t} else {\n\t\tfactory( global );\n\t}\n\n// Pass this if window is not defined yet\n} )( typeof window !== \"undefined\" ? window : this, function( window, noGlobal ) {\n\n// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1\n// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode\n// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common\n// enough that all such attempts are guarded in a try block.\n\"use strict\";\n\nvar arr = [];\n\nvar document = window.document;\n\nvar getProto = Object.getPrototypeOf;\n\nvar slice = arr.slice;\n\nvar concat = arr.concat;\n\nvar push = arr.push;\n\nvar indexOf = arr.indexOf;\n\nvar class2type = {};\n\nvar toString = class2type.toString;\n\nvar hasOwn = class2type.hasOwnProperty;\n\nvar fnToString = hasOwn.toString;\n\nvar ObjectFunctionString = fnToString.call( Object );\n\nvar support = {};\n\nvar isFunction = function isFunction( obj ) {\n\n      // Support: Chrome <=57, Firefox <=52\n      // In some browsers, typeof returns \"function\" for HTML <object> elements\n      // (i.e., `typeof document.createElement( \"object\" ) === \"function\"`).\n      // We don't want to classify *any* DOM node as a function.\n      return typeof obj === \"function\" && typeof obj.nodeType !== \"number\";\n  };\n\n\nvar isWindow = function isWindow( obj ) {\n\t\treturn obj != null && obj === obj.window;\n\t};\n\n\n\n\n\tvar preservedScriptAttributes = {\n\t\ttype: true,\n\t\tsrc: true,\n\t\tnoModule: true\n\t};\n\n\tfunction DOMEval( code, doc, node ) {\n\t\tdoc = doc || document;\n\n\t\tvar i,\n\t\t\tscript = doc.createElement( \"script\" );\n\n\t\tscript.text = code;\n\t\tif ( node ) {\n\t\t\tfor ( i in preservedScriptAttributes ) {\n\t\t\t\tif ( node[ i ] ) {\n\t\t\t\t\tscript[ i ] = node[ i ];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tdoc.head.appendChild( script ).parentNode.removeChild( script );\n\t}\n\n\nfunction toType( obj ) {\n\tif ( obj == null ) {\n\t\treturn obj + \"\";\n\t}\n\n\t// Support: Android <=2.3 only (functionish RegExp)\n\treturn typeof obj === \"object\" || typeof obj === \"function\" ?\n\t\tclass2type[ toString.call( obj ) ] || \"object\" :\n\t\ttypeof obj;\n}\n/* global Symbol */\n// Defining this global in .eslintrc.json would create a danger of using the global\n// unguarded in another place, it seems safer to define global only for this module\n\n\n\nvar\n\tversion = \"3.3.1\",\n\n\t// Define a local copy of jQuery\n\tjQuery = function( selector, context ) {\n\n\t\t// The jQuery object is actually just the init constructor 'enhanced'\n\t\t// Need init if jQuery is called (just allow error to be thrown if not included)\n\t\treturn new jQuery.fn.init( selector, context );\n\t},\n\n\t// Support: Android <=4.0 only\n\t// Make sure we trim BOM and NBSP\n\trtrim = /^[\\s\\uFEFF\\xA0]+|[\\s\\uFEFF\\xA0]+$/g;\n\njQuery.fn = jQuery.prototype = {\n\n\t// The current version of jQuery being used\n\tjquery: version,\n\n\tconstructor: jQuery,\n\n\t// The default length of a jQuery object is 0\n\tlength: 0,\n\n\ttoArray: function() {\n\t\treturn slice.call( this );\n\t},\n\n\t// Get the Nth element in the matched element set OR\n\t// Get the whole matched element set as a clean array\n\tget: function( num ) {\n\n\t\t// Return all the elements in a clean array\n\t\tif ( num == null ) {\n\t\t\treturn slice.call( this );\n\t\t}\n\n\t\t// Return just the one element from the set\n\t\treturn num < 0 ? this[ num + this.length ] : this[ num ];\n\t},\n\n\t// Take an array of elements and push it onto the stack\n\t// (returning the new matched element set)\n\tpushStack: function( elems ) {\n\n\t\t// Build a new jQuery matched element set\n\t\tvar ret = jQuery.merge( this.constructor(), elems );\n\n\t\t// Add the old object onto the stack (as a reference)\n\t\tret.prevObject = this;\n\n\t\t// Return the newly-formed element set\n\t\treturn ret;\n\t},\n\n\t// Execute a callback for every element in the matched set.\n\teach: function( callback ) {\n\t\treturn jQuery.each( this, callback );\n\t},\n\n\tmap: function( callback ) {\n\t\treturn this.pushStack( jQuery.map( this, function( elem, i ) {\n\t\t\treturn callback.call( elem, i, elem );\n\t\t} ) );\n\t},\n\n\tslice: function() {\n\t\treturn this.pushStack( slice.apply( this, arguments ) );\n\t},\n\n\tfirst: function() {\n\t\treturn this.eq( 0 );\n\t},\n\n\tlast: function() {\n\t\treturn this.eq( -1 );\n\t},\n\n\teq: function( i ) {\n\t\tvar len = this.length,\n\t\t\tj = +i + ( i < 0 ? len : 0 );\n\t\treturn this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] );\n\t},\n\n\tend: function() {\n\t\treturn this.prevObject || this.constructor();\n\t},\n\n\t// For internal use only.\n\t// Behaves like an Array's method, not like a jQuery method.\n\tpush: push,\n\tsort: arr.sort,\n\tsplice: arr.splice\n};\n\njQuery.extend = jQuery.fn.extend = function() {\n\tvar options, name, src, copy, copyIsArray, clone,\n\t\ttarget = arguments[ 0 ] || {},\n\t\ti = 1,\n\t\tlength = arguments.length,\n\t\tdeep = false;\n\n\t// Handle a deep copy situation\n\tif ( typeof target === \"boolean\" ) {\n\t\tdeep = target;\n\n\t\t// Skip the boolean and the target\n\t\ttarget = arguments[ i ] || {};\n\t\ti++;\n\t}\n\n\t// Handle case when target is a string or something (possible in deep copy)\n\tif ( typeof target !== \"object\" && !isFunction( target ) ) {\n\t\ttarget = {};\n\t}\n\n\t// Extend jQuery itself if only one argument is passed\n\tif ( i === length ) {\n\t\ttarget = this;\n\t\ti--;\n\t}\n\n\tfor ( ; i < length; i++ ) {\n\n\t\t// Only deal with non-null/undefined values\n\t\tif ( ( options = arguments[ i ] ) != null ) {\n\n\t\t\t// Extend the base object\n\t\t\tfor ( name in options ) {\n\t\t\t\tsrc = target[ name ];\n\t\t\t\tcopy = options[ name ];\n\n\t\t\t\t// Prevent never-ending loop\n\t\t\t\tif ( name === '__proto__' || target === copy ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// Recurse if we're merging plain objects or arrays\n\t\t\t\tif ( deep && copy && ( jQuery.isPlainObject( copy ) ||\n\t\t\t\t\t( copyIsArray = Array.isArray( copy ) ) ) ) {\n\n\t\t\t\t\tif ( copyIsArray ) {\n\t\t\t\t\t\tcopyIsArray = false;\n\t\t\t\t\t\tclone = src && Array.isArray( src ) ? src : [];\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tclone = src && jQuery.isPlainObject( src ) ? src : {};\n\t\t\t\t\t}\n\n\t\t\t\t\t// Never move original objects, clone them\n\t\t\t\t\ttarget[ name ] = jQuery.extend( deep, clone, copy );\n\n\t\t\t\t// Don't bring in undefined values\n\t\t\t\t} else if ( copy !== undefined ) {\n\t\t\t\t\ttarget[ name ] = copy;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Return the modified object\n\treturn target;\n};\n\njQuery.extend( {\n\n\t// Unique for each copy of jQuery on the page\n\texpando: \"jQuery\" + ( version + Math.random() ).replace( /\\D/g, \"\" ),\n\n\t// Assume jQuery is ready without the ready module\n\tisReady: true,\n\n\terror: function( msg ) {\n\t\tthrow new Error( msg );\n\t},\n\n\tnoop: function() {},\n\n\tisPlainObject: function( obj ) {\n\t\tvar proto, Ctor;\n\n\t\t// Detect obvious negatives\n\t\t// Use toString instead of jQuery.type to catch host objects\n\t\tif ( !obj || toString.call( obj ) !== \"[object Object]\" ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tproto = getProto( obj );\n\n\t\t// Objects with no prototype (e.g., `Object.create( null )`) are plain\n\t\tif ( !proto ) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// Objects with prototype are plain iff they were constructed by a global Object function\n\t\tCtor = hasOwn.call( proto, \"constructor\" ) && proto.constructor;\n\t\treturn typeof Ctor === \"function\" && fnToString.call( Ctor ) === ObjectFunctionString;\n\t},\n\n\tisEmptyObject: function( obj ) {\n\n\t\t/* eslint-disable no-unused-vars */\n\t\t// See https://github.com/eslint/eslint/issues/6125\n\t\tvar name;\n\n\t\tfor ( name in obj ) {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t},\n\n\t// Evaluates a script in a global context\n\tglobalEval: function( code ) {\n\t\tDOMEval( code );\n\t},\n\n\teach: function( obj, callback ) {\n\t\tvar length, i = 0;\n\n\t\tif ( isArrayLike( obj ) ) {\n\t\t\tlength = obj.length;\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tif ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tfor ( i in obj ) {\n\t\t\t\tif ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn obj;\n\t},\n\n\t// Support: Android <=4.0 only\n\ttrim: function( text ) {\n\t\treturn text == null ?\n\t\t\t\"\" :\n\t\t\t( text + \"\" ).replace( rtrim, \"\" );\n\t},\n\n\t// results is for internal usage only\n\tmakeArray: function( arr, results ) {\n\t\tvar ret = results || [];\n\n\t\tif ( arr != null ) {\n\t\t\tif ( isArrayLike( Object( arr ) ) ) {\n\t\t\t\tjQuery.merge( ret,\n\t\t\t\t\ttypeof arr === \"string\" ?\n\t\t\t\t\t[ arr ] : arr\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tpush.call( ret, arr );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tinArray: function( elem, arr, i ) {\n\t\treturn arr == null ? -1 : indexOf.call( arr, elem, i );\n\t},\n\n\t// Support: Android <=4.0 only, PhantomJS 1 only\n\t// push.apply(_, arraylike) throws on ancient WebKit\n\tmerge: function( first, second ) {\n\t\tvar len = +second.length,\n\t\t\tj = 0,\n\t\t\ti = first.length;\n\n\t\tfor ( ; j < len; j++ ) {\n\t\t\tfirst[ i++ ] = second[ j ];\n\t\t}\n\n\t\tfirst.length = i;\n\n\t\treturn first;\n\t},\n\n\tgrep: function( elems, callback, invert ) {\n\t\tvar callbackInverse,\n\t\t\tmatches = [],\n\t\t\ti = 0,\n\t\t\tlength = elems.length,\n\t\t\tcallbackExpect = !invert;\n\n\t\t// Go through the array, only saving the items\n\t\t// that pass the validator function\n\t\tfor ( ; i < length; i++ ) {\n\t\t\tcallbackInverse = !callback( elems[ i ], i );\n\t\t\tif ( callbackInverse !== callbackExpect ) {\n\t\t\t\tmatches.push( elems[ i ] );\n\t\t\t}\n\t\t}\n\n\t\treturn matches;\n\t},\n\n\t// arg is for internal usage only\n\tmap: function( elems, callback, arg ) {\n\t\tvar length, value,\n\t\t\ti = 0,\n\t\t\tret = [];\n\n\t\t// Go through the array, translating each of the items to their new values\n\t\tif ( isArrayLike( elems ) ) {\n\t\t\tlength = elems.length;\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tvalue = callback( elems[ i ], i, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret.push( value );\n\t\t\t\t}\n\t\t\t}\n\n\t\t// Go through every key on the object,\n\t\t} else {\n\t\t\tfor ( i in elems ) {\n\t\t\t\tvalue = callback( elems[ i ], i, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret.push( value );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Flatten any nested arrays\n\t\treturn concat.apply( [], ret );\n\t},\n\n\t// A global GUID counter for objects\n\tguid: 1,\n\n\t// jQuery.support is not used in Core but other projects attach their\n\t// properties to it so it needs to exist.\n\tsupport: support\n} );\n\nif ( typeof Symbol === \"function\" ) {\n\tjQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ];\n}\n\n// Populate the class2type map\njQuery.each( \"Boolean Number String Function Array Date RegExp Object Error Symbol\".split( \" \" ),\nfunction( i, name ) {\n\tclass2type[ \"[object \" + name + \"]\" ] = name.toLowerCase();\n} );\n\nfunction isArrayLike( obj ) {\n\n\t// Support: real iOS 8.2 only (not reproducible in simulator)\n\t// `in` check used to prevent JIT error (gh-2145)\n\t// hasOwn isn't used here due to false negatives\n\t// regarding Nodelist length in IE\n\tvar length = !!obj && \"length\" in obj && obj.length,\n\t\ttype = toType( obj );\n\n\tif ( isFunction( obj ) || isWindow( obj ) ) {\n\t\treturn false;\n\t}\n\n\treturn type === \"array\" || length === 0 ||\n\t\ttypeof length === \"number\" && length > 0 && ( length - 1 ) in obj;\n}\nvar Sizzle =\n/*!\n * Sizzle CSS Selector Engine v2.3.3\n * https://sizzlejs.com/\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license\n * http://jquery.org/license\n *\n * Date: 2016-08-08\n */\n(function( window ) {\n\nvar i,\n\tsupport,\n\tExpr,\n\tgetText,\n\tisXML,\n\ttokenize,\n\tcompile,\n\tselect,\n\toutermostContext,\n\tsortInput,\n\thasDuplicate,\n\n\t// Local document vars\n\tsetDocument,\n\tdocument,\n\tdocElem,\n\tdocumentIsHTML,\n\trbuggyQSA,\n\trbuggyMatches,\n\tmatches,\n\tcontains,\n\n\t// Instance-specific data\n\texpando = \"sizzle\" + 1 * new Date(),\n\tpreferredDoc = window.document,\n\tdirruns = 0,\n\tdone = 0,\n\tclassCache = createCache(),\n\ttokenCache = createCache(),\n\tcompilerCache = createCache(),\n\tsortOrder = function( a, b ) {\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t}\n\t\treturn 0;\n\t},\n\n\t// Instance methods\n\thasOwn = ({}).hasOwnProperty,\n\tarr = [],\n\tpop = arr.pop,\n\tpush_native = arr.push,\n\tpush = arr.push,\n\tslice = arr.slice,\n\t// Use a stripped-down indexOf as it's faster than native\n\t// https://jsperf.com/thor-indexof-vs-for/5\n\tindexOf = function( list, elem ) {\n\t\tvar i = 0,\n\t\t\tlen = list.length;\n\t\tfor ( ; i < len; i++ ) {\n\t\t\tif ( list[i] === elem ) {\n\t\t\t\treturn i;\n\t\t\t}\n\t\t}\n\t\treturn -1;\n\t},\n\n\tbooleans = \"checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped\",\n\n\t// Regular expressions\n\n\t// http://www.w3.org/TR/css3-selectors/#whitespace\n\twhitespace = \"[\\\\x20\\\\t\\\\r\\\\n\\\\f]\",\n\n\t// http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier\n\tidentifier = \"(?:\\\\\\\\.|[\\\\w-]|[^\\0-\\\\xa0])+\",\n\n\t// Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors\n\tattributes = \"\\\\[\" + whitespace + \"*(\" + identifier + \")(?:\" + whitespace +\n\t\t// Operator (capture 2)\n\t\t\"*([*^$|!~]?=)\" + whitespace +\n\t\t// \"Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]\"\n\t\t\"*(?:'((?:\\\\\\\\.|[^\\\\\\\\'])*)'|\\\"((?:\\\\\\\\.|[^\\\\\\\\\\\"])*)\\\"|(\" + identifier + \"))|)\" + whitespace +\n\t\t\"*\\\\]\",\n\n\tpseudos = \":(\" + identifier + \")(?:\\\\((\" +\n\t\t// To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:\n\t\t// 1. quoted (capture 3; capture 4 or capture 5)\n\t\t\"('((?:\\\\\\\\.|[^\\\\\\\\'])*)'|\\\"((?:\\\\\\\\.|[^\\\\\\\\\\\"])*)\\\")|\" +\n\t\t// 2. simple (capture 6)\n\t\t\"((?:\\\\\\\\.|[^\\\\\\\\()[\\\\]]|\" + attributes + \")*)|\" +\n\t\t// 3. anything else (capture 2)\n\t\t\".*\" +\n\t\t\")\\\\)|)\",\n\n\t// Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter\n\trwhitespace = new RegExp( whitespace + \"+\", \"g\" ),\n\trtrim = new RegExp( \"^\" + whitespace + \"+|((?:^|[^\\\\\\\\])(?:\\\\\\\\.)*)\" + whitespace + \"+$\", \"g\" ),\n\n\trcomma = new RegExp( \"^\" + whitespace + \"*,\" + whitespace + \"*\" ),\n\trcombinators = new RegExp( \"^\" + whitespace + \"*([>+~]|\" + whitespace + \")\" + whitespace + \"*\" ),\n\n\trattributeQuotes = new RegExp( \"=\" + whitespace + \"*([^\\\\]'\\\"]*?)\" + whitespace + \"*\\\\]\", \"g\" ),\n\n\trpseudo = new RegExp( pseudos ),\n\tridentifier = new RegExp( \"^\" + identifier + \"$\" ),\n\n\tmatchExpr = {\n\t\t\"ID\": new RegExp( \"^#(\" + identifier + \")\" ),\n\t\t\"CLASS\": new RegExp( \"^\\\\.(\" + identifier + \")\" ),\n\t\t\"TAG\": new RegExp( \"^(\" + identifier + \"|[*])\" ),\n\t\t\"ATTR\": new RegExp( \"^\" + attributes ),\n\t\t\"PSEUDO\": new RegExp( \"^\" + pseudos ),\n\t\t\"CHILD\": new RegExp( \"^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\\\(\" + whitespace +\n\t\t\t\"*(even|odd|(([+-]|)(\\\\d*)n|)\" + whitespace + \"*(?:([+-]|)\" + whitespace +\n\t\t\t\"*(\\\\d+)|))\" + whitespace + \"*\\\\)|)\", \"i\" ),\n\t\t\"bool\": new RegExp( \"^(?:\" + booleans + \")$\", \"i\" ),\n\t\t// For use in libraries implementing .is()\n\t\t// We use this for POS matching in `select`\n\t\t\"needsContext\": new RegExp( \"^\" + whitespace + \"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\\\(\" +\n\t\t\twhitespace + \"*((?:-\\\\d)?\\\\d*)\" + whitespace + \"*\\\\)|)(?=[^-]|$)\", \"i\" )\n\t},\n\n\trinputs = /^(?:input|select|textarea|button)$/i,\n\trheader = /^h\\d$/i,\n\n\trnative = /^[^{]+\\{\\s*\\[native \\w/,\n\n\t// Easily-parseable/retrievable ID or TAG or CLASS selectors\n\trquickExpr = /^(?:#([\\w-]+)|(\\w+)|\\.([\\w-]+))$/,\n\n\trsibling = /[+~]/,\n\n\t// CSS escapes\n\t// http://www.w3.org/TR/CSS21/syndata.html#escaped-characters\n\trunescape = new RegExp( \"\\\\\\\\([\\\\da-f]{1,6}\" + whitespace + \"?|(\" + whitespace + \")|.)\", \"ig\" ),\n\tfunescape = function( _, escaped, escapedWhitespace ) {\n\t\tvar high = \"0x\" + escaped - 0x10000;\n\t\t// NaN means non-codepoint\n\t\t// Support: Firefox<24\n\t\t// Workaround erroneous numeric interpretation of +\"0x\"\n\t\treturn high !== high || escapedWhitespace ?\n\t\t\tescaped :\n\t\t\thigh < 0 ?\n\t\t\t\t// BMP codepoint\n\t\t\t\tString.fromCharCode( high + 0x10000 ) :\n\t\t\t\t// Supplemental Plane codepoint (surrogate pair)\n\t\t\t\tString.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );\n\t},\n\n\t// CSS string/identifier serialization\n\t// https://drafts.csswg.org/cssom/#common-serializing-idioms\n\trcssescape = /([\\0-\\x1f\\x7f]|^-?\\d)|^-$|[^\\0-\\x1f\\x7f-\\uFFFF\\w-]/g,\n\tfcssescape = function( ch, asCodePoint ) {\n\t\tif ( asCodePoint ) {\n\n\t\t\t// U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER\n\t\t\tif ( ch === \"\\0\" ) {\n\t\t\t\treturn \"\\uFFFD\";\n\t\t\t}\n\n\t\t\t// Control characters and (dependent upon position) numbers get escaped as code points\n\t\t\treturn ch.slice( 0, -1 ) + \"\\\\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + \" \";\n\t\t}\n\n\t\t// Other potentially-special ASCII characters get backslash-escaped\n\t\treturn \"\\\\\" + ch;\n\t},\n\n\t// Used for iframes\n\t// See setDocument()\n\t// Removing the function wrapper causes a \"Permission Denied\"\n\t// error in IE\n\tunloadHandler = function() {\n\t\tsetDocument();\n\t},\n\n\tdisabledAncestor = addCombinator(\n\t\tfunction( elem ) {\n\t\t\treturn elem.disabled === true && (\"form\" in elem || \"label\" in elem);\n\t\t},\n\t\t{ dir: \"parentNode\", next: \"legend\" }\n\t);\n\n// Optimize for push.apply( _, NodeList )\ntry {\n\tpush.apply(\n\t\t(arr = slice.call( preferredDoc.childNodes )),\n\t\tpreferredDoc.childNodes\n\t);\n\t// Support: Android<4.0\n\t// Detect silently failing push.apply\n\tarr[ preferredDoc.childNodes.length ].nodeType;\n} catch ( e ) {\n\tpush = { apply: arr.length ?\n\n\t\t// Leverage slice if possible\n\t\tfunction( target, els ) {\n\t\t\tpush_native.apply( target, slice.call(els) );\n\t\t} :\n\n\t\t// Support: IE<9\n\t\t// Otherwise append directly\n\t\tfunction( target, els ) {\n\t\t\tvar j = target.length,\n\t\t\t\ti = 0;\n\t\t\t// Can't trust NodeList.length\n\t\t\twhile ( (target[j++] = els[i++]) ) {}\n\t\t\ttarget.length = j - 1;\n\t\t}\n\t};\n}\n\nfunction Sizzle( selector, context, results, seed ) {\n\tvar m, i, elem, nid, match, groups, newSelector,\n\t\tnewContext = context && context.ownerDocument,\n\n\t\t// nodeType defaults to 9, since context defaults to document\n\t\tnodeType = context ? context.nodeType : 9;\n\n\tresults = results || [];\n\n\t// Return early from calls with invalid selector or context\n\tif ( typeof selector !== \"string\" || !selector ||\n\t\tnodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {\n\n\t\treturn results;\n\t}\n\n\t// Try to shortcut find operations (as opposed to filters) in HTML documents\n\tif ( !seed ) {\n\n\t\tif ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {\n\t\t\tsetDocument( context );\n\t\t}\n\t\tcontext = context || document;\n\n\t\tif ( documentIsHTML ) {\n\n\t\t\t// If the selector is sufficiently simple, try using a \"get*By*\" DOM method\n\t\t\t// (excepting DocumentFragment context, where the methods don't exist)\n\t\t\tif ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) {\n\n\t\t\t\t// ID selector\n\t\t\t\tif ( (m = match[1]) ) {\n\n\t\t\t\t\t// Document context\n\t\t\t\t\tif ( nodeType === 9 ) {\n\t\t\t\t\t\tif ( (elem = context.getElementById( m )) ) {\n\n\t\t\t\t\t\t\t// Support: IE, Opera, Webkit\n\t\t\t\t\t\t\t// TODO: identify versions\n\t\t\t\t\t\t\t// getElementById can match elements by name instead of ID\n\t\t\t\t\t\t\tif ( elem.id === m ) {\n\t\t\t\t\t\t\t\tresults.push( elem );\n\t\t\t\t\t\t\t\treturn results;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\treturn results;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t// Element context\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t// Support: IE, Opera, Webkit\n\t\t\t\t\t\t// TODO: identify versions\n\t\t\t\t\t\t// getElementById can match elements by name instead of ID\n\t\t\t\t\t\tif ( newContext && (elem = newContext.getElementById( m )) &&\n\t\t\t\t\t\t\tcontains( context, elem ) &&\n\t\t\t\t\t\t\telem.id === m ) {\n\n\t\t\t\t\t\t\tresults.push( elem );\n\t\t\t\t\t\t\treturn results;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t// Type selector\n\t\t\t\t} else if ( match[2] ) {\n\t\t\t\t\tpush.apply( results, context.getElementsByTagName( selector ) );\n\t\t\t\t\treturn results;\n\n\t\t\t\t// Class selector\n\t\t\t\t} else if ( (m = match[3]) && support.getElementsByClassName &&\n\t\t\t\t\tcontext.getElementsByClassName ) {\n\n\t\t\t\t\tpush.apply( results, context.getElementsByClassName( m ) );\n\t\t\t\t\treturn results;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Take advantage of querySelectorAll\n\t\t\tif ( support.qsa &&\n\t\t\t\t!compilerCache[ selector + \" \" ] &&\n\t\t\t\t(!rbuggyQSA || !rbuggyQSA.test( selector )) ) {\n\n\t\t\t\tif ( nodeType !== 1 ) {\n\t\t\t\t\tnewContext = context;\n\t\t\t\t\tnewSelector = selector;\n\n\t\t\t\t// qSA looks outside Element context, which is not what we want\n\t\t\t\t// Thanks to Andrew Dupont for this workaround technique\n\t\t\t\t// Support: IE <=8\n\t\t\t\t// Exclude object elements\n\t\t\t\t} else if ( context.nodeName.toLowerCase() !== \"object\" ) {\n\n\t\t\t\t\t// Capture the context ID, setting it first if necessary\n\t\t\t\t\tif ( (nid = context.getAttribute( \"id\" )) ) {\n\t\t\t\t\t\tnid = nid.replace( rcssescape, fcssescape );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tcontext.setAttribute( \"id\", (nid = expando) );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Prefix every selector in the list\n\t\t\t\t\tgroups = tokenize( selector );\n\t\t\t\t\ti = groups.length;\n\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\tgroups[i] = \"#\" + nid + \" \" + toSelector( groups[i] );\n\t\t\t\t\t}\n\t\t\t\t\tnewSelector = groups.join( \",\" );\n\n\t\t\t\t\t// Expand context for sibling selectors\n\t\t\t\t\tnewContext = rsibling.test( selector ) && testContext( context.parentNode ) ||\n\t\t\t\t\t\tcontext;\n\t\t\t\t}\n\n\t\t\t\tif ( newSelector ) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tpush.apply( results,\n\t\t\t\t\t\t\tnewContext.querySelectorAll( newSelector )\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn results;\n\t\t\t\t\t} catch ( qsaError ) {\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tif ( nid === expando ) {\n\t\t\t\t\t\t\tcontext.removeAttribute( \"id\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// All others\n\treturn select( selector.replace( rtrim, \"$1\" ), context, results, seed );\n}\n\n/**\n * Create key-value caches of limited size\n * @returns {function(string, object)} Returns the Object data after storing it on itself with\n *\tproperty name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)\n *\tdeleting the oldest entry\n */\nfunction createCache() {\n\tvar keys = [];\n\n\tfunction cache( key, value ) {\n\t\t// Use (key + \" \") to avoid collision with native prototype properties (see Issue #157)\n\t\tif ( keys.push( key + \" \" ) > Expr.cacheLength ) {\n\t\t\t// Only keep the most recent entries\n\t\t\tdelete cache[ keys.shift() ];\n\t\t}\n\t\treturn (cache[ key + \" \" ] = value);\n\t}\n\treturn cache;\n}\n\n/**\n * Mark a function for special use by Sizzle\n * @param {Function} fn The function to mark\n */\nfunction markFunction( fn ) {\n\tfn[ expando ] = true;\n\treturn fn;\n}\n\n/**\n * Support testing using an element\n * @param {Function} fn Passed the created element and returns a boolean result\n */\nfunction assert( fn ) {\n\tvar el = document.createElement(\"fieldset\");\n\n\ttry {\n\t\treturn !!fn( el );\n\t} catch (e) {\n\t\treturn false;\n\t} finally {\n\t\t// Remove from its parent by default\n\t\tif ( el.parentNode ) {\n\t\t\tel.parentNode.removeChild( el );\n\t\t}\n\t\t// release memory in IE\n\t\tel = null;\n\t}\n}\n\n/**\n * Adds the same handler for all of the specified attrs\n * @param {String} attrs Pipe-separated list of attributes\n * @param {Function} handler The method that will be applied\n */\nfunction addHandle( attrs, handler ) {\n\tvar arr = attrs.split(\"|\"),\n\t\ti = arr.length;\n\n\twhile ( i-- ) {\n\t\tExpr.attrHandle[ arr[i] ] = handler;\n\t}\n}\n\n/**\n * Checks document order of two siblings\n * @param {Element} a\n * @param {Element} b\n * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b\n */\nfunction siblingCheck( a, b ) {\n\tvar cur = b && a,\n\t\tdiff = cur && a.nodeType === 1 && b.nodeType === 1 &&\n\t\t\ta.sourceIndex - b.sourceIndex;\n\n\t// Use IE sourceIndex if available on both nodes\n\tif ( diff ) {\n\t\treturn diff;\n\t}\n\n\t// Check if b follows a\n\tif ( cur ) {\n\t\twhile ( (cur = cur.nextSibling) ) {\n\t\t\tif ( cur === b ) {\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn a ? 1 : -1;\n}\n\n/**\n * Returns a function to use in pseudos for input types\n * @param {String} type\n */\nfunction createInputPseudo( type ) {\n\treturn function( elem ) {\n\t\tvar name = elem.nodeName.toLowerCase();\n\t\treturn name === \"input\" && elem.type === type;\n\t};\n}\n\n/**\n * Returns a function to use in pseudos for buttons\n * @param {String} type\n */\nfunction createButtonPseudo( type ) {\n\treturn function( elem ) {\n\t\tvar name = elem.nodeName.toLowerCase();\n\t\treturn (name === \"input\" || name === \"button\") && elem.type === type;\n\t};\n}\n\n/**\n * Returns a function to use in pseudos for :enabled/:disabled\n * @param {Boolean} disabled true for :disabled; false for :enabled\n */\nfunction createDisabledPseudo( disabled ) {\n\n\t// Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable\n\treturn function( elem ) {\n\n\t\t// Only certain elements can match :enabled or :disabled\n\t\t// https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled\n\t\t// https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled\n\t\tif ( \"form\" in elem ) {\n\n\t\t\t// Check for inherited disabledness on relevant non-disabled elements:\n\t\t\t// * listed form-associated elements in a disabled fieldset\n\t\t\t//   https://html.spec.whatwg.org/multipage/forms.html#category-listed\n\t\t\t//   https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled\n\t\t\t// * option elements in a disabled optgroup\n\t\t\t//   https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled\n\t\t\t// All such elements have a \"form\" property.\n\t\t\tif ( elem.parentNode && elem.disabled === false ) {\n\n\t\t\t\t// Option elements defer to a parent optgroup if present\n\t\t\t\tif ( \"label\" in elem ) {\n\t\t\t\t\tif ( \"label\" in elem.parentNode ) {\n\t\t\t\t\t\treturn elem.parentNode.disabled === disabled;\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn elem.disabled === disabled;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Support: IE 6 - 11\n\t\t\t\t// Use the isDisabled shortcut property to check for disabled fieldset ancestors\n\t\t\t\treturn elem.isDisabled === disabled ||\n\n\t\t\t\t\t// Where there is no isDisabled, check manually\n\t\t\t\t\t/* jshint -W018 */\n\t\t\t\t\telem.isDisabled !== !disabled &&\n\t\t\t\t\t\tdisabledAncestor( elem ) === disabled;\n\t\t\t}\n\n\t\t\treturn elem.disabled === disabled;\n\n\t\t// Try to winnow out elements that can't be disabled before trusting the disabled property.\n\t\t// Some victims get caught in our net (label, legend, menu, track), but it shouldn't\n\t\t// even exist on them, let alone have a boolean value.\n\t\t} else if ( \"label\" in elem ) {\n\t\t\treturn elem.disabled === disabled;\n\t\t}\n\n\t\t// Remaining elements are neither :enabled nor :disabled\n\t\treturn false;\n\t};\n}\n\n/**\n * Returns a function to use in pseudos for positionals\n * @param {Function} fn\n */\nfunction createPositionalPseudo( fn ) {\n\treturn markFunction(function( argument ) {\n\t\targument = +argument;\n\t\treturn markFunction(function( seed, matches ) {\n\t\t\tvar j,\n\t\t\t\tmatchIndexes = fn( [], seed.length, argument ),\n\t\t\t\ti = matchIndexes.length;\n\n\t\t\t// Match elements found at the specified indexes\n\t\t\twhile ( i-- ) {\n\t\t\t\tif ( seed[ (j = matchIndexes[i]) ] ) {\n\t\t\t\t\tseed[j] = !(matches[j] = seed[j]);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t});\n}\n\n/**\n * Checks a node for validity as a Sizzle context\n * @param {Element|Object=} context\n * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value\n */\nfunction testContext( context ) {\n\treturn context && typeof context.getElementsByTagName !== \"undefined\" && context;\n}\n\n// Expose support vars for convenience\nsupport = Sizzle.support = {};\n\n/**\n * Detects XML nodes\n * @param {Element|Object} elem An element or a document\n * @returns {Boolean} True iff elem is a non-HTML XML node\n */\nisXML = Sizzle.isXML = function( elem ) {\n\t// documentElement is verified for cases where it doesn't yet exist\n\t// (such as loading iframes in IE - #4833)\n\tvar documentElement = elem && (elem.ownerDocument || elem).documentElement;\n\treturn documentElement ? documentElement.nodeName !== \"HTML\" : false;\n};\n\n/**\n * Sets document-related variables once based on the current document\n * @param {Element|Object} [doc] An element or document object to use to set the document\n * @returns {Object} Returns the current document\n */\nsetDocument = Sizzle.setDocument = function( node ) {\n\tvar hasCompare, subWindow,\n\t\tdoc = node ? node.ownerDocument || node : preferredDoc;\n\n\t// Return early if doc is invalid or already selected\n\tif ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {\n\t\treturn document;\n\t}\n\n\t// Update global variables\n\tdocument = doc;\n\tdocElem = document.documentElement;\n\tdocumentIsHTML = !isXML( document );\n\n\t// Support: IE 9-11, Edge\n\t// Accessing iframe documents after unload throws \"permission denied\" errors (jQuery #13936)\n\tif ( preferredDoc !== document &&\n\t\t(subWindow = document.defaultView) && subWindow.top !== subWindow ) {\n\n\t\t// Support: IE 11, Edge\n\t\tif ( subWindow.addEventListener ) {\n\t\t\tsubWindow.addEventListener( \"unload\", unloadHandler, false );\n\n\t\t// Support: IE 9 - 10 only\n\t\t} else if ( subWindow.attachEvent ) {\n\t\t\tsubWindow.attachEvent( \"onunload\", unloadHandler );\n\t\t}\n\t}\n\n\t/* Attributes\n\t---------------------------------------------------------------------- */\n\n\t// Support: IE<8\n\t// Verify that getAttribute really returns attributes and not properties\n\t// (excepting IE8 booleans)\n\tsupport.attributes = assert(function( el ) {\n\t\tel.className = \"i\";\n\t\treturn !el.getAttribute(\"className\");\n\t});\n\n\t/* getElement(s)By*\n\t---------------------------------------------------------------------- */\n\n\t// Check if getElementsByTagName(\"*\") returns only elements\n\tsupport.getElementsByTagName = assert(function( el ) {\n\t\tel.appendChild( document.createComment(\"\") );\n\t\treturn !el.getElementsByTagName(\"*\").length;\n\t});\n\n\t// Support: IE<9\n\tsupport.getElementsByClassName = rnative.test( document.getElementsByClassName );\n\n\t// Support: IE<10\n\t// Check if getElementById returns elements by name\n\t// The broken getElementById methods don't pick up programmatically-set names,\n\t// so use a roundabout getElementsByName test\n\tsupport.getById = assert(function( el ) {\n\t\tdocElem.appendChild( el ).id = expando;\n\t\treturn !document.getElementsByName || !document.getElementsByName( expando ).length;\n\t});\n\n\t// ID filter and find\n\tif ( support.getById ) {\n\t\tExpr.filter[\"ID\"] = function( id ) {\n\t\t\tvar attrId = id.replace( runescape, funescape );\n\t\t\treturn function( elem ) {\n\t\t\t\treturn elem.getAttribute(\"id\") === attrId;\n\t\t\t};\n\t\t};\n\t\tExpr.find[\"ID\"] = function( id, context ) {\n\t\t\tif ( typeof context.getElementById !== \"undefined\" && documentIsHTML ) {\n\t\t\t\tvar elem = context.getElementById( id );\n\t\t\t\treturn elem ? [ elem ] : [];\n\t\t\t}\n\t\t};\n\t} else {\n\t\tExpr.filter[\"ID\"] =  function( id ) {\n\t\t\tvar attrId = id.replace( runescape, funescape );\n\t\t\treturn function( elem ) {\n\t\t\t\tvar node = typeof elem.getAttributeNode !== \"undefined\" &&\n\t\t\t\t\telem.getAttributeNode(\"id\");\n\t\t\t\treturn node && node.value === attrId;\n\t\t\t};\n\t\t};\n\n\t\t// Support: IE 6 - 7 only\n\t\t// getElementById is not reliable as a find shortcut\n\t\tExpr.find[\"ID\"] = function( id, context ) {\n\t\t\tif ( typeof context.getElementById !== \"undefined\" && documentIsHTML ) {\n\t\t\t\tvar node, i, elems,\n\t\t\t\t\telem = context.getElementById( id );\n\n\t\t\t\tif ( elem ) {\n\n\t\t\t\t\t// Verify the id attribute\n\t\t\t\t\tnode = elem.getAttributeNode(\"id\");\n\t\t\t\t\tif ( node && node.value === id ) {\n\t\t\t\t\t\treturn [ elem ];\n\t\t\t\t\t}\n\n\t\t\t\t\t// Fall back on getElementsByName\n\t\t\t\t\telems = context.getElementsByName( id );\n\t\t\t\t\ti = 0;\n\t\t\t\t\twhile ( (elem = elems[i++]) ) {\n\t\t\t\t\t\tnode = elem.getAttributeNode(\"id\");\n\t\t\t\t\t\tif ( node && node.value === id ) {\n\t\t\t\t\t\t\treturn [ elem ];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn [];\n\t\t\t}\n\t\t};\n\t}\n\n\t// Tag\n\tExpr.find[\"TAG\"] = support.getElementsByTagName ?\n\t\tfunction( tag, context ) {\n\t\t\tif ( typeof context.getElementsByTagName !== \"undefined\" ) {\n\t\t\t\treturn context.getElementsByTagName( tag );\n\n\t\t\t// DocumentFragment nodes don't have gEBTN\n\t\t\t} else if ( support.qsa ) {\n\t\t\t\treturn context.querySelectorAll( tag );\n\t\t\t}\n\t\t} :\n\n\t\tfunction( tag, context ) {\n\t\t\tvar elem,\n\t\t\t\ttmp = [],\n\t\t\t\ti = 0,\n\t\t\t\t// By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too\n\t\t\t\tresults = context.getElementsByTagName( tag );\n\n\t\t\t// Filter out possible comments\n\t\t\tif ( tag === \"*\" ) {\n\t\t\t\twhile ( (elem = results[i++]) ) {\n\t\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\t\ttmp.push( elem );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn tmp;\n\t\t\t}\n\t\t\treturn results;\n\t\t};\n\n\t// Class\n\tExpr.find[\"CLASS\"] = support.getElementsByClassName && function( className, context ) {\n\t\tif ( typeof context.getElementsByClassName !== \"undefined\" && documentIsHTML ) {\n\t\t\treturn context.getElementsByClassName( className );\n\t\t}\n\t};\n\n\t/* QSA/matchesSelector\n\t---------------------------------------------------------------------- */\n\n\t// QSA and matchesSelector support\n\n\t// matchesSelector(:active) reports false when true (IE9/Opera 11.5)\n\trbuggyMatches = [];\n\n\t// qSa(:focus) reports false when true (Chrome 21)\n\t// We allow this because of a bug in IE8/9 that throws an error\n\t// whenever `document.activeElement` is accessed on an iframe\n\t// So, we allow :focus to pass through QSA all the time to avoid the IE error\n\t// See https://bugs.jquery.com/ticket/13378\n\trbuggyQSA = [];\n\n\tif ( (support.qsa = rnative.test( document.querySelectorAll )) ) {\n\t\t// Build QSA regex\n\t\t// Regex strategy adopted from Diego Perini\n\t\tassert(function( el ) {\n\t\t\t// Select is set to empty string on purpose\n\t\t\t// This is to test IE's treatment of not explicitly\n\t\t\t// setting a boolean content attribute,\n\t\t\t// since its presence should be enough\n\t\t\t// https://bugs.jquery.com/ticket/12359\n\t\t\tdocElem.appendChild( el ).innerHTML = \"<a id='\" + expando + \"'></a>\" +\n\t\t\t\t\"<select id='\" + expando + \"-\\r\\\\' msallowcapture=''>\" +\n\t\t\t\t\"<option selected=''></option></select>\";\n\n\t\t\t// Support: IE8, Opera 11-12.16\n\t\t\t// Nothing should be selected when empty strings follow ^= or $= or *=\n\t\t\t// The test attribute must be unknown in Opera but \"safe\" for WinRT\n\t\t\t// https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section\n\t\t\tif ( el.querySelectorAll(\"[msallowcapture^='']\").length ) {\n\t\t\t\trbuggyQSA.push( \"[*^$]=\" + whitespace + \"*(?:''|\\\"\\\")\" );\n\t\t\t}\n\n\t\t\t// Support: IE8\n\t\t\t// Boolean attributes and \"value\" are not treated correctly\n\t\t\tif ( !el.querySelectorAll(\"[selected]\").length ) {\n\t\t\t\trbuggyQSA.push( \"\\\\[\" + whitespace + \"*(?:value|\" + booleans + \")\" );\n\t\t\t}\n\n\t\t\t// Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+\n\t\t\tif ( !el.querySelectorAll( \"[id~=\" + expando + \"-]\" ).length ) {\n\t\t\t\trbuggyQSA.push(\"~=\");\n\t\t\t}\n\n\t\t\t// Webkit/Opera - :checked should return selected option elements\n\t\t\t// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked\n\t\t\t// IE8 throws error here and will not see later tests\n\t\t\tif ( !el.querySelectorAll(\":checked\").length ) {\n\t\t\t\trbuggyQSA.push(\":checked\");\n\t\t\t}\n\n\t\t\t// Support: Safari 8+, iOS 8+\n\t\t\t// https://bugs.webkit.org/show_bug.cgi?id=136851\n\t\t\t// In-page `selector#id sibling-combinator selector` fails\n\t\t\tif ( !el.querySelectorAll( \"a#\" + expando + \"+*\" ).length ) {\n\t\t\t\trbuggyQSA.push(\".#.+[+~]\");\n\t\t\t}\n\t\t});\n\n\t\tassert(function( el ) {\n\t\t\tel.innerHTML = \"<a href='' disabled='disabled'></a>\" +\n\t\t\t\t\"<select disabled='disabled'><option/></select>\";\n\n\t\t\t// Support: Windows 8 Native Apps\n\t\t\t// The type and name attributes are restricted during .innerHTML assignment\n\t\t\tvar input = document.createElement(\"input\");\n\t\t\tinput.setAttribute( \"type\", \"hidden\" );\n\t\t\tel.appendChild( input ).setAttribute( \"name\", \"D\" );\n\n\t\t\t// Support: IE8\n\t\t\t// Enforce case-sensitivity of name attribute\n\t\t\tif ( el.querySelectorAll(\"[name=d]\").length ) {\n\t\t\t\trbuggyQSA.push( \"name\" + whitespace + \"*[*^$|!~]?=\" );\n\t\t\t}\n\n\t\t\t// FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)\n\t\t\t// IE8 throws error here and will not see later tests\n\t\t\tif ( el.querySelectorAll(\":enabled\").length !== 2 ) {\n\t\t\t\trbuggyQSA.push( \":enabled\", \":disabled\" );\n\t\t\t}\n\n\t\t\t// Support: IE9-11+\n\t\t\t// IE's :disabled selector does not pick up the children of disabled fieldsets\n\t\t\tdocElem.appendChild( el ).disabled = true;\n\t\t\tif ( el.querySelectorAll(\":disabled\").length !== 2 ) {\n\t\t\t\trbuggyQSA.push( \":enabled\", \":disabled\" );\n\t\t\t}\n\n\t\t\t// Opera 10-11 does not throw on post-comma invalid pseudos\n\t\t\tel.querySelectorAll(\"*,:x\");\n\t\t\trbuggyQSA.push(\",.*:\");\n\t\t});\n\t}\n\n\tif ( (support.matchesSelector = rnative.test( (matches = docElem.matches ||\n\t\tdocElem.webkitMatchesSelector ||\n\t\tdocElem.mozMatchesSelector ||\n\t\tdocElem.oMatchesSelector ||\n\t\tdocElem.msMatchesSelector) )) ) {\n\n\t\tassert(function( el ) {\n\t\t\t// Check to see if it's possible to do matchesSelector\n\t\t\t// on a disconnected node (IE 9)\n\t\t\tsupport.disconnectedMatch = matches.call( el, \"*\" );\n\n\t\t\t// This should fail with an exception\n\t\t\t// Gecko does not error, returns false instead\n\t\t\tmatches.call( el, \"[s!='']:x\" );\n\t\t\trbuggyMatches.push( \"!=\", pseudos );\n\t\t});\n\t}\n\n\trbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join(\"|\") );\n\trbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join(\"|\") );\n\n\t/* Contains\n\t---------------------------------------------------------------------- */\n\thasCompare = rnative.test( docElem.compareDocumentPosition );\n\n\t// Element contains another\n\t// Purposefully self-exclusive\n\t// As in, an element does not contain itself\n\tcontains = hasCompare || rnative.test( docElem.contains ) ?\n\t\tfunction( a, b ) {\n\t\t\tvar adown = a.nodeType === 9 ? a.documentElement : a,\n\t\t\t\tbup = b && b.parentNode;\n\t\t\treturn a === bup || !!( bup && bup.nodeType === 1 && (\n\t\t\t\tadown.contains ?\n\t\t\t\t\tadown.contains( bup ) :\n\t\t\t\t\ta.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16\n\t\t\t));\n\t\t} :\n\t\tfunction( a, b ) {\n\t\t\tif ( b ) {\n\t\t\t\twhile ( (b = b.parentNode) ) {\n\t\t\t\t\tif ( b === a ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn false;\n\t\t};\n\n\t/* Sorting\n\t---------------------------------------------------------------------- */\n\n\t// Document order sorting\n\tsortOrder = hasCompare ?\n\tfunction( a, b ) {\n\n\t\t// Flag for duplicate removal\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\t\t}\n\n\t\t// Sort on method existence if only one input has compareDocumentPosition\n\t\tvar compare = !a.compareDocumentPosition - !b.compareDocumentPosition;\n\t\tif ( compare ) {\n\t\t\treturn compare;\n\t\t}\n\n\t\t// Calculate position if both inputs belong to the same document\n\t\tcompare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ?\n\t\t\ta.compareDocumentPosition( b ) :\n\n\t\t\t// Otherwise we know they are disconnected\n\t\t\t1;\n\n\t\t// Disconnected nodes\n\t\tif ( compare & 1 ||\n\t\t\t(!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {\n\n\t\t\t// Choose the first element that is related to our preferred document\n\t\t\tif ( a === document || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t\tif ( b === document || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {\n\t\t\t\treturn 1;\n\t\t\t}\n\n\t\t\t// Maintain original order\n\t\t\treturn sortInput ?\n\t\t\t\t( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :\n\t\t\t\t0;\n\t\t}\n\n\t\treturn compare & 4 ? -1 : 1;\n\t} :\n\tfunction( a, b ) {\n\t\t// Exit early if the nodes are identical\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\t\t}\n\n\t\tvar cur,\n\t\t\ti = 0,\n\t\t\taup = a.parentNode,\n\t\t\tbup = b.parentNode,\n\t\t\tap = [ a ],\n\t\t\tbp = [ b ];\n\n\t\t// Parentless nodes are either documents or disconnected\n\t\tif ( !aup || !bup ) {\n\t\t\treturn a === document ? -1 :\n\t\t\t\tb === document ? 1 :\n\t\t\t\taup ? -1 :\n\t\t\t\tbup ? 1 :\n\t\t\t\tsortInput ?\n\t\t\t\t( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :\n\t\t\t\t0;\n\n\t\t// If the nodes are siblings, we can do a quick check\n\t\t} else if ( aup === bup ) {\n\t\t\treturn siblingCheck( a, b );\n\t\t}\n\n\t\t// Otherwise we need full lists of their ancestors for comparison\n\t\tcur = a;\n\t\twhile ( (cur = cur.parentNode) ) {\n\t\t\tap.unshift( cur );\n\t\t}\n\t\tcur = b;\n\t\twhile ( (cur = cur.parentNode) ) {\n\t\t\tbp.unshift( cur );\n\t\t}\n\n\t\t// Walk down the tree looking for a discrepancy\n\t\twhile ( ap[i] === bp[i] ) {\n\t\t\ti++;\n\t\t}\n\n\t\treturn i ?\n\t\t\t// Do a sibling check if the nodes have a common ancestor\n\t\t\tsiblingCheck( ap[i], bp[i] ) :\n\n\t\t\t// Otherwise nodes in our document sort first\n\t\t\tap[i] === preferredDoc ? -1 :\n\t\t\tbp[i] === preferredDoc ? 1 :\n\t\t\t0;\n\t};\n\n\treturn document;\n};\n\nSizzle.matches = function( expr, elements ) {\n\treturn Sizzle( expr, null, null, elements );\n};\n\nSizzle.matchesSelector = function( elem, expr ) {\n\t// Set document vars if needed\n\tif ( ( elem.ownerDocument || elem ) !== document ) {\n\t\tsetDocument( elem );\n\t}\n\n\t// Make sure that attribute selectors are quoted\n\texpr = expr.replace( rattributeQuotes, \"='$1']\" );\n\n\tif ( support.matchesSelector && documentIsHTML &&\n\t\t!compilerCache[ expr + \" \" ] &&\n\t\t( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&\n\t\t( !rbuggyQSA     || !rbuggyQSA.test( expr ) ) ) {\n\n\t\ttry {\n\t\t\tvar ret = matches.call( elem, expr );\n\n\t\t\t// IE 9's matchesSelector returns false on disconnected nodes\n\t\t\tif ( ret || support.disconnectedMatch ||\n\t\t\t\t\t// As well, disconnected nodes are said to be in a document\n\t\t\t\t\t// fragment in IE 9\n\t\t\t\t\telem.document && elem.document.nodeType !== 11 ) {\n\t\t\t\treturn ret;\n\t\t\t}\n\t\t} catch (e) {}\n\t}\n\n\treturn Sizzle( expr, document, null, [ elem ] ).length > 0;\n};\n\nSizzle.contains = function( context, elem ) {\n\t// Set document vars if needed\n\tif ( ( context.ownerDocument || context ) !== document ) {\n\t\tsetDocument( context );\n\t}\n\treturn contains( context, elem );\n};\n\nSizzle.attr = function( elem, name ) {\n\t// Set document vars if needed\n\tif ( ( elem.ownerDocument || elem ) !== document ) {\n\t\tsetDocument( elem );\n\t}\n\n\tvar fn = Expr.attrHandle[ name.toLowerCase() ],\n\t\t// Don't get fooled by Object.prototype properties (jQuery #13807)\n\t\tval = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?\n\t\t\tfn( elem, name, !documentIsHTML ) :\n\t\t\tundefined;\n\n\treturn val !== undefined ?\n\t\tval :\n\t\tsupport.attributes || !documentIsHTML ?\n\t\t\telem.getAttribute( name ) :\n\t\t\t(val = elem.getAttributeNode(name)) && val.specified ?\n\t\t\t\tval.value :\n\t\t\t\tnull;\n};\n\nSizzle.escape = function( sel ) {\n\treturn (sel + \"\").replace( rcssescape, fcssescape );\n};\n\nSizzle.error = function( msg ) {\n\tthrow new Error( \"Syntax error, unrecognized expression: \" + msg );\n};\n\n/**\n * Document sorting and removing duplicates\n * @param {ArrayLike} results\n */\nSizzle.uniqueSort = function( results ) {\n\tvar elem,\n\t\tduplicates = [],\n\t\tj = 0,\n\t\ti = 0;\n\n\t// Unless we *know* we can detect duplicates, assume their presence\n\thasDuplicate = !support.detectDuplicates;\n\tsortInput = !support.sortStable && results.slice( 0 );\n\tresults.sort( sortOrder );\n\n\tif ( hasDuplicate ) {\n\t\twhile ( (elem = results[i++]) ) {\n\t\t\tif ( elem === results[ i ] ) {\n\t\t\t\tj = duplicates.push( i );\n\t\t\t}\n\t\t}\n\t\twhile ( j-- ) {\n\t\t\tresults.splice( duplicates[ j ], 1 );\n\t\t}\n\t}\n\n\t// Clear input after sorting to release objects\n\t// See https://github.com/jquery/sizzle/pull/225\n\tsortInput = null;\n\n\treturn results;\n};\n\n/**\n * Utility function for retrieving the text value of an array of DOM nodes\n * @param {Array|Element} elem\n */\ngetText = Sizzle.getText = function( elem ) {\n\tvar node,\n\t\tret = \"\",\n\t\ti = 0,\n\t\tnodeType = elem.nodeType;\n\n\tif ( !nodeType ) {\n\t\t// If no nodeType, this is expected to be an array\n\t\twhile ( (node = elem[i++]) ) {\n\t\t\t// Do not traverse comment nodes\n\t\t\tret += getText( node );\n\t\t}\n\t} else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {\n\t\t// Use textContent for elements\n\t\t// innerText usage removed for consistency of new lines (jQuery #11153)\n\t\tif ( typeof elem.textContent === \"string\" ) {\n\t\t\treturn elem.textContent;\n\t\t} else {\n\t\t\t// Traverse its children\n\t\t\tfor ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {\n\t\t\t\tret += getText( elem );\n\t\t\t}\n\t\t}\n\t} else if ( nodeType === 3 || nodeType === 4 ) {\n\t\treturn elem.nodeValue;\n\t}\n\t// Do not include comment or processing instruction nodes\n\n\treturn ret;\n};\n\nExpr = Sizzle.selectors = {\n\n\t// Can be adjusted by the user\n\tcacheLength: 50,\n\n\tcreatePseudo: markFunction,\n\n\tmatch: matchExpr,\n\n\tattrHandle: {},\n\n\tfind: {},\n\n\trelative: {\n\t\t\">\": { dir: \"parentNode\", first: true },\n\t\t\" \": { dir: \"parentNode\" },\n\t\t\"+\": { dir: \"previousSibling\", first: true },\n\t\t\"~\": { dir: \"previousSibling\" }\n\t},\n\n\tpreFilter: {\n\t\t\"ATTR\": function( match ) {\n\t\t\tmatch[1] = match[1].replace( runescape, funescape );\n\n\t\t\t// Move the given value to match[3] whether quoted or unquoted\n\t\t\tmatch[3] = ( match[3] || match[4] || match[5] || \"\" ).replace( runescape, funescape );\n\n\t\t\tif ( match[2] === \"~=\" ) {\n\t\t\t\tmatch[3] = \" \" + match[3] + \" \";\n\t\t\t}\n\n\t\t\treturn match.slice( 0, 4 );\n\t\t},\n\n\t\t\"CHILD\": function( match ) {\n\t\t\t/* matches from matchExpr[\"CHILD\"]\n\t\t\t\t1 type (only|nth|...)\n\t\t\t\t2 what (child|of-type)\n\t\t\t\t3 argument (even|odd|\\d*|\\d*n([+-]\\d+)?|...)\n\t\t\t\t4 xn-component of xn+y argument ([+-]?\\d*n|)\n\t\t\t\t5 sign of xn-component\n\t\t\t\t6 x of xn-component\n\t\t\t\t7 sign of y-component\n\t\t\t\t8 y of y-component\n\t\t\t*/\n\t\t\tmatch[1] = match[1].toLowerCase();\n\n\t\t\tif ( match[1].slice( 0, 3 ) === \"nth\" ) {\n\t\t\t\t// nth-* requires argument\n\t\t\t\tif ( !match[3] ) {\n\t\t\t\t\tSizzle.error( match[0] );\n\t\t\t\t}\n\n\t\t\t\t// numeric x and y parameters for Expr.filter.CHILD\n\t\t\t\t// remember that false/true cast respectively to 0/1\n\t\t\t\tmatch[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === \"even\" || match[3] === \"odd\" ) );\n\t\t\t\tmatch[5] = +( ( match[7] + match[8] ) || match[3] === \"odd\" );\n\n\t\t\t// other types prohibit arguments\n\t\t\t} else if ( match[3] ) {\n\t\t\t\tSizzle.error( match[0] );\n\t\t\t}\n\n\t\t\treturn match;\n\t\t},\n\n\t\t\"PSEUDO\": function( match ) {\n\t\t\tvar excess,\n\t\t\t\tunquoted = !match[6] && match[2];\n\n\t\t\tif ( matchExpr[\"CHILD\"].test( match[0] ) ) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\t// Accept quoted arguments as-is\n\t\t\tif ( match[3] ) {\n\t\t\t\tmatch[2] = match[4] || match[5] || \"\";\n\n\t\t\t// Strip excess characters from unquoted arguments\n\t\t\t} else if ( unquoted && rpseudo.test( unquoted ) &&\n\t\t\t\t// Get excess from tokenize (recursively)\n\t\t\t\t(excess = tokenize( unquoted, true )) &&\n\t\t\t\t// advance to the next closing parenthesis\n\t\t\t\t(excess = unquoted.indexOf( \")\", unquoted.length - excess ) - unquoted.length) ) {\n\n\t\t\t\t// excess is a negative index\n\t\t\t\tmatch[0] = match[0].slice( 0, excess );\n\t\t\t\tmatch[2] = unquoted.slice( 0, excess );\n\t\t\t}\n\n\t\t\t// Return only captures needed by the pseudo filter method (type and argument)\n\t\t\treturn match.slice( 0, 3 );\n\t\t}\n\t},\n\n\tfilter: {\n\n\t\t\"TAG\": function( nodeNameSelector ) {\n\t\t\tvar nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();\n\t\t\treturn nodeNameSelector === \"*\" ?\n\t\t\t\tfunction() { return true; } :\n\t\t\t\tfunction( elem ) {\n\t\t\t\t\treturn elem.nodeName && elem.nodeName.toLowerCase() === nodeName;\n\t\t\t\t};\n\t\t},\n\n\t\t\"CLASS\": function( className ) {\n\t\t\tvar pattern = classCache[ className + \" \" ];\n\n\t\t\treturn pattern ||\n\t\t\t\t(pattern = new RegExp( \"(^|\" + whitespace + \")\" + className + \"(\" + whitespace + \"|$)\" )) &&\n\t\t\t\tclassCache( className, function( elem ) {\n\t\t\t\t\treturn pattern.test( typeof elem.className === \"string\" && elem.className || typeof elem.getAttribute !== \"undefined\" && elem.getAttribute(\"class\") || \"\" );\n\t\t\t\t});\n\t\t},\n\n\t\t\"ATTR\": function( name, operator, check ) {\n\t\t\treturn function( elem ) {\n\t\t\t\tvar result = Sizzle.attr( elem, name );\n\n\t\t\t\tif ( result == null ) {\n\t\t\t\t\treturn operator === \"!=\";\n\t\t\t\t}\n\t\t\t\tif ( !operator ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\tresult += \"\";\n\n\t\t\t\treturn operator === \"=\" ? result === check :\n\t\t\t\t\toperator === \"!=\" ? result !== check :\n\t\t\t\t\toperator === \"^=\" ? check && result.indexOf( check ) === 0 :\n\t\t\t\t\toperator === \"*=\" ? check && result.indexOf( check ) > -1 :\n\t\t\t\t\toperator === \"$=\" ? check && result.slice( -check.length ) === check :\n\t\t\t\t\toperator === \"~=\" ? ( \" \" + result.replace( rwhitespace, \" \" ) + \" \" ).indexOf( check ) > -1 :\n\t\t\t\t\toperator === \"|=\" ? result === check || result.slice( 0, check.length + 1 ) === check + \"-\" :\n\t\t\t\t\tfalse;\n\t\t\t};\n\t\t},\n\n\t\t\"CHILD\": function( type, what, argument, first, last ) {\n\t\t\tvar simple = type.slice( 0, 3 ) !== \"nth\",\n\t\t\t\tforward = type.slice( -4 ) !== \"last\",\n\t\t\t\tofType = what === \"of-type\";\n\n\t\t\treturn first === 1 && last === 0 ?\n\n\t\t\t\t// Shortcut for :nth-*(n)\n\t\t\t\tfunction( elem ) {\n\t\t\t\t\treturn !!elem.parentNode;\n\t\t\t\t} :\n\n\t\t\t\tfunction( elem, context, xml ) {\n\t\t\t\t\tvar cache, uniqueCache, outerCache, node, nodeIndex, start,\n\t\t\t\t\t\tdir = simple !== forward ? \"nextSibling\" : \"previousSibling\",\n\t\t\t\t\t\tparent = elem.parentNode,\n\t\t\t\t\t\tname = ofType && elem.nodeName.toLowerCase(),\n\t\t\t\t\t\tuseCache = !xml && !ofType,\n\t\t\t\t\t\tdiff = false;\n\n\t\t\t\t\tif ( parent ) {\n\n\t\t\t\t\t\t// :(first|last|only)-(child|of-type)\n\t\t\t\t\t\tif ( simple ) {\n\t\t\t\t\t\t\twhile ( dir ) {\n\t\t\t\t\t\t\t\tnode = elem;\n\t\t\t\t\t\t\t\twhile ( (node = node[ dir ]) ) {\n\t\t\t\t\t\t\t\t\tif ( ofType ?\n\t\t\t\t\t\t\t\t\t\tnode.nodeName.toLowerCase() === name :\n\t\t\t\t\t\t\t\t\t\tnode.nodeType === 1 ) {\n\n\t\t\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t// Reverse direction for :only-* (if we haven't yet done so)\n\t\t\t\t\t\t\t\tstart = dir = type === \"only\" && !start && \"nextSibling\";\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tstart = [ forward ? parent.firstChild : parent.lastChild ];\n\n\t\t\t\t\t\t// non-xml :nth-child(...) stores cache data on `parent`\n\t\t\t\t\t\tif ( forward && useCache ) {\n\n\t\t\t\t\t\t\t// Seek `elem` from a previously-cached index\n\n\t\t\t\t\t\t\t// ...in a gzip-friendly way\n\t\t\t\t\t\t\tnode = parent;\n\t\t\t\t\t\t\touterCache = node[ expando ] || (node[ expando ] = {});\n\n\t\t\t\t\t\t\t// Support: IE <9 only\n\t\t\t\t\t\t\t// Defend against cloned attroperties (jQuery gh-1709)\n\t\t\t\t\t\t\tuniqueCache = outerCache[ node.uniqueID ] ||\n\t\t\t\t\t\t\t\t(outerCache[ node.uniqueID ] = {});\n\n\t\t\t\t\t\t\tcache = uniqueCache[ type ] || [];\n\t\t\t\t\t\t\tnodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];\n\t\t\t\t\t\t\tdiff = nodeIndex && cache[ 2 ];\n\t\t\t\t\t\t\tnode = nodeIndex && parent.childNodes[ nodeIndex ];\n\n\t\t\t\t\t\t\twhile ( (node = ++nodeIndex && node && node[ dir ] ||\n\n\t\t\t\t\t\t\t\t// Fallback to seeking `elem` from the start\n\t\t\t\t\t\t\t\t(diff = nodeIndex = 0) || start.pop()) ) {\n\n\t\t\t\t\t\t\t\t// When found, cache indexes on `parent` and break\n\t\t\t\t\t\t\t\tif ( node.nodeType === 1 && ++diff && node === elem ) {\n\t\t\t\t\t\t\t\t\tuniqueCache[ type ] = [ dirruns, nodeIndex, diff ];\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Use previously-cached element index if available\n\t\t\t\t\t\t\tif ( useCache ) {\n\t\t\t\t\t\t\t\t// ...in a gzip-friendly way\n\t\t\t\t\t\t\t\tnode = elem;\n\t\t\t\t\t\t\t\touterCache = node[ expando ] || (node[ expando ] = {});\n\n\t\t\t\t\t\t\t\t// Support: IE <9 only\n\t\t\t\t\t\t\t\t// Defend against cloned attroperties (jQuery gh-1709)\n\t\t\t\t\t\t\t\tuniqueCache = outerCache[ node.uniqueID ] ||\n\t\t\t\t\t\t\t\t\t(outerCache[ node.uniqueID ] = {});\n\n\t\t\t\t\t\t\t\tcache = uniqueCache[ type ] || [];\n\t\t\t\t\t\t\t\tnodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];\n\t\t\t\t\t\t\t\tdiff = nodeIndex;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// xml :nth-child(...)\n\t\t\t\t\t\t\t// or :nth-last-child(...) or :nth(-last)?-of-type(...)\n\t\t\t\t\t\t\tif ( diff === false ) {\n\t\t\t\t\t\t\t\t// Use the same loop as above to seek `elem` from the start\n\t\t\t\t\t\t\t\twhile ( (node = ++nodeIndex && node && node[ dir ] ||\n\t\t\t\t\t\t\t\t\t(diff = nodeIndex = 0) || start.pop()) ) {\n\n\t\t\t\t\t\t\t\t\tif ( ( ofType ?\n\t\t\t\t\t\t\t\t\t\tnode.nodeName.toLowerCase() === name :\n\t\t\t\t\t\t\t\t\t\tnode.nodeType === 1 ) &&\n\t\t\t\t\t\t\t\t\t\t++diff ) {\n\n\t\t\t\t\t\t\t\t\t\t// Cache the index of each encountered element\n\t\t\t\t\t\t\t\t\t\tif ( useCache ) {\n\t\t\t\t\t\t\t\t\t\t\touterCache = node[ expando ] || (node[ expando ] = {});\n\n\t\t\t\t\t\t\t\t\t\t\t// Support: IE <9 only\n\t\t\t\t\t\t\t\t\t\t\t// Defend against cloned attroperties (jQuery gh-1709)\n\t\t\t\t\t\t\t\t\t\t\tuniqueCache = outerCache[ node.uniqueID ] ||\n\t\t\t\t\t\t\t\t\t\t\t\t(outerCache[ node.uniqueID ] = {});\n\n\t\t\t\t\t\t\t\t\t\t\tuniqueCache[ type ] = [ dirruns, diff ];\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\tif ( node === elem ) {\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Incorporate the offset, then check against cycle size\n\t\t\t\t\t\tdiff -= last;\n\t\t\t\t\t\treturn diff === first || ( diff % first === 0 && diff / first >= 0 );\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t},\n\n\t\t\"PSEUDO\": function( pseudo, argument ) {\n\t\t\t// pseudo-class names are case-insensitive\n\t\t\t// http://www.w3.org/TR/selectors/#pseudo-classes\n\t\t\t// Prioritize by case sensitivity in case custom pseudos are added with uppercase letters\n\t\t\t// Remember that setFilters inherits from pseudos\n\t\t\tvar args,\n\t\t\t\tfn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||\n\t\t\t\t\tSizzle.error( \"unsupported pseudo: \" + pseudo );\n\n\t\t\t// The user may use createPseudo to indicate that\n\t\t\t// arguments are needed to create the filter function\n\t\t\t// just as Sizzle does\n\t\t\tif ( fn[ expando ] ) {\n\t\t\t\treturn fn( argument );\n\t\t\t}\n\n\t\t\t// But maintain support for old signatures\n\t\t\tif ( fn.length > 1 ) {\n\t\t\t\targs = [ pseudo, pseudo, \"\", argument ];\n\t\t\t\treturn Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?\n\t\t\t\t\tmarkFunction(function( seed, matches ) {\n\t\t\t\t\t\tvar idx,\n\t\t\t\t\t\t\tmatched = fn( seed, argument ),\n\t\t\t\t\t\t\ti = matched.length;\n\t\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\t\tidx = indexOf( seed, matched[i] );\n\t\t\t\t\t\t\tseed[ idx ] = !( matches[ idx ] = matched[i] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}) :\n\t\t\t\t\tfunction( elem ) {\n\t\t\t\t\t\treturn fn( elem, 0, args );\n\t\t\t\t\t};\n\t\t\t}\n\n\t\t\treturn fn;\n\t\t}\n\t},\n\n\tpseudos: {\n\t\t// Potentially complex pseudos\n\t\t\"not\": markFunction(function( selector ) {\n\t\t\t// Trim the selector passed to compile\n\t\t\t// to avoid treating leading and trailing\n\t\t\t// spaces as combinators\n\t\t\tvar input = [],\n\t\t\t\tresults = [],\n\t\t\t\tmatcher = compile( selector.replace( rtrim, \"$1\" ) );\n\n\t\t\treturn matcher[ expando ] ?\n\t\t\t\tmarkFunction(function( seed, matches, context, xml ) {\n\t\t\t\t\tvar elem,\n\t\t\t\t\t\tunmatched = matcher( seed, null, xml, [] ),\n\t\t\t\t\t\ti = seed.length;\n\n\t\t\t\t\t// Match elements unmatched by `matcher`\n\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\tif ( (elem = unmatched[i]) ) {\n\t\t\t\t\t\t\tseed[i] = !(matches[i] = elem);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}) :\n\t\t\t\tfunction( elem, context, xml ) {\n\t\t\t\t\tinput[0] = elem;\n\t\t\t\t\tmatcher( input, null, xml, results );\n\t\t\t\t\t// Don't keep the element (issue #299)\n\t\t\t\t\tinput[0] = null;\n\t\t\t\t\treturn !results.pop();\n\t\t\t\t};\n\t\t}),\n\n\t\t\"has\": markFunction(function( selector ) {\n\t\t\treturn function( elem ) {\n\t\t\t\treturn Sizzle( selector, elem ).length > 0;\n\t\t\t};\n\t\t}),\n\n\t\t\"contains\": markFunction(function( text ) {\n\t\t\ttext = text.replace( runescape, funescape );\n\t\t\treturn function( elem ) {\n\t\t\t\treturn ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;\n\t\t\t};\n\t\t}),\n\n\t\t// \"Whether an element is represented by a :lang() selector\n\t\t// is based solely on the element's language value\n\t\t// being equal to the identifier C,\n\t\t// or beginning with the identifier C immediately followed by \"-\".\n\t\t// The matching of C against the element's language value is performed case-insensitively.\n\t\t// The identifier C does not have to be a valid language name.\"\n\t\t// http://www.w3.org/TR/selectors/#lang-pseudo\n\t\t\"lang\": markFunction( function( lang ) {\n\t\t\t// lang value must be a valid identifier\n\t\t\tif ( !ridentifier.test(lang || \"\") ) {\n\t\t\t\tSizzle.error( \"unsupported lang: \" + lang );\n\t\t\t}\n\t\t\tlang = lang.replace( runescape, funescape ).toLowerCase();\n\t\t\treturn function( elem ) {\n\t\t\t\tvar elemLang;\n\t\t\t\tdo {\n\t\t\t\t\tif ( (elemLang = documentIsHTML ?\n\t\t\t\t\t\telem.lang :\n\t\t\t\t\t\telem.getAttribute(\"xml:lang\") || elem.getAttribute(\"lang\")) ) {\n\n\t\t\t\t\t\telemLang = elemLang.toLowerCase();\n\t\t\t\t\t\treturn elemLang === lang || elemLang.indexOf( lang + \"-\" ) === 0;\n\t\t\t\t\t}\n\t\t\t\t} while ( (elem = elem.parentNode) && elem.nodeType === 1 );\n\t\t\t\treturn false;\n\t\t\t};\n\t\t}),\n\n\t\t// Miscellaneous\n\t\t\"target\": function( elem ) {\n\t\t\tvar hash = window.location && window.location.hash;\n\t\t\treturn hash && hash.slice( 1 ) === elem.id;\n\t\t},\n\n\t\t\"root\": function( elem ) {\n\t\t\treturn elem === docElem;\n\t\t},\n\n\t\t\"focus\": function( elem ) {\n\t\t\treturn elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);\n\t\t},\n\n\t\t// Boolean properties\n\t\t\"enabled\": createDisabledPseudo( false ),\n\t\t\"disabled\": createDisabledPseudo( true ),\n\n\t\t\"checked\": function( elem ) {\n\t\t\t// In CSS3, :checked should return both checked and selected elements\n\t\t\t// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked\n\t\t\tvar nodeName = elem.nodeName.toLowerCase();\n\t\t\treturn (nodeName === \"input\" && !!elem.checked) || (nodeName === \"option\" && !!elem.selected);\n\t\t},\n\n\t\t\"selected\": function( elem ) {\n\t\t\t// Accessing this property makes selected-by-default\n\t\t\t// options in Safari work properly\n\t\t\tif ( elem.parentNode ) {\n\t\t\t\telem.parentNode.selectedIndex;\n\t\t\t}\n\n\t\t\treturn elem.selected === true;\n\t\t},\n\n\t\t// Contents\n\t\t\"empty\": function( elem ) {\n\t\t\t// http://www.w3.org/TR/selectors/#empty-pseudo\n\t\t\t// :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),\n\t\t\t//   but not by others (comment: 8; processing instruction: 7; etc.)\n\t\t\t// nodeType < 6 works because attributes (2) do not appear as children\n\t\t\tfor ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {\n\t\t\t\tif ( elem.nodeType < 6 ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t},\n\n\t\t\"parent\": function( elem ) {\n\t\t\treturn !Expr.pseudos[\"empty\"]( elem );\n\t\t},\n\n\t\t// Element/input types\n\t\t\"header\": function( elem ) {\n\t\t\treturn rheader.test( elem.nodeName );\n\t\t},\n\n\t\t\"input\": function( elem ) {\n\t\t\treturn rinputs.test( elem.nodeName );\n\t\t},\n\n\t\t\"button\": function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn name === \"input\" && elem.type === \"button\" || name === \"button\";\n\t\t},\n\n\t\t\"text\": function( elem ) {\n\t\t\tvar attr;\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" &&\n\t\t\t\telem.type === \"text\" &&\n\n\t\t\t\t// Support: IE<8\n\t\t\t\t// New HTML5 attribute values (e.g., \"search\") appear with elem.type === \"text\"\n\t\t\t\t( (attr = elem.getAttribute(\"type\")) == null || attr.toLowerCase() === \"text\" );\n\t\t},\n\n\t\t// Position-in-collection\n\t\t\"first\": createPositionalPseudo(function() {\n\t\t\treturn [ 0 ];\n\t\t}),\n\n\t\t\"last\": createPositionalPseudo(function( matchIndexes, length ) {\n\t\t\treturn [ length - 1 ];\n\t\t}),\n\n\t\t\"eq\": createPositionalPseudo(function( matchIndexes, length, argument ) {\n\t\t\treturn [ argument < 0 ? argument + length : argument ];\n\t\t}),\n\n\t\t\"even\": createPositionalPseudo(function( matchIndexes, length ) {\n\t\t\tvar i = 0;\n\t\t\tfor ( ; i < length; i += 2 ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t}),\n\n\t\t\"odd\": createPositionalPseudo(function( matchIndexes, length ) {\n\t\t\tvar i = 1;\n\t\t\tfor ( ; i < length; i += 2 ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t}),\n\n\t\t\"lt\": createPositionalPseudo(function( matchIndexes, length, argument ) {\n\t\t\tvar i = argument < 0 ? argument + length : argument;\n\t\t\tfor ( ; --i >= 0; ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t}),\n\n\t\t\"gt\": createPositionalPseudo(function( matchIndexes, length, argument ) {\n\t\t\tvar i = argument < 0 ? argument + length : argument;\n\t\t\tfor ( ; ++i < length; ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t})\n\t}\n};\n\nExpr.pseudos[\"nth\"] = Expr.pseudos[\"eq\"];\n\n// Add button/input type pseudos\nfor ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {\n\tExpr.pseudos[ i ] = createInputPseudo( i );\n}\nfor ( i in { submit: true, reset: true } ) {\n\tExpr.pseudos[ i ] = createButtonPseudo( i );\n}\n\n// Easy API for creating new setFilters\nfunction setFilters() {}\nsetFilters.prototype = Expr.filters = Expr.pseudos;\nExpr.setFilters = new setFilters();\n\ntokenize = Sizzle.tokenize = function( selector, parseOnly ) {\n\tvar matched, match, tokens, type,\n\t\tsoFar, groups, preFilters,\n\t\tcached = tokenCache[ selector + \" \" ];\n\n\tif ( cached ) {\n\t\treturn parseOnly ? 0 : cached.slice( 0 );\n\t}\n\n\tsoFar = selector;\n\tgroups = [];\n\tpreFilters = Expr.preFilter;\n\n\twhile ( soFar ) {\n\n\t\t// Comma and first run\n\t\tif ( !matched || (match = rcomma.exec( soFar )) ) {\n\t\t\tif ( match ) {\n\t\t\t\t// Don't consume trailing commas as valid\n\t\t\t\tsoFar = soFar.slice( match[0].length ) || soFar;\n\t\t\t}\n\t\t\tgroups.push( (tokens = []) );\n\t\t}\n\n\t\tmatched = false;\n\n\t\t// Combinators\n\t\tif ( (match = rcombinators.exec( soFar )) ) {\n\t\t\tmatched = match.shift();\n\t\t\ttokens.push({\n\t\t\t\tvalue: matched,\n\t\t\t\t// Cast descendant combinators to space\n\t\t\t\ttype: match[0].replace( rtrim, \" \" )\n\t\t\t});\n\t\t\tsoFar = soFar.slice( matched.length );\n\t\t}\n\n\t\t// Filters\n\t\tfor ( type in Expr.filter ) {\n\t\t\tif ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||\n\t\t\t\t(match = preFilters[ type ]( match ))) ) {\n\t\t\t\tmatched = match.shift();\n\t\t\t\ttokens.push({\n\t\t\t\t\tvalue: matched,\n\t\t\t\t\ttype: type,\n\t\t\t\t\tmatches: match\n\t\t\t\t});\n\t\t\t\tsoFar = soFar.slice( matched.length );\n\t\t\t}\n\t\t}\n\n\t\tif ( !matched ) {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t// Return the length of the invalid excess\n\t// if we're just parsing\n\t// Otherwise, throw an error or return tokens\n\treturn parseOnly ?\n\t\tsoFar.length :\n\t\tsoFar ?\n\t\t\tSizzle.error( selector ) :\n\t\t\t// Cache the tokens\n\t\t\ttokenCache( selector, groups ).slice( 0 );\n};\n\nfunction toSelector( tokens ) {\n\tvar i = 0,\n\t\tlen = tokens.length,\n\t\tselector = \"\";\n\tfor ( ; i < len; i++ ) {\n\t\tselector += tokens[i].value;\n\t}\n\treturn selector;\n}\n\nfunction addCombinator( matcher, combinator, base ) {\n\tvar dir = combinator.dir,\n\t\tskip = combinator.next,\n\t\tkey = skip || dir,\n\t\tcheckNonElements = base && key === \"parentNode\",\n\t\tdoneName = done++;\n\n\treturn combinator.first ?\n\t\t// Check against closest ancestor/preceding element\n\t\tfunction( elem, context, xml ) {\n\t\t\twhile ( (elem = elem[ dir ]) ) {\n\t\t\t\tif ( elem.nodeType === 1 || checkNonElements ) {\n\t\t\t\t\treturn matcher( elem, context, xml );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn false;\n\t\t} :\n\n\t\t// Check against all ancestor/preceding elements\n\t\tfunction( elem, context, xml ) {\n\t\t\tvar oldCache, uniqueCache, outerCache,\n\t\t\t\tnewCache = [ dirruns, doneName ];\n\n\t\t\t// We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching\n\t\t\tif ( xml ) {\n\t\t\t\twhile ( (elem = elem[ dir ]) ) {\n\t\t\t\t\tif ( elem.nodeType === 1 || checkNonElements ) {\n\t\t\t\t\t\tif ( matcher( elem, context, xml ) ) {\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\twhile ( (elem = elem[ dir ]) ) {\n\t\t\t\t\tif ( elem.nodeType === 1 || checkNonElements ) {\n\t\t\t\t\t\touterCache = elem[ expando ] || (elem[ expando ] = {});\n\n\t\t\t\t\t\t// Support: IE <9 only\n\t\t\t\t\t\t// Defend against cloned attroperties (jQuery gh-1709)\n\t\t\t\t\t\tuniqueCache = outerCache[ elem.uniqueID ] || (outerCache[ elem.uniqueID ] = {});\n\n\t\t\t\t\t\tif ( skip && skip === elem.nodeName.toLowerCase() ) {\n\t\t\t\t\t\t\telem = elem[ dir ] || elem;\n\t\t\t\t\t\t} else if ( (oldCache = uniqueCache[ key ]) &&\n\t\t\t\t\t\t\toldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {\n\n\t\t\t\t\t\t\t// Assign to newCache so results back-propagate to previous elements\n\t\t\t\t\t\t\treturn (newCache[ 2 ] = oldCache[ 2 ]);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Reuse newcache so results back-propagate to previous elements\n\t\t\t\t\t\t\tuniqueCache[ key ] = newCache;\n\n\t\t\t\t\t\t\t// A match means we're done; a fail means we have to keep checking\n\t\t\t\t\t\t\tif ( (newCache[ 2 ] = matcher( elem, context, xml )) ) {\n\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn false;\n\t\t};\n}\n\nfunction elementMatcher( matchers ) {\n\treturn matchers.length > 1 ?\n\t\tfunction( elem, context, xml ) {\n\t\t\tvar i = matchers.length;\n\t\t\twhile ( i-- ) {\n\t\t\t\tif ( !matchers[i]( elem, context, xml ) ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t} :\n\t\tmatchers[0];\n}\n\nfunction multipleContexts( selector, contexts, results ) {\n\tvar i = 0,\n\t\tlen = contexts.length;\n\tfor ( ; i < len; i++ ) {\n\t\tSizzle( selector, contexts[i], results );\n\t}\n\treturn results;\n}\n\nfunction condense( unmatched, map, filter, context, xml ) {\n\tvar elem,\n\t\tnewUnmatched = [],\n\t\ti = 0,\n\t\tlen = unmatched.length,\n\t\tmapped = map != null;\n\n\tfor ( ; i < len; i++ ) {\n\t\tif ( (elem = unmatched[i]) ) {\n\t\t\tif ( !filter || filter( elem, context, xml ) ) {\n\t\t\t\tnewUnmatched.push( elem );\n\t\t\t\tif ( mapped ) {\n\t\t\t\t\tmap.push( i );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn newUnmatched;\n}\n\nfunction setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {\n\tif ( postFilter && !postFilter[ expando ] ) {\n\t\tpostFilter = setMatcher( postFilter );\n\t}\n\tif ( postFinder && !postFinder[ expando ] ) {\n\t\tpostFinder = setMatcher( postFinder, postSelector );\n\t}\n\treturn markFunction(function( seed, results, context, xml ) {\n\t\tvar temp, i, elem,\n\t\t\tpreMap = [],\n\t\t\tpostMap = [],\n\t\t\tpreexisting = results.length,\n\n\t\t\t// Get initial elements from seed or context\n\t\t\telems = seed || multipleContexts( selector || \"*\", context.nodeType ? [ context ] : context, [] ),\n\n\t\t\t// Prefilter to get matcher input, preserving a map for seed-results synchronization\n\t\t\tmatcherIn = preFilter && ( seed || !selector ) ?\n\t\t\t\tcondense( elems, preMap, preFilter, context, xml ) :\n\t\t\t\telems,\n\n\t\t\tmatcherOut = matcher ?\n\t\t\t\t// If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,\n\t\t\t\tpostFinder || ( seed ? preFilter : preexisting || postFilter ) ?\n\n\t\t\t\t\t// ...intermediate processing is necessary\n\t\t\t\t\t[] :\n\n\t\t\t\t\t// ...otherwise use results directly\n\t\t\t\t\tresults :\n\t\t\t\tmatcherIn;\n\n\t\t// Find primary matches\n\t\tif ( matcher ) {\n\t\t\tmatcher( matcherIn, matcherOut, context, xml );\n\t\t}\n\n\t\t// Apply postFilter\n\t\tif ( postFilter ) {\n\t\t\ttemp = condense( matcherOut, postMap );\n\t\t\tpostFilter( temp, [], context, xml );\n\n\t\t\t// Un-match failing elements by moving them back to matcherIn\n\t\t\ti = temp.length;\n\t\t\twhile ( i-- ) {\n\t\t\t\tif ( (elem = temp[i]) ) {\n\t\t\t\t\tmatcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif ( seed ) {\n\t\t\tif ( postFinder || preFilter ) {\n\t\t\t\tif ( postFinder ) {\n\t\t\t\t\t// Get the final matcherOut by condensing this intermediate into postFinder contexts\n\t\t\t\t\ttemp = [];\n\t\t\t\t\ti = matcherOut.length;\n\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\tif ( (elem = matcherOut[i]) ) {\n\t\t\t\t\t\t\t// Restore matcherIn since elem is not yet a final match\n\t\t\t\t\t\t\ttemp.push( (matcherIn[i] = elem) );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tpostFinder( null, (matcherOut = []), temp, xml );\n\t\t\t\t}\n\n\t\t\t\t// Move matched elements from seed to results to keep them synchronized\n\t\t\t\ti = matcherOut.length;\n\t\t\t\twhile ( i-- ) {\n\t\t\t\t\tif ( (elem = matcherOut[i]) &&\n\t\t\t\t\t\t(temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) {\n\n\t\t\t\t\t\tseed[temp] = !(results[temp] = elem);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t// Add elements to results, through postFinder if defined\n\t\t} else {\n\t\t\tmatcherOut = condense(\n\t\t\t\tmatcherOut === results ?\n\t\t\t\t\tmatcherOut.splice( preexisting, matcherOut.length ) :\n\t\t\t\t\tmatcherOut\n\t\t\t);\n\t\t\tif ( postFinder ) {\n\t\t\t\tpostFinder( null, results, matcherOut, xml );\n\t\t\t} else {\n\t\t\t\tpush.apply( results, matcherOut );\n\t\t\t}\n\t\t}\n\t});\n}\n\nfunction matcherFromTokens( tokens ) {\n\tvar checkContext, matcher, j,\n\t\tlen = tokens.length,\n\t\tleadingRelative = Expr.relative[ tokens[0].type ],\n\t\timplicitRelative = leadingRelative || Expr.relative[\" \"],\n\t\ti = leadingRelative ? 1 : 0,\n\n\t\t// The foundational matcher ensures that elements are reachable from top-level context(s)\n\t\tmatchContext = addCombinator( function( elem ) {\n\t\t\treturn elem === checkContext;\n\t\t}, implicitRelative, true ),\n\t\tmatchAnyContext = addCombinator( function( elem ) {\n\t\t\treturn indexOf( checkContext, elem ) > -1;\n\t\t}, implicitRelative, true ),\n\t\tmatchers = [ function( elem, context, xml ) {\n\t\t\tvar ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || (\n\t\t\t\t(checkContext = context).nodeType ?\n\t\t\t\t\tmatchContext( elem, context, xml ) :\n\t\t\t\t\tmatchAnyContext( elem, context, xml ) );\n\t\t\t// Avoid hanging onto element (issue #299)\n\t\t\tcheckContext = null;\n\t\t\treturn ret;\n\t\t} ];\n\n\tfor ( ; i < len; i++ ) {\n\t\tif ( (matcher = Expr.relative[ tokens[i].type ]) ) {\n\t\t\tmatchers = [ addCombinator(elementMatcher( matchers ), matcher) ];\n\t\t} else {\n\t\t\tmatcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );\n\n\t\t\t// Return special upon seeing a positional matcher\n\t\t\tif ( matcher[ expando ] ) {\n\t\t\t\t// Find the next relative operator (if any) for proper handling\n\t\t\t\tj = ++i;\n\t\t\t\tfor ( ; j < len; j++ ) {\n\t\t\t\t\tif ( Expr.relative[ tokens[j].type ] ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn setMatcher(\n\t\t\t\t\ti > 1 && elementMatcher( matchers ),\n\t\t\t\t\ti > 1 && toSelector(\n\t\t\t\t\t\t// If the preceding token was a descendant combinator, insert an implicit any-element `*`\n\t\t\t\t\t\ttokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === \" \" ? \"*\" : \"\" })\n\t\t\t\t\t).replace( rtrim, \"$1\" ),\n\t\t\t\t\tmatcher,\n\t\t\t\t\ti < j && matcherFromTokens( tokens.slice( i, j ) ),\n\t\t\t\t\tj < len && matcherFromTokens( (tokens = tokens.slice( j )) ),\n\t\t\t\t\tj < len && toSelector( tokens )\n\t\t\t\t);\n\t\t\t}\n\t\t\tmatchers.push( matcher );\n\t\t}\n\t}\n\n\treturn elementMatcher( matchers );\n}\n\nfunction matcherFromGroupMatchers( elementMatchers, setMatchers ) {\n\tvar bySet = setMatchers.length > 0,\n\t\tbyElement = elementMatchers.length > 0,\n\t\tsuperMatcher = function( seed, context, xml, results, outermost ) {\n\t\t\tvar elem, j, matcher,\n\t\t\t\tmatchedCount = 0,\n\t\t\t\ti = \"0\",\n\t\t\t\tunmatched = seed && [],\n\t\t\t\tsetMatched = [],\n\t\t\t\tcontextBackup = outermostContext,\n\t\t\t\t// We must always have either seed elements or outermost context\n\t\t\t\telems = seed || byElement && Expr.find[\"TAG\"]( \"*\", outermost ),\n\t\t\t\t// Use integer dirruns iff this is the outermost matcher\n\t\t\t\tdirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),\n\t\t\t\tlen = elems.length;\n\n\t\t\tif ( outermost ) {\n\t\t\t\toutermostContext = context === document || context || outermost;\n\t\t\t}\n\n\t\t\t// Add elements passing elementMatchers directly to results\n\t\t\t// Support: IE<9, Safari\n\t\t\t// Tolerate NodeList properties (IE: \"length\"; Safari: <number>) matching elements by id\n\t\t\tfor ( ; i !== len && (elem = elems[i]) != null; i++ ) {\n\t\t\t\tif ( byElement && elem ) {\n\t\t\t\t\tj = 0;\n\t\t\t\t\tif ( !context && elem.ownerDocument !== document ) {\n\t\t\t\t\t\tsetDocument( elem );\n\t\t\t\t\t\txml = !documentIsHTML;\n\t\t\t\t\t}\n\t\t\t\t\twhile ( (matcher = elementMatchers[j++]) ) {\n\t\t\t\t\t\tif ( matcher( elem, context || document, xml) ) {\n\t\t\t\t\t\t\tresults.push( elem );\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ( outermost ) {\n\t\t\t\t\t\tdirruns = dirrunsUnique;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Track unmatched elements for set filters\n\t\t\t\tif ( bySet ) {\n\t\t\t\t\t// They will have gone through all possible matchers\n\t\t\t\t\tif ( (elem = !matcher && elem) ) {\n\t\t\t\t\t\tmatchedCount--;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Lengthen the array for every element, matched or not\n\t\t\t\t\tif ( seed ) {\n\t\t\t\t\t\tunmatched.push( elem );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// `i` is now the count of elements visited above, and adding it to `matchedCount`\n\t\t\t// makes the latter nonnegative.\n\t\t\tmatchedCount += i;\n\n\t\t\t// Apply set filters to unmatched elements\n\t\t\t// NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount`\n\t\t\t// equals `i`), unless we didn't visit _any_ elements in the above loop because we have\n\t\t\t// no element matchers and no seed.\n\t\t\t// Incrementing an initially-string \"0\" `i` allows `i` to remain a string only in that\n\t\t\t// case, which will result in a \"00\" `matchedCount` that differs from `i` but is also\n\t\t\t// numerically zero.\n\t\t\tif ( bySet && i !== matchedCount ) {\n\t\t\t\tj = 0;\n\t\t\t\twhile ( (matcher = setMatchers[j++]) ) {\n\t\t\t\t\tmatcher( unmatched, setMatched, context, xml );\n\t\t\t\t}\n\n\t\t\t\tif ( seed ) {\n\t\t\t\t\t// Reintegrate element matches to eliminate the need for sorting\n\t\t\t\t\tif ( matchedCount > 0 ) {\n\t\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\t\tif ( !(unmatched[i] || setMatched[i]) ) {\n\t\t\t\t\t\t\t\tsetMatched[i] = pop.call( results );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Discard index placeholder values to get only actual matches\n\t\t\t\t\tsetMatched = condense( setMatched );\n\t\t\t\t}\n\n\t\t\t\t// Add matches to results\n\t\t\t\tpush.apply( results, setMatched );\n\n\t\t\t\t// Seedless set matches succeeding multiple successful matchers stipulate sorting\n\t\t\t\tif ( outermost && !seed && setMatched.length > 0 &&\n\t\t\t\t\t( matchedCount + setMatchers.length ) > 1 ) {\n\n\t\t\t\t\tSizzle.uniqueSort( results );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Override manipulation of globals by nested matchers\n\t\t\tif ( outermost ) {\n\t\t\t\tdirruns = dirrunsUnique;\n\t\t\t\toutermostContext = contextBackup;\n\t\t\t}\n\n\t\t\treturn unmatched;\n\t\t};\n\n\treturn bySet ?\n\t\tmarkFunction( superMatcher ) :\n\t\tsuperMatcher;\n}\n\ncompile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) {\n\tvar i,\n\t\tsetMatchers = [],\n\t\telementMatchers = [],\n\t\tcached = compilerCache[ selector + \" \" ];\n\n\tif ( !cached ) {\n\t\t// Generate a function of recursive functions that can be used to check each element\n\t\tif ( !match ) {\n\t\t\tmatch = tokenize( selector );\n\t\t}\n\t\ti = match.length;\n\t\twhile ( i-- ) {\n\t\t\tcached = matcherFromTokens( match[i] );\n\t\t\tif ( cached[ expando ] ) {\n\t\t\t\tsetMatchers.push( cached );\n\t\t\t} else {\n\t\t\t\telementMatchers.push( cached );\n\t\t\t}\n\t\t}\n\n\t\t// Cache the compiled function\n\t\tcached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );\n\n\t\t// Save selector and tokenization\n\t\tcached.selector = selector;\n\t}\n\treturn cached;\n};\n\n/**\n * A low-level selection function that works with Sizzle's compiled\n *  selector functions\n * @param {String|Function} selector A selector or a pre-compiled\n *  selector function built with Sizzle.compile\n * @param {Element} context\n * @param {Array} [results]\n * @param {Array} [seed] A set of elements to match against\n */\nselect = Sizzle.select = function( selector, context, results, seed ) {\n\tvar i, tokens, token, type, find,\n\t\tcompiled = typeof selector === \"function\" && selector,\n\t\tmatch = !seed && tokenize( (selector = compiled.selector || selector) );\n\n\tresults = results || [];\n\n\t// Try to minimize operations if there is only one selector in the list and no seed\n\t// (the latter of which guarantees us context)\n\tif ( match.length === 1 ) {\n\n\t\t// Reduce context if the leading compound selector is an ID\n\t\ttokens = match[0] = match[0].slice( 0 );\n\t\tif ( tokens.length > 2 && (token = tokens[0]).type === \"ID\" &&\n\t\t\t\tcontext.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[1].type ] ) {\n\n\t\t\tcontext = ( Expr.find[\"ID\"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];\n\t\t\tif ( !context ) {\n\t\t\t\treturn results;\n\n\t\t\t// Precompiled matchers will still verify ancestry, so step up a level\n\t\t\t} else if ( compiled ) {\n\t\t\t\tcontext = context.parentNode;\n\t\t\t}\n\n\t\t\tselector = selector.slice( tokens.shift().value.length );\n\t\t}\n\n\t\t// Fetch a seed set for right-to-left matching\n\t\ti = matchExpr[\"needsContext\"].test( selector ) ? 0 : tokens.length;\n\t\twhile ( i-- ) {\n\t\t\ttoken = tokens[i];\n\n\t\t\t// Abort if we hit a combinator\n\t\t\tif ( Expr.relative[ (type = token.type) ] ) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif ( (find = Expr.find[ type ]) ) {\n\t\t\t\t// Search, expanding context for leading sibling combinators\n\t\t\t\tif ( (seed = find(\n\t\t\t\t\ttoken.matches[0].replace( runescape, funescape ),\n\t\t\t\t\trsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context\n\t\t\t\t)) ) {\n\n\t\t\t\t\t// If seed is empty or no tokens remain, we can return early\n\t\t\t\t\ttokens.splice( i, 1 );\n\t\t\t\t\tselector = seed.length && toSelector( tokens );\n\t\t\t\t\tif ( !selector ) {\n\t\t\t\t\t\tpush.apply( results, seed );\n\t\t\t\t\t\treturn results;\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Compile and execute a filtering function if one is not provided\n\t// Provide `match` to avoid retokenization if we modified the selector above\n\t( compiled || compile( selector, match ) )(\n\t\tseed,\n\t\tcontext,\n\t\t!documentIsHTML,\n\t\tresults,\n\t\t!context || rsibling.test( selector ) && testContext( context.parentNode ) || context\n\t);\n\treturn results;\n};\n\n// One-time assignments\n\n// Sort stability\nsupport.sortStable = expando.split(\"\").sort( sortOrder ).join(\"\") === expando;\n\n// Support: Chrome 14-35+\n// Always assume duplicates if they aren't passed to the comparison function\nsupport.detectDuplicates = !!hasDuplicate;\n\n// Initialize against the default document\nsetDocument();\n\n// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)\n// Detached nodes confoundingly follow *each other*\nsupport.sortDetached = assert(function( el ) {\n\t// Should return 1, but returns 4 (following)\n\treturn el.compareDocumentPosition( document.createElement(\"fieldset\") ) & 1;\n});\n\n// Support: IE<8\n// Prevent attribute/property \"interpolation\"\n// https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx\nif ( !assert(function( el ) {\n\tel.innerHTML = \"<a href='#'></a>\";\n\treturn el.firstChild.getAttribute(\"href\") === \"#\" ;\n}) ) {\n\taddHandle( \"type|href|height|width\", function( elem, name, isXML ) {\n\t\tif ( !isXML ) {\n\t\t\treturn elem.getAttribute( name, name.toLowerCase() === \"type\" ? 1 : 2 );\n\t\t}\n\t});\n}\n\n// Support: IE<9\n// Use defaultValue in place of getAttribute(\"value\")\nif ( !support.attributes || !assert(function( el ) {\n\tel.innerHTML = \"<input/>\";\n\tel.firstChild.setAttribute( \"value\", \"\" );\n\treturn el.firstChild.getAttribute( \"value\" ) === \"\";\n}) ) {\n\taddHandle( \"value\", function( elem, name, isXML ) {\n\t\tif ( !isXML && elem.nodeName.toLowerCase() === \"input\" ) {\n\t\t\treturn elem.defaultValue;\n\t\t}\n\t});\n}\n\n// Support: IE<9\n// Use getAttributeNode to fetch booleans when getAttribute lies\nif ( !assert(function( el ) {\n\treturn el.getAttribute(\"disabled\") == null;\n}) ) {\n\taddHandle( booleans, function( elem, name, isXML ) {\n\t\tvar val;\n\t\tif ( !isXML ) {\n\t\t\treturn elem[ name ] === true ? name.toLowerCase() :\n\t\t\t\t\t(val = elem.getAttributeNode( name )) && val.specified ?\n\t\t\t\t\tval.value :\n\t\t\t\tnull;\n\t\t}\n\t});\n}\n\nreturn Sizzle;\n\n})( window );\n\n\n\njQuery.find = Sizzle;\njQuery.expr = Sizzle.selectors;\n\n// Deprecated\njQuery.expr[ \":\" ] = jQuery.expr.pseudos;\njQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort;\njQuery.text = Sizzle.getText;\njQuery.isXMLDoc = Sizzle.isXML;\njQuery.contains = Sizzle.contains;\njQuery.escapeSelector = Sizzle.escape;\n\n\n\n\nvar dir = function( elem, dir, until ) {\n\tvar matched = [],\n\t\ttruncate = until !== undefined;\n\n\twhile ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) {\n\t\tif ( elem.nodeType === 1 ) {\n\t\t\tif ( truncate && jQuery( elem ).is( until ) ) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tmatched.push( elem );\n\t\t}\n\t}\n\treturn matched;\n};\n\n\nvar siblings = function( n, elem ) {\n\tvar matched = [];\n\n\tfor ( ; n; n = n.nextSibling ) {\n\t\tif ( n.nodeType === 1 && n !== elem ) {\n\t\t\tmatched.push( n );\n\t\t}\n\t}\n\n\treturn matched;\n};\n\n\nvar rneedsContext = jQuery.expr.match.needsContext;\n\n\n\nfunction nodeName( elem, name ) {\n\n  return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();\n\n};\nvar rsingleTag = ( /^<([a-z][^\\/\\0>:\\x20\\t\\r\\n\\f]*)[\\x20\\t\\r\\n\\f]*\\/?>(?:<\\/\\1>|)$/i );\n\n\n\n// Implement the identical functionality for filter and not\nfunction winnow( elements, qualifier, not ) {\n\tif ( isFunction( qualifier ) ) {\n\t\treturn jQuery.grep( elements, function( elem, i ) {\n\t\t\treturn !!qualifier.call( elem, i, elem ) !== not;\n\t\t} );\n\t}\n\n\t// Single element\n\tif ( qualifier.nodeType ) {\n\t\treturn jQuery.grep( elements, function( elem ) {\n\t\t\treturn ( elem === qualifier ) !== not;\n\t\t} );\n\t}\n\n\t// Arraylike of elements (jQuery, arguments, Array)\n\tif ( typeof qualifier !== \"string\" ) {\n\t\treturn jQuery.grep( elements, function( elem ) {\n\t\t\treturn ( indexOf.call( qualifier, elem ) > -1 ) !== not;\n\t\t} );\n\t}\n\n\t// Filtered directly for both simple and complex selectors\n\treturn jQuery.filter( qualifier, elements, not );\n}\n\njQuery.filter = function( expr, elems, not ) {\n\tvar elem = elems[ 0 ];\n\n\tif ( not ) {\n\t\texpr = \":not(\" + expr + \")\";\n\t}\n\n\tif ( elems.length === 1 && elem.nodeType === 1 ) {\n\t\treturn jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [];\n\t}\n\n\treturn jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) {\n\t\treturn elem.nodeType === 1;\n\t} ) );\n};\n\njQuery.fn.extend( {\n\tfind: function( selector ) {\n\t\tvar i, ret,\n\t\t\tlen = this.length,\n\t\t\tself = this;\n\n\t\tif ( typeof selector !== \"string\" ) {\n\t\t\treturn this.pushStack( jQuery( selector ).filter( function() {\n\t\t\t\tfor ( i = 0; i < len; i++ ) {\n\t\t\t\t\tif ( jQuery.contains( self[ i ], this ) ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} ) );\n\t\t}\n\n\t\tret = this.pushStack( [] );\n\n\t\tfor ( i = 0; i < len; i++ ) {\n\t\t\tjQuery.find( selector, self[ i ], ret );\n\t\t}\n\n\t\treturn len > 1 ? jQuery.uniqueSort( ret ) : ret;\n\t},\n\tfilter: function( selector ) {\n\t\treturn this.pushStack( winnow( this, selector || [], false ) );\n\t},\n\tnot: function( selector ) {\n\t\treturn this.pushStack( winnow( this, selector || [], true ) );\n\t},\n\tis: function( selector ) {\n\t\treturn !!winnow(\n\t\t\tthis,\n\n\t\t\t// If this is a positional/relative selector, check membership in the returned set\n\t\t\t// so $(\"p:first\").is(\"p:last\") won't return true for a doc with two \"p\".\n\t\t\ttypeof selector === \"string\" && rneedsContext.test( selector ) ?\n\t\t\t\tjQuery( selector ) :\n\t\t\t\tselector || [],\n\t\t\tfalse\n\t\t).length;\n\t}\n} );\n\n\n// Initialize a jQuery object\n\n\n// A central reference to the root jQuery(document)\nvar rootjQuery,\n\n\t// A simple way to check for HTML strings\n\t// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)\n\t// Strict HTML recognition (#11290: must start with <)\n\t// Shortcut simple #id case for speed\n\trquickExpr = /^(?:\\s*(<[\\w\\W]+>)[^>]*|#([\\w-]+))$/,\n\n\tinit = jQuery.fn.init = function( selector, context, root ) {\n\t\tvar match, elem;\n\n\t\t// HANDLE: $(\"\"), $(null), $(undefined), $(false)\n\t\tif ( !selector ) {\n\t\t\treturn this;\n\t\t}\n\n\t\t// Method init() accepts an alternate rootjQuery\n\t\t// so migrate can support jQuery.sub (gh-2101)\n\t\troot = root || rootjQuery;\n\n\t\t// Handle HTML strings\n\t\tif ( typeof selector === \"string\" ) {\n\t\t\tif ( selector[ 0 ] === \"<\" &&\n\t\t\t\tselector[ selector.length - 1 ] === \">\" &&\n\t\t\t\tselector.length >= 3 ) {\n\n\t\t\t\t// Assume that strings that start and end with <> are HTML and skip the regex check\n\t\t\t\tmatch = [ null, selector, null ];\n\n\t\t\t} else {\n\t\t\t\tmatch = rquickExpr.exec( selector );\n\t\t\t}\n\n\t\t\t// Match html or make sure no context is specified for #id\n\t\t\tif ( match && ( match[ 1 ] || !context ) ) {\n\n\t\t\t\t// HANDLE: $(html) -> $(array)\n\t\t\t\tif ( match[ 1 ] ) {\n\t\t\t\t\tcontext = context instanceof jQuery ? context[ 0 ] : context;\n\n\t\t\t\t\t// Option to run scripts is true for back-compat\n\t\t\t\t\t// Intentionally let the error be thrown if parseHTML is not present\n\t\t\t\t\tjQuery.merge( this, jQuery.parseHTML(\n\t\t\t\t\t\tmatch[ 1 ],\n\t\t\t\t\t\tcontext && context.nodeType ? context.ownerDocument || context : document,\n\t\t\t\t\t\ttrue\n\t\t\t\t\t) );\n\n\t\t\t\t\t// HANDLE: $(html, props)\n\t\t\t\t\tif ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) {\n\t\t\t\t\t\tfor ( match in context ) {\n\n\t\t\t\t\t\t\t// Properties of context are called as methods if possible\n\t\t\t\t\t\t\tif ( isFunction( this[ match ] ) ) {\n\t\t\t\t\t\t\t\tthis[ match ]( context[ match ] );\n\n\t\t\t\t\t\t\t// ...and otherwise set as attributes\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tthis.attr( match, context[ match ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn this;\n\n\t\t\t\t// HANDLE: $(#id)\n\t\t\t\t} else {\n\t\t\t\t\telem = document.getElementById( match[ 2 ] );\n\n\t\t\t\t\tif ( elem ) {\n\n\t\t\t\t\t\t// Inject the element directly into the jQuery object\n\t\t\t\t\t\tthis[ 0 ] = elem;\n\t\t\t\t\t\tthis.length = 1;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\n\t\t\t// HANDLE: $(expr, $(...))\n\t\t\t} else if ( !context || context.jquery ) {\n\t\t\t\treturn ( context || root ).find( selector );\n\n\t\t\t// HANDLE: $(expr, context)\n\t\t\t// (which is just equivalent to: $(context).find(expr)\n\t\t\t} else {\n\t\t\t\treturn this.constructor( context ).find( selector );\n\t\t\t}\n\n\t\t// HANDLE: $(DOMElement)\n\t\t} else if ( selector.nodeType ) {\n\t\t\tthis[ 0 ] = selector;\n\t\t\tthis.length = 1;\n\t\t\treturn this;\n\n\t\t// HANDLE: $(function)\n\t\t// Shortcut for document ready\n\t\t} else if ( isFunction( selector ) ) {\n\t\t\treturn root.ready !== undefined ?\n\t\t\t\troot.ready( selector ) :\n\n\t\t\t\t// Execute immediately if ready is not present\n\t\t\t\tselector( jQuery );\n\t\t}\n\n\t\treturn jQuery.makeArray( selector, this );\n\t};\n\n// Give the init function the jQuery prototype for later instantiation\ninit.prototype = jQuery.fn;\n\n// Initialize central reference\nrootjQuery = jQuery( document );\n\n\nvar rparentsprev = /^(?:parents|prev(?:Until|All))/,\n\n\t// Methods guaranteed to produce a unique set when starting from a unique set\n\tguaranteedUnique = {\n\t\tchildren: true,\n\t\tcontents: true,\n\t\tnext: true,\n\t\tprev: true\n\t};\n\njQuery.fn.extend( {\n\thas: function( target ) {\n\t\tvar targets = jQuery( target, this ),\n\t\t\tl = targets.length;\n\n\t\treturn this.filter( function() {\n\t\t\tvar i = 0;\n\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\tif ( jQuery.contains( this, targets[ i ] ) ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\t},\n\n\tclosest: function( selectors, context ) {\n\t\tvar cur,\n\t\t\ti = 0,\n\t\t\tl = this.length,\n\t\t\tmatched = [],\n\t\t\ttargets = typeof selectors !== \"string\" && jQuery( selectors );\n\n\t\t// Positional selectors never match, since there's no _selection_ context\n\t\tif ( !rneedsContext.test( selectors ) ) {\n\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\tfor ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) {\n\n\t\t\t\t\t// Always skip document fragments\n\t\t\t\t\tif ( cur.nodeType < 11 && ( targets ?\n\t\t\t\t\t\ttargets.index( cur ) > -1 :\n\n\t\t\t\t\t\t// Don't pass non-elements to Sizzle\n\t\t\t\t\t\tcur.nodeType === 1 &&\n\t\t\t\t\t\t\tjQuery.find.matchesSelector( cur, selectors ) ) ) {\n\n\t\t\t\t\t\tmatched.push( cur );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched );\n\t},\n\n\t// Determine the position of an element within the set\n\tindex: function( elem ) {\n\n\t\t// No argument, return index in parent\n\t\tif ( !elem ) {\n\t\t\treturn ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1;\n\t\t}\n\n\t\t// Index in selector\n\t\tif ( typeof elem === \"string\" ) {\n\t\t\treturn indexOf.call( jQuery( elem ), this[ 0 ] );\n\t\t}\n\n\t\t// Locate the position of the desired element\n\t\treturn indexOf.call( this,\n\n\t\t\t// If it receives a jQuery object, the first element is used\n\t\t\telem.jquery ? elem[ 0 ] : elem\n\t\t);\n\t},\n\n\tadd: function( selector, context ) {\n\t\treturn this.pushStack(\n\t\t\tjQuery.uniqueSort(\n\t\t\t\tjQuery.merge( this.get(), jQuery( selector, context ) )\n\t\t\t)\n\t\t);\n\t},\n\n\taddBack: function( selector ) {\n\t\treturn this.add( selector == null ?\n\t\t\tthis.prevObject : this.prevObject.filter( selector )\n\t\t);\n\t}\n} );\n\nfunction sibling( cur, dir ) {\n\twhile ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {}\n\treturn cur;\n}\n\njQuery.each( {\n\tparent: function( elem ) {\n\t\tvar parent = elem.parentNode;\n\t\treturn parent && parent.nodeType !== 11 ? parent : null;\n\t},\n\tparents: function( elem ) {\n\t\treturn dir( elem, \"parentNode\" );\n\t},\n\tparentsUntil: function( elem, i, until ) {\n\t\treturn dir( elem, \"parentNode\", until );\n\t},\n\tnext: function( elem ) {\n\t\treturn sibling( elem, \"nextSibling\" );\n\t},\n\tprev: function( elem ) {\n\t\treturn sibling( elem, \"previousSibling\" );\n\t},\n\tnextAll: function( elem ) {\n\t\treturn dir( elem, \"nextSibling\" );\n\t},\n\tprevAll: function( elem ) {\n\t\treturn dir( elem, \"previousSibling\" );\n\t},\n\tnextUntil: function( elem, i, until ) {\n\t\treturn dir( elem, \"nextSibling\", until );\n\t},\n\tprevUntil: function( elem, i, until ) {\n\t\treturn dir( elem, \"previousSibling\", until );\n\t},\n\tsiblings: function( elem ) {\n\t\treturn siblings( ( elem.parentNode || {} ).firstChild, elem );\n\t},\n\tchildren: function( elem ) {\n\t\treturn siblings( elem.firstChild );\n\t},\n\tcontents: function( elem ) {\n        if ( nodeName( elem, \"iframe\" ) ) {\n            return elem.contentDocument;\n        }\n\n        // Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only\n        // Treat the template element as a regular one in browsers that\n        // don't support it.\n        if ( nodeName( elem, \"template\" ) ) {\n            elem = elem.content || elem;\n        }\n\n        return jQuery.merge( [], elem.childNodes );\n\t}\n}, function( name, fn ) {\n\tjQuery.fn[ name ] = function( until, selector ) {\n\t\tvar matched = jQuery.map( this, fn, until );\n\n\t\tif ( name.slice( -5 ) !== \"Until\" ) {\n\t\t\tselector = until;\n\t\t}\n\n\t\tif ( selector && typeof selector === \"string\" ) {\n\t\t\tmatched = jQuery.filter( selector, matched );\n\t\t}\n\n\t\tif ( this.length > 1 ) {\n\n\t\t\t// Remove duplicates\n\t\t\tif ( !guaranteedUnique[ name ] ) {\n\t\t\t\tjQuery.uniqueSort( matched );\n\t\t\t}\n\n\t\t\t// Reverse order for parents* and prev-derivatives\n\t\t\tif ( rparentsprev.test( name ) ) {\n\t\t\t\tmatched.reverse();\n\t\t\t}\n\t\t}\n\n\t\treturn this.pushStack( matched );\n\t};\n} );\nvar rnothtmlwhite = ( /[^\\x20\\t\\r\\n\\f]+/g );\n\n\n\n// Convert String-formatted options into Object-formatted ones\nfunction createOptions( options ) {\n\tvar object = {};\n\tjQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) {\n\t\tobject[ flag ] = true;\n\t} );\n\treturn object;\n}\n\n/*\n * Create a callback list using the following parameters:\n *\n *\toptions: an optional list of space-separated options that will change how\n *\t\t\tthe callback list behaves or a more traditional option object\n *\n * By default a callback list will act like an event callback list and can be\n * \"fired\" multiple times.\n *\n * Possible options:\n *\n *\tonce:\t\t\twill ensure the callback list can only be fired once (like a Deferred)\n *\n *\tmemory:\t\t\twill keep track of previous values and will call any callback added\n *\t\t\t\t\tafter the list has been fired right away with the latest \"memorized\"\n *\t\t\t\t\tvalues (like a Deferred)\n *\n *\tunique:\t\t\twill ensure a callback can only be added once (no duplicate in the list)\n *\n *\tstopOnFalse:\tinterrupt callings when a callback returns false\n *\n */\njQuery.Callbacks = function( options ) {\n\n\t// Convert options from String-formatted to Object-formatted if needed\n\t// (we check in cache first)\n\toptions = typeof options === \"string\" ?\n\t\tcreateOptions( options ) :\n\t\tjQuery.extend( {}, options );\n\n\tvar // Flag to know if list is currently firing\n\t\tfiring,\n\n\t\t// Last fire value for non-forgettable lists\n\t\tmemory,\n\n\t\t// Flag to know if list was already fired\n\t\tfired,\n\n\t\t// Flag to prevent firing\n\t\tlocked,\n\n\t\t// Actual callback list\n\t\tlist = [],\n\n\t\t// Queue of execution data for repeatable lists\n\t\tqueue = [],\n\n\t\t// Index of currently firing callback (modified by add/remove as needed)\n\t\tfiringIndex = -1,\n\n\t\t// Fire callbacks\n\t\tfire = function() {\n\n\t\t\t// Enforce single-firing\n\t\t\tlocked = locked || options.once;\n\n\t\t\t// Execute callbacks for all pending executions,\n\t\t\t// respecting firingIndex overrides and runtime changes\n\t\t\tfired = firing = true;\n\t\t\tfor ( ; queue.length; firingIndex = -1 ) {\n\t\t\t\tmemory = queue.shift();\n\t\t\t\twhile ( ++firingIndex < list.length ) {\n\n\t\t\t\t\t// Run callback and check for early termination\n\t\t\t\t\tif ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false &&\n\t\t\t\t\t\toptions.stopOnFalse ) {\n\n\t\t\t\t\t\t// Jump to end and forget the data so .add doesn't re-fire\n\t\t\t\t\t\tfiringIndex = list.length;\n\t\t\t\t\t\tmemory = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Forget the data if we're done with it\n\t\t\tif ( !options.memory ) {\n\t\t\t\tmemory = false;\n\t\t\t}\n\n\t\t\tfiring = false;\n\n\t\t\t// Clean up if we're done firing for good\n\t\t\tif ( locked ) {\n\n\t\t\t\t// Keep an empty list if we have data for future add calls\n\t\t\t\tif ( memory ) {\n\t\t\t\t\tlist = [];\n\n\t\t\t\t// Otherwise, this object is spent\n\t\t\t\t} else {\n\t\t\t\t\tlist = \"\";\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t// Actual Callbacks object\n\t\tself = {\n\n\t\t\t// Add a callback or a collection of callbacks to the list\n\t\t\tadd: function() {\n\t\t\t\tif ( list ) {\n\n\t\t\t\t\t// If we have memory from a past run, we should fire after adding\n\t\t\t\t\tif ( memory && !firing ) {\n\t\t\t\t\t\tfiringIndex = list.length - 1;\n\t\t\t\t\t\tqueue.push( memory );\n\t\t\t\t\t}\n\n\t\t\t\t\t( function add( args ) {\n\t\t\t\t\t\tjQuery.each( args, function( _, arg ) {\n\t\t\t\t\t\t\tif ( isFunction( arg ) ) {\n\t\t\t\t\t\t\t\tif ( !options.unique || !self.has( arg ) ) {\n\t\t\t\t\t\t\t\t\tlist.push( arg );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else if ( arg && arg.length && toType( arg ) !== \"string\" ) {\n\n\t\t\t\t\t\t\t\t// Inspect recursively\n\t\t\t\t\t\t\t\tadd( arg );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} );\n\t\t\t\t\t} )( arguments );\n\n\t\t\t\t\tif ( memory && !firing ) {\n\t\t\t\t\t\tfire();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\n\t\t\t// Remove a callback from the list\n\t\t\tremove: function() {\n\t\t\t\tjQuery.each( arguments, function( _, arg ) {\n\t\t\t\t\tvar index;\n\t\t\t\t\twhile ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {\n\t\t\t\t\t\tlist.splice( index, 1 );\n\n\t\t\t\t\t\t// Handle firing indexes\n\t\t\t\t\t\tif ( index <= firingIndex ) {\n\t\t\t\t\t\t\tfiringIndex--;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t\treturn this;\n\t\t\t},\n\n\t\t\t// Check if a given callback is in the list.\n\t\t\t// If no argument is given, return whether or not list has callbacks attached.\n\t\t\thas: function( fn ) {\n\t\t\t\treturn fn ?\n\t\t\t\t\tjQuery.inArray( fn, list ) > -1 :\n\t\t\t\t\tlist.length > 0;\n\t\t\t},\n\n\t\t\t// Remove all callbacks from the list\n\t\t\tempty: function() {\n\t\t\t\tif ( list ) {\n\t\t\t\t\tlist = [];\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\n\t\t\t// Disable .fire and .add\n\t\t\t// Abort any current/pending executions\n\t\t\t// Clear all callbacks and values\n\t\t\tdisable: function() {\n\t\t\t\tlocked = queue = [];\n\t\t\t\tlist = memory = \"\";\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\tdisabled: function() {\n\t\t\t\treturn !list;\n\t\t\t},\n\n\t\t\t// Disable .fire\n\t\t\t// Also disable .add unless we have memory (since it would have no effect)\n\t\t\t// Abort any pending executions\n\t\t\tlock: function() {\n\t\t\t\tlocked = queue = [];\n\t\t\t\tif ( !memory && !firing ) {\n\t\t\t\t\tlist = memory = \"\";\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\tlocked: function() {\n\t\t\t\treturn !!locked;\n\t\t\t},\n\n\t\t\t// Call all callbacks with the given context and arguments\n\t\t\tfireWith: function( context, args ) {\n\t\t\t\tif ( !locked ) {\n\t\t\t\t\targs = args || [];\n\t\t\t\t\targs = [ context, args.slice ? args.slice() : args ];\n\t\t\t\t\tqueue.push( args );\n\t\t\t\t\tif ( !firing ) {\n\t\t\t\t\t\tfire();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\n\t\t\t// Call all the callbacks with the given arguments\n\t\t\tfire: function() {\n\t\t\t\tself.fireWith( this, arguments );\n\t\t\t\treturn this;\n\t\t\t},\n\n\t\t\t// To know if the callbacks have already been called at least once\n\t\t\tfired: function() {\n\t\t\t\treturn !!fired;\n\t\t\t}\n\t\t};\n\n\treturn self;\n};\n\n\nfunction Identity( v ) {\n\treturn v;\n}\nfunction Thrower( ex ) {\n\tthrow ex;\n}\n\nfunction adoptValue( value, resolve, reject, noValue ) {\n\tvar method;\n\n\ttry {\n\n\t\t// Check for promise aspect first to privilege synchronous behavior\n\t\tif ( value && isFunction( ( method = value.promise ) ) ) {\n\t\t\tmethod.call( value ).done( resolve ).fail( reject );\n\n\t\t// Other thenables\n\t\t} else if ( value && isFunction( ( method = value.then ) ) ) {\n\t\t\tmethod.call( value, resolve, reject );\n\n\t\t// Other non-thenables\n\t\t} else {\n\n\t\t\t// Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer:\n\t\t\t// * false: [ value ].slice( 0 ) => resolve( value )\n\t\t\t// * true: [ value ].slice( 1 ) => resolve()\n\t\t\tresolve.apply( undefined, [ value ].slice( noValue ) );\n\t\t}\n\n\t// For Promises/A+, convert exceptions into rejections\n\t// Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in\n\t// Deferred#then to conditionally suppress rejection.\n\t} catch ( value ) {\n\n\t\t// Support: Android 4.0 only\n\t\t// Strict mode functions invoked without .call/.apply get global-object context\n\t\treject.apply( undefined, [ value ] );\n\t}\n}\n\njQuery.extend( {\n\n\tDeferred: function( func ) {\n\t\tvar tuples = [\n\n\t\t\t\t// action, add listener, callbacks,\n\t\t\t\t// ... .then handlers, argument index, [final state]\n\t\t\t\t[ \"notify\", \"progress\", jQuery.Callbacks( \"memory\" ),\n\t\t\t\t\tjQuery.Callbacks( \"memory\" ), 2 ],\n\t\t\t\t[ \"resolve\", \"done\", jQuery.Callbacks( \"once memory\" ),\n\t\t\t\t\tjQuery.Callbacks( \"once memory\" ), 0, \"resolved\" ],\n\t\t\t\t[ \"reject\", \"fail\", jQuery.Callbacks( \"once memory\" ),\n\t\t\t\t\tjQuery.Callbacks( \"once memory\" ), 1, \"rejected\" ]\n\t\t\t],\n\t\t\tstate = \"pending\",\n\t\t\tpromise = {\n\t\t\t\tstate: function() {\n\t\t\t\t\treturn state;\n\t\t\t\t},\n\t\t\t\talways: function() {\n\t\t\t\t\tdeferred.done( arguments ).fail( arguments );\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\t\t\t\t\"catch\": function( fn ) {\n\t\t\t\t\treturn promise.then( null, fn );\n\t\t\t\t},\n\n\t\t\t\t// Keep pipe for back-compat\n\t\t\t\tpipe: function( /* fnDone, fnFail, fnProgress */ ) {\n\t\t\t\t\tvar fns = arguments;\n\n\t\t\t\t\treturn jQuery.Deferred( function( newDefer ) {\n\t\t\t\t\t\tjQuery.each( tuples, function( i, tuple ) {\n\n\t\t\t\t\t\t\t// Map tuples (progress, done, fail) to arguments (done, fail, progress)\n\t\t\t\t\t\t\tvar fn = isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ];\n\n\t\t\t\t\t\t\t// deferred.progress(function() { bind to newDefer or newDefer.notify })\n\t\t\t\t\t\t\t// deferred.done(function() { bind to newDefer or newDefer.resolve })\n\t\t\t\t\t\t\t// deferred.fail(function() { bind to newDefer or newDefer.reject })\n\t\t\t\t\t\t\tdeferred[ tuple[ 1 ] ]( function() {\n\t\t\t\t\t\t\t\tvar returned = fn && fn.apply( this, arguments );\n\t\t\t\t\t\t\t\tif ( returned && isFunction( returned.promise ) ) {\n\t\t\t\t\t\t\t\t\treturned.promise()\n\t\t\t\t\t\t\t\t\t\t.progress( newDefer.notify )\n\t\t\t\t\t\t\t\t\t\t.done( newDefer.resolve )\n\t\t\t\t\t\t\t\t\t\t.fail( newDefer.reject );\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tnewDefer[ tuple[ 0 ] + \"With\" ](\n\t\t\t\t\t\t\t\t\t\tthis,\n\t\t\t\t\t\t\t\t\t\tfn ? [ returned ] : arguments\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t} );\n\t\t\t\t\t\tfns = null;\n\t\t\t\t\t} ).promise();\n\t\t\t\t},\n\t\t\t\tthen: function( onFulfilled, onRejected, onProgress ) {\n\t\t\t\t\tvar maxDepth = 0;\n\t\t\t\t\tfunction resolve( depth, deferred, handler, special ) {\n\t\t\t\t\t\treturn function() {\n\t\t\t\t\t\t\tvar that = this,\n\t\t\t\t\t\t\t\targs = arguments,\n\t\t\t\t\t\t\t\tmightThrow = function() {\n\t\t\t\t\t\t\t\t\tvar returned, then;\n\n\t\t\t\t\t\t\t\t\t// Support: Promises/A+ section 2.3.3.3.3\n\t\t\t\t\t\t\t\t\t// https://promisesaplus.com/#point-59\n\t\t\t\t\t\t\t\t\t// Ignore double-resolution attempts\n\t\t\t\t\t\t\t\t\tif ( depth < maxDepth ) {\n\t\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\treturned = handler.apply( that, args );\n\n\t\t\t\t\t\t\t\t\t// Support: Promises/A+ section 2.3.1\n\t\t\t\t\t\t\t\t\t// https://promisesaplus.com/#point-48\n\t\t\t\t\t\t\t\t\tif ( returned === deferred.promise() ) {\n\t\t\t\t\t\t\t\t\t\tthrow new TypeError( \"Thenable self-resolution\" );\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// Support: Promises/A+ sections 2.3.3.1, 3.5\n\t\t\t\t\t\t\t\t\t// https://promisesaplus.com/#point-54\n\t\t\t\t\t\t\t\t\t// https://promisesaplus.com/#point-75\n\t\t\t\t\t\t\t\t\t// Retrieve `then` only once\n\t\t\t\t\t\t\t\t\tthen = returned &&\n\n\t\t\t\t\t\t\t\t\t\t// Support: Promises/A+ section 2.3.4\n\t\t\t\t\t\t\t\t\t\t// https://promisesaplus.com/#point-64\n\t\t\t\t\t\t\t\t\t\t// Only check objects and functions for thenability\n\t\t\t\t\t\t\t\t\t\t( typeof returned === \"object\" ||\n\t\t\t\t\t\t\t\t\t\t\ttypeof returned === \"function\" ) &&\n\t\t\t\t\t\t\t\t\t\treturned.then;\n\n\t\t\t\t\t\t\t\t\t// Handle a returned thenable\n\t\t\t\t\t\t\t\t\tif ( isFunction( then ) ) {\n\n\t\t\t\t\t\t\t\t\t\t// Special processors (notify) just wait for resolution\n\t\t\t\t\t\t\t\t\t\tif ( special ) {\n\t\t\t\t\t\t\t\t\t\t\tthen.call(\n\t\t\t\t\t\t\t\t\t\t\t\treturned,\n\t\t\t\t\t\t\t\t\t\t\t\tresolve( maxDepth, deferred, Identity, special ),\n\t\t\t\t\t\t\t\t\t\t\t\tresolve( maxDepth, deferred, Thrower, special )\n\t\t\t\t\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\t\t\t\t// Normal processors (resolve) also hook into progress\n\t\t\t\t\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t\t\t\t\t// ...and disregard older resolution values\n\t\t\t\t\t\t\t\t\t\t\tmaxDepth++;\n\n\t\t\t\t\t\t\t\t\t\t\tthen.call(\n\t\t\t\t\t\t\t\t\t\t\t\treturned,\n\t\t\t\t\t\t\t\t\t\t\t\tresolve( maxDepth, deferred, Identity, special ),\n\t\t\t\t\t\t\t\t\t\t\t\tresolve( maxDepth, deferred, Thrower, special ),\n\t\t\t\t\t\t\t\t\t\t\t\tresolve( maxDepth, deferred, Identity,\n\t\t\t\t\t\t\t\t\t\t\t\t\tdeferred.notifyWith )\n\t\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// Handle all other returned values\n\t\t\t\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t\t\t\t// Only substitute handlers pass on context\n\t\t\t\t\t\t\t\t\t\t// and multiple values (non-spec behavior)\n\t\t\t\t\t\t\t\t\t\tif ( handler !== Identity ) {\n\t\t\t\t\t\t\t\t\t\t\tthat = undefined;\n\t\t\t\t\t\t\t\t\t\t\targs = [ returned ];\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t// Process the value(s)\n\t\t\t\t\t\t\t\t\t\t// Default process is resolve\n\t\t\t\t\t\t\t\t\t\t( special || deferred.resolveWith )( that, args );\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\n\t\t\t\t\t\t\t\t// Only normal processors (resolve) catch and reject exceptions\n\t\t\t\t\t\t\t\tprocess = special ?\n\t\t\t\t\t\t\t\t\tmightThrow :\n\t\t\t\t\t\t\t\t\tfunction() {\n\t\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\t\tmightThrow();\n\t\t\t\t\t\t\t\t\t\t} catch ( e ) {\n\n\t\t\t\t\t\t\t\t\t\t\tif ( jQuery.Deferred.exceptionHook ) {\n\t\t\t\t\t\t\t\t\t\t\t\tjQuery.Deferred.exceptionHook( e,\n\t\t\t\t\t\t\t\t\t\t\t\t\tprocess.stackTrace );\n\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t// Support: Promises/A+ section 2.3.3.3.4.1\n\t\t\t\t\t\t\t\t\t\t\t// https://promisesaplus.com/#point-61\n\t\t\t\t\t\t\t\t\t\t\t// Ignore post-resolution exceptions\n\t\t\t\t\t\t\t\t\t\t\tif ( depth + 1 >= maxDepth ) {\n\n\t\t\t\t\t\t\t\t\t\t\t\t// Only substitute handlers pass on context\n\t\t\t\t\t\t\t\t\t\t\t\t// and multiple values (non-spec behavior)\n\t\t\t\t\t\t\t\t\t\t\t\tif ( handler !== Thrower ) {\n\t\t\t\t\t\t\t\t\t\t\t\t\tthat = undefined;\n\t\t\t\t\t\t\t\t\t\t\t\t\targs = [ e ];\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\tdeferred.rejectWith( that, args );\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t};\n\n\t\t\t\t\t\t\t// Support: Promises/A+ section 2.3.3.3.1\n\t\t\t\t\t\t\t// https://promisesaplus.com/#point-57\n\t\t\t\t\t\t\t// Re-resolve promises immediately to dodge false rejection from\n\t\t\t\t\t\t\t// subsequent errors\n\t\t\t\t\t\t\tif ( depth ) {\n\t\t\t\t\t\t\t\tprocess();\n\t\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t\t// Call an optional hook to record the stack, in case of exception\n\t\t\t\t\t\t\t\t// since it's otherwise lost when execution goes async\n\t\t\t\t\t\t\t\tif ( jQuery.Deferred.getStackHook ) {\n\t\t\t\t\t\t\t\t\tprocess.stackTrace = jQuery.Deferred.getStackHook();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\twindow.setTimeout( process );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\n\t\t\t\t\treturn jQuery.Deferred( function( newDefer ) {\n\n\t\t\t\t\t\t// progress_handlers.add( ... )\n\t\t\t\t\t\ttuples[ 0 ][ 3 ].add(\n\t\t\t\t\t\t\tresolve(\n\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\tnewDefer,\n\t\t\t\t\t\t\t\tisFunction( onProgress ) ?\n\t\t\t\t\t\t\t\t\tonProgress :\n\t\t\t\t\t\t\t\t\tIdentity,\n\t\t\t\t\t\t\t\tnewDefer.notifyWith\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\t// fulfilled_handlers.add( ... )\n\t\t\t\t\t\ttuples[ 1 ][ 3 ].add(\n\t\t\t\t\t\t\tresolve(\n\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\tnewDefer,\n\t\t\t\t\t\t\t\tisFunction( onFulfilled ) ?\n\t\t\t\t\t\t\t\t\tonFulfilled :\n\t\t\t\t\t\t\t\t\tIdentity\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\t// rejected_handlers.add( ... )\n\t\t\t\t\t\ttuples[ 2 ][ 3 ].add(\n\t\t\t\t\t\t\tresolve(\n\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\tnewDefer,\n\t\t\t\t\t\t\t\tisFunction( onRejected ) ?\n\t\t\t\t\t\t\t\t\tonRejected :\n\t\t\t\t\t\t\t\t\tThrower\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t);\n\t\t\t\t\t} ).promise();\n\t\t\t\t},\n\n\t\t\t\t// Get a promise for this deferred\n\t\t\t\t// If obj is provided, the promise aspect is added to the object\n\t\t\t\tpromise: function( obj ) {\n\t\t\t\t\treturn obj != null ? jQuery.extend( obj, promise ) : promise;\n\t\t\t\t}\n\t\t\t},\n\t\t\tdeferred = {};\n\n\t\t// Add list-specific methods\n\t\tjQuery.each( tuples, function( i, tuple ) {\n\t\t\tvar list = tuple[ 2 ],\n\t\t\t\tstateString = tuple[ 5 ];\n\n\t\t\t// promise.progress = list.add\n\t\t\t// promise.done = list.add\n\t\t\t// promise.fail = list.add\n\t\t\tpromise[ tuple[ 1 ] ] = list.add;\n\n\t\t\t// Handle state\n\t\t\tif ( stateString ) {\n\t\t\t\tlist.add(\n\t\t\t\t\tfunction() {\n\n\t\t\t\t\t\t// state = \"resolved\" (i.e., fulfilled)\n\t\t\t\t\t\t// state = \"rejected\"\n\t\t\t\t\t\tstate = stateString;\n\t\t\t\t\t},\n\n\t\t\t\t\t// rejected_callbacks.disable\n\t\t\t\t\t// fulfilled_callbacks.disable\n\t\t\t\t\ttuples[ 3 - i ][ 2 ].disable,\n\n\t\t\t\t\t// rejected_handlers.disable\n\t\t\t\t\t// fulfilled_handlers.disable\n\t\t\t\t\ttuples[ 3 - i ][ 3 ].disable,\n\n\t\t\t\t\t// progress_callbacks.lock\n\t\t\t\t\ttuples[ 0 ][ 2 ].lock,\n\n\t\t\t\t\t// progress_handlers.lock\n\t\t\t\t\ttuples[ 0 ][ 3 ].lock\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// progress_handlers.fire\n\t\t\t// fulfilled_handlers.fire\n\t\t\t// rejected_handlers.fire\n\t\t\tlist.add( tuple[ 3 ].fire );\n\n\t\t\t// deferred.notify = function() { deferred.notifyWith(...) }\n\t\t\t// deferred.resolve = function() { deferred.resolveWith(...) }\n\t\t\t// deferred.reject = function() { deferred.rejectWith(...) }\n\t\t\tdeferred[ tuple[ 0 ] ] = function() {\n\t\t\t\tdeferred[ tuple[ 0 ] + \"With\" ]( this === deferred ? undefined : this, arguments );\n\t\t\t\treturn this;\n\t\t\t};\n\n\t\t\t// deferred.notifyWith = list.fireWith\n\t\t\t// deferred.resolveWith = list.fireWith\n\t\t\t// deferred.rejectWith = list.fireWith\n\t\t\tdeferred[ tuple[ 0 ] + \"With\" ] = list.fireWith;\n\t\t} );\n\n\t\t// Make the deferred a promise\n\t\tpromise.promise( deferred );\n\n\t\t// Call given func if any\n\t\tif ( func ) {\n\t\t\tfunc.call( deferred, deferred );\n\t\t}\n\n\t\t// All done!\n\t\treturn deferred;\n\t},\n\n\t// Deferred helper\n\twhen: function( singleValue ) {\n\t\tvar\n\n\t\t\t// count of uncompleted subordinates\n\t\t\tremaining = arguments.length,\n\n\t\t\t// count of unprocessed arguments\n\t\t\ti = remaining,\n\n\t\t\t// subordinate fulfillment data\n\t\t\tresolveContexts = Array( i ),\n\t\t\tresolveValues = slice.call( arguments ),\n\n\t\t\t// the master Deferred\n\t\t\tmaster = jQuery.Deferred(),\n\n\t\t\t// subordinate callback factory\n\t\t\tupdateFunc = function( i ) {\n\t\t\t\treturn function( value ) {\n\t\t\t\t\tresolveContexts[ i ] = this;\n\t\t\t\t\tresolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;\n\t\t\t\t\tif ( !( --remaining ) ) {\n\t\t\t\t\t\tmaster.resolveWith( resolveContexts, resolveValues );\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t};\n\n\t\t// Single- and empty arguments are adopted like Promise.resolve\n\t\tif ( remaining <= 1 ) {\n\t\t\tadoptValue( singleValue, master.done( updateFunc( i ) ).resolve, master.reject,\n\t\t\t\t!remaining );\n\n\t\t\t// Use .then() to unwrap secondary thenables (cf. gh-3000)\n\t\t\tif ( master.state() === \"pending\" ||\n\t\t\t\tisFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) {\n\n\t\t\t\treturn master.then();\n\t\t\t}\n\t\t}\n\n\t\t// Multiple arguments are aggregated like Promise.all array elements\n\t\twhile ( i-- ) {\n\t\t\tadoptValue( resolveValues[ i ], updateFunc( i ), master.reject );\n\t\t}\n\n\t\treturn master.promise();\n\t}\n} );\n\n\n// These usually indicate a programmer mistake during development,\n// warn about them ASAP rather than swallowing them by default.\nvar rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;\n\njQuery.Deferred.exceptionHook = function( error, stack ) {\n\n\t// Support: IE 8 - 9 only\n\t// Console exists when dev tools are open, which can happen at any time\n\tif ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) {\n\t\twindow.console.warn( \"jQuery.Deferred exception: \" + error.message, error.stack, stack );\n\t}\n};\n\n\n\n\njQuery.readyException = function( error ) {\n\twindow.setTimeout( function() {\n\t\tthrow error;\n\t} );\n};\n\n\n\n\n// The deferred used on DOM ready\nvar readyList = jQuery.Deferred();\n\njQuery.fn.ready = function( fn ) {\n\n\treadyList\n\t\t.then( fn )\n\n\t\t// Wrap jQuery.readyException in a function so that the lookup\n\t\t// happens at the time of error handling instead of callback\n\t\t// registration.\n\t\t.catch( function( error ) {\n\t\t\tjQuery.readyException( error );\n\t\t} );\n\n\treturn this;\n};\n\njQuery.extend( {\n\n\t// Is the DOM ready to be used? Set to true once it occurs.\n\tisReady: false,\n\n\t// A counter to track how many items to wait for before\n\t// the ready event fires. See #6781\n\treadyWait: 1,\n\n\t// Handle when the DOM is ready\n\tready: function( wait ) {\n\n\t\t// Abort if there are pending holds or we're already ready\n\t\tif ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Remember that the DOM is ready\n\t\tjQuery.isReady = true;\n\n\t\t// If a normal DOM Ready event fired, decrement, and wait if need be\n\t\tif ( wait !== true && --jQuery.readyWait > 0 ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// If there are functions bound, to execute\n\t\treadyList.resolveWith( document, [ jQuery ] );\n\t}\n} );\n\njQuery.ready.then = readyList.then;\n\n// The ready event handler and self cleanup method\nfunction completed() {\n\tdocument.removeEventListener( \"DOMContentLoaded\", completed );\n\twindow.removeEventListener( \"load\", completed );\n\tjQuery.ready();\n}\n\n// Catch cases where $(document).ready() is called\n// after the browser event has already occurred.\n// Support: IE <=9 - 10 only\n// Older IE sometimes signals \"interactive\" too soon\nif ( document.readyState === \"complete\" ||\n\t( document.readyState !== \"loading\" && !document.documentElement.doScroll ) ) {\n\n\t// Handle it asynchronously to allow scripts the opportunity to delay ready\n\twindow.setTimeout( jQuery.ready );\n\n} else {\n\n\t// Use the handy event callback\n\tdocument.addEventListener( \"DOMContentLoaded\", completed );\n\n\t// A fallback to window.onload, that will always work\n\twindow.addEventListener( \"load\", completed );\n}\n\n\n\n\n// Multifunctional method to get and set values of a collection\n// The value/s can optionally be executed if it's a function\nvar access = function( elems, fn, key, value, chainable, emptyGet, raw ) {\n\tvar i = 0,\n\t\tlen = elems.length,\n\t\tbulk = key == null;\n\n\t// Sets many values\n\tif ( toType( key ) === \"object\" ) {\n\t\tchainable = true;\n\t\tfor ( i in key ) {\n\t\t\taccess( elems, fn, i, key[ i ], true, emptyGet, raw );\n\t\t}\n\n\t// Sets one value\n\t} else if ( value !== undefined ) {\n\t\tchainable = true;\n\n\t\tif ( !isFunction( value ) ) {\n\t\t\traw = true;\n\t\t}\n\n\t\tif ( bulk ) {\n\n\t\t\t// Bulk operations run against the entire set\n\t\t\tif ( raw ) {\n\t\t\t\tfn.call( elems, value );\n\t\t\t\tfn = null;\n\n\t\t\t// ...except when executing function values\n\t\t\t} else {\n\t\t\t\tbulk = fn;\n\t\t\t\tfn = function( elem, key, value ) {\n\t\t\t\t\treturn bulk.call( jQuery( elem ), value );\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\tif ( fn ) {\n\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\tfn(\n\t\t\t\t\telems[ i ], key, raw ?\n\t\t\t\t\tvalue :\n\t\t\t\t\tvalue.call( elems[ i ], i, fn( elems[ i ], key ) )\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\tif ( chainable ) {\n\t\treturn elems;\n\t}\n\n\t// Gets\n\tif ( bulk ) {\n\t\treturn fn.call( elems );\n\t}\n\n\treturn len ? fn( elems[ 0 ], key ) : emptyGet;\n};\n\n\n// Matches dashed string for camelizing\nvar rmsPrefix = /^-ms-/,\n\trdashAlpha = /-([a-z])/g;\n\n// Used by camelCase as callback to replace()\nfunction fcamelCase( all, letter ) {\n\treturn letter.toUpperCase();\n}\n\n// Convert dashed to camelCase; used by the css and data modules\n// Support: IE <=9 - 11, Edge 12 - 15\n// Microsoft forgot to hump their vendor prefix (#9572)\nfunction camelCase( string ) {\n\treturn string.replace( rmsPrefix, \"ms-\" ).replace( rdashAlpha, fcamelCase );\n}\nvar acceptData = function( owner ) {\n\n\t// Accepts only:\n\t//  - Node\n\t//    - Node.ELEMENT_NODE\n\t//    - Node.DOCUMENT_NODE\n\t//  - Object\n\t//    - Any\n\treturn owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType );\n};\n\n\n\n\nfunction Data() {\n\tthis.expando = jQuery.expando + Data.uid++;\n}\n\nData.uid = 1;\n\nData.prototype = {\n\n\tcache: function( owner ) {\n\n\t\t// Check if the owner object already has a cache\n\t\tvar value = owner[ this.expando ];\n\n\t\t// If not, create one\n\t\tif ( !value ) {\n\t\t\tvalue = {};\n\n\t\t\t// We can accept data for non-element nodes in modern browsers,\n\t\t\t// but we should not, see #8335.\n\t\t\t// Always return an empty object.\n\t\t\tif ( acceptData( owner ) ) {\n\n\t\t\t\t// If it is a node unlikely to be stringify-ed or looped over\n\t\t\t\t// use plain assignment\n\t\t\t\tif ( owner.nodeType ) {\n\t\t\t\t\towner[ this.expando ] = value;\n\n\t\t\t\t// Otherwise secure it in a non-enumerable property\n\t\t\t\t// configurable must be true to allow the property to be\n\t\t\t\t// deleted when data is removed\n\t\t\t\t} else {\n\t\t\t\t\tObject.defineProperty( owner, this.expando, {\n\t\t\t\t\t\tvalue: value,\n\t\t\t\t\t\tconfigurable: true\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn value;\n\t},\n\tset: function( owner, data, value ) {\n\t\tvar prop,\n\t\t\tcache = this.cache( owner );\n\n\t\t// Handle: [ owner, key, value ] args\n\t\t// Always use camelCase key (gh-2257)\n\t\tif ( typeof data === \"string\" ) {\n\t\t\tcache[ camelCase( data ) ] = value;\n\n\t\t// Handle: [ owner, { properties } ] args\n\t\t} else {\n\n\t\t\t// Copy the properties one-by-one to the cache object\n\t\t\tfor ( prop in data ) {\n\t\t\t\tcache[ camelCase( prop ) ] = data[ prop ];\n\t\t\t}\n\t\t}\n\t\treturn cache;\n\t},\n\tget: function( owner, key ) {\n\t\treturn key === undefined ?\n\t\t\tthis.cache( owner ) :\n\n\t\t\t// Always use camelCase key (gh-2257)\n\t\t\towner[ this.expando ] && owner[ this.expando ][ camelCase( key ) ];\n\t},\n\taccess: function( owner, key, value ) {\n\n\t\t// In cases where either:\n\t\t//\n\t\t//   1. No key was specified\n\t\t//   2. A string key was specified, but no value provided\n\t\t//\n\t\t// Take the \"read\" path and allow the get method to determine\n\t\t// which value to return, respectively either:\n\t\t//\n\t\t//   1. The entire cache object\n\t\t//   2. The data stored at the key\n\t\t//\n\t\tif ( key === undefined ||\n\t\t\t\t( ( key && typeof key === \"string\" ) && value === undefined ) ) {\n\n\t\t\treturn this.get( owner, key );\n\t\t}\n\n\t\t// When the key is not a string, or both a key and value\n\t\t// are specified, set or extend (existing objects) with either:\n\t\t//\n\t\t//   1. An object of properties\n\t\t//   2. A key and value\n\t\t//\n\t\tthis.set( owner, key, value );\n\n\t\t// Since the \"set\" path can have two possible entry points\n\t\t// return the expected data based on which path was taken[*]\n\t\treturn value !== undefined ? value : key;\n\t},\n\tremove: function( owner, key ) {\n\t\tvar i,\n\t\t\tcache = owner[ this.expando ];\n\n\t\tif ( cache === undefined ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( key !== undefined ) {\n\n\t\t\t// Support array or space separated string of keys\n\t\t\tif ( Array.isArray( key ) ) {\n\n\t\t\t\t// If key is an array of keys...\n\t\t\t\t// We always set camelCase keys, so remove that.\n\t\t\t\tkey = key.map( camelCase );\n\t\t\t} else {\n\t\t\t\tkey = camelCase( key );\n\n\t\t\t\t// If a key with the spaces exists, use it.\n\t\t\t\t// Otherwise, create an array by matching non-whitespace\n\t\t\t\tkey = key in cache ?\n\t\t\t\t\t[ key ] :\n\t\t\t\t\t( key.match( rnothtmlwhite ) || [] );\n\t\t\t}\n\n\t\t\ti = key.length;\n\n\t\t\twhile ( i-- ) {\n\t\t\t\tdelete cache[ key[ i ] ];\n\t\t\t}\n\t\t}\n\n\t\t// Remove the expando if there's no more data\n\t\tif ( key === undefined || jQuery.isEmptyObject( cache ) ) {\n\n\t\t\t// Support: Chrome <=35 - 45\n\t\t\t// Webkit & Blink performance suffers when deleting properties\n\t\t\t// from DOM nodes, so set to undefined instead\n\t\t\t// https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted)\n\t\t\tif ( owner.nodeType ) {\n\t\t\t\towner[ this.expando ] = undefined;\n\t\t\t} else {\n\t\t\t\tdelete owner[ this.expando ];\n\t\t\t}\n\t\t}\n\t},\n\thasData: function( owner ) {\n\t\tvar cache = owner[ this.expando ];\n\t\treturn cache !== undefined && !jQuery.isEmptyObject( cache );\n\t}\n};\nvar dataPriv = new Data();\n\nvar dataUser = new Data();\n\n\n\n//\tImplementation Summary\n//\n//\t1. Enforce API surface and semantic compatibility with 1.9.x branch\n//\t2. Improve the module's maintainability by reducing the storage\n//\t\tpaths to a single mechanism.\n//\t3. Use the same single mechanism to support \"private\" and \"user\" data.\n//\t4. _Never_ expose \"private\" data to user code (TODO: Drop _data, _removeData)\n//\t5. Avoid exposing implementation details on user objects (eg. expando properties)\n//\t6. Provide a clear path for implementation upgrade to WeakMap in 2014\n\nvar rbrace = /^(?:\\{[\\w\\W]*\\}|\\[[\\w\\W]*\\])$/,\n\trmultiDash = /[A-Z]/g;\n\nfunction getData( data ) {\n\tif ( data === \"true\" ) {\n\t\treturn true;\n\t}\n\n\tif ( data === \"false\" ) {\n\t\treturn false;\n\t}\n\n\tif ( data === \"null\" ) {\n\t\treturn null;\n\t}\n\n\t// Only convert to a number if it doesn't change the string\n\tif ( data === +data + \"\" ) {\n\t\treturn +data;\n\t}\n\n\tif ( rbrace.test( data ) ) {\n\t\treturn JSON.parse( data );\n\t}\n\n\treturn data;\n}\n\nfunction dataAttr( elem, key, data ) {\n\tvar name;\n\n\t// If nothing was found internally, try to fetch any\n\t// data from the HTML5 data-* attribute\n\tif ( data === undefined && elem.nodeType === 1 ) {\n\t\tname = \"data-\" + key.replace( rmultiDash, \"-$&\" ).toLowerCase();\n\t\tdata = elem.getAttribute( name );\n\n\t\tif ( typeof data === \"string\" ) {\n\t\t\ttry {\n\t\t\t\tdata = getData( data );\n\t\t\t} catch ( e ) {}\n\n\t\t\t// Make sure we set the data so it isn't changed later\n\t\t\tdataUser.set( elem, key, data );\n\t\t} else {\n\t\t\tdata = undefined;\n\t\t}\n\t}\n\treturn data;\n}\n\njQuery.extend( {\n\thasData: function( elem ) {\n\t\treturn dataUser.hasData( elem ) || dataPriv.hasData( elem );\n\t},\n\n\tdata: function( elem, name, data ) {\n\t\treturn dataUser.access( elem, name, data );\n\t},\n\n\tremoveData: function( elem, name ) {\n\t\tdataUser.remove( elem, name );\n\t},\n\n\t// TODO: Now that all calls to _data and _removeData have been replaced\n\t// with direct calls to dataPriv methods, these can be deprecated.\n\t_data: function( elem, name, data ) {\n\t\treturn dataPriv.access( elem, name, data );\n\t},\n\n\t_removeData: function( elem, name ) {\n\t\tdataPriv.remove( elem, name );\n\t}\n} );\n\njQuery.fn.extend( {\n\tdata: function( key, value ) {\n\t\tvar i, name, data,\n\t\t\telem = this[ 0 ],\n\t\t\tattrs = elem && elem.attributes;\n\n\t\t// Gets all values\n\t\tif ( key === undefined ) {\n\t\t\tif ( this.length ) {\n\t\t\t\tdata = dataUser.get( elem );\n\n\t\t\t\tif ( elem.nodeType === 1 && !dataPriv.get( elem, \"hasDataAttrs\" ) ) {\n\t\t\t\t\ti = attrs.length;\n\t\t\t\t\twhile ( i-- ) {\n\n\t\t\t\t\t\t// Support: IE 11 only\n\t\t\t\t\t\t// The attrs elements can be null (#14894)\n\t\t\t\t\t\tif ( attrs[ i ] ) {\n\t\t\t\t\t\t\tname = attrs[ i ].name;\n\t\t\t\t\t\t\tif ( name.indexOf( \"data-\" ) === 0 ) {\n\t\t\t\t\t\t\t\tname = camelCase( name.slice( 5 ) );\n\t\t\t\t\t\t\t\tdataAttr( elem, name, data[ name ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tdataPriv.set( elem, \"hasDataAttrs\", true );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn data;\n\t\t}\n\n\t\t// Sets multiple values\n\t\tif ( typeof key === \"object\" ) {\n\t\t\treturn this.each( function() {\n\t\t\t\tdataUser.set( this, key );\n\t\t\t} );\n\t\t}\n\n\t\treturn access( this, function( value ) {\n\t\t\tvar data;\n\n\t\t\t// The calling jQuery object (element matches) is not empty\n\t\t\t// (and therefore has an element appears at this[ 0 ]) and the\n\t\t\t// `value` parameter was not undefined. An empty jQuery object\n\t\t\t// will result in `undefined` for elem = this[ 0 ] which will\n\t\t\t// throw an exception if an attempt to read a data cache is made.\n\t\t\tif ( elem && value === undefined ) {\n\n\t\t\t\t// Attempt to get data from the cache\n\t\t\t\t// The key will always be camelCased in Data\n\t\t\t\tdata = dataUser.get( elem, key );\n\t\t\t\tif ( data !== undefined ) {\n\t\t\t\t\treturn data;\n\t\t\t\t}\n\n\t\t\t\t// Attempt to \"discover\" the data in\n\t\t\t\t// HTML5 custom data-* attrs\n\t\t\t\tdata = dataAttr( elem, key );\n\t\t\t\tif ( data !== undefined ) {\n\t\t\t\t\treturn data;\n\t\t\t\t}\n\n\t\t\t\t// We tried really hard, but the data doesn't exist.\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Set the data...\n\t\t\tthis.each( function() {\n\n\t\t\t\t// We always store the camelCased key\n\t\t\t\tdataUser.set( this, key, value );\n\t\t\t} );\n\t\t}, null, value, arguments.length > 1, null, true );\n\t},\n\n\tremoveData: function( key ) {\n\t\treturn this.each( function() {\n\t\t\tdataUser.remove( this, key );\n\t\t} );\n\t}\n} );\n\n\njQuery.extend( {\n\tqueue: function( elem, type, data ) {\n\t\tvar queue;\n\n\t\tif ( elem ) {\n\t\t\ttype = ( type || \"fx\" ) + \"queue\";\n\t\t\tqueue = dataPriv.get( elem, type );\n\n\t\t\t// Speed up dequeue by getting out quickly if this is just a lookup\n\t\t\tif ( data ) {\n\t\t\t\tif ( !queue || Array.isArray( data ) ) {\n\t\t\t\t\tqueue = dataPriv.access( elem, type, jQuery.makeArray( data ) );\n\t\t\t\t} else {\n\t\t\t\t\tqueue.push( data );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn queue || [];\n\t\t}\n\t},\n\n\tdequeue: function( elem, type ) {\n\t\ttype = type || \"fx\";\n\n\t\tvar queue = jQuery.queue( elem, type ),\n\t\t\tstartLength = queue.length,\n\t\t\tfn = queue.shift(),\n\t\t\thooks = jQuery._queueHooks( elem, type ),\n\t\t\tnext = function() {\n\t\t\t\tjQuery.dequeue( elem, type );\n\t\t\t};\n\n\t\t// If the fx queue is dequeued, always remove the progress sentinel\n\t\tif ( fn === \"inprogress\" ) {\n\t\t\tfn = queue.shift();\n\t\t\tstartLength--;\n\t\t}\n\n\t\tif ( fn ) {\n\n\t\t\t// Add a progress sentinel to prevent the fx queue from being\n\t\t\t// automatically dequeued\n\t\t\tif ( type === \"fx\" ) {\n\t\t\t\tqueue.unshift( \"inprogress\" );\n\t\t\t}\n\n\t\t\t// Clear up the last queue stop function\n\t\t\tdelete hooks.stop;\n\t\t\tfn.call( elem, next, hooks );\n\t\t}\n\n\t\tif ( !startLength && hooks ) {\n\t\t\thooks.empty.fire();\n\t\t}\n\t},\n\n\t// Not public - generate a queueHooks object, or return the current one\n\t_queueHooks: function( elem, type ) {\n\t\tvar key = type + \"queueHooks\";\n\t\treturn dataPriv.get( elem, key ) || dataPriv.access( elem, key, {\n\t\t\tempty: jQuery.Callbacks( \"once memory\" ).add( function() {\n\t\t\t\tdataPriv.remove( elem, [ type + \"queue\", key ] );\n\t\t\t} )\n\t\t} );\n\t}\n} );\n\njQuery.fn.extend( {\n\tqueue: function( type, data ) {\n\t\tvar setter = 2;\n\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tdata = type;\n\t\t\ttype = \"fx\";\n\t\t\tsetter--;\n\t\t}\n\n\t\tif ( arguments.length < setter ) {\n\t\t\treturn jQuery.queue( this[ 0 ], type );\n\t\t}\n\n\t\treturn data === undefined ?\n\t\t\tthis :\n\t\t\tthis.each( function() {\n\t\t\t\tvar queue = jQuery.queue( this, type, data );\n\n\t\t\t\t// Ensure a hooks for this queue\n\t\t\t\tjQuery._queueHooks( this, type );\n\n\t\t\t\tif ( type === \"fx\" && queue[ 0 ] !== \"inprogress\" ) {\n\t\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t\t}\n\t\t\t} );\n\t},\n\tdequeue: function( type ) {\n\t\treturn this.each( function() {\n\t\t\tjQuery.dequeue( this, type );\n\t\t} );\n\t},\n\tclearQueue: function( type ) {\n\t\treturn this.queue( type || \"fx\", [] );\n\t},\n\n\t// Get a promise resolved when queues of a certain type\n\t// are emptied (fx is the type by default)\n\tpromise: function( type, obj ) {\n\t\tvar tmp,\n\t\t\tcount = 1,\n\t\t\tdefer = jQuery.Deferred(),\n\t\t\telements = this,\n\t\t\ti = this.length,\n\t\t\tresolve = function() {\n\t\t\t\tif ( !( --count ) ) {\n\t\t\t\t\tdefer.resolveWith( elements, [ elements ] );\n\t\t\t\t}\n\t\t\t};\n\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tobj = type;\n\t\t\ttype = undefined;\n\t\t}\n\t\ttype = type || \"fx\";\n\n\t\twhile ( i-- ) {\n\t\t\ttmp = dataPriv.get( elements[ i ], type + \"queueHooks\" );\n\t\t\tif ( tmp && tmp.empty ) {\n\t\t\t\tcount++;\n\t\t\t\ttmp.empty.add( resolve );\n\t\t\t}\n\t\t}\n\t\tresolve();\n\t\treturn defer.promise( obj );\n\t}\n} );\nvar pnum = ( /[+-]?(?:\\d*\\.|)\\d+(?:[eE][+-]?\\d+|)/ ).source;\n\nvar rcssNum = new RegExp( \"^(?:([+-])=|)(\" + pnum + \")([a-z%]*)$\", \"i\" );\n\n\nvar cssExpand = [ \"Top\", \"Right\", \"Bottom\", \"Left\" ];\n\nvar isHiddenWithinTree = function( elem, el ) {\n\n\t\t// isHiddenWithinTree might be called from jQuery#filter function;\n\t\t// in that case, element will be second argument\n\t\telem = el || elem;\n\n\t\t// Inline style trumps all\n\t\treturn elem.style.display === \"none\" ||\n\t\t\telem.style.display === \"\" &&\n\n\t\t\t// Otherwise, check computed style\n\t\t\t// Support: Firefox <=43 - 45\n\t\t\t// Disconnected elements can have computed display: none, so first confirm that elem is\n\t\t\t// in the document.\n\t\t\tjQuery.contains( elem.ownerDocument, elem ) &&\n\n\t\t\tjQuery.css( elem, \"display\" ) === \"none\";\n\t};\n\nvar swap = function( elem, options, callback, args ) {\n\tvar ret, name,\n\t\told = {};\n\n\t// Remember the old values, and insert the new ones\n\tfor ( name in options ) {\n\t\told[ name ] = elem.style[ name ];\n\t\telem.style[ name ] = options[ name ];\n\t}\n\n\tret = callback.apply( elem, args || [] );\n\n\t// Revert the old values\n\tfor ( name in options ) {\n\t\telem.style[ name ] = old[ name ];\n\t}\n\n\treturn ret;\n};\n\n\n\n\nfunction adjustCSS( elem, prop, valueParts, tween ) {\n\tvar adjusted, scale,\n\t\tmaxIterations = 20,\n\t\tcurrentValue = tween ?\n\t\t\tfunction() {\n\t\t\t\treturn tween.cur();\n\t\t\t} :\n\t\t\tfunction() {\n\t\t\t\treturn jQuery.css( elem, prop, \"\" );\n\t\t\t},\n\t\tinitial = currentValue(),\n\t\tunit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? \"\" : \"px\" ),\n\n\t\t// Starting value computation is required for potential unit mismatches\n\t\tinitialInUnit = ( jQuery.cssNumber[ prop ] || unit !== \"px\" && +initial ) &&\n\t\t\trcssNum.exec( jQuery.css( elem, prop ) );\n\n\tif ( initialInUnit && initialInUnit[ 3 ] !== unit ) {\n\n\t\t// Support: Firefox <=54\n\t\t// Halve the iteration target value to prevent interference from CSS upper bounds (gh-2144)\n\t\tinitial = initial / 2;\n\n\t\t// Trust units reported by jQuery.css\n\t\tunit = unit || initialInUnit[ 3 ];\n\n\t\t// Iteratively approximate from a nonzero starting point\n\t\tinitialInUnit = +initial || 1;\n\n\t\twhile ( maxIterations-- ) {\n\n\t\t\t// Evaluate and update our best guess (doubling guesses that zero out).\n\t\t\t// Finish if the scale equals or crosses 1 (making the old*new product non-positive).\n\t\t\tjQuery.style( elem, prop, initialInUnit + unit );\n\t\t\tif ( ( 1 - scale ) * ( 1 - ( scale = currentValue() / initial || 0.5 ) ) <= 0 ) {\n\t\t\t\tmaxIterations = 0;\n\t\t\t}\n\t\t\tinitialInUnit = initialInUnit / scale;\n\n\t\t}\n\n\t\tinitialInUnit = initialInUnit * 2;\n\t\tjQuery.style( elem, prop, initialInUnit + unit );\n\n\t\t// Make sure we update the tween properties later on\n\t\tvalueParts = valueParts || [];\n\t}\n\n\tif ( valueParts ) {\n\t\tinitialInUnit = +initialInUnit || +initial || 0;\n\n\t\t// Apply relative offset (+=/-=) if specified\n\t\tadjusted = valueParts[ 1 ] ?\n\t\t\tinitialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] :\n\t\t\t+valueParts[ 2 ];\n\t\tif ( tween ) {\n\t\t\ttween.unit = unit;\n\t\t\ttween.start = initialInUnit;\n\t\t\ttween.end = adjusted;\n\t\t}\n\t}\n\treturn adjusted;\n}\n\n\nvar defaultDisplayMap = {};\n\nfunction getDefaultDisplay( elem ) {\n\tvar temp,\n\t\tdoc = elem.ownerDocument,\n\t\tnodeName = elem.nodeName,\n\t\tdisplay = defaultDisplayMap[ nodeName ];\n\n\tif ( display ) {\n\t\treturn display;\n\t}\n\n\ttemp = doc.body.appendChild( doc.createElement( nodeName ) );\n\tdisplay = jQuery.css( temp, \"display\" );\n\n\ttemp.parentNode.removeChild( temp );\n\n\tif ( display === \"none\" ) {\n\t\tdisplay = \"block\";\n\t}\n\tdefaultDisplayMap[ nodeName ] = display;\n\n\treturn display;\n}\n\nfunction showHide( elements, show ) {\n\tvar display, elem,\n\t\tvalues = [],\n\t\tindex = 0,\n\t\tlength = elements.length;\n\n\t// Determine new display value for elements that need to change\n\tfor ( ; index < length; index++ ) {\n\t\telem = elements[ index ];\n\t\tif ( !elem.style ) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tdisplay = elem.style.display;\n\t\tif ( show ) {\n\n\t\t\t// Since we force visibility upon cascade-hidden elements, an immediate (and slow)\n\t\t\t// check is required in this first loop unless we have a nonempty display value (either\n\t\t\t// inline or about-to-be-restored)\n\t\t\tif ( display === \"none\" ) {\n\t\t\t\tvalues[ index ] = dataPriv.get( elem, \"display\" ) || null;\n\t\t\t\tif ( !values[ index ] ) {\n\t\t\t\t\telem.style.display = \"\";\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ( elem.style.display === \"\" && isHiddenWithinTree( elem ) ) {\n\t\t\t\tvalues[ index ] = getDefaultDisplay( elem );\n\t\t\t}\n\t\t} else {\n\t\t\tif ( display !== \"none\" ) {\n\t\t\t\tvalues[ index ] = \"none\";\n\n\t\t\t\t// Remember what we're overwriting\n\t\t\t\tdataPriv.set( elem, \"display\", display );\n\t\t\t}\n\t\t}\n\t}\n\n\t// Set the display of the elements in a second loop to avoid constant reflow\n\tfor ( index = 0; index < length; index++ ) {\n\t\tif ( values[ index ] != null ) {\n\t\t\telements[ index ].style.display = values[ index ];\n\t\t}\n\t}\n\n\treturn elements;\n}\n\njQuery.fn.extend( {\n\tshow: function() {\n\t\treturn showHide( this, true );\n\t},\n\thide: function() {\n\t\treturn showHide( this );\n\t},\n\ttoggle: function( state ) {\n\t\tif ( typeof state === \"boolean\" ) {\n\t\t\treturn state ? this.show() : this.hide();\n\t\t}\n\n\t\treturn this.each( function() {\n\t\t\tif ( isHiddenWithinTree( this ) ) {\n\t\t\t\tjQuery( this ).show();\n\t\t\t} else {\n\t\t\t\tjQuery( this ).hide();\n\t\t\t}\n\t\t} );\n\t}\n} );\nvar rcheckableType = ( /^(?:checkbox|radio)$/i );\n\nvar rtagName = ( /<([a-z][^\\/\\0>\\x20\\t\\r\\n\\f]+)/i );\n\nvar rscriptType = ( /^$|^module$|\\/(?:java|ecma)script/i );\n\n\n\n// We have to close these tags to support XHTML (#13200)\nvar wrapMap = {\n\n\t// Support: IE <=9 only\n\toption: [ 1, \"<select multiple='multiple'>\", \"</select>\" ],\n\n\t// XHTML parsers do not magically insert elements in the\n\t// same way that tag soup parsers do. So we cannot shorten\n\t// this by omitting <tbody> or other required elements.\n\tthead: [ 1, \"<table>\", \"</table>\" ],\n\tcol: [ 2, \"<table><colgroup>\", \"</colgroup></table>\" ],\n\ttr: [ 2, \"<table><tbody>\", \"</tbody></table>\" ],\n\ttd: [ 3, \"<table><tbody><tr>\", \"</tr></tbody></table>\" ],\n\n\t_default: [ 0, \"\", \"\" ]\n};\n\n// Support: IE <=9 only\nwrapMap.optgroup = wrapMap.option;\n\nwrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;\nwrapMap.th = wrapMap.td;\n\n\nfunction getAll( context, tag ) {\n\n\t// Support: IE <=9 - 11 only\n\t// Use typeof to avoid zero-argument method invocation on host objects (#15151)\n\tvar ret;\n\n\tif ( typeof context.getElementsByTagName !== \"undefined\" ) {\n\t\tret = context.getElementsByTagName( tag || \"*\" );\n\n\t} else if ( typeof context.querySelectorAll !== \"undefined\" ) {\n\t\tret = context.querySelectorAll( tag || \"*\" );\n\n\t} else {\n\t\tret = [];\n\t}\n\n\tif ( tag === undefined || tag && nodeName( context, tag ) ) {\n\t\treturn jQuery.merge( [ context ], ret );\n\t}\n\n\treturn ret;\n}\n\n\n// Mark scripts as having already been evaluated\nfunction setGlobalEval( elems, refElements ) {\n\tvar i = 0,\n\t\tl = elems.length;\n\n\tfor ( ; i < l; i++ ) {\n\t\tdataPriv.set(\n\t\t\telems[ i ],\n\t\t\t\"globalEval\",\n\t\t\t!refElements || dataPriv.get( refElements[ i ], \"globalEval\" )\n\t\t);\n\t}\n}\n\n\nvar rhtml = /<|&#?\\w+;/;\n\nfunction buildFragment( elems, context, scripts, selection, ignored ) {\n\tvar elem, tmp, tag, wrap, contains, j,\n\t\tfragment = context.createDocumentFragment(),\n\t\tnodes = [],\n\t\ti = 0,\n\t\tl = elems.length;\n\n\tfor ( ; i < l; i++ ) {\n\t\telem = elems[ i ];\n\n\t\tif ( elem || elem === 0 ) {\n\n\t\t\t// Add nodes directly\n\t\t\tif ( toType( elem ) === \"object\" ) {\n\n\t\t\t\t// Support: Android <=4.0 only, PhantomJS 1 only\n\t\t\t\t// push.apply(_, arraylike) throws on ancient WebKit\n\t\t\t\tjQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );\n\n\t\t\t// Convert non-html into a text node\n\t\t\t} else if ( !rhtml.test( elem ) ) {\n\t\t\t\tnodes.push( context.createTextNode( elem ) );\n\n\t\t\t// Convert html into DOM nodes\n\t\t\t} else {\n\t\t\t\ttmp = tmp || fragment.appendChild( context.createElement( \"div\" ) );\n\n\t\t\t\t// Deserialize a standard representation\n\t\t\t\ttag = ( rtagName.exec( elem ) || [ \"\", \"\" ] )[ 1 ].toLowerCase();\n\t\t\t\twrap = wrapMap[ tag ] || wrapMap._default;\n\t\t\t\ttmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ];\n\n\t\t\t\t// Descend through wrappers to the right content\n\t\t\t\tj = wrap[ 0 ];\n\t\t\t\twhile ( j-- ) {\n\t\t\t\t\ttmp = tmp.lastChild;\n\t\t\t\t}\n\n\t\t\t\t// Support: Android <=4.0 only, PhantomJS 1 only\n\t\t\t\t// push.apply(_, arraylike) throws on ancient WebKit\n\t\t\t\tjQuery.merge( nodes, tmp.childNodes );\n\n\t\t\t\t// Remember the top-level container\n\t\t\t\ttmp = fragment.firstChild;\n\n\t\t\t\t// Ensure the created nodes are orphaned (#12392)\n\t\t\t\ttmp.textContent = \"\";\n\t\t\t}\n\t\t}\n\t}\n\n\t// Remove wrapper from fragment\n\tfragment.textContent = \"\";\n\n\ti = 0;\n\twhile ( ( elem = nodes[ i++ ] ) ) {\n\n\t\t// Skip elements already in the context collection (trac-4087)\n\t\tif ( selection && jQuery.inArray( elem, selection ) > -1 ) {\n\t\t\tif ( ignored ) {\n\t\t\t\tignored.push( elem );\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tcontains = jQuery.contains( elem.ownerDocument, elem );\n\n\t\t// Append to fragment\n\t\ttmp = getAll( fragment.appendChild( elem ), \"script\" );\n\n\t\t// Preserve script evaluation history\n\t\tif ( contains ) {\n\t\t\tsetGlobalEval( tmp );\n\t\t}\n\n\t\t// Capture executables\n\t\tif ( scripts ) {\n\t\t\tj = 0;\n\t\t\twhile ( ( elem = tmp[ j++ ] ) ) {\n\t\t\t\tif ( rscriptType.test( elem.type || \"\" ) ) {\n\t\t\t\t\tscripts.push( elem );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn fragment;\n}\n\n\n( function() {\n\tvar fragment = document.createDocumentFragment(),\n\t\tdiv = fragment.appendChild( document.createElement( \"div\" ) ),\n\t\tinput = document.createElement( \"input\" );\n\n\t// Support: Android 4.0 - 4.3 only\n\t// Check state lost if the name is set (#11217)\n\t// Support: Windows Web Apps (WWA)\n\t// `name` and `type` must use .setAttribute for WWA (#14901)\n\tinput.setAttribute( \"type\", \"radio\" );\n\tinput.setAttribute( \"checked\", \"checked\" );\n\tinput.setAttribute( \"name\", \"t\" );\n\n\tdiv.appendChild( input );\n\n\t// Support: Android <=4.1 only\n\t// Older WebKit doesn't clone checked state correctly in fragments\n\tsupport.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;\n\n\t// Support: IE <=11 only\n\t// Make sure textarea (and checkbox) defaultValue is properly cloned\n\tdiv.innerHTML = \"<textarea>x</textarea>\";\n\tsupport.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;\n} )();\nvar documentElement = document.documentElement;\n\n\n\nvar\n\trkeyEvent = /^key/,\n\trmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/,\n\trtypenamespace = /^([^.]*)(?:\\.(.+)|)/;\n\nfunction returnTrue() {\n\treturn true;\n}\n\nfunction returnFalse() {\n\treturn false;\n}\n\n// Support: IE <=9 only\n// See #13393 for more info\nfunction safeActiveElement() {\n\ttry {\n\t\treturn document.activeElement;\n\t} catch ( err ) { }\n}\n\nfunction on( elem, types, selector, data, fn, one ) {\n\tvar origFn, type;\n\n\t// Types can be a map of types/handlers\n\tif ( typeof types === \"object\" ) {\n\n\t\t// ( types-Object, selector, data )\n\t\tif ( typeof selector !== \"string\" ) {\n\n\t\t\t// ( types-Object, data )\n\t\t\tdata = data || selector;\n\t\t\tselector = undefined;\n\t\t}\n\t\tfor ( type in types ) {\n\t\t\ton( elem, type, selector, data, types[ type ], one );\n\t\t}\n\t\treturn elem;\n\t}\n\n\tif ( data == null && fn == null ) {\n\n\t\t// ( types, fn )\n\t\tfn = selector;\n\t\tdata = selector = undefined;\n\t} else if ( fn == null ) {\n\t\tif ( typeof selector === \"string\" ) {\n\n\t\t\t// ( types, selector, fn )\n\t\t\tfn = data;\n\t\t\tdata = undefined;\n\t\t} else {\n\n\t\t\t// ( types, data, fn )\n\t\t\tfn = data;\n\t\t\tdata = selector;\n\t\t\tselector = undefined;\n\t\t}\n\t}\n\tif ( fn === false ) {\n\t\tfn = returnFalse;\n\t} else if ( !fn ) {\n\t\treturn elem;\n\t}\n\n\tif ( one === 1 ) {\n\t\torigFn = fn;\n\t\tfn = function( event ) {\n\n\t\t\t// Can use an empty set, since event contains the info\n\t\t\tjQuery().off( event );\n\t\t\treturn origFn.apply( this, arguments );\n\t\t};\n\n\t\t// Use same guid so caller can remove using origFn\n\t\tfn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );\n\t}\n\treturn elem.each( function() {\n\t\tjQuery.event.add( this, types, fn, data, selector );\n\t} );\n}\n\n/*\n * Helper functions for managing events -- not part of the public interface.\n * Props to Dean Edwards' addEvent library for many of the ideas.\n */\njQuery.event = {\n\n\tglobal: {},\n\n\tadd: function( elem, types, handler, data, selector ) {\n\n\t\tvar handleObjIn, eventHandle, tmp,\n\t\t\tevents, t, handleObj,\n\t\t\tspecial, handlers, type, namespaces, origType,\n\t\t\telemData = dataPriv.get( elem );\n\n\t\t// Don't attach events to noData or text/comment nodes (but allow plain objects)\n\t\tif ( !elemData ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Caller can pass in an object of custom data in lieu of the handler\n\t\tif ( handler.handler ) {\n\t\t\thandleObjIn = handler;\n\t\t\thandler = handleObjIn.handler;\n\t\t\tselector = handleObjIn.selector;\n\t\t}\n\n\t\t// Ensure that invalid selectors throw exceptions at attach time\n\t\t// Evaluate against documentElement in case elem is a non-element node (e.g., document)\n\t\tif ( selector ) {\n\t\t\tjQuery.find.matchesSelector( documentElement, selector );\n\t\t}\n\n\t\t// Make sure that the handler has a unique ID, used to find/remove it later\n\t\tif ( !handler.guid ) {\n\t\t\thandler.guid = jQuery.guid++;\n\t\t}\n\n\t\t// Init the element's event structure and main handler, if this is the first\n\t\tif ( !( events = elemData.events ) ) {\n\t\t\tevents = elemData.events = {};\n\t\t}\n\t\tif ( !( eventHandle = elemData.handle ) ) {\n\t\t\teventHandle = elemData.handle = function( e ) {\n\n\t\t\t\t// Discard the second event of a jQuery.event.trigger() and\n\t\t\t\t// when an event is called after a page has unloaded\n\t\t\t\treturn typeof jQuery !== \"undefined\" && jQuery.event.triggered !== e.type ?\n\t\t\t\t\tjQuery.event.dispatch.apply( elem, arguments ) : undefined;\n\t\t\t};\n\t\t}\n\n\t\t// Handle multiple events separated by a space\n\t\ttypes = ( types || \"\" ).match( rnothtmlwhite ) || [ \"\" ];\n\t\tt = types.length;\n\t\twhile ( t-- ) {\n\t\t\ttmp = rtypenamespace.exec( types[ t ] ) || [];\n\t\t\ttype = origType = tmp[ 1 ];\n\t\t\tnamespaces = ( tmp[ 2 ] || \"\" ).split( \".\" ).sort();\n\n\t\t\t// There *must* be a type, no attaching namespace-only handlers\n\t\t\tif ( !type ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// If event changes its type, use the special event handlers for the changed type\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t// If selector defined, determine special event api type, otherwise given type\n\t\t\ttype = ( selector ? special.delegateType : special.bindType ) || type;\n\n\t\t\t// Update special based on newly reset type\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t// handleObj is passed to all event handlers\n\t\t\thandleObj = jQuery.extend( {\n\t\t\t\ttype: type,\n\t\t\t\torigType: origType,\n\t\t\t\tdata: data,\n\t\t\t\thandler: handler,\n\t\t\t\tguid: handler.guid,\n\t\t\t\tselector: selector,\n\t\t\t\tneedsContext: selector && jQuery.expr.match.needsContext.test( selector ),\n\t\t\t\tnamespace: namespaces.join( \".\" )\n\t\t\t}, handleObjIn );\n\n\t\t\t// Init the event handler queue if we're the first\n\t\t\tif ( !( handlers = events[ type ] ) ) {\n\t\t\t\thandlers = events[ type ] = [];\n\t\t\t\thandlers.delegateCount = 0;\n\n\t\t\t\t// Only use addEventListener if the special events handler returns false\n\t\t\t\tif ( !special.setup ||\n\t\t\t\t\tspecial.setup.call( elem, data, namespaces, eventHandle ) === false ) {\n\n\t\t\t\t\tif ( elem.addEventListener ) {\n\t\t\t\t\t\telem.addEventListener( type, eventHandle );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( special.add ) {\n\t\t\t\tspecial.add.call( elem, handleObj );\n\n\t\t\t\tif ( !handleObj.handler.guid ) {\n\t\t\t\t\thandleObj.handler.guid = handler.guid;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Add to the element's handler list, delegates in front\n\t\t\tif ( selector ) {\n\t\t\t\thandlers.splice( handlers.delegateCount++, 0, handleObj );\n\t\t\t} else {\n\t\t\t\thandlers.push( handleObj );\n\t\t\t}\n\n\t\t\t// Keep track of which events have ever been used, for event optimization\n\t\t\tjQuery.event.global[ type ] = true;\n\t\t}\n\n\t},\n\n\t// Detach an event or set of events from an element\n\tremove: function( elem, types, handler, selector, mappedTypes ) {\n\n\t\tvar j, origCount, tmp,\n\t\t\tevents, t, handleObj,\n\t\t\tspecial, handlers, type, namespaces, origType,\n\t\t\telemData = dataPriv.hasData( elem ) && dataPriv.get( elem );\n\n\t\tif ( !elemData || !( events = elemData.events ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Once for each type.namespace in types; type may be omitted\n\t\ttypes = ( types || \"\" ).match( rnothtmlwhite ) || [ \"\" ];\n\t\tt = types.length;\n\t\twhile ( t-- ) {\n\t\t\ttmp = rtypenamespace.exec( types[ t ] ) || [];\n\t\t\ttype = origType = tmp[ 1 ];\n\t\t\tnamespaces = ( tmp[ 2 ] || \"\" ).split( \".\" ).sort();\n\n\t\t\t// Unbind all events (on this namespace, if provided) for the element\n\t\t\tif ( !type ) {\n\t\t\t\tfor ( type in events ) {\n\t\t\t\t\tjQuery.event.remove( elem, type + types[ t ], handler, selector, true );\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\t\t\ttype = ( selector ? special.delegateType : special.bindType ) || type;\n\t\t\thandlers = events[ type ] || [];\n\t\t\ttmp = tmp[ 2 ] &&\n\t\t\t\tnew RegExp( \"(^|\\\\.)\" + namespaces.join( \"\\\\.(?:.*\\\\.|)\" ) + \"(\\\\.|$)\" );\n\n\t\t\t// Remove matching events\n\t\t\torigCount = j = handlers.length;\n\t\t\twhile ( j-- ) {\n\t\t\t\thandleObj = handlers[ j ];\n\n\t\t\t\tif ( ( mappedTypes || origType === handleObj.origType ) &&\n\t\t\t\t\t( !handler || handler.guid === handleObj.guid ) &&\n\t\t\t\t\t( !tmp || tmp.test( handleObj.namespace ) ) &&\n\t\t\t\t\t( !selector || selector === handleObj.selector ||\n\t\t\t\t\t\tselector === \"**\" && handleObj.selector ) ) {\n\t\t\t\t\thandlers.splice( j, 1 );\n\n\t\t\t\t\tif ( handleObj.selector ) {\n\t\t\t\t\t\thandlers.delegateCount--;\n\t\t\t\t\t}\n\t\t\t\t\tif ( special.remove ) {\n\t\t\t\t\t\tspecial.remove.call( elem, handleObj );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Remove generic event handler if we removed something and no more handlers exist\n\t\t\t// (avoids potential for endless recursion during removal of special event handlers)\n\t\t\tif ( origCount && !handlers.length ) {\n\t\t\t\tif ( !special.teardown ||\n\t\t\t\t\tspecial.teardown.call( elem, namespaces, elemData.handle ) === false ) {\n\n\t\t\t\t\tjQuery.removeEvent( elem, type, elemData.handle );\n\t\t\t\t}\n\n\t\t\t\tdelete events[ type ];\n\t\t\t}\n\t\t}\n\n\t\t// Remove data and the expando if it's no longer used\n\t\tif ( jQuery.isEmptyObject( events ) ) {\n\t\t\tdataPriv.remove( elem, \"handle events\" );\n\t\t}\n\t},\n\n\tdispatch: function( nativeEvent ) {\n\n\t\t// Make a writable jQuery.Event from the native event object\n\t\tvar event = jQuery.event.fix( nativeEvent );\n\n\t\tvar i, j, ret, matched, handleObj, handlerQueue,\n\t\t\targs = new Array( arguments.length ),\n\t\t\thandlers = ( dataPriv.get( this, \"events\" ) || {} )[ event.type ] || [],\n\t\t\tspecial = jQuery.event.special[ event.type ] || {};\n\n\t\t// Use the fix-ed jQuery.Event rather than the (read-only) native event\n\t\targs[ 0 ] = event;\n\n\t\tfor ( i = 1; i < arguments.length; i++ ) {\n\t\t\targs[ i ] = arguments[ i ];\n\t\t}\n\n\t\tevent.delegateTarget = this;\n\n\t\t// Call the preDispatch hook for the mapped type, and let it bail if desired\n\t\tif ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Determine handlers\n\t\thandlerQueue = jQuery.event.handlers.call( this, event, handlers );\n\n\t\t// Run delegates first; they may want to stop propagation beneath us\n\t\ti = 0;\n\t\twhile ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) {\n\t\t\tevent.currentTarget = matched.elem;\n\n\t\t\tj = 0;\n\t\t\twhile ( ( handleObj = matched.handlers[ j++ ] ) &&\n\t\t\t\t!event.isImmediatePropagationStopped() ) {\n\n\t\t\t\t// Triggered event must either 1) have no namespace, or 2) have namespace(s)\n\t\t\t\t// a subset or equal to those in the bound event (both can have no namespace).\n\t\t\t\tif ( !event.rnamespace || event.rnamespace.test( handleObj.namespace ) ) {\n\n\t\t\t\t\tevent.handleObj = handleObj;\n\t\t\t\t\tevent.data = handleObj.data;\n\n\t\t\t\t\tret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle ||\n\t\t\t\t\t\thandleObj.handler ).apply( matched.elem, args );\n\n\t\t\t\t\tif ( ret !== undefined ) {\n\t\t\t\t\t\tif ( ( event.result = ret ) === false ) {\n\t\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Call the postDispatch hook for the mapped type\n\t\tif ( special.postDispatch ) {\n\t\t\tspecial.postDispatch.call( this, event );\n\t\t}\n\n\t\treturn event.result;\n\t},\n\n\thandlers: function( event, handlers ) {\n\t\tvar i, handleObj, sel, matchedHandlers, matchedSelectors,\n\t\t\thandlerQueue = [],\n\t\t\tdelegateCount = handlers.delegateCount,\n\t\t\tcur = event.target;\n\n\t\t// Find delegate handlers\n\t\tif ( delegateCount &&\n\n\t\t\t// Support: IE <=9\n\t\t\t// Black-hole SVG <use> instance trees (trac-13180)\n\t\t\tcur.nodeType &&\n\n\t\t\t// Support: Firefox <=42\n\t\t\t// Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861)\n\t\t\t// https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click\n\t\t\t// Support: IE 11 only\n\t\t\t// ...but not arrow key \"clicks\" of radio inputs, which can have `button` -1 (gh-2343)\n\t\t\t!( event.type === \"click\" && event.button >= 1 ) ) {\n\n\t\t\tfor ( ; cur !== this; cur = cur.parentNode || this ) {\n\n\t\t\t\t// Don't check non-elements (#13208)\n\t\t\t\t// Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)\n\t\t\t\tif ( cur.nodeType === 1 && !( event.type === \"click\" && cur.disabled === true ) ) {\n\t\t\t\t\tmatchedHandlers = [];\n\t\t\t\t\tmatchedSelectors = {};\n\t\t\t\t\tfor ( i = 0; i < delegateCount; i++ ) {\n\t\t\t\t\t\thandleObj = handlers[ i ];\n\n\t\t\t\t\t\t// Don't conflict with Object.prototype properties (#13203)\n\t\t\t\t\t\tsel = handleObj.selector + \" \";\n\n\t\t\t\t\t\tif ( matchedSelectors[ sel ] === undefined ) {\n\t\t\t\t\t\t\tmatchedSelectors[ sel ] = handleObj.needsContext ?\n\t\t\t\t\t\t\t\tjQuery( sel, this ).index( cur ) > -1 :\n\t\t\t\t\t\t\t\tjQuery.find( sel, this, null, [ cur ] ).length;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( matchedSelectors[ sel ] ) {\n\t\t\t\t\t\t\tmatchedHandlers.push( handleObj );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ( matchedHandlers.length ) {\n\t\t\t\t\t\thandlerQueue.push( { elem: cur, handlers: matchedHandlers } );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Add the remaining (directly-bound) handlers\n\t\tcur = this;\n\t\tif ( delegateCount < handlers.length ) {\n\t\t\thandlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } );\n\t\t}\n\n\t\treturn handlerQueue;\n\t},\n\n\taddProp: function( name, hook ) {\n\t\tObject.defineProperty( jQuery.Event.prototype, name, {\n\t\t\tenumerable: true,\n\t\t\tconfigurable: true,\n\n\t\t\tget: isFunction( hook ) ?\n\t\t\t\tfunction() {\n\t\t\t\t\tif ( this.originalEvent ) {\n\t\t\t\t\t\t\treturn hook( this.originalEvent );\n\t\t\t\t\t}\n\t\t\t\t} :\n\t\t\t\tfunction() {\n\t\t\t\t\tif ( this.originalEvent ) {\n\t\t\t\t\t\t\treturn this.originalEvent[ name ];\n\t\t\t\t\t}\n\t\t\t\t},\n\n\t\t\tset: function( value ) {\n\t\t\t\tObject.defineProperty( this, name, {\n\t\t\t\t\tenumerable: true,\n\t\t\t\t\tconfigurable: true,\n\t\t\t\t\twritable: true,\n\t\t\t\t\tvalue: value\n\t\t\t\t} );\n\t\t\t}\n\t\t} );\n\t},\n\n\tfix: function( originalEvent ) {\n\t\treturn originalEvent[ jQuery.expando ] ?\n\t\t\toriginalEvent :\n\t\t\tnew jQuery.Event( originalEvent );\n\t},\n\n\tspecial: {\n\t\tload: {\n\n\t\t\t// Prevent triggered image.load events from bubbling to window.load\n\t\t\tnoBubble: true\n\t\t},\n\t\tfocus: {\n\n\t\t\t// Fire native event if possible so blur/focus sequence is correct\n\t\t\ttrigger: function() {\n\t\t\t\tif ( this !== safeActiveElement() && this.focus ) {\n\t\t\t\t\tthis.focus();\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t},\n\t\t\tdelegateType: \"focusin\"\n\t\t},\n\t\tblur: {\n\t\t\ttrigger: function() {\n\t\t\t\tif ( this === safeActiveElement() && this.blur ) {\n\t\t\t\t\tthis.blur();\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t},\n\t\t\tdelegateType: \"focusout\"\n\t\t},\n\t\tclick: {\n\n\t\t\t// For checkbox, fire native event so checked state will be right\n\t\t\ttrigger: function() {\n\t\t\t\tif ( this.type === \"checkbox\" && this.click && nodeName( this, \"input\" ) ) {\n\t\t\t\t\tthis.click();\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t// For cross-browser consistency, don't fire native .click() on links\n\t\t\t_default: function( event ) {\n\t\t\t\treturn nodeName( event.target, \"a\" );\n\t\t\t}\n\t\t},\n\n\t\tbeforeunload: {\n\t\t\tpostDispatch: function( event ) {\n\n\t\t\t\t// Support: Firefox 20+\n\t\t\t\t// Firefox doesn't alert if the returnValue field is not set.\n\t\t\t\tif ( event.result !== undefined && event.originalEvent ) {\n\t\t\t\t\tevent.originalEvent.returnValue = event.result;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n};\n\njQuery.removeEvent = function( elem, type, handle ) {\n\n\t// This \"if\" is needed for plain objects\n\tif ( elem.removeEventListener ) {\n\t\telem.removeEventListener( type, handle );\n\t}\n};\n\njQuery.Event = function( src, props ) {\n\n\t// Allow instantiation without the 'new' keyword\n\tif ( !( this instanceof jQuery.Event ) ) {\n\t\treturn new jQuery.Event( src, props );\n\t}\n\n\t// Event object\n\tif ( src && src.type ) {\n\t\tthis.originalEvent = src;\n\t\tthis.type = src.type;\n\n\t\t// Events bubbling up the document may have been marked as prevented\n\t\t// by a handler lower down the tree; reflect the correct value.\n\t\tthis.isDefaultPrevented = src.defaultPrevented ||\n\t\t\t\tsrc.defaultPrevented === undefined &&\n\n\t\t\t\t// Support: Android <=2.3 only\n\t\t\t\tsrc.returnValue === false ?\n\t\t\treturnTrue :\n\t\t\treturnFalse;\n\n\t\t// Create target properties\n\t\t// Support: Safari <=6 - 7 only\n\t\t// Target should not be a text node (#504, #13143)\n\t\tthis.target = ( src.target && src.target.nodeType === 3 ) ?\n\t\t\tsrc.target.parentNode :\n\t\t\tsrc.target;\n\n\t\tthis.currentTarget = src.currentTarget;\n\t\tthis.relatedTarget = src.relatedTarget;\n\n\t// Event type\n\t} else {\n\t\tthis.type = src;\n\t}\n\n\t// Put explicitly provided properties onto the event object\n\tif ( props ) {\n\t\tjQuery.extend( this, props );\n\t}\n\n\t// Create a timestamp if incoming event doesn't have one\n\tthis.timeStamp = src && src.timeStamp || Date.now();\n\n\t// Mark it as fixed\n\tthis[ jQuery.expando ] = true;\n};\n\n// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding\n// https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html\njQuery.Event.prototype = {\n\tconstructor: jQuery.Event,\n\tisDefaultPrevented: returnFalse,\n\tisPropagationStopped: returnFalse,\n\tisImmediatePropagationStopped: returnFalse,\n\tisSimulated: false,\n\n\tpreventDefault: function() {\n\t\tvar e = this.originalEvent;\n\n\t\tthis.isDefaultPrevented = returnTrue;\n\n\t\tif ( e && !this.isSimulated ) {\n\t\t\te.preventDefault();\n\t\t}\n\t},\n\tstopPropagation: function() {\n\t\tvar e = this.originalEvent;\n\n\t\tthis.isPropagationStopped = returnTrue;\n\n\t\tif ( e && !this.isSimulated ) {\n\t\t\te.stopPropagation();\n\t\t}\n\t},\n\tstopImmediatePropagation: function() {\n\t\tvar e = this.originalEvent;\n\n\t\tthis.isImmediatePropagationStopped = returnTrue;\n\n\t\tif ( e && !this.isSimulated ) {\n\t\t\te.stopImmediatePropagation();\n\t\t}\n\n\t\tthis.stopPropagation();\n\t}\n};\n\n// Includes all common event props including KeyEvent and MouseEvent specific props\njQuery.each( {\n\taltKey: true,\n\tbubbles: true,\n\tcancelable: true,\n\tchangedTouches: true,\n\tctrlKey: true,\n\tdetail: true,\n\teventPhase: true,\n\tmetaKey: true,\n\tpageX: true,\n\tpageY: true,\n\tshiftKey: true,\n\tview: true,\n\t\"char\": true,\n\tcharCode: true,\n\tkey: true,\n\tkeyCode: true,\n\tbutton: true,\n\tbuttons: true,\n\tclientX: true,\n\tclientY: true,\n\toffsetX: true,\n\toffsetY: true,\n\tpointerId: true,\n\tpointerType: true,\n\tscreenX: true,\n\tscreenY: true,\n\ttargetTouches: true,\n\ttoElement: true,\n\ttouches: true,\n\n\twhich: function( event ) {\n\t\tvar button = event.button;\n\n\t\t// Add which for key events\n\t\tif ( event.which == null && rkeyEvent.test( event.type ) ) {\n\t\t\treturn event.charCode != null ? event.charCode : event.keyCode;\n\t\t}\n\n\t\t// Add which for click: 1 === left; 2 === middle; 3 === right\n\t\tif ( !event.which && button !== undefined && rmouseEvent.test( event.type ) ) {\n\t\t\tif ( button & 1 ) {\n\t\t\t\treturn 1;\n\t\t\t}\n\n\t\t\tif ( button & 2 ) {\n\t\t\t\treturn 3;\n\t\t\t}\n\n\t\t\tif ( button & 4 ) {\n\t\t\t\treturn 2;\n\t\t\t}\n\n\t\t\treturn 0;\n\t\t}\n\n\t\treturn event.which;\n\t}\n}, jQuery.event.addProp );\n\n// Create mouseenter/leave events using mouseover/out and event-time checks\n// so that event delegation works in jQuery.\n// Do the same for pointerenter/pointerleave and pointerover/pointerout\n//\n// Support: Safari 7 only\n// Safari sends mouseenter too often; see:\n// https://bugs.chromium.org/p/chromium/issues/detail?id=470258\n// for the description of the bug (it existed in older Chrome versions as well).\njQuery.each( {\n\tmouseenter: \"mouseover\",\n\tmouseleave: \"mouseout\",\n\tpointerenter: \"pointerover\",\n\tpointerleave: \"pointerout\"\n}, function( orig, fix ) {\n\tjQuery.event.special[ orig ] = {\n\t\tdelegateType: fix,\n\t\tbindType: fix,\n\n\t\thandle: function( event ) {\n\t\t\tvar ret,\n\t\t\t\ttarget = this,\n\t\t\t\trelated = event.relatedTarget,\n\t\t\t\thandleObj = event.handleObj;\n\n\t\t\t// For mouseenter/leave call the handler if related is outside the target.\n\t\t\t// NB: No relatedTarget if the mouse left/entered the browser window\n\t\t\tif ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) {\n\t\t\t\tevent.type = handleObj.origType;\n\t\t\t\tret = handleObj.handler.apply( this, arguments );\n\t\t\t\tevent.type = fix;\n\t\t\t}\n\t\t\treturn ret;\n\t\t}\n\t};\n} );\n\njQuery.fn.extend( {\n\n\ton: function( types, selector, data, fn ) {\n\t\treturn on( this, types, selector, data, fn );\n\t},\n\tone: function( types, selector, data, fn ) {\n\t\treturn on( this, types, selector, data, fn, 1 );\n\t},\n\toff: function( types, selector, fn ) {\n\t\tvar handleObj, type;\n\t\tif ( types && types.preventDefault && types.handleObj ) {\n\n\t\t\t// ( event )  dispatched jQuery.Event\n\t\t\thandleObj = types.handleObj;\n\t\t\tjQuery( types.delegateTarget ).off(\n\t\t\t\thandleObj.namespace ?\n\t\t\t\t\thandleObj.origType + \".\" + handleObj.namespace :\n\t\t\t\t\thandleObj.origType,\n\t\t\t\thandleObj.selector,\n\t\t\t\thandleObj.handler\n\t\t\t);\n\t\t\treturn this;\n\t\t}\n\t\tif ( typeof types === \"object\" ) {\n\n\t\t\t// ( types-object [, selector] )\n\t\t\tfor ( type in types ) {\n\t\t\t\tthis.off( type, selector, types[ type ] );\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\t\tif ( selector === false || typeof selector === \"function\" ) {\n\n\t\t\t// ( types [, fn] )\n\t\t\tfn = selector;\n\t\t\tselector = undefined;\n\t\t}\n\t\tif ( fn === false ) {\n\t\t\tfn = returnFalse;\n\t\t}\n\t\treturn this.each( function() {\n\t\t\tjQuery.event.remove( this, types, fn, selector );\n\t\t} );\n\t}\n} );\n\n\nvar\n\n\t/* eslint-disable max-len */\n\n\t// See https://github.com/eslint/eslint/issues/3229\n\trxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\\/\\0>\\x20\\t\\r\\n\\f]*)[^>]*)\\/>/gi,\n\n\t/* eslint-enable */\n\n\t// Support: IE <=10 - 11, Edge 12 - 13 only\n\t// In IE/Edge using regex groups here causes severe slowdowns.\n\t// See https://connect.microsoft.com/IE/feedback/details/1736512/\n\trnoInnerhtml = /<script|<style|<link/i,\n\n\t// checked=\"checked\" or checked\n\trchecked = /checked\\s*(?:[^=]|=\\s*.checked.)/i,\n\trcleanScript = /^\\s*<!(?:\\[CDATA\\[|--)|(?:\\]\\]|--)>\\s*$/g;\n\n// Prefer a tbody over its parent table for containing new rows\nfunction manipulationTarget( elem, content ) {\n\tif ( nodeName( elem, \"table\" ) &&\n\t\tnodeName( content.nodeType !== 11 ? content : content.firstChild, \"tr\" ) ) {\n\n\t\treturn jQuery( elem ).children( \"tbody\" )[ 0 ] || elem;\n\t}\n\n\treturn elem;\n}\n\n// Replace/restore the type attribute of script elements for safe DOM manipulation\nfunction disableScript( elem ) {\n\telem.type = ( elem.getAttribute( \"type\" ) !== null ) + \"/\" + elem.type;\n\treturn elem;\n}\nfunction restoreScript( elem ) {\n\tif ( ( elem.type || \"\" ).slice( 0, 5 ) === \"true/\" ) {\n\t\telem.type = elem.type.slice( 5 );\n\t} else {\n\t\telem.removeAttribute( \"type\" );\n\t}\n\n\treturn elem;\n}\n\nfunction cloneCopyEvent( src, dest ) {\n\tvar i, l, type, pdataOld, pdataCur, udataOld, udataCur, events;\n\n\tif ( dest.nodeType !== 1 ) {\n\t\treturn;\n\t}\n\n\t// 1. Copy private data: events, handlers, etc.\n\tif ( dataPriv.hasData( src ) ) {\n\t\tpdataOld = dataPriv.access( src );\n\t\tpdataCur = dataPriv.set( dest, pdataOld );\n\t\tevents = pdataOld.events;\n\n\t\tif ( events ) {\n\t\t\tdelete pdataCur.handle;\n\t\t\tpdataCur.events = {};\n\n\t\t\tfor ( type in events ) {\n\t\t\t\tfor ( i = 0, l = events[ type ].length; i < l; i++ ) {\n\t\t\t\t\tjQuery.event.add( dest, type, events[ type ][ i ] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// 2. Copy user data\n\tif ( dataUser.hasData( src ) ) {\n\t\tudataOld = dataUser.access( src );\n\t\tudataCur = jQuery.extend( {}, udataOld );\n\n\t\tdataUser.set( dest, udataCur );\n\t}\n}\n\n// Fix IE bugs, see support tests\nfunction fixInput( src, dest ) {\n\tvar nodeName = dest.nodeName.toLowerCase();\n\n\t// Fails to persist the checked state of a cloned checkbox or radio button.\n\tif ( nodeName === \"input\" && rcheckableType.test( src.type ) ) {\n\t\tdest.checked = src.checked;\n\n\t// Fails to return the selected option to the default selected state when cloning options\n\t} else if ( nodeName === \"input\" || nodeName === \"textarea\" ) {\n\t\tdest.defaultValue = src.defaultValue;\n\t}\n}\n\nfunction domManip( collection, args, callback, ignored ) {\n\n\t// Flatten any nested arrays\n\targs = concat.apply( [], args );\n\n\tvar fragment, first, scripts, hasScripts, node, doc,\n\t\ti = 0,\n\t\tl = collection.length,\n\t\tiNoClone = l - 1,\n\t\tvalue = args[ 0 ],\n\t\tvalueIsFunction = isFunction( value );\n\n\t// We can't cloneNode fragments that contain checked, in WebKit\n\tif ( valueIsFunction ||\n\t\t\t( l > 1 && typeof value === \"string\" &&\n\t\t\t\t!support.checkClone && rchecked.test( value ) ) ) {\n\t\treturn collection.each( function( index ) {\n\t\t\tvar self = collection.eq( index );\n\t\t\tif ( valueIsFunction ) {\n\t\t\t\targs[ 0 ] = value.call( this, index, self.html() );\n\t\t\t}\n\t\t\tdomManip( self, args, callback, ignored );\n\t\t} );\n\t}\n\n\tif ( l ) {\n\t\tfragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored );\n\t\tfirst = fragment.firstChild;\n\n\t\tif ( fragment.childNodes.length === 1 ) {\n\t\t\tfragment = first;\n\t\t}\n\n\t\t// Require either new content or an interest in ignored elements to invoke the callback\n\t\tif ( first || ignored ) {\n\t\t\tscripts = jQuery.map( getAll( fragment, \"script\" ), disableScript );\n\t\t\thasScripts = scripts.length;\n\n\t\t\t// Use the original fragment for the last item\n\t\t\t// instead of the first because it can end up\n\t\t\t// being emptied incorrectly in certain situations (#8070).\n\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\tnode = fragment;\n\n\t\t\t\tif ( i !== iNoClone ) {\n\t\t\t\t\tnode = jQuery.clone( node, true, true );\n\n\t\t\t\t\t// Keep references to cloned scripts for later restoration\n\t\t\t\t\tif ( hasScripts ) {\n\n\t\t\t\t\t\t// Support: Android <=4.0 only, PhantomJS 1 only\n\t\t\t\t\t\t// push.apply(_, arraylike) throws on ancient WebKit\n\t\t\t\t\t\tjQuery.merge( scripts, getAll( node, \"script\" ) );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tcallback.call( collection[ i ], node, i );\n\t\t\t}\n\n\t\t\tif ( hasScripts ) {\n\t\t\t\tdoc = scripts[ scripts.length - 1 ].ownerDocument;\n\n\t\t\t\t// Reenable scripts\n\t\t\t\tjQuery.map( scripts, restoreScript );\n\n\t\t\t\t// Evaluate executable scripts on first document insertion\n\t\t\t\tfor ( i = 0; i < hasScripts; i++ ) {\n\t\t\t\t\tnode = scripts[ i ];\n\t\t\t\t\tif ( rscriptType.test( node.type || \"\" ) &&\n\t\t\t\t\t\t!dataPriv.access( node, \"globalEval\" ) &&\n\t\t\t\t\t\tjQuery.contains( doc, node ) ) {\n\n\t\t\t\t\t\tif ( node.src && ( node.type || \"\" ).toLowerCase()  !== \"module\" ) {\n\n\t\t\t\t\t\t\t// Optional AJAX dependency, but won't run scripts if not present\n\t\t\t\t\t\t\tif ( jQuery._evalUrl ) {\n\t\t\t\t\t\t\t\tjQuery._evalUrl( node.src );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tDOMEval( node.textContent.replace( rcleanScript, \"\" ), doc, node );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn collection;\n}\n\nfunction remove( elem, selector, keepData ) {\n\tvar node,\n\t\tnodes = selector ? jQuery.filter( selector, elem ) : elem,\n\t\ti = 0;\n\n\tfor ( ; ( node = nodes[ i ] ) != null; i++ ) {\n\t\tif ( !keepData && node.nodeType === 1 ) {\n\t\t\tjQuery.cleanData( getAll( node ) );\n\t\t}\n\n\t\tif ( node.parentNode ) {\n\t\t\tif ( keepData && jQuery.contains( node.ownerDocument, node ) ) {\n\t\t\t\tsetGlobalEval( getAll( node, \"script\" ) );\n\t\t\t}\n\t\t\tnode.parentNode.removeChild( node );\n\t\t}\n\t}\n\n\treturn elem;\n}\n\njQuery.extend( {\n\thtmlPrefilter: function( html ) {\n\t\treturn html.replace( rxhtmlTag, \"<$1></$2>\" );\n\t},\n\n\tclone: function( elem, dataAndEvents, deepDataAndEvents ) {\n\t\tvar i, l, srcElements, destElements,\n\t\t\tclone = elem.cloneNode( true ),\n\t\t\tinPage = jQuery.contains( elem.ownerDocument, elem );\n\n\t\t// Fix IE cloning issues\n\t\tif ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) &&\n\t\t\t\t!jQuery.isXMLDoc( elem ) ) {\n\n\t\t\t// We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2\n\t\t\tdestElements = getAll( clone );\n\t\t\tsrcElements = getAll( elem );\n\n\t\t\tfor ( i = 0, l = srcElements.length; i < l; i++ ) {\n\t\t\t\tfixInput( srcElements[ i ], destElements[ i ] );\n\t\t\t}\n\t\t}\n\n\t\t// Copy the events from the original to the clone\n\t\tif ( dataAndEvents ) {\n\t\t\tif ( deepDataAndEvents ) {\n\t\t\t\tsrcElements = srcElements || getAll( elem );\n\t\t\t\tdestElements = destElements || getAll( clone );\n\n\t\t\t\tfor ( i = 0, l = srcElements.length; i < l; i++ ) {\n\t\t\t\t\tcloneCopyEvent( srcElements[ i ], destElements[ i ] );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tcloneCopyEvent( elem, clone );\n\t\t\t}\n\t\t}\n\n\t\t// Preserve script evaluation history\n\t\tdestElements = getAll( clone, \"script\" );\n\t\tif ( destElements.length > 0 ) {\n\t\t\tsetGlobalEval( destElements, !inPage && getAll( elem, \"script\" ) );\n\t\t}\n\n\t\t// Return the cloned set\n\t\treturn clone;\n\t},\n\n\tcleanData: function( elems ) {\n\t\tvar data, elem, type,\n\t\t\tspecial = jQuery.event.special,\n\t\t\ti = 0;\n\n\t\tfor ( ; ( elem = elems[ i ] ) !== undefined; i++ ) {\n\t\t\tif ( acceptData( elem ) ) {\n\t\t\t\tif ( ( data = elem[ dataPriv.expando ] ) ) {\n\t\t\t\t\tif ( data.events ) {\n\t\t\t\t\t\tfor ( type in data.events ) {\n\t\t\t\t\t\t\tif ( special[ type ] ) {\n\t\t\t\t\t\t\t\tjQuery.event.remove( elem, type );\n\n\t\t\t\t\t\t\t// This is a shortcut to avoid jQuery.event.remove's overhead\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tjQuery.removeEvent( elem, type, data.handle );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Support: Chrome <=35 - 45+\n\t\t\t\t\t// Assign undefined instead of using delete, see Data#remove\n\t\t\t\t\telem[ dataPriv.expando ] = undefined;\n\t\t\t\t}\n\t\t\t\tif ( elem[ dataUser.expando ] ) {\n\n\t\t\t\t\t// Support: Chrome <=35 - 45+\n\t\t\t\t\t// Assign undefined instead of using delete, see Data#remove\n\t\t\t\t\telem[ dataUser.expando ] = undefined;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n} );\n\njQuery.fn.extend( {\n\tdetach: function( selector ) {\n\t\treturn remove( this, selector, true );\n\t},\n\n\tremove: function( selector ) {\n\t\treturn remove( this, selector );\n\t},\n\n\ttext: function( value ) {\n\t\treturn access( this, function( value ) {\n\t\t\treturn value === undefined ?\n\t\t\t\tjQuery.text( this ) :\n\t\t\t\tthis.empty().each( function() {\n\t\t\t\t\tif ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {\n\t\t\t\t\t\tthis.textContent = value;\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t}, null, value, arguments.length );\n\t},\n\n\tappend: function() {\n\t\treturn domManip( this, arguments, function( elem ) {\n\t\t\tif ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {\n\t\t\t\tvar target = manipulationTarget( this, elem );\n\t\t\t\ttarget.appendChild( elem );\n\t\t\t}\n\t\t} );\n\t},\n\n\tprepend: function() {\n\t\treturn domManip( this, arguments, function( elem ) {\n\t\t\tif ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {\n\t\t\t\tvar target = manipulationTarget( this, elem );\n\t\t\t\ttarget.insertBefore( elem, target.firstChild );\n\t\t\t}\n\t\t} );\n\t},\n\n\tbefore: function() {\n\t\treturn domManip( this, arguments, function( elem ) {\n\t\t\tif ( this.parentNode ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this );\n\t\t\t}\n\t\t} );\n\t},\n\n\tafter: function() {\n\t\treturn domManip( this, arguments, function( elem ) {\n\t\t\tif ( this.parentNode ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this.nextSibling );\n\t\t\t}\n\t\t} );\n\t},\n\n\tempty: function() {\n\t\tvar elem,\n\t\t\ti = 0;\n\n\t\tfor ( ; ( elem = this[ i ] ) != null; i++ ) {\n\t\t\tif ( elem.nodeType === 1 ) {\n\n\t\t\t\t// Prevent memory leaks\n\t\t\t\tjQuery.cleanData( getAll( elem, false ) );\n\n\t\t\t\t// Remove any remaining nodes\n\t\t\t\telem.textContent = \"\";\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tclone: function( dataAndEvents, deepDataAndEvents ) {\n\t\tdataAndEvents = dataAndEvents == null ? false : dataAndEvents;\n\t\tdeepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;\n\n\t\treturn this.map( function() {\n\t\t\treturn jQuery.clone( this, dataAndEvents, deepDataAndEvents );\n\t\t} );\n\t},\n\n\thtml: function( value ) {\n\t\treturn access( this, function( value ) {\n\t\t\tvar elem = this[ 0 ] || {},\n\t\t\t\ti = 0,\n\t\t\t\tl = this.length;\n\n\t\t\tif ( value === undefined && elem.nodeType === 1 ) {\n\t\t\t\treturn elem.innerHTML;\n\t\t\t}\n\n\t\t\t// See if we can take a shortcut and just use innerHTML\n\t\t\tif ( typeof value === \"string\" && !rnoInnerhtml.test( value ) &&\n\t\t\t\t!wrapMap[ ( rtagName.exec( value ) || [ \"\", \"\" ] )[ 1 ].toLowerCase() ] ) {\n\n\t\t\t\tvalue = jQuery.htmlPrefilter( value );\n\n\t\t\t\ttry {\n\t\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\t\telem = this[ i ] || {};\n\n\t\t\t\t\t\t// Remove element nodes and prevent memory leaks\n\t\t\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\t\t\tjQuery.cleanData( getAll( elem, false ) );\n\t\t\t\t\t\t\telem.innerHTML = value;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\telem = 0;\n\n\t\t\t\t// If using innerHTML throws an exception, use the fallback method\n\t\t\t\t} catch ( e ) {}\n\t\t\t}\n\n\t\t\tif ( elem ) {\n\t\t\t\tthis.empty().append( value );\n\t\t\t}\n\t\t}, null, value, arguments.length );\n\t},\n\n\treplaceWith: function() {\n\t\tvar ignored = [];\n\n\t\t// Make the changes, replacing each non-ignored context element with the new content\n\t\treturn domManip( this, arguments, function( elem ) {\n\t\t\tvar parent = this.parentNode;\n\n\t\t\tif ( jQuery.inArray( this, ignored ) < 0 ) {\n\t\t\t\tjQuery.cleanData( getAll( this ) );\n\t\t\t\tif ( parent ) {\n\t\t\t\t\tparent.replaceChild( elem, this );\n\t\t\t\t}\n\t\t\t}\n\n\t\t// Force callback invocation\n\t\t}, ignored );\n\t}\n} );\n\njQuery.each( {\n\tappendTo: \"append\",\n\tprependTo: \"prepend\",\n\tinsertBefore: \"before\",\n\tinsertAfter: \"after\",\n\treplaceAll: \"replaceWith\"\n}, function( name, original ) {\n\tjQuery.fn[ name ] = function( selector ) {\n\t\tvar elems,\n\t\t\tret = [],\n\t\t\tinsert = jQuery( selector ),\n\t\t\tlast = insert.length - 1,\n\t\t\ti = 0;\n\n\t\tfor ( ; i <= last; i++ ) {\n\t\t\telems = i === last ? this : this.clone( true );\n\t\t\tjQuery( insert[ i ] )[ original ]( elems );\n\n\t\t\t// Support: Android <=4.0 only, PhantomJS 1 only\n\t\t\t// .get() because push.apply(_, arraylike) throws on ancient WebKit\n\t\t\tpush.apply( ret, elems.get() );\n\t\t}\n\n\t\treturn this.pushStack( ret );\n\t};\n} );\nvar rnumnonpx = new RegExp( \"^(\" + pnum + \")(?!px)[a-z%]+$\", \"i\" );\n\nvar getStyles = function( elem ) {\n\n\t\t// Support: IE <=11 only, Firefox <=30 (#15098, #14150)\n\t\t// IE throws on elements created in popups\n\t\t// FF meanwhile throws on frame elements through \"defaultView.getComputedStyle\"\n\t\tvar view = elem.ownerDocument.defaultView;\n\n\t\tif ( !view || !view.opener ) {\n\t\t\tview = window;\n\t\t}\n\n\t\treturn view.getComputedStyle( elem );\n\t};\n\nvar rboxStyle = new RegExp( cssExpand.join( \"|\" ), \"i\" );\n\n\n\n( function() {\n\n\t// Executing both pixelPosition & boxSizingReliable tests require only one layout\n\t// so they're executed at the same time to save the second computation.\n\tfunction computeStyleTests() {\n\n\t\t// This is a singleton, we need to execute it only once\n\t\tif ( !div ) {\n\t\t\treturn;\n\t\t}\n\n\t\tcontainer.style.cssText = \"position:absolute;left:-11111px;width:60px;\" +\n\t\t\t\"margin-top:1px;padding:0;border:0\";\n\t\tdiv.style.cssText =\n\t\t\t\"position:relative;display:block;box-sizing:border-box;overflow:scroll;\" +\n\t\t\t\"margin:auto;border:1px;padding:1px;\" +\n\t\t\t\"width:60%;top:1%\";\n\t\tdocumentElement.appendChild( container ).appendChild( div );\n\n\t\tvar divStyle = window.getComputedStyle( div );\n\t\tpixelPositionVal = divStyle.top !== \"1%\";\n\n\t\t// Support: Android 4.0 - 4.3 only, Firefox <=3 - 44\n\t\treliableMarginLeftVal = roundPixelMeasures( divStyle.marginLeft ) === 12;\n\n\t\t// Support: Android 4.0 - 4.3 only, Safari <=9.1 - 10.1, iOS <=7.0 - 9.3\n\t\t// Some styles come back with percentage values, even though they shouldn't\n\t\tdiv.style.right = \"60%\";\n\t\tpixelBoxStylesVal = roundPixelMeasures( divStyle.right ) === 36;\n\n\t\t// Support: IE 9 - 11 only\n\t\t// Detect misreporting of content dimensions for box-sizing:border-box elements\n\t\tboxSizingReliableVal = roundPixelMeasures( divStyle.width ) === 36;\n\n\t\t// Support: IE 9 only\n\t\t// Detect overflow:scroll screwiness (gh-3699)\n\t\tdiv.style.position = \"absolute\";\n\t\tscrollboxSizeVal = div.offsetWidth === 36 || \"absolute\";\n\n\t\tdocumentElement.removeChild( container );\n\n\t\t// Nullify the div so it wouldn't be stored in the memory and\n\t\t// it will also be a sign that checks already performed\n\t\tdiv = null;\n\t}\n\n\tfunction roundPixelMeasures( measure ) {\n\t\treturn Math.round( parseFloat( measure ) );\n\t}\n\n\tvar pixelPositionVal, boxSizingReliableVal, scrollboxSizeVal, pixelBoxStylesVal,\n\t\treliableMarginLeftVal,\n\t\tcontainer = document.createElement( \"div\" ),\n\t\tdiv = document.createElement( \"div\" );\n\n\t// Finish early in limited (non-browser) environments\n\tif ( !div.style ) {\n\t\treturn;\n\t}\n\n\t// Support: IE <=9 - 11 only\n\t// Style of cloned element affects source element cloned (#8908)\n\tdiv.style.backgroundClip = \"content-box\";\n\tdiv.cloneNode( true ).style.backgroundClip = \"\";\n\tsupport.clearCloneStyle = div.style.backgroundClip === \"content-box\";\n\n\tjQuery.extend( support, {\n\t\tboxSizingReliable: function() {\n\t\t\tcomputeStyleTests();\n\t\t\treturn boxSizingReliableVal;\n\t\t},\n\t\tpixelBoxStyles: function() {\n\t\t\tcomputeStyleTests();\n\t\t\treturn pixelBoxStylesVal;\n\t\t},\n\t\tpixelPosition: function() {\n\t\t\tcomputeStyleTests();\n\t\t\treturn pixelPositionVal;\n\t\t},\n\t\treliableMarginLeft: function() {\n\t\t\tcomputeStyleTests();\n\t\t\treturn reliableMarginLeftVal;\n\t\t},\n\t\tscrollboxSize: function() {\n\t\t\tcomputeStyleTests();\n\t\t\treturn scrollboxSizeVal;\n\t\t}\n\t} );\n} )();\n\n\nfunction curCSS( elem, name, computed ) {\n\tvar width, minWidth, maxWidth, ret,\n\n\t\t// Support: Firefox 51+\n\t\t// Retrieving style before computed somehow\n\t\t// fixes an issue with getting wrong values\n\t\t// on detached elements\n\t\tstyle = elem.style;\n\n\tcomputed = computed || getStyles( elem );\n\n\t// getPropertyValue is needed for:\n\t//   .css('filter') (IE 9 only, #12537)\n\t//   .css('--customProperty) (#3144)\n\tif ( computed ) {\n\t\tret = computed.getPropertyValue( name ) || computed[ name ];\n\n\t\tif ( ret === \"\" && !jQuery.contains( elem.ownerDocument, elem ) ) {\n\t\t\tret = jQuery.style( elem, name );\n\t\t}\n\n\t\t// A tribute to the \"awesome hack by Dean Edwards\"\n\t\t// Android Browser returns percentage for some values,\n\t\t// but width seems to be reliably pixels.\n\t\t// This is against the CSSOM draft spec:\n\t\t// https://drafts.csswg.org/cssom/#resolved-values\n\t\tif ( !support.pixelBoxStyles() && rnumnonpx.test( ret ) && rboxStyle.test( name ) ) {\n\n\t\t\t// Remember the original values\n\t\t\twidth = style.width;\n\t\t\tminWidth = style.minWidth;\n\t\t\tmaxWidth = style.maxWidth;\n\n\t\t\t// Put in the new values to get a computed value out\n\t\t\tstyle.minWidth = style.maxWidth = style.width = ret;\n\t\t\tret = computed.width;\n\n\t\t\t// Revert the changed values\n\t\t\tstyle.width = width;\n\t\t\tstyle.minWidth = minWidth;\n\t\t\tstyle.maxWidth = maxWidth;\n\t\t}\n\t}\n\n\treturn ret !== undefined ?\n\n\t\t// Support: IE <=9 - 11 only\n\t\t// IE returns zIndex value as an integer.\n\t\tret + \"\" :\n\t\tret;\n}\n\n\nfunction addGetHookIf( conditionFn, hookFn ) {\n\n\t// Define the hook, we'll check on the first run if it's really needed.\n\treturn {\n\t\tget: function() {\n\t\t\tif ( conditionFn() ) {\n\n\t\t\t\t// Hook not needed (or it's not possible to use it due\n\t\t\t\t// to missing dependency), remove it.\n\t\t\t\tdelete this.get;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Hook needed; redefine it so that the support test is not executed again.\n\t\t\treturn ( this.get = hookFn ).apply( this, arguments );\n\t\t}\n\t};\n}\n\n\nvar\n\n\t// Swappable if display is none or starts with table\n\t// except \"table\", \"table-cell\", or \"table-caption\"\n\t// See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display\n\trdisplayswap = /^(none|table(?!-c[ea]).+)/,\n\trcustomProp = /^--/,\n\tcssShow = { position: \"absolute\", visibility: \"hidden\", display: \"block\" },\n\tcssNormalTransform = {\n\t\tletterSpacing: \"0\",\n\t\tfontWeight: \"400\"\n\t},\n\n\tcssPrefixes = [ \"Webkit\", \"Moz\", \"ms\" ],\n\temptyStyle = document.createElement( \"div\" ).style;\n\n// Return a css property mapped to a potentially vendor prefixed property\nfunction vendorPropName( name ) {\n\n\t// Shortcut for names that are not vendor prefixed\n\tif ( name in emptyStyle ) {\n\t\treturn name;\n\t}\n\n\t// Check for vendor prefixed names\n\tvar capName = name[ 0 ].toUpperCase() + name.slice( 1 ),\n\t\ti = cssPrefixes.length;\n\n\twhile ( i-- ) {\n\t\tname = cssPrefixes[ i ] + capName;\n\t\tif ( name in emptyStyle ) {\n\t\t\treturn name;\n\t\t}\n\t}\n}\n\n// Return a property mapped along what jQuery.cssProps suggests or to\n// a vendor prefixed property.\nfunction finalPropName( name ) {\n\tvar ret = jQuery.cssProps[ name ];\n\tif ( !ret ) {\n\t\tret = jQuery.cssProps[ name ] = vendorPropName( name ) || name;\n\t}\n\treturn ret;\n}\n\nfunction setPositiveNumber( elem, value, subtract ) {\n\n\t// Any relative (+/-) values have already been\n\t// normalized at this point\n\tvar matches = rcssNum.exec( value );\n\treturn matches ?\n\n\t\t// Guard against undefined \"subtract\", e.g., when used as in cssHooks\n\t\tMath.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || \"px\" ) :\n\t\tvalue;\n}\n\nfunction boxModelAdjustment( elem, dimension, box, isBorderBox, styles, computedVal ) {\n\tvar i = dimension === \"width\" ? 1 : 0,\n\t\textra = 0,\n\t\tdelta = 0;\n\n\t// Adjustment may not be necessary\n\tif ( box === ( isBorderBox ? \"border\" : \"content\" ) ) {\n\t\treturn 0;\n\t}\n\n\tfor ( ; i < 4; i += 2 ) {\n\n\t\t// Both box models exclude margin\n\t\tif ( box === \"margin\" ) {\n\t\t\tdelta += jQuery.css( elem, box + cssExpand[ i ], true, styles );\n\t\t}\n\n\t\t// If we get here with a content-box, we're seeking \"padding\" or \"border\" or \"margin\"\n\t\tif ( !isBorderBox ) {\n\n\t\t\t// Add padding\n\t\t\tdelta += jQuery.css( elem, \"padding\" + cssExpand[ i ], true, styles );\n\n\t\t\t// For \"border\" or \"margin\", add border\n\t\t\tif ( box !== \"padding\" ) {\n\t\t\t\tdelta += jQuery.css( elem, \"border\" + cssExpand[ i ] + \"Width\", true, styles );\n\n\t\t\t// But still keep track of it otherwise\n\t\t\t} else {\n\t\t\t\textra += jQuery.css( elem, \"border\" + cssExpand[ i ] + \"Width\", true, styles );\n\t\t\t}\n\n\t\t// If we get here with a border-box (content + padding + border), we're seeking \"content\" or\n\t\t// \"padding\" or \"margin\"\n\t\t} else {\n\n\t\t\t// For \"content\", subtract padding\n\t\t\tif ( box === \"content\" ) {\n\t\t\t\tdelta -= jQuery.css( elem, \"padding\" + cssExpand[ i ], true, styles );\n\t\t\t}\n\n\t\t\t// For \"content\" or \"padding\", subtract border\n\t\t\tif ( box !== \"margin\" ) {\n\t\t\t\tdelta -= jQuery.css( elem, \"border\" + cssExpand[ i ] + \"Width\", true, styles );\n\t\t\t}\n\t\t}\n\t}\n\n\t// Account for positive content-box scroll gutter when requested by providing computedVal\n\tif ( !isBorderBox && computedVal >= 0 ) {\n\n\t\t// offsetWidth/offsetHeight is a rounded sum of content, padding, scroll gutter, and border\n\t\t// Assuming integer scroll gutter, subtract the rest and round down\n\t\tdelta += Math.max( 0, Math.ceil(\n\t\t\telem[ \"offset\" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] -\n\t\t\tcomputedVal -\n\t\t\tdelta -\n\t\t\textra -\n\t\t\t0.5\n\t\t) );\n\t}\n\n\treturn delta;\n}\n\nfunction getWidthOrHeight( elem, dimension, extra ) {\n\n\t// Start with computed style\n\tvar styles = getStyles( elem ),\n\t\tval = curCSS( elem, dimension, styles ),\n\t\tisBorderBox = jQuery.css( elem, \"boxSizing\", false, styles ) === \"border-box\",\n\t\tvalueIsBorderBox = isBorderBox;\n\n\t// Support: Firefox <=54\n\t// Return a confounding non-pixel value or feign ignorance, as appropriate.\n\tif ( rnumnonpx.test( val ) ) {\n\t\tif ( !extra ) {\n\t\t\treturn val;\n\t\t}\n\t\tval = \"auto\";\n\t}\n\n\t// Check for style in case a browser which returns unreliable values\n\t// for getComputedStyle silently falls back to the reliable elem.style\n\tvalueIsBorderBox = valueIsBorderBox &&\n\t\t( support.boxSizingReliable() || val === elem.style[ dimension ] );\n\n\t// Fall back to offsetWidth/offsetHeight when value is \"auto\"\n\t// This happens for inline elements with no explicit setting (gh-3571)\n\t// Support: Android <=4.1 - 4.3 only\n\t// Also use offsetWidth/offsetHeight for misreported inline dimensions (gh-3602)\n\tif ( val === \"auto\" ||\n\t\t!parseFloat( val ) && jQuery.css( elem, \"display\", false, styles ) === \"inline\" ) {\n\n\t\tval = elem[ \"offset\" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ];\n\n\t\t// offsetWidth/offsetHeight provide border-box values\n\t\tvalueIsBorderBox = true;\n\t}\n\n\t// Normalize \"\" and auto\n\tval = parseFloat( val ) || 0;\n\n\t// Adjust for the element's box model\n\treturn ( val +\n\t\tboxModelAdjustment(\n\t\t\telem,\n\t\t\tdimension,\n\t\t\textra || ( isBorderBox ? \"border\" : \"content\" ),\n\t\t\tvalueIsBorderBox,\n\t\t\tstyles,\n\n\t\t\t// Provide the current computed size to request scroll gutter calculation (gh-3589)\n\t\t\tval\n\t\t)\n\t) + \"px\";\n}\n\njQuery.extend( {\n\n\t// Add in style property hooks for overriding the default\n\t// behavior of getting and setting a style property\n\tcssHooks: {\n\t\topacity: {\n\t\t\tget: function( elem, computed ) {\n\t\t\t\tif ( computed ) {\n\n\t\t\t\t\t// We should always get a number back from opacity\n\t\t\t\t\tvar ret = curCSS( elem, \"opacity\" );\n\t\t\t\t\treturn ret === \"\" ? \"1\" : ret;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\t// Don't automatically add \"px\" to these possibly-unitless properties\n\tcssNumber: {\n\t\t\"animationIterationCount\": true,\n\t\t\"columnCount\": true,\n\t\t\"fillOpacity\": true,\n\t\t\"flexGrow\": true,\n\t\t\"flexShrink\": true,\n\t\t\"fontWeight\": true,\n\t\t\"lineHeight\": true,\n\t\t\"opacity\": true,\n\t\t\"order\": true,\n\t\t\"orphans\": true,\n\t\t\"widows\": true,\n\t\t\"zIndex\": true,\n\t\t\"zoom\": true\n\t},\n\n\t// Add in properties whose names you wish to fix before\n\t// setting or getting the value\n\tcssProps: {},\n\n\t// Get and set the style property on a DOM Node\n\tstyle: function( elem, name, value, extra ) {\n\n\t\t// Don't set styles on text and comment nodes\n\t\tif ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Make sure that we're working with the right name\n\t\tvar ret, type, hooks,\n\t\t\torigName = camelCase( name ),\n\t\t\tisCustomProp = rcustomProp.test( name ),\n\t\t\tstyle = elem.style;\n\n\t\t// Make sure that we're working with the right name. We don't\n\t\t// want to query the value if it is a CSS custom property\n\t\t// since they are user-defined.\n\t\tif ( !isCustomProp ) {\n\t\t\tname = finalPropName( origName );\n\t\t}\n\n\t\t// Gets hook for the prefixed version, then unprefixed version\n\t\thooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];\n\n\t\t// Check if we're setting a value\n\t\tif ( value !== undefined ) {\n\t\t\ttype = typeof value;\n\n\t\t\t// Convert \"+=\" or \"-=\" to relative numbers (#7345)\n\t\t\tif ( type === \"string\" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) {\n\t\t\t\tvalue = adjustCSS( elem, name, ret );\n\n\t\t\t\t// Fixes bug #9237\n\t\t\t\ttype = \"number\";\n\t\t\t}\n\n\t\t\t// Make sure that null and NaN values aren't set (#7116)\n\t\t\tif ( value == null || value !== value ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// If a number was passed in, add the unit (except for certain CSS properties)\n\t\t\tif ( type === \"number\" ) {\n\t\t\t\tvalue += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? \"\" : \"px\" );\n\t\t\t}\n\n\t\t\t// background-* props affect original clone's values\n\t\t\tif ( !support.clearCloneStyle && value === \"\" && name.indexOf( \"background\" ) === 0 ) {\n\t\t\t\tstyle[ name ] = \"inherit\";\n\t\t\t}\n\n\t\t\t// If a hook was provided, use that value, otherwise just set the specified value\n\t\t\tif ( !hooks || !( \"set\" in hooks ) ||\n\t\t\t\t( value = hooks.set( elem, value, extra ) ) !== undefined ) {\n\n\t\t\t\tif ( isCustomProp ) {\n\t\t\t\t\tstyle.setProperty( name, value );\n\t\t\t\t} else {\n\t\t\t\t\tstyle[ name ] = value;\n\t\t\t\t}\n\t\t\t}\n\n\t\t} else {\n\n\t\t\t// If a hook was provided get the non-computed value from there\n\t\t\tif ( hooks && \"get\" in hooks &&\n\t\t\t\t( ret = hooks.get( elem, false, extra ) ) !== undefined ) {\n\n\t\t\t\treturn ret;\n\t\t\t}\n\n\t\t\t// Otherwise just get the value from the style object\n\t\t\treturn style[ name ];\n\t\t}\n\t},\n\n\tcss: function( elem, name, extra, styles ) {\n\t\tvar val, num, hooks,\n\t\t\torigName = camelCase( name ),\n\t\t\tisCustomProp = rcustomProp.test( name );\n\n\t\t// Make sure that we're working with the right name. We don't\n\t\t// want to modify the value if it is a CSS custom property\n\t\t// since they are user-defined.\n\t\tif ( !isCustomProp ) {\n\t\t\tname = finalPropName( origName );\n\t\t}\n\n\t\t// Try prefixed name followed by the unprefixed name\n\t\thooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];\n\n\t\t// If a hook was provided get the computed value from there\n\t\tif ( hooks && \"get\" in hooks ) {\n\t\t\tval = hooks.get( elem, true, extra );\n\t\t}\n\n\t\t// Otherwise, if a way to get the computed value exists, use that\n\t\tif ( val === undefined ) {\n\t\t\tval = curCSS( elem, name, styles );\n\t\t}\n\n\t\t// Convert \"normal\" to computed value\n\t\tif ( val === \"normal\" && name in cssNormalTransform ) {\n\t\t\tval = cssNormalTransform[ name ];\n\t\t}\n\n\t\t// Make numeric if forced or a qualifier was provided and val looks numeric\n\t\tif ( extra === \"\" || extra ) {\n\t\t\tnum = parseFloat( val );\n\t\t\treturn extra === true || isFinite( num ) ? num || 0 : val;\n\t\t}\n\n\t\treturn val;\n\t}\n} );\n\njQuery.each( [ \"height\", \"width\" ], function( i, dimension ) {\n\tjQuery.cssHooks[ dimension ] = {\n\t\tget: function( elem, computed, extra ) {\n\t\t\tif ( computed ) {\n\n\t\t\t\t// Certain elements can have dimension info if we invisibly show them\n\t\t\t\t// but it must have a current display style that would benefit\n\t\t\t\treturn rdisplayswap.test( jQuery.css( elem, \"display\" ) ) &&\n\n\t\t\t\t\t// Support: Safari 8+\n\t\t\t\t\t// Table columns in Safari have non-zero offsetWidth & zero\n\t\t\t\t\t// getBoundingClientRect().width unless display is changed.\n\t\t\t\t\t// Support: IE <=11 only\n\t\t\t\t\t// Running getBoundingClientRect on a disconnected node\n\t\t\t\t\t// in IE throws an error.\n\t\t\t\t\t( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ?\n\t\t\t\t\t\tswap( elem, cssShow, function() {\n\t\t\t\t\t\t\treturn getWidthOrHeight( elem, dimension, extra );\n\t\t\t\t\t\t} ) :\n\t\t\t\t\t\tgetWidthOrHeight( elem, dimension, extra );\n\t\t\t}\n\t\t},\n\n\t\tset: function( elem, value, extra ) {\n\t\t\tvar matches,\n\t\t\t\tstyles = getStyles( elem ),\n\t\t\t\tisBorderBox = jQuery.css( elem, \"boxSizing\", false, styles ) === \"border-box\",\n\t\t\t\tsubtract = extra && boxModelAdjustment(\n\t\t\t\t\telem,\n\t\t\t\t\tdimension,\n\t\t\t\t\textra,\n\t\t\t\t\tisBorderBox,\n\t\t\t\t\tstyles\n\t\t\t\t);\n\n\t\t\t// Account for unreliable border-box dimensions by comparing offset* to computed and\n\t\t\t// faking a content-box to get border and padding (gh-3699)\n\t\t\tif ( isBorderBox && support.scrollboxSize() === styles.position ) {\n\t\t\t\tsubtract -= Math.ceil(\n\t\t\t\t\telem[ \"offset\" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] -\n\t\t\t\t\tparseFloat( styles[ dimension ] ) -\n\t\t\t\t\tboxModelAdjustment( elem, dimension, \"border\", false, styles ) -\n\t\t\t\t\t0.5\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Convert to pixels if value adjustment is needed\n\t\t\tif ( subtract && ( matches = rcssNum.exec( value ) ) &&\n\t\t\t\t( matches[ 3 ] || \"px\" ) !== \"px\" ) {\n\n\t\t\t\telem.style[ dimension ] = value;\n\t\t\t\tvalue = jQuery.css( elem, dimension );\n\t\t\t}\n\n\t\t\treturn setPositiveNumber( elem, value, subtract );\n\t\t}\n\t};\n} );\n\njQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft,\n\tfunction( elem, computed ) {\n\t\tif ( computed ) {\n\t\t\treturn ( parseFloat( curCSS( elem, \"marginLeft\" ) ) ||\n\t\t\t\telem.getBoundingClientRect().left -\n\t\t\t\t\tswap( elem, { marginLeft: 0 }, function() {\n\t\t\t\t\t\treturn elem.getBoundingClientRect().left;\n\t\t\t\t\t} )\n\t\t\t\t) + \"px\";\n\t\t}\n\t}\n);\n\n// These hooks are used by animate to expand properties\njQuery.each( {\n\tmargin: \"\",\n\tpadding: \"\",\n\tborder: \"Width\"\n}, function( prefix, suffix ) {\n\tjQuery.cssHooks[ prefix + suffix ] = {\n\t\texpand: function( value ) {\n\t\t\tvar i = 0,\n\t\t\t\texpanded = {},\n\n\t\t\t\t// Assumes a single number if not a string\n\t\t\t\tparts = typeof value === \"string\" ? value.split( \" \" ) : [ value ];\n\n\t\t\tfor ( ; i < 4; i++ ) {\n\t\t\t\texpanded[ prefix + cssExpand[ i ] + suffix ] =\n\t\t\t\t\tparts[ i ] || parts[ i - 2 ] || parts[ 0 ];\n\t\t\t}\n\n\t\t\treturn expanded;\n\t\t}\n\t};\n\n\tif ( prefix !== \"margin\" ) {\n\t\tjQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;\n\t}\n} );\n\njQuery.fn.extend( {\n\tcss: function( name, value ) {\n\t\treturn access( this, function( elem, name, value ) {\n\t\t\tvar styles, len,\n\t\t\t\tmap = {},\n\t\t\t\ti = 0;\n\n\t\t\tif ( Array.isArray( name ) ) {\n\t\t\t\tstyles = getStyles( elem );\n\t\t\t\tlen = name.length;\n\n\t\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\t\tmap[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );\n\t\t\t\t}\n\n\t\t\t\treturn map;\n\t\t\t}\n\n\t\t\treturn value !== undefined ?\n\t\t\t\tjQuery.style( elem, name, value ) :\n\t\t\t\tjQuery.css( elem, name );\n\t\t}, name, value, arguments.length > 1 );\n\t}\n} );\n\n\nfunction Tween( elem, options, prop, end, easing ) {\n\treturn new Tween.prototype.init( elem, options, prop, end, easing );\n}\njQuery.Tween = Tween;\n\nTween.prototype = {\n\tconstructor: Tween,\n\tinit: function( elem, options, prop, end, easing, unit ) {\n\t\tthis.elem = elem;\n\t\tthis.prop = prop;\n\t\tthis.easing = easing || jQuery.easing._default;\n\t\tthis.options = options;\n\t\tthis.start = this.now = this.cur();\n\t\tthis.end = end;\n\t\tthis.unit = unit || ( jQuery.cssNumber[ prop ] ? \"\" : \"px\" );\n\t},\n\tcur: function() {\n\t\tvar hooks = Tween.propHooks[ this.prop ];\n\n\t\treturn hooks && hooks.get ?\n\t\t\thooks.get( this ) :\n\t\t\tTween.propHooks._default.get( this );\n\t},\n\trun: function( percent ) {\n\t\tvar eased,\n\t\t\thooks = Tween.propHooks[ this.prop ];\n\n\t\tif ( this.options.duration ) {\n\t\t\tthis.pos = eased = jQuery.easing[ this.easing ](\n\t\t\t\tpercent, this.options.duration * percent, 0, 1, this.options.duration\n\t\t\t);\n\t\t} else {\n\t\t\tthis.pos = eased = percent;\n\t\t}\n\t\tthis.now = ( this.end - this.start ) * eased + this.start;\n\n\t\tif ( this.options.step ) {\n\t\t\tthis.options.step.call( this.elem, this.now, this );\n\t\t}\n\n\t\tif ( hooks && hooks.set ) {\n\t\t\thooks.set( this );\n\t\t} else {\n\t\t\tTween.propHooks._default.set( this );\n\t\t}\n\t\treturn this;\n\t}\n};\n\nTween.prototype.init.prototype = Tween.prototype;\n\nTween.propHooks = {\n\t_default: {\n\t\tget: function( tween ) {\n\t\t\tvar result;\n\n\t\t\t// Use a property on the element directly when it is not a DOM element,\n\t\t\t// or when there is no matching style property that exists.\n\t\t\tif ( tween.elem.nodeType !== 1 ||\n\t\t\t\ttween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) {\n\t\t\t\treturn tween.elem[ tween.prop ];\n\t\t\t}\n\n\t\t\t// Passing an empty string as a 3rd parameter to .css will automatically\n\t\t\t// attempt a parseFloat and fallback to a string if the parse fails.\n\t\t\t// Simple values such as \"10px\" are parsed to Float;\n\t\t\t// complex values such as \"rotate(1rad)\" are returned as-is.\n\t\t\tresult = jQuery.css( tween.elem, tween.prop, \"\" );\n\n\t\t\t// Empty strings, null, undefined and \"auto\" are converted to 0.\n\t\t\treturn !result || result === \"auto\" ? 0 : result;\n\t\t},\n\t\tset: function( tween ) {\n\n\t\t\t// Use step hook for back compat.\n\t\t\t// Use cssHook if its there.\n\t\t\t// Use .style if available and use plain properties where available.\n\t\t\tif ( jQuery.fx.step[ tween.prop ] ) {\n\t\t\t\tjQuery.fx.step[ tween.prop ]( tween );\n\t\t\t} else if ( tween.elem.nodeType === 1 &&\n\t\t\t\t( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null ||\n\t\t\t\t\tjQuery.cssHooks[ tween.prop ] ) ) {\n\t\t\t\tjQuery.style( tween.elem, tween.prop, tween.now + tween.unit );\n\t\t\t} else {\n\t\t\t\ttween.elem[ tween.prop ] = tween.now;\n\t\t\t}\n\t\t}\n\t}\n};\n\n// Support: IE <=9 only\n// Panic based approach to setting things on disconnected nodes\nTween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {\n\tset: function( tween ) {\n\t\tif ( tween.elem.nodeType && tween.elem.parentNode ) {\n\t\t\ttween.elem[ tween.prop ] = tween.now;\n\t\t}\n\t}\n};\n\njQuery.easing = {\n\tlinear: function( p ) {\n\t\treturn p;\n\t},\n\tswing: function( p ) {\n\t\treturn 0.5 - Math.cos( p * Math.PI ) / 2;\n\t},\n\t_default: \"swing\"\n};\n\njQuery.fx = Tween.prototype.init;\n\n// Back compat <1.8 extension point\njQuery.fx.step = {};\n\n\n\n\nvar\n\tfxNow, inProgress,\n\trfxtypes = /^(?:toggle|show|hide)$/,\n\trrun = /queueHooks$/;\n\nfunction schedule() {\n\tif ( inProgress ) {\n\t\tif ( document.hidden === false && window.requestAnimationFrame ) {\n\t\t\twindow.requestAnimationFrame( schedule );\n\t\t} else {\n\t\t\twindow.setTimeout( schedule, jQuery.fx.interval );\n\t\t}\n\n\t\tjQuery.fx.tick();\n\t}\n}\n\n// Animations created synchronously will run synchronously\nfunction createFxNow() {\n\twindow.setTimeout( function() {\n\t\tfxNow = undefined;\n\t} );\n\treturn ( fxNow = Date.now() );\n}\n\n// Generate parameters to create a standard animation\nfunction genFx( type, includeWidth ) {\n\tvar which,\n\t\ti = 0,\n\t\tattrs = { height: type };\n\n\t// If we include width, step value is 1 to do all cssExpand values,\n\t// otherwise step value is 2 to skip over Left and Right\n\tincludeWidth = includeWidth ? 1 : 0;\n\tfor ( ; i < 4; i += 2 - includeWidth ) {\n\t\twhich = cssExpand[ i ];\n\t\tattrs[ \"margin\" + which ] = attrs[ \"padding\" + which ] = type;\n\t}\n\n\tif ( includeWidth ) {\n\t\tattrs.opacity = attrs.width = type;\n\t}\n\n\treturn attrs;\n}\n\nfunction createTween( value, prop, animation ) {\n\tvar tween,\n\t\tcollection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ \"*\" ] ),\n\t\tindex = 0,\n\t\tlength = collection.length;\n\tfor ( ; index < length; index++ ) {\n\t\tif ( ( tween = collection[ index ].call( animation, prop, value ) ) ) {\n\n\t\t\t// We're done with this property\n\t\t\treturn tween;\n\t\t}\n\t}\n}\n\nfunction defaultPrefilter( elem, props, opts ) {\n\tvar prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display,\n\t\tisBox = \"width\" in props || \"height\" in props,\n\t\tanim = this,\n\t\torig = {},\n\t\tstyle = elem.style,\n\t\thidden = elem.nodeType && isHiddenWithinTree( elem ),\n\t\tdataShow = dataPriv.get( elem, \"fxshow\" );\n\n\t// Queue-skipping animations hijack the fx hooks\n\tif ( !opts.queue ) {\n\t\thooks = jQuery._queueHooks( elem, \"fx\" );\n\t\tif ( hooks.unqueued == null ) {\n\t\t\thooks.unqueued = 0;\n\t\t\toldfire = hooks.empty.fire;\n\t\t\thooks.empty.fire = function() {\n\t\t\t\tif ( !hooks.unqueued ) {\n\t\t\t\t\toldfire();\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t\thooks.unqueued++;\n\n\t\tanim.always( function() {\n\n\t\t\t// Ensure the complete handler is called before this completes\n\t\t\tanim.always( function() {\n\t\t\t\thooks.unqueued--;\n\t\t\t\tif ( !jQuery.queue( elem, \"fx\" ).length ) {\n\t\t\t\t\thooks.empty.fire();\n\t\t\t\t}\n\t\t\t} );\n\t\t} );\n\t}\n\n\t// Detect show/hide animations\n\tfor ( prop in props ) {\n\t\tvalue = props[ prop ];\n\t\tif ( rfxtypes.test( value ) ) {\n\t\t\tdelete props[ prop ];\n\t\t\ttoggle = toggle || value === \"toggle\";\n\t\t\tif ( value === ( hidden ? \"hide\" : \"show\" ) ) {\n\n\t\t\t\t// Pretend to be hidden if this is a \"show\" and\n\t\t\t\t// there is still data from a stopped show/hide\n\t\t\t\tif ( value === \"show\" && dataShow && dataShow[ prop ] !== undefined ) {\n\t\t\t\t\thidden = true;\n\n\t\t\t\t// Ignore all other no-op show/hide data\n\t\t\t\t} else {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\torig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop );\n\t\t}\n\t}\n\n\t// Bail out if this is a no-op like .hide().hide()\n\tpropTween = !jQuery.isEmptyObject( props );\n\tif ( !propTween && jQuery.isEmptyObject( orig ) ) {\n\t\treturn;\n\t}\n\n\t// Restrict \"overflow\" and \"display\" styles during box animations\n\tif ( isBox && elem.nodeType === 1 ) {\n\n\t\t// Support: IE <=9 - 11, Edge 12 - 15\n\t\t// Record all 3 overflow attributes because IE does not infer the shorthand\n\t\t// from identically-valued overflowX and overflowY and Edge just mirrors\n\t\t// the overflowX value there.\n\t\topts.overflow = [ style.overflow, style.overflowX, style.overflowY ];\n\n\t\t// Identify a display type, preferring old show/hide data over the CSS cascade\n\t\trestoreDisplay = dataShow && dataShow.display;\n\t\tif ( restoreDisplay == null ) {\n\t\t\trestoreDisplay = dataPriv.get( elem, \"display\" );\n\t\t}\n\t\tdisplay = jQuery.css( elem, \"display\" );\n\t\tif ( display === \"none\" ) {\n\t\t\tif ( restoreDisplay ) {\n\t\t\t\tdisplay = restoreDisplay;\n\t\t\t} else {\n\n\t\t\t\t// Get nonempty value(s) by temporarily forcing visibility\n\t\t\t\tshowHide( [ elem ], true );\n\t\t\t\trestoreDisplay = elem.style.display || restoreDisplay;\n\t\t\t\tdisplay = jQuery.css( elem, \"display\" );\n\t\t\t\tshowHide( [ elem ] );\n\t\t\t}\n\t\t}\n\n\t\t// Animate inline elements as inline-block\n\t\tif ( display === \"inline\" || display === \"inline-block\" && restoreDisplay != null ) {\n\t\t\tif ( jQuery.css( elem, \"float\" ) === \"none\" ) {\n\n\t\t\t\t// Restore the original display value at the end of pure show/hide animations\n\t\t\t\tif ( !propTween ) {\n\t\t\t\t\tanim.done( function() {\n\t\t\t\t\t\tstyle.display = restoreDisplay;\n\t\t\t\t\t} );\n\t\t\t\t\tif ( restoreDisplay == null ) {\n\t\t\t\t\t\tdisplay = style.display;\n\t\t\t\t\t\trestoreDisplay = display === \"none\" ? \"\" : display;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tstyle.display = \"inline-block\";\n\t\t\t}\n\t\t}\n\t}\n\n\tif ( opts.overflow ) {\n\t\tstyle.overflow = \"hidden\";\n\t\tanim.always( function() {\n\t\t\tstyle.overflow = opts.overflow[ 0 ];\n\t\t\tstyle.overflowX = opts.overflow[ 1 ];\n\t\t\tstyle.overflowY = opts.overflow[ 2 ];\n\t\t} );\n\t}\n\n\t// Implement show/hide animations\n\tpropTween = false;\n\tfor ( prop in orig ) {\n\n\t\t// General show/hide setup for this element animation\n\t\tif ( !propTween ) {\n\t\t\tif ( dataShow ) {\n\t\t\t\tif ( \"hidden\" in dataShow ) {\n\t\t\t\t\thidden = dataShow.hidden;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tdataShow = dataPriv.access( elem, \"fxshow\", { display: restoreDisplay } );\n\t\t\t}\n\n\t\t\t// Store hidden/visible for toggle so `.stop().toggle()` \"reverses\"\n\t\t\tif ( toggle ) {\n\t\t\t\tdataShow.hidden = !hidden;\n\t\t\t}\n\n\t\t\t// Show elements before animating them\n\t\t\tif ( hidden ) {\n\t\t\t\tshowHide( [ elem ], true );\n\t\t\t}\n\n\t\t\t/* eslint-disable no-loop-func */\n\n\t\t\tanim.done( function() {\n\n\t\t\t/* eslint-enable no-loop-func */\n\n\t\t\t\t// The final step of a \"hide\" animation is actually hiding the element\n\t\t\t\tif ( !hidden ) {\n\t\t\t\t\tshowHide( [ elem ] );\n\t\t\t\t}\n\t\t\t\tdataPriv.remove( elem, \"fxshow\" );\n\t\t\t\tfor ( prop in orig ) {\n\t\t\t\t\tjQuery.style( elem, prop, orig[ prop ] );\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\n\t\t// Per-property setup\n\t\tpropTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim );\n\t\tif ( !( prop in dataShow ) ) {\n\t\t\tdataShow[ prop ] = propTween.start;\n\t\t\tif ( hidden ) {\n\t\t\t\tpropTween.end = propTween.start;\n\t\t\t\tpropTween.start = 0;\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunction propFilter( props, specialEasing ) {\n\tvar index, name, easing, value, hooks;\n\n\t// camelCase, specialEasing and expand cssHook pass\n\tfor ( index in props ) {\n\t\tname = camelCase( index );\n\t\teasing = specialEasing[ name ];\n\t\tvalue = props[ index ];\n\t\tif ( Array.isArray( value ) ) {\n\t\t\teasing = value[ 1 ];\n\t\t\tvalue = props[ index ] = value[ 0 ];\n\t\t}\n\n\t\tif ( index !== name ) {\n\t\t\tprops[ name ] = value;\n\t\t\tdelete props[ index ];\n\t\t}\n\n\t\thooks = jQuery.cssHooks[ name ];\n\t\tif ( hooks && \"expand\" in hooks ) {\n\t\t\tvalue = hooks.expand( value );\n\t\t\tdelete props[ name ];\n\n\t\t\t// Not quite $.extend, this won't overwrite existing keys.\n\t\t\t// Reusing 'index' because we have the correct \"name\"\n\t\t\tfor ( index in value ) {\n\t\t\t\tif ( !( index in props ) ) {\n\t\t\t\t\tprops[ index ] = value[ index ];\n\t\t\t\t\tspecialEasing[ index ] = easing;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tspecialEasing[ name ] = easing;\n\t\t}\n\t}\n}\n\nfunction Animation( elem, properties, options ) {\n\tvar result,\n\t\tstopped,\n\t\tindex = 0,\n\t\tlength = Animation.prefilters.length,\n\t\tdeferred = jQuery.Deferred().always( function() {\n\n\t\t\t// Don't match elem in the :animated selector\n\t\t\tdelete tick.elem;\n\t\t} ),\n\t\ttick = function() {\n\t\t\tif ( stopped ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tvar currentTime = fxNow || createFxNow(),\n\t\t\t\tremaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),\n\n\t\t\t\t// Support: Android 2.3 only\n\t\t\t\t// Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497)\n\t\t\t\ttemp = remaining / animation.duration || 0,\n\t\t\t\tpercent = 1 - temp,\n\t\t\t\tindex = 0,\n\t\t\t\tlength = animation.tweens.length;\n\n\t\t\tfor ( ; index < length; index++ ) {\n\t\t\t\tanimation.tweens[ index ].run( percent );\n\t\t\t}\n\n\t\t\tdeferred.notifyWith( elem, [ animation, percent, remaining ] );\n\n\t\t\t// If there's more to do, yield\n\t\t\tif ( percent < 1 && length ) {\n\t\t\t\treturn remaining;\n\t\t\t}\n\n\t\t\t// If this was an empty animation, synthesize a final progress notification\n\t\t\tif ( !length ) {\n\t\t\t\tdeferred.notifyWith( elem, [ animation, 1, 0 ] );\n\t\t\t}\n\n\t\t\t// Resolve the animation and report its conclusion\n\t\t\tdeferred.resolveWith( elem, [ animation ] );\n\t\t\treturn false;\n\t\t},\n\t\tanimation = deferred.promise( {\n\t\t\telem: elem,\n\t\t\tprops: jQuery.extend( {}, properties ),\n\t\t\topts: jQuery.extend( true, {\n\t\t\t\tspecialEasing: {},\n\t\t\t\teasing: jQuery.easing._default\n\t\t\t}, options ),\n\t\t\toriginalProperties: properties,\n\t\t\toriginalOptions: options,\n\t\t\tstartTime: fxNow || createFxNow(),\n\t\t\tduration: options.duration,\n\t\t\ttweens: [],\n\t\t\tcreateTween: function( prop, end ) {\n\t\t\t\tvar tween = jQuery.Tween( elem, animation.opts, prop, end,\n\t\t\t\t\t\tanimation.opts.specialEasing[ prop ] || animation.opts.easing );\n\t\t\t\tanimation.tweens.push( tween );\n\t\t\t\treturn tween;\n\t\t\t},\n\t\t\tstop: function( gotoEnd ) {\n\t\t\t\tvar index = 0,\n\n\t\t\t\t\t// If we are going to the end, we want to run all the tweens\n\t\t\t\t\t// otherwise we skip this part\n\t\t\t\t\tlength = gotoEnd ? animation.tweens.length : 0;\n\t\t\t\tif ( stopped ) {\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\t\t\t\tstopped = true;\n\t\t\t\tfor ( ; index < length; index++ ) {\n\t\t\t\t\tanimation.tweens[ index ].run( 1 );\n\t\t\t\t}\n\n\t\t\t\t// Resolve when we played the last frame; otherwise, reject\n\t\t\t\tif ( gotoEnd ) {\n\t\t\t\t\tdeferred.notifyWith( elem, [ animation, 1, 0 ] );\n\t\t\t\t\tdeferred.resolveWith( elem, [ animation, gotoEnd ] );\n\t\t\t\t} else {\n\t\t\t\t\tdeferred.rejectWith( elem, [ animation, gotoEnd ] );\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t}\n\t\t} ),\n\t\tprops = animation.props;\n\n\tpropFilter( props, animation.opts.specialEasing );\n\n\tfor ( ; index < length; index++ ) {\n\t\tresult = Animation.prefilters[ index ].call( animation, elem, props, animation.opts );\n\t\tif ( result ) {\n\t\t\tif ( isFunction( result.stop ) ) {\n\t\t\t\tjQuery._queueHooks( animation.elem, animation.opts.queue ).stop =\n\t\t\t\t\tresult.stop.bind( result );\n\t\t\t}\n\t\t\treturn result;\n\t\t}\n\t}\n\n\tjQuery.map( props, createTween, animation );\n\n\tif ( isFunction( animation.opts.start ) ) {\n\t\tanimation.opts.start.call( elem, animation );\n\t}\n\n\t// Attach callbacks from options\n\tanimation\n\t\t.progress( animation.opts.progress )\n\t\t.done( animation.opts.done, animation.opts.complete )\n\t\t.fail( animation.opts.fail )\n\t\t.always( animation.opts.always );\n\n\tjQuery.fx.timer(\n\t\tjQuery.extend( tick, {\n\t\t\telem: elem,\n\t\t\tanim: animation,\n\t\t\tqueue: animation.opts.queue\n\t\t} )\n\t);\n\n\treturn animation;\n}\n\njQuery.Animation = jQuery.extend( Animation, {\n\n\ttweeners: {\n\t\t\"*\": [ function( prop, value ) {\n\t\t\tvar tween = this.createTween( prop, value );\n\t\t\tadjustCSS( tween.elem, prop, rcssNum.exec( value ), tween );\n\t\t\treturn tween;\n\t\t} ]\n\t},\n\n\ttweener: function( props, callback ) {\n\t\tif ( isFunction( props ) ) {\n\t\t\tcallback = props;\n\t\t\tprops = [ \"*\" ];\n\t\t} else {\n\t\t\tprops = props.match( rnothtmlwhite );\n\t\t}\n\n\t\tvar prop,\n\t\t\tindex = 0,\n\t\t\tlength = props.length;\n\n\t\tfor ( ; index < length; index++ ) {\n\t\t\tprop = props[ index ];\n\t\t\tAnimation.tweeners[ prop ] = Animation.tweeners[ prop ] || [];\n\t\t\tAnimation.tweeners[ prop ].unshift( callback );\n\t\t}\n\t},\n\n\tprefilters: [ defaultPrefilter ],\n\n\tprefilter: function( callback, prepend ) {\n\t\tif ( prepend ) {\n\t\t\tAnimation.prefilters.unshift( callback );\n\t\t} else {\n\t\t\tAnimation.prefilters.push( callback );\n\t\t}\n\t}\n} );\n\njQuery.speed = function( speed, easing, fn ) {\n\tvar opt = speed && typeof speed === \"object\" ? jQuery.extend( {}, speed ) : {\n\t\tcomplete: fn || !fn && easing ||\n\t\t\tisFunction( speed ) && speed,\n\t\tduration: speed,\n\t\teasing: fn && easing || easing && !isFunction( easing ) && easing\n\t};\n\n\t// Go to the end state if fx are off\n\tif ( jQuery.fx.off ) {\n\t\topt.duration = 0;\n\n\t} else {\n\t\tif ( typeof opt.duration !== \"number\" ) {\n\t\t\tif ( opt.duration in jQuery.fx.speeds ) {\n\t\t\t\topt.duration = jQuery.fx.speeds[ opt.duration ];\n\n\t\t\t} else {\n\t\t\t\topt.duration = jQuery.fx.speeds._default;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Normalize opt.queue - true/undefined/null -> \"fx\"\n\tif ( opt.queue == null || opt.queue === true ) {\n\t\topt.queue = \"fx\";\n\t}\n\n\t// Queueing\n\topt.old = opt.complete;\n\n\topt.complete = function() {\n\t\tif ( isFunction( opt.old ) ) {\n\t\t\topt.old.call( this );\n\t\t}\n\n\t\tif ( opt.queue ) {\n\t\t\tjQuery.dequeue( this, opt.queue );\n\t\t}\n\t};\n\n\treturn opt;\n};\n\njQuery.fn.extend( {\n\tfadeTo: function( speed, to, easing, callback ) {\n\n\t\t// Show any hidden elements after setting opacity to 0\n\t\treturn this.filter( isHiddenWithinTree ).css( \"opacity\", 0 ).show()\n\n\t\t\t// Animate to the value specified\n\t\t\t.end().animate( { opacity: to }, speed, easing, callback );\n\t},\n\tanimate: function( prop, speed, easing, callback ) {\n\t\tvar empty = jQuery.isEmptyObject( prop ),\n\t\t\toptall = jQuery.speed( speed, easing, callback ),\n\t\t\tdoAnimation = function() {\n\n\t\t\t\t// Operate on a copy of prop so per-property easing won't be lost\n\t\t\t\tvar anim = Animation( this, jQuery.extend( {}, prop ), optall );\n\n\t\t\t\t// Empty animations, or finishing resolves immediately\n\t\t\t\tif ( empty || dataPriv.get( this, \"finish\" ) ) {\n\t\t\t\t\tanim.stop( true );\n\t\t\t\t}\n\t\t\t};\n\t\t\tdoAnimation.finish = doAnimation;\n\n\t\treturn empty || optall.queue === false ?\n\t\t\tthis.each( doAnimation ) :\n\t\t\tthis.queue( optall.queue, doAnimation );\n\t},\n\tstop: function( type, clearQueue, gotoEnd ) {\n\t\tvar stopQueue = function( hooks ) {\n\t\t\tvar stop = hooks.stop;\n\t\t\tdelete hooks.stop;\n\t\t\tstop( gotoEnd );\n\t\t};\n\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tgotoEnd = clearQueue;\n\t\t\tclearQueue = type;\n\t\t\ttype = undefined;\n\t\t}\n\t\tif ( clearQueue && type !== false ) {\n\t\t\tthis.queue( type || \"fx\", [] );\n\t\t}\n\n\t\treturn this.each( function() {\n\t\t\tvar dequeue = true,\n\t\t\t\tindex = type != null && type + \"queueHooks\",\n\t\t\t\ttimers = jQuery.timers,\n\t\t\t\tdata = dataPriv.get( this );\n\n\t\t\tif ( index ) {\n\t\t\t\tif ( data[ index ] && data[ index ].stop ) {\n\t\t\t\t\tstopQueue( data[ index ] );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( index in data ) {\n\t\t\t\t\tif ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {\n\t\t\t\t\t\tstopQueue( data[ index ] );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor ( index = timers.length; index--; ) {\n\t\t\t\tif ( timers[ index ].elem === this &&\n\t\t\t\t\t( type == null || timers[ index ].queue === type ) ) {\n\n\t\t\t\t\ttimers[ index ].anim.stop( gotoEnd );\n\t\t\t\t\tdequeue = false;\n\t\t\t\t\ttimers.splice( index, 1 );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Start the next in the queue if the last step wasn't forced.\n\t\t\t// Timers currently will call their complete callbacks, which\n\t\t\t// will dequeue but only if they were gotoEnd.\n\t\t\tif ( dequeue || !gotoEnd ) {\n\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t}\n\t\t} );\n\t},\n\tfinish: function( type ) {\n\t\tif ( type !== false ) {\n\t\t\ttype = type || \"fx\";\n\t\t}\n\t\treturn this.each( function() {\n\t\t\tvar index,\n\t\t\t\tdata = dataPriv.get( this ),\n\t\t\t\tqueue = data[ type + \"queue\" ],\n\t\t\t\thooks = data[ type + \"queueHooks\" ],\n\t\t\t\ttimers = jQuery.timers,\n\t\t\t\tlength = queue ? queue.length : 0;\n\n\t\t\t// Enable finishing flag on private data\n\t\t\tdata.finish = true;\n\n\t\t\t// Empty the queue first\n\t\t\tjQuery.queue( this, type, [] );\n\n\t\t\tif ( hooks && hooks.stop ) {\n\t\t\t\thooks.stop.call( this, true );\n\t\t\t}\n\n\t\t\t// Look for any active animations, and finish them\n\t\t\tfor ( index = timers.length; index--; ) {\n\t\t\t\tif ( timers[ index ].elem === this && timers[ index ].queue === type ) {\n\t\t\t\t\ttimers[ index ].anim.stop( true );\n\t\t\t\t\ttimers.splice( index, 1 );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Look for any animations in the old queue and finish them\n\t\t\tfor ( index = 0; index < length; index++ ) {\n\t\t\t\tif ( queue[ index ] && queue[ index ].finish ) {\n\t\t\t\t\tqueue[ index ].finish.call( this );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Turn off finishing flag\n\t\t\tdelete data.finish;\n\t\t} );\n\t}\n} );\n\njQuery.each( [ \"toggle\", \"show\", \"hide\" ], function( i, name ) {\n\tvar cssFn = jQuery.fn[ name ];\n\tjQuery.fn[ name ] = function( speed, easing, callback ) {\n\t\treturn speed == null || typeof speed === \"boolean\" ?\n\t\t\tcssFn.apply( this, arguments ) :\n\t\t\tthis.animate( genFx( name, true ), speed, easing, callback );\n\t};\n} );\n\n// Generate shortcuts for custom animations\njQuery.each( {\n\tslideDown: genFx( \"show\" ),\n\tslideUp: genFx( \"hide\" ),\n\tslideToggle: genFx( \"toggle\" ),\n\tfadeIn: { opacity: \"show\" },\n\tfadeOut: { opacity: \"hide\" },\n\tfadeToggle: { opacity: \"toggle\" }\n}, function( name, props ) {\n\tjQuery.fn[ name ] = function( speed, easing, callback ) {\n\t\treturn this.animate( props, speed, easing, callback );\n\t};\n} );\n\njQuery.timers = [];\njQuery.fx.tick = function() {\n\tvar timer,\n\t\ti = 0,\n\t\ttimers = jQuery.timers;\n\n\tfxNow = Date.now();\n\n\tfor ( ; i < timers.length; i++ ) {\n\t\ttimer = timers[ i ];\n\n\t\t// Run the timer and safely remove it when done (allowing for external removal)\n\t\tif ( !timer() && timers[ i ] === timer ) {\n\t\t\ttimers.splice( i--, 1 );\n\t\t}\n\t}\n\n\tif ( !timers.length ) {\n\t\tjQuery.fx.stop();\n\t}\n\tfxNow = undefined;\n};\n\njQuery.fx.timer = function( timer ) {\n\tjQuery.timers.push( timer );\n\tjQuery.fx.start();\n};\n\njQuery.fx.interval = 13;\njQuery.fx.start = function() {\n\tif ( inProgress ) {\n\t\treturn;\n\t}\n\n\tinProgress = true;\n\tschedule();\n};\n\njQuery.fx.stop = function() {\n\tinProgress = null;\n};\n\njQuery.fx.speeds = {\n\tslow: 600,\n\tfast: 200,\n\n\t// Default speed\n\t_default: 400\n};\n\n\n// Based off of the plugin by Clint Helfers, with permission.\n// https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/\njQuery.fn.delay = function( time, type ) {\n\ttime = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;\n\ttype = type || \"fx\";\n\n\treturn this.queue( type, function( next, hooks ) {\n\t\tvar timeout = window.setTimeout( next, time );\n\t\thooks.stop = function() {\n\t\t\twindow.clearTimeout( timeout );\n\t\t};\n\t} );\n};\n\n\n( function() {\n\tvar input = document.createElement( \"input\" ),\n\t\tselect = document.createElement( \"select\" ),\n\t\topt = select.appendChild( document.createElement( \"option\" ) );\n\n\tinput.type = \"checkbox\";\n\n\t// Support: Android <=4.3 only\n\t// Default value for a checkbox should be \"on\"\n\tsupport.checkOn = input.value !== \"\";\n\n\t// Support: IE <=11 only\n\t// Must access selectedIndex to make default options select\n\tsupport.optSelected = opt.selected;\n\n\t// Support: IE <=11 only\n\t// An input loses its value after becoming a radio\n\tinput = document.createElement( \"input\" );\n\tinput.value = \"t\";\n\tinput.type = \"radio\";\n\tsupport.radioValue = input.value === \"t\";\n} )();\n\n\nvar boolHook,\n\tattrHandle = jQuery.expr.attrHandle;\n\njQuery.fn.extend( {\n\tattr: function( name, value ) {\n\t\treturn access( this, jQuery.attr, name, value, arguments.length > 1 );\n\t},\n\n\tremoveAttr: function( name ) {\n\t\treturn this.each( function() {\n\t\t\tjQuery.removeAttr( this, name );\n\t\t} );\n\t}\n} );\n\njQuery.extend( {\n\tattr: function( elem, name, value ) {\n\t\tvar ret, hooks,\n\t\t\tnType = elem.nodeType;\n\n\t\t// Don't get/set attributes on text, comment and attribute nodes\n\t\tif ( nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Fallback to prop when attributes are not supported\n\t\tif ( typeof elem.getAttribute === \"undefined\" ) {\n\t\t\treturn jQuery.prop( elem, name, value );\n\t\t}\n\n\t\t// Attribute hooks are determined by the lowercase version\n\t\t// Grab necessary hook if one is defined\n\t\tif ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {\n\t\t\thooks = jQuery.attrHooks[ name.toLowerCase() ] ||\n\t\t\t\t( jQuery.expr.match.bool.test( name ) ? boolHook : undefined );\n\t\t}\n\n\t\tif ( value !== undefined ) {\n\t\t\tif ( value === null ) {\n\t\t\t\tjQuery.removeAttr( elem, name );\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( hooks && \"set\" in hooks &&\n\t\t\t\t( ret = hooks.set( elem, value, name ) ) !== undefined ) {\n\t\t\t\treturn ret;\n\t\t\t}\n\n\t\t\telem.setAttribute( name, value + \"\" );\n\t\t\treturn value;\n\t\t}\n\n\t\tif ( hooks && \"get\" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) {\n\t\t\treturn ret;\n\t\t}\n\n\t\tret = jQuery.find.attr( elem, name );\n\n\t\t// Non-existent attributes return null, we normalize to undefined\n\t\treturn ret == null ? undefined : ret;\n\t},\n\n\tattrHooks: {\n\t\ttype: {\n\t\t\tset: function( elem, value ) {\n\t\t\t\tif ( !support.radioValue && value === \"radio\" &&\n\t\t\t\t\tnodeName( elem, \"input\" ) ) {\n\t\t\t\t\tvar val = elem.value;\n\t\t\t\t\telem.setAttribute( \"type\", value );\n\t\t\t\t\tif ( val ) {\n\t\t\t\t\t\telem.value = val;\n\t\t\t\t\t}\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\tremoveAttr: function( elem, value ) {\n\t\tvar name,\n\t\t\ti = 0,\n\n\t\t\t// Attribute names can contain non-HTML whitespace characters\n\t\t\t// https://html.spec.whatwg.org/multipage/syntax.html#attributes-2\n\t\t\tattrNames = value && value.match( rnothtmlwhite );\n\n\t\tif ( attrNames && elem.nodeType === 1 ) {\n\t\t\twhile ( ( name = attrNames[ i++ ] ) ) {\n\t\t\t\telem.removeAttribute( name );\n\t\t\t}\n\t\t}\n\t}\n} );\n\n// Hooks for boolean attributes\nboolHook = {\n\tset: function( elem, value, name ) {\n\t\tif ( value === false ) {\n\n\t\t\t// Remove boolean attributes when set to false\n\t\t\tjQuery.removeAttr( elem, name );\n\t\t} else {\n\t\t\telem.setAttribute( name, name );\n\t\t}\n\t\treturn name;\n\t}\n};\n\njQuery.each( jQuery.expr.match.bool.source.match( /\\w+/g ), function( i, name ) {\n\tvar getter = attrHandle[ name ] || jQuery.find.attr;\n\n\tattrHandle[ name ] = function( elem, name, isXML ) {\n\t\tvar ret, handle,\n\t\t\tlowercaseName = name.toLowerCase();\n\n\t\tif ( !isXML ) {\n\n\t\t\t// Avoid an infinite loop by temporarily removing this function from the getter\n\t\t\thandle = attrHandle[ lowercaseName ];\n\t\t\tattrHandle[ lowercaseName ] = ret;\n\t\t\tret = getter( elem, name, isXML ) != null ?\n\t\t\t\tlowercaseName :\n\t\t\t\tnull;\n\t\t\tattrHandle[ lowercaseName ] = handle;\n\t\t}\n\t\treturn ret;\n\t};\n} );\n\n\n\n\nvar rfocusable = /^(?:input|select|textarea|button)$/i,\n\trclickable = /^(?:a|area)$/i;\n\njQuery.fn.extend( {\n\tprop: function( name, value ) {\n\t\treturn access( this, jQuery.prop, name, value, arguments.length > 1 );\n\t},\n\n\tremoveProp: function( name ) {\n\t\treturn this.each( function() {\n\t\t\tdelete this[ jQuery.propFix[ name ] || name ];\n\t\t} );\n\t}\n} );\n\njQuery.extend( {\n\tprop: function( elem, name, value ) {\n\t\tvar ret, hooks,\n\t\t\tnType = elem.nodeType;\n\n\t\t// Don't get/set properties on text, comment and attribute nodes\n\t\tif ( nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {\n\n\t\t\t// Fix name and attach hooks\n\t\t\tname = jQuery.propFix[ name ] || name;\n\t\t\thooks = jQuery.propHooks[ name ];\n\t\t}\n\n\t\tif ( value !== undefined ) {\n\t\t\tif ( hooks && \"set\" in hooks &&\n\t\t\t\t( ret = hooks.set( elem, value, name ) ) !== undefined ) {\n\t\t\t\treturn ret;\n\t\t\t}\n\n\t\t\treturn ( elem[ name ] = value );\n\t\t}\n\n\t\tif ( hooks && \"get\" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) {\n\t\t\treturn ret;\n\t\t}\n\n\t\treturn elem[ name ];\n\t},\n\n\tpropHooks: {\n\t\ttabIndex: {\n\t\t\tget: function( elem ) {\n\n\t\t\t\t// Support: IE <=9 - 11 only\n\t\t\t\t// elem.tabIndex doesn't always return the\n\t\t\t\t// correct value when it hasn't been explicitly set\n\t\t\t\t// https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/\n\t\t\t\t// Use proper attribute retrieval(#12072)\n\t\t\t\tvar tabindex = jQuery.find.attr( elem, \"tabindex\" );\n\n\t\t\t\tif ( tabindex ) {\n\t\t\t\t\treturn parseInt( tabindex, 10 );\n\t\t\t\t}\n\n\t\t\t\tif (\n\t\t\t\t\trfocusable.test( elem.nodeName ) ||\n\t\t\t\t\trclickable.test( elem.nodeName ) &&\n\t\t\t\t\telem.href\n\t\t\t\t) {\n\t\t\t\t\treturn 0;\n\t\t\t\t}\n\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t}\n\t},\n\n\tpropFix: {\n\t\t\"for\": \"htmlFor\",\n\t\t\"class\": \"className\"\n\t}\n} );\n\n// Support: IE <=11 only\n// Accessing the selectedIndex property\n// forces the browser to respect setting selected\n// on the option\n// The getter ensures a default option is selected\n// when in an optgroup\n// eslint rule \"no-unused-expressions\" is disabled for this code\n// since it considers such accessions noop\nif ( !support.optSelected ) {\n\tjQuery.propHooks.selected = {\n\t\tget: function( elem ) {\n\n\t\t\t/* eslint no-unused-expressions: \"off\" */\n\n\t\t\tvar parent = elem.parentNode;\n\t\t\tif ( parent && parent.parentNode ) {\n\t\t\t\tparent.parentNode.selectedIndex;\n\t\t\t}\n\t\t\treturn null;\n\t\t},\n\t\tset: function( elem ) {\n\n\t\t\t/* eslint no-unused-expressions: \"off\" */\n\n\t\t\tvar parent = elem.parentNode;\n\t\t\tif ( parent ) {\n\t\t\t\tparent.selectedIndex;\n\n\t\t\t\tif ( parent.parentNode ) {\n\t\t\t\t\tparent.parentNode.selectedIndex;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n}\n\njQuery.each( [\n\t\"tabIndex\",\n\t\"readOnly\",\n\t\"maxLength\",\n\t\"cellSpacing\",\n\t\"cellPadding\",\n\t\"rowSpan\",\n\t\"colSpan\",\n\t\"useMap\",\n\t\"frameBorder\",\n\t\"contentEditable\"\n], function() {\n\tjQuery.propFix[ this.toLowerCase() ] = this;\n} );\n\n\n\n\n\t// Strip and collapse whitespace according to HTML spec\n\t// https://infra.spec.whatwg.org/#strip-and-collapse-ascii-whitespace\n\tfunction stripAndCollapse( value ) {\n\t\tvar tokens = value.match( rnothtmlwhite ) || [];\n\t\treturn tokens.join( \" \" );\n\t}\n\n\nfunction getClass( elem ) {\n\treturn elem.getAttribute && elem.getAttribute( \"class\" ) || \"\";\n}\n\nfunction classesToArray( value ) {\n\tif ( Array.isArray( value ) ) {\n\t\treturn value;\n\t}\n\tif ( typeof value === \"string\" ) {\n\t\treturn value.match( rnothtmlwhite ) || [];\n\t}\n\treturn [];\n}\n\njQuery.fn.extend( {\n\taddClass: function( value ) {\n\t\tvar classes, elem, cur, curValue, clazz, j, finalValue,\n\t\t\ti = 0;\n\n\t\tif ( isFunction( value ) ) {\n\t\t\treturn this.each( function( j ) {\n\t\t\t\tjQuery( this ).addClass( value.call( this, j, getClass( this ) ) );\n\t\t\t} );\n\t\t}\n\n\t\tclasses = classesToArray( value );\n\n\t\tif ( classes.length ) {\n\t\t\twhile ( ( elem = this[ i++ ] ) ) {\n\t\t\t\tcurValue = getClass( elem );\n\t\t\t\tcur = elem.nodeType === 1 && ( \" \" + stripAndCollapse( curValue ) + \" \" );\n\n\t\t\t\tif ( cur ) {\n\t\t\t\t\tj = 0;\n\t\t\t\t\twhile ( ( clazz = classes[ j++ ] ) ) {\n\t\t\t\t\t\tif ( cur.indexOf( \" \" + clazz + \" \" ) < 0 ) {\n\t\t\t\t\t\t\tcur += clazz + \" \";\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Only assign if different to avoid unneeded rendering.\n\t\t\t\t\tfinalValue = stripAndCollapse( cur );\n\t\t\t\t\tif ( curValue !== finalValue ) {\n\t\t\t\t\t\telem.setAttribute( \"class\", finalValue );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tremoveClass: function( value ) {\n\t\tvar classes, elem, cur, curValue, clazz, j, finalValue,\n\t\t\ti = 0;\n\n\t\tif ( isFunction( value ) ) {\n\t\t\treturn this.each( function( j ) {\n\t\t\t\tjQuery( this ).removeClass( value.call( this, j, getClass( this ) ) );\n\t\t\t} );\n\t\t}\n\n\t\tif ( !arguments.length ) {\n\t\t\treturn this.attr( \"class\", \"\" );\n\t\t}\n\n\t\tclasses = classesToArray( value );\n\n\t\tif ( classes.length ) {\n\t\t\twhile ( ( elem = this[ i++ ] ) ) {\n\t\t\t\tcurValue = getClass( elem );\n\n\t\t\t\t// This expression is here for better compressibility (see addClass)\n\t\t\t\tcur = elem.nodeType === 1 && ( \" \" + stripAndCollapse( curValue ) + \" \" );\n\n\t\t\t\tif ( cur ) {\n\t\t\t\t\tj = 0;\n\t\t\t\t\twhile ( ( clazz = classes[ j++ ] ) ) {\n\n\t\t\t\t\t\t// Remove *all* instances\n\t\t\t\t\t\twhile ( cur.indexOf( \" \" + clazz + \" \" ) > -1 ) {\n\t\t\t\t\t\t\tcur = cur.replace( \" \" + clazz + \" \", \" \" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Only assign if different to avoid unneeded rendering.\n\t\t\t\t\tfinalValue = stripAndCollapse( cur );\n\t\t\t\t\tif ( curValue !== finalValue ) {\n\t\t\t\t\t\telem.setAttribute( \"class\", finalValue );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\ttoggleClass: function( value, stateVal ) {\n\t\tvar type = typeof value,\n\t\t\tisValidValue = type === \"string\" || Array.isArray( value );\n\n\t\tif ( typeof stateVal === \"boolean\" && isValidValue ) {\n\t\t\treturn stateVal ? this.addClass( value ) : this.removeClass( value );\n\t\t}\n\n\t\tif ( isFunction( value ) ) {\n\t\t\treturn this.each( function( i ) {\n\t\t\t\tjQuery( this ).toggleClass(\n\t\t\t\t\tvalue.call( this, i, getClass( this ), stateVal ),\n\t\t\t\t\tstateVal\n\t\t\t\t);\n\t\t\t} );\n\t\t}\n\n\t\treturn this.each( function() {\n\t\t\tvar className, i, self, classNames;\n\n\t\t\tif ( isValidValue ) {\n\n\t\t\t\t// Toggle individual class names\n\t\t\t\ti = 0;\n\t\t\t\tself = jQuery( this );\n\t\t\t\tclassNames = classesToArray( value );\n\n\t\t\t\twhile ( ( className = classNames[ i++ ] ) ) {\n\n\t\t\t\t\t// Check each className given, space separated list\n\t\t\t\t\tif ( self.hasClass( className ) ) {\n\t\t\t\t\t\tself.removeClass( className );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tself.addClass( className );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t// Toggle whole class name\n\t\t\t} else if ( value === undefined || type === \"boolean\" ) {\n\t\t\t\tclassName = getClass( this );\n\t\t\t\tif ( className ) {\n\n\t\t\t\t\t// Store className if set\n\t\t\t\t\tdataPriv.set( this, \"__className__\", className );\n\t\t\t\t}\n\n\t\t\t\t// If the element has a class name or if we're passed `false`,\n\t\t\t\t// then remove the whole classname (if there was one, the above saved it).\n\t\t\t\t// Otherwise bring back whatever was previously saved (if anything),\n\t\t\t\t// falling back to the empty string if nothing was stored.\n\t\t\t\tif ( this.setAttribute ) {\n\t\t\t\t\tthis.setAttribute( \"class\",\n\t\t\t\t\t\tclassName || value === false ?\n\t\t\t\t\t\t\"\" :\n\t\t\t\t\t\tdataPriv.get( this, \"__className__\" ) || \"\"\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\t},\n\n\thasClass: function( selector ) {\n\t\tvar className, elem,\n\t\t\ti = 0;\n\n\t\tclassName = \" \" + selector + \" \";\n\t\twhile ( ( elem = this[ i++ ] ) ) {\n\t\t\tif ( elem.nodeType === 1 &&\n\t\t\t\t( \" \" + stripAndCollapse( getClass( elem ) ) + \" \" ).indexOf( className ) > -1 ) {\n\t\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n} );\n\n\n\n\nvar rreturn = /\\r/g;\n\njQuery.fn.extend( {\n\tval: function( value ) {\n\t\tvar hooks, ret, valueIsFunction,\n\t\t\telem = this[ 0 ];\n\n\t\tif ( !arguments.length ) {\n\t\t\tif ( elem ) {\n\t\t\t\thooks = jQuery.valHooks[ elem.type ] ||\n\t\t\t\t\tjQuery.valHooks[ elem.nodeName.toLowerCase() ];\n\n\t\t\t\tif ( hooks &&\n\t\t\t\t\t\"get\" in hooks &&\n\t\t\t\t\t( ret = hooks.get( elem, \"value\" ) ) !== undefined\n\t\t\t\t) {\n\t\t\t\t\treturn ret;\n\t\t\t\t}\n\n\t\t\t\tret = elem.value;\n\n\t\t\t\t// Handle most common string cases\n\t\t\t\tif ( typeof ret === \"string\" ) {\n\t\t\t\t\treturn ret.replace( rreturn, \"\" );\n\t\t\t\t}\n\n\t\t\t\t// Handle cases where value is null/undef or number\n\t\t\t\treturn ret == null ? \"\" : ret;\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\tvalueIsFunction = isFunction( value );\n\n\t\treturn this.each( function( i ) {\n\t\t\tvar val;\n\n\t\t\tif ( this.nodeType !== 1 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( valueIsFunction ) {\n\t\t\t\tval = value.call( this, i, jQuery( this ).val() );\n\t\t\t} else {\n\t\t\t\tval = value;\n\t\t\t}\n\n\t\t\t// Treat null/undefined as \"\"; convert numbers to string\n\t\t\tif ( val == null ) {\n\t\t\t\tval = \"\";\n\n\t\t\t} else if ( typeof val === \"number\" ) {\n\t\t\t\tval += \"\";\n\n\t\t\t} else if ( Array.isArray( val ) ) {\n\t\t\t\tval = jQuery.map( val, function( value ) {\n\t\t\t\t\treturn value == null ? \"\" : value + \"\";\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\thooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];\n\n\t\t\t// If set returns undefined, fall back to normal setting\n\t\t\tif ( !hooks || !( \"set\" in hooks ) || hooks.set( this, val, \"value\" ) === undefined ) {\n\t\t\t\tthis.value = val;\n\t\t\t}\n\t\t} );\n\t}\n} );\n\njQuery.extend( {\n\tvalHooks: {\n\t\toption: {\n\t\t\tget: function( elem ) {\n\n\t\t\t\tvar val = jQuery.find.attr( elem, \"value\" );\n\t\t\t\treturn val != null ?\n\t\t\t\t\tval :\n\n\t\t\t\t\t// Support: IE <=10 - 11 only\n\t\t\t\t\t// option.text throws exceptions (#14686, #14858)\n\t\t\t\t\t// Strip and collapse whitespace\n\t\t\t\t\t// https://html.spec.whatwg.org/#strip-and-collapse-whitespace\n\t\t\t\t\tstripAndCollapse( jQuery.text( elem ) );\n\t\t\t}\n\t\t},\n\t\tselect: {\n\t\t\tget: function( elem ) {\n\t\t\t\tvar value, option, i,\n\t\t\t\t\toptions = elem.options,\n\t\t\t\t\tindex = elem.selectedIndex,\n\t\t\t\t\tone = elem.type === \"select-one\",\n\t\t\t\t\tvalues = one ? null : [],\n\t\t\t\t\tmax = one ? index + 1 : options.length;\n\n\t\t\t\tif ( index < 0 ) {\n\t\t\t\t\ti = max;\n\n\t\t\t\t} else {\n\t\t\t\t\ti = one ? index : 0;\n\t\t\t\t}\n\n\t\t\t\t// Loop through all the selected options\n\t\t\t\tfor ( ; i < max; i++ ) {\n\t\t\t\t\toption = options[ i ];\n\n\t\t\t\t\t// Support: IE <=9 only\n\t\t\t\t\t// IE8-9 doesn't update selected after form reset (#2551)\n\t\t\t\t\tif ( ( option.selected || i === index ) &&\n\n\t\t\t\t\t\t\t// Don't return options that are disabled or in a disabled optgroup\n\t\t\t\t\t\t\t!option.disabled &&\n\t\t\t\t\t\t\t( !option.parentNode.disabled ||\n\t\t\t\t\t\t\t\t!nodeName( option.parentNode, \"optgroup\" ) ) ) {\n\n\t\t\t\t\t\t// Get the specific value for the option\n\t\t\t\t\t\tvalue = jQuery( option ).val();\n\n\t\t\t\t\t\t// We don't need an array for one selects\n\t\t\t\t\t\tif ( one ) {\n\t\t\t\t\t\t\treturn value;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Multi-Selects return an array\n\t\t\t\t\t\tvalues.push( value );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn values;\n\t\t\t},\n\n\t\t\tset: function( elem, value ) {\n\t\t\t\tvar optionSet, option,\n\t\t\t\t\toptions = elem.options,\n\t\t\t\t\tvalues = jQuery.makeArray( value ),\n\t\t\t\t\ti = options.length;\n\n\t\t\t\twhile ( i-- ) {\n\t\t\t\t\toption = options[ i ];\n\n\t\t\t\t\t/* eslint-disable no-cond-assign */\n\n\t\t\t\t\tif ( option.selected =\n\t\t\t\t\t\tjQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1\n\t\t\t\t\t) {\n\t\t\t\t\t\toptionSet = true;\n\t\t\t\t\t}\n\n\t\t\t\t\t/* eslint-enable no-cond-assign */\n\t\t\t\t}\n\n\t\t\t\t// Force browsers to behave consistently when non-matching value is set\n\t\t\t\tif ( !optionSet ) {\n\t\t\t\t\telem.selectedIndex = -1;\n\t\t\t\t}\n\t\t\t\treturn values;\n\t\t\t}\n\t\t}\n\t}\n} );\n\n// Radios and checkboxes getter/setter\njQuery.each( [ \"radio\", \"checkbox\" ], function() {\n\tjQuery.valHooks[ this ] = {\n\t\tset: function( elem, value ) {\n\t\t\tif ( Array.isArray( value ) ) {\n\t\t\t\treturn ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 );\n\t\t\t}\n\t\t}\n\t};\n\tif ( !support.checkOn ) {\n\t\tjQuery.valHooks[ this ].get = function( elem ) {\n\t\t\treturn elem.getAttribute( \"value\" ) === null ? \"on\" : elem.value;\n\t\t};\n\t}\n} );\n\n\n\n\n// Return jQuery for attributes-only inclusion\n\n\nsupport.focusin = \"onfocusin\" in window;\n\n\nvar rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,\n\tstopPropagationCallback = function( e ) {\n\t\te.stopPropagation();\n\t};\n\njQuery.extend( jQuery.event, {\n\n\ttrigger: function( event, data, elem, onlyHandlers ) {\n\n\t\tvar i, cur, tmp, bubbleType, ontype, handle, special, lastElement,\n\t\t\teventPath = [ elem || document ],\n\t\t\ttype = hasOwn.call( event, \"type\" ) ? event.type : event,\n\t\t\tnamespaces = hasOwn.call( event, \"namespace\" ) ? event.namespace.split( \".\" ) : [];\n\n\t\tcur = lastElement = tmp = elem = elem || document;\n\n\t\t// Don't do events on text and comment nodes\n\t\tif ( elem.nodeType === 3 || elem.nodeType === 8 ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// focus/blur morphs to focusin/out; ensure we're not firing them right now\n\t\tif ( rfocusMorph.test( type + jQuery.event.triggered ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( type.indexOf( \".\" ) > -1 ) {\n\n\t\t\t// Namespaced trigger; create a regexp to match event type in handle()\n\t\t\tnamespaces = type.split( \".\" );\n\t\t\ttype = namespaces.shift();\n\t\t\tnamespaces.sort();\n\t\t}\n\t\tontype = type.indexOf( \":\" ) < 0 && \"on\" + type;\n\n\t\t// Caller can pass in a jQuery.Event object, Object, or just an event type string\n\t\tevent = event[ jQuery.expando ] ?\n\t\t\tevent :\n\t\t\tnew jQuery.Event( type, typeof event === \"object\" && event );\n\n\t\t// Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)\n\t\tevent.isTrigger = onlyHandlers ? 2 : 3;\n\t\tevent.namespace = namespaces.join( \".\" );\n\t\tevent.rnamespace = event.namespace ?\n\t\t\tnew RegExp( \"(^|\\\\.)\" + namespaces.join( \"\\\\.(?:.*\\\\.|)\" ) + \"(\\\\.|$)\" ) :\n\t\t\tnull;\n\n\t\t// Clean up the event in case it is being reused\n\t\tevent.result = undefined;\n\t\tif ( !event.target ) {\n\t\t\tevent.target = elem;\n\t\t}\n\n\t\t// Clone any incoming data and prepend the event, creating the handler arg list\n\t\tdata = data == null ?\n\t\t\t[ event ] :\n\t\t\tjQuery.makeArray( data, [ event ] );\n\n\t\t// Allow special events to draw outside the lines\n\t\tspecial = jQuery.event.special[ type ] || {};\n\t\tif ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Determine event propagation path in advance, per W3C events spec (#9951)\n\t\t// Bubble up to document, then to window; watch for a global ownerDocument var (#9724)\n\t\tif ( !onlyHandlers && !special.noBubble && !isWindow( elem ) ) {\n\n\t\t\tbubbleType = special.delegateType || type;\n\t\t\tif ( !rfocusMorph.test( bubbleType + type ) ) {\n\t\t\t\tcur = cur.parentNode;\n\t\t\t}\n\t\t\tfor ( ; cur; cur = cur.parentNode ) {\n\t\t\t\teventPath.push( cur );\n\t\t\t\ttmp = cur;\n\t\t\t}\n\n\t\t\t// Only add window if we got to document (e.g., not plain obj or detached DOM)\n\t\t\tif ( tmp === ( elem.ownerDocument || document ) ) {\n\t\t\t\teventPath.push( tmp.defaultView || tmp.parentWindow || window );\n\t\t\t}\n\t\t}\n\n\t\t// Fire handlers on the event path\n\t\ti = 0;\n\t\twhile ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) {\n\t\t\tlastElement = cur;\n\t\t\tevent.type = i > 1 ?\n\t\t\t\tbubbleType :\n\t\t\t\tspecial.bindType || type;\n\n\t\t\t// jQuery handler\n\t\t\thandle = ( dataPriv.get( cur, \"events\" ) || {} )[ event.type ] &&\n\t\t\t\tdataPriv.get( cur, \"handle\" );\n\t\t\tif ( handle ) {\n\t\t\t\thandle.apply( cur, data );\n\t\t\t}\n\n\t\t\t// Native handler\n\t\t\thandle = ontype && cur[ ontype ];\n\t\t\tif ( handle && handle.apply && acceptData( cur ) ) {\n\t\t\t\tevent.result = handle.apply( cur, data );\n\t\t\t\tif ( event.result === false ) {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tevent.type = type;\n\n\t\t// If nobody prevented the default action, do it now\n\t\tif ( !onlyHandlers && !event.isDefaultPrevented() ) {\n\n\t\t\tif ( ( !special._default ||\n\t\t\t\tspecial._default.apply( eventPath.pop(), data ) === false ) &&\n\t\t\t\tacceptData( elem ) ) {\n\n\t\t\t\t// Call a native DOM method on the target with the same name as the event.\n\t\t\t\t// Don't do default actions on window, that's where global variables be (#6170)\n\t\t\t\tif ( ontype && isFunction( elem[ type ] ) && !isWindow( elem ) ) {\n\n\t\t\t\t\t// Don't re-trigger an onFOO event when we call its FOO() method\n\t\t\t\t\ttmp = elem[ ontype ];\n\n\t\t\t\t\tif ( tmp ) {\n\t\t\t\t\t\telem[ ontype ] = null;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Prevent re-triggering of the same event, since we already bubbled it above\n\t\t\t\t\tjQuery.event.triggered = type;\n\n\t\t\t\t\tif ( event.isPropagationStopped() ) {\n\t\t\t\t\t\tlastElement.addEventListener( type, stopPropagationCallback );\n\t\t\t\t\t}\n\n\t\t\t\t\telem[ type ]();\n\n\t\t\t\t\tif ( event.isPropagationStopped() ) {\n\t\t\t\t\t\tlastElement.removeEventListener( type, stopPropagationCallback );\n\t\t\t\t\t}\n\n\t\t\t\t\tjQuery.event.triggered = undefined;\n\n\t\t\t\t\tif ( tmp ) {\n\t\t\t\t\t\telem[ ontype ] = tmp;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn event.result;\n\t},\n\n\t// Piggyback on a donor event to simulate a different one\n\t// Used only for `focus(in | out)` events\n\tsimulate: function( type, elem, event ) {\n\t\tvar e = jQuery.extend(\n\t\t\tnew jQuery.Event(),\n\t\t\tevent,\n\t\t\t{\n\t\t\t\ttype: type,\n\t\t\t\tisSimulated: true\n\t\t\t}\n\t\t);\n\n\t\tjQuery.event.trigger( e, null, elem );\n\t}\n\n} );\n\njQuery.fn.extend( {\n\n\ttrigger: function( type, data ) {\n\t\treturn this.each( function() {\n\t\t\tjQuery.event.trigger( type, data, this );\n\t\t} );\n\t},\n\ttriggerHandler: function( type, data ) {\n\t\tvar elem = this[ 0 ];\n\t\tif ( elem ) {\n\t\t\treturn jQuery.event.trigger( type, data, elem, true );\n\t\t}\n\t}\n} );\n\n\n// Support: Firefox <=44\n// Firefox doesn't have focus(in | out) events\n// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787\n//\n// Support: Chrome <=48 - 49, Safari <=9.0 - 9.1\n// focus(in | out) events fire after focus & blur events,\n// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order\n// Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857\nif ( !support.focusin ) {\n\tjQuery.each( { focus: \"focusin\", blur: \"focusout\" }, function( orig, fix ) {\n\n\t\t// Attach a single capturing handler on the document while someone wants focusin/focusout\n\t\tvar handler = function( event ) {\n\t\t\tjQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) );\n\t\t};\n\n\t\tjQuery.event.special[ fix ] = {\n\t\t\tsetup: function() {\n\t\t\t\tvar doc = this.ownerDocument || this,\n\t\t\t\t\tattaches = dataPriv.access( doc, fix );\n\n\t\t\t\tif ( !attaches ) {\n\t\t\t\t\tdoc.addEventListener( orig, handler, true );\n\t\t\t\t}\n\t\t\t\tdataPriv.access( doc, fix, ( attaches || 0 ) + 1 );\n\t\t\t},\n\t\t\tteardown: function() {\n\t\t\t\tvar doc = this.ownerDocument || this,\n\t\t\t\t\tattaches = dataPriv.access( doc, fix ) - 1;\n\n\t\t\t\tif ( !attaches ) {\n\t\t\t\t\tdoc.removeEventListener( orig, handler, true );\n\t\t\t\t\tdataPriv.remove( doc, fix );\n\n\t\t\t\t} else {\n\t\t\t\t\tdataPriv.access( doc, fix, attaches );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t} );\n}\nvar location = window.location;\n\nvar nonce = Date.now();\n\nvar rquery = ( /\\?/ );\n\n\n\n// Cross-browser xml parsing\njQuery.parseXML = function( data ) {\n\tvar xml;\n\tif ( !data || typeof data !== \"string\" ) {\n\t\treturn null;\n\t}\n\n\t// Support: IE 9 - 11 only\n\t// IE throws on parseFromString with invalid input.\n\ttry {\n\t\txml = ( new window.DOMParser() ).parseFromString( data, \"text/xml\" );\n\t} catch ( e ) {\n\t\txml = undefined;\n\t}\n\n\tif ( !xml || xml.getElementsByTagName( \"parsererror\" ).length ) {\n\t\tjQuery.error( \"Invalid XML: \" + data );\n\t}\n\treturn xml;\n};\n\n\nvar\n\trbracket = /\\[\\]$/,\n\trCRLF = /\\r?\\n/g,\n\trsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,\n\trsubmittable = /^(?:input|select|textarea|keygen)/i;\n\nfunction buildParams( prefix, obj, traditional, add ) {\n\tvar name;\n\n\tif ( Array.isArray( obj ) ) {\n\n\t\t// Serialize array item.\n\t\tjQuery.each( obj, function( i, v ) {\n\t\t\tif ( traditional || rbracket.test( prefix ) ) {\n\n\t\t\t\t// Treat each array item as a scalar.\n\t\t\t\tadd( prefix, v );\n\n\t\t\t} else {\n\n\t\t\t\t// Item is non-scalar (array or object), encode its numeric index.\n\t\t\t\tbuildParams(\n\t\t\t\t\tprefix + \"[\" + ( typeof v === \"object\" && v != null ? i : \"\" ) + \"]\",\n\t\t\t\t\tv,\n\t\t\t\t\ttraditional,\n\t\t\t\t\tadd\n\t\t\t\t);\n\t\t\t}\n\t\t} );\n\n\t} else if ( !traditional && toType( obj ) === \"object\" ) {\n\n\t\t// Serialize object item.\n\t\tfor ( name in obj ) {\n\t\t\tbuildParams( prefix + \"[\" + name + \"]\", obj[ name ], traditional, add );\n\t\t}\n\n\t} else {\n\n\t\t// Serialize scalar item.\n\t\tadd( prefix, obj );\n\t}\n}\n\n// Serialize an array of form elements or a set of\n// key/values into a query string\njQuery.param = function( a, traditional ) {\n\tvar prefix,\n\t\ts = [],\n\t\tadd = function( key, valueOrFunction ) {\n\n\t\t\t// If value is a function, invoke it and use its return value\n\t\t\tvar value = isFunction( valueOrFunction ) ?\n\t\t\t\tvalueOrFunction() :\n\t\t\t\tvalueOrFunction;\n\n\t\t\ts[ s.length ] = encodeURIComponent( key ) + \"=\" +\n\t\t\t\tencodeURIComponent( value == null ? \"\" : value );\n\t\t};\n\n\t// If an array was passed in, assume that it is an array of form elements.\n\tif ( Array.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {\n\n\t\t// Serialize the form elements\n\t\tjQuery.each( a, function() {\n\t\t\tadd( this.name, this.value );\n\t\t} );\n\n\t} else {\n\n\t\t// If traditional, encode the \"old\" way (the way 1.3.2 or older\n\t\t// did it), otherwise encode params recursively.\n\t\tfor ( prefix in a ) {\n\t\t\tbuildParams( prefix, a[ prefix ], traditional, add );\n\t\t}\n\t}\n\n\t// Return the resulting serialization\n\treturn s.join( \"&\" );\n};\n\njQuery.fn.extend( {\n\tserialize: function() {\n\t\treturn jQuery.param( this.serializeArray() );\n\t},\n\tserializeArray: function() {\n\t\treturn this.map( function() {\n\n\t\t\t// Can add propHook for \"elements\" to filter or add form elements\n\t\t\tvar elements = jQuery.prop( this, \"elements\" );\n\t\t\treturn elements ? jQuery.makeArray( elements ) : this;\n\t\t} )\n\t\t.filter( function() {\n\t\t\tvar type = this.type;\n\n\t\t\t// Use .is( \":disabled\" ) so that fieldset[disabled] works\n\t\t\treturn this.name && !jQuery( this ).is( \":disabled\" ) &&\n\t\t\t\trsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&\n\t\t\t\t( this.checked || !rcheckableType.test( type ) );\n\t\t} )\n\t\t.map( function( i, elem ) {\n\t\t\tvar val = jQuery( this ).val();\n\n\t\t\tif ( val == null ) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tif ( Array.isArray( val ) ) {\n\t\t\t\treturn jQuery.map( val, function( val ) {\n\t\t\t\t\treturn { name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\treturn { name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t} ).get();\n\t}\n} );\n\n\nvar\n\tr20 = /%20/g,\n\trhash = /#.*$/,\n\trantiCache = /([?&])_=[^&]*/,\n\trheaders = /^(.*?):[ \\t]*([^\\r\\n]*)$/mg,\n\n\t// #7653, #8125, #8152: local protocol detection\n\trlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,\n\trnoContent = /^(?:GET|HEAD)$/,\n\trprotocol = /^\\/\\//,\n\n\t/* Prefilters\n\t * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)\n\t * 2) These are called:\n\t *    - BEFORE asking for a transport\n\t *    - AFTER param serialization (s.data is a string if s.processData is true)\n\t * 3) key is the dataType\n\t * 4) the catchall symbol \"*\" can be used\n\t * 5) execution will start with transport dataType and THEN continue down to \"*\" if needed\n\t */\n\tprefilters = {},\n\n\t/* Transports bindings\n\t * 1) key is the dataType\n\t * 2) the catchall symbol \"*\" can be used\n\t * 3) selection will start with transport dataType and THEN go to \"*\" if needed\n\t */\n\ttransports = {},\n\n\t// Avoid comment-prolog char sequence (#10098); must appease lint and evade compression\n\tallTypes = \"*/\".concat( \"*\" ),\n\n\t// Anchor tag for parsing the document origin\n\toriginAnchor = document.createElement( \"a\" );\n\toriginAnchor.href = location.href;\n\n// Base \"constructor\" for jQuery.ajaxPrefilter and jQuery.ajaxTransport\nfunction addToPrefiltersOrTransports( structure ) {\n\n\t// dataTypeExpression is optional and defaults to \"*\"\n\treturn function( dataTypeExpression, func ) {\n\n\t\tif ( typeof dataTypeExpression !== \"string\" ) {\n\t\t\tfunc = dataTypeExpression;\n\t\t\tdataTypeExpression = \"*\";\n\t\t}\n\n\t\tvar dataType,\n\t\t\ti = 0,\n\t\t\tdataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || [];\n\n\t\tif ( isFunction( func ) ) {\n\n\t\t\t// For each dataType in the dataTypeExpression\n\t\t\twhile ( ( dataType = dataTypes[ i++ ] ) ) {\n\n\t\t\t\t// Prepend if requested\n\t\t\t\tif ( dataType[ 0 ] === \"+\" ) {\n\t\t\t\t\tdataType = dataType.slice( 1 ) || \"*\";\n\t\t\t\t\t( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func );\n\n\t\t\t\t// Otherwise append\n\t\t\t\t} else {\n\t\t\t\t\t( structure[ dataType ] = structure[ dataType ] || [] ).push( func );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n}\n\n// Base inspection function for prefilters and transports\nfunction inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {\n\n\tvar inspected = {},\n\t\tseekingTransport = ( structure === transports );\n\n\tfunction inspect( dataType ) {\n\t\tvar selected;\n\t\tinspected[ dataType ] = true;\n\t\tjQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {\n\t\t\tvar dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );\n\t\t\tif ( typeof dataTypeOrTransport === \"string\" &&\n\t\t\t\t!seekingTransport && !inspected[ dataTypeOrTransport ] ) {\n\n\t\t\t\toptions.dataTypes.unshift( dataTypeOrTransport );\n\t\t\t\tinspect( dataTypeOrTransport );\n\t\t\t\treturn false;\n\t\t\t} else if ( seekingTransport ) {\n\t\t\t\treturn !( selected = dataTypeOrTransport );\n\t\t\t}\n\t\t} );\n\t\treturn selected;\n\t}\n\n\treturn inspect( options.dataTypes[ 0 ] ) || !inspected[ \"*\" ] && inspect( \"*\" );\n}\n\n// A special extend for ajax options\n// that takes \"flat\" options (not to be deep extended)\n// Fixes #9887\nfunction ajaxExtend( target, src ) {\n\tvar key, deep,\n\t\tflatOptions = jQuery.ajaxSettings.flatOptions || {};\n\n\tfor ( key in src ) {\n\t\tif ( src[ key ] !== undefined ) {\n\t\t\t( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];\n\t\t}\n\t}\n\tif ( deep ) {\n\t\tjQuery.extend( true, target, deep );\n\t}\n\n\treturn target;\n}\n\n/* Handles responses to an ajax request:\n * - finds the right dataType (mediates between content-type and expected dataType)\n * - returns the corresponding response\n */\nfunction ajaxHandleResponses( s, jqXHR, responses ) {\n\n\tvar ct, type, finalDataType, firstDataType,\n\t\tcontents = s.contents,\n\t\tdataTypes = s.dataTypes;\n\n\t// Remove auto dataType and get content-type in the process\n\twhile ( dataTypes[ 0 ] === \"*\" ) {\n\t\tdataTypes.shift();\n\t\tif ( ct === undefined ) {\n\t\t\tct = s.mimeType || jqXHR.getResponseHeader( \"Content-Type\" );\n\t\t}\n\t}\n\n\t// Check if we're dealing with a known content-type\n\tif ( ct ) {\n\t\tfor ( type in contents ) {\n\t\t\tif ( contents[ type ] && contents[ type ].test( ct ) ) {\n\t\t\t\tdataTypes.unshift( type );\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Check to see if we have a response for the expected dataType\n\tif ( dataTypes[ 0 ] in responses ) {\n\t\tfinalDataType = dataTypes[ 0 ];\n\t} else {\n\n\t\t// Try convertible dataTypes\n\t\tfor ( type in responses ) {\n\t\t\tif ( !dataTypes[ 0 ] || s.converters[ type + \" \" + dataTypes[ 0 ] ] ) {\n\t\t\t\tfinalDataType = type;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif ( !firstDataType ) {\n\t\t\t\tfirstDataType = type;\n\t\t\t}\n\t\t}\n\n\t\t// Or just use first one\n\t\tfinalDataType = finalDataType || firstDataType;\n\t}\n\n\t// If we found a dataType\n\t// We add the dataType to the list if needed\n\t// and return the corresponding response\n\tif ( finalDataType ) {\n\t\tif ( finalDataType !== dataTypes[ 0 ] ) {\n\t\t\tdataTypes.unshift( finalDataType );\n\t\t}\n\t\treturn responses[ finalDataType ];\n\t}\n}\n\n/* Chain conversions given the request and the original response\n * Also sets the responseXXX fields on the jqXHR instance\n */\nfunction ajaxConvert( s, response, jqXHR, isSuccess ) {\n\tvar conv2, current, conv, tmp, prev,\n\t\tconverters = {},\n\n\t\t// Work with a copy of dataTypes in case we need to modify it for conversion\n\t\tdataTypes = s.dataTypes.slice();\n\n\t// Create converters map with lowercased keys\n\tif ( dataTypes[ 1 ] ) {\n\t\tfor ( conv in s.converters ) {\n\t\t\tconverters[ conv.toLowerCase() ] = s.converters[ conv ];\n\t\t}\n\t}\n\n\tcurrent = dataTypes.shift();\n\n\t// Convert to each sequential dataType\n\twhile ( current ) {\n\n\t\tif ( s.responseFields[ current ] ) {\n\t\t\tjqXHR[ s.responseFields[ current ] ] = response;\n\t\t}\n\n\t\t// Apply the dataFilter if provided\n\t\tif ( !prev && isSuccess && s.dataFilter ) {\n\t\t\tresponse = s.dataFilter( response, s.dataType );\n\t\t}\n\n\t\tprev = current;\n\t\tcurrent = dataTypes.shift();\n\n\t\tif ( current ) {\n\n\t\t\t// There's only work to do if current dataType is non-auto\n\t\t\tif ( current === \"*\" ) {\n\n\t\t\t\tcurrent = prev;\n\n\t\t\t// Convert response if prev dataType is non-auto and differs from current\n\t\t\t} else if ( prev !== \"*\" && prev !== current ) {\n\n\t\t\t\t// Seek a direct converter\n\t\t\t\tconv = converters[ prev + \" \" + current ] || converters[ \"* \" + current ];\n\n\t\t\t\t// If none found, seek a pair\n\t\t\t\tif ( !conv ) {\n\t\t\t\t\tfor ( conv2 in converters ) {\n\n\t\t\t\t\t\t// If conv2 outputs current\n\t\t\t\t\t\ttmp = conv2.split( \" \" );\n\t\t\t\t\t\tif ( tmp[ 1 ] === current ) {\n\n\t\t\t\t\t\t\t// If prev can be converted to accepted input\n\t\t\t\t\t\t\tconv = converters[ prev + \" \" + tmp[ 0 ] ] ||\n\t\t\t\t\t\t\t\tconverters[ \"* \" + tmp[ 0 ] ];\n\t\t\t\t\t\t\tif ( conv ) {\n\n\t\t\t\t\t\t\t\t// Condense equivalence converters\n\t\t\t\t\t\t\t\tif ( conv === true ) {\n\t\t\t\t\t\t\t\t\tconv = converters[ conv2 ];\n\n\t\t\t\t\t\t\t\t// Otherwise, insert the intermediate dataType\n\t\t\t\t\t\t\t\t} else if ( converters[ conv2 ] !== true ) {\n\t\t\t\t\t\t\t\t\tcurrent = tmp[ 0 ];\n\t\t\t\t\t\t\t\t\tdataTypes.unshift( tmp[ 1 ] );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Apply converter (if not an equivalence)\n\t\t\t\tif ( conv !== true ) {\n\n\t\t\t\t\t// Unless errors are allowed to bubble, catch and return them\n\t\t\t\t\tif ( conv && s.throws ) {\n\t\t\t\t\t\tresponse = conv( response );\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tresponse = conv( response );\n\t\t\t\t\t\t} catch ( e ) {\n\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\tstate: \"parsererror\",\n\t\t\t\t\t\t\t\terror: conv ? e : \"No conversion from \" + prev + \" to \" + current\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn { state: \"success\", data: response };\n}\n\njQuery.extend( {\n\n\t// Counter for holding the number of active queries\n\tactive: 0,\n\n\t// Last-Modified header cache for next request\n\tlastModified: {},\n\tetag: {},\n\n\tajaxSettings: {\n\t\turl: location.href,\n\t\ttype: \"GET\",\n\t\tisLocal: rlocalProtocol.test( location.protocol ),\n\t\tglobal: true,\n\t\tprocessData: true,\n\t\tasync: true,\n\t\tcontentType: \"application/x-www-form-urlencoded; charset=UTF-8\",\n\n\t\t/*\n\t\ttimeout: 0,\n\t\tdata: null,\n\t\tdataType: null,\n\t\tusername: null,\n\t\tpassword: null,\n\t\tcache: null,\n\t\tthrows: false,\n\t\ttraditional: false,\n\t\theaders: {},\n\t\t*/\n\n\t\taccepts: {\n\t\t\t\"*\": allTypes,\n\t\t\ttext: \"text/plain\",\n\t\t\thtml: \"text/html\",\n\t\t\txml: \"application/xml, text/xml\",\n\t\t\tjson: \"application/json, text/javascript\"\n\t\t},\n\n\t\tcontents: {\n\t\t\txml: /\\bxml\\b/,\n\t\t\thtml: /\\bhtml/,\n\t\t\tjson: /\\bjson\\b/\n\t\t},\n\n\t\tresponseFields: {\n\t\t\txml: \"responseXML\",\n\t\t\ttext: \"responseText\",\n\t\t\tjson: \"responseJSON\"\n\t\t},\n\n\t\t// Data converters\n\t\t// Keys separate source (or catchall \"*\") and destination types with a single space\n\t\tconverters: {\n\n\t\t\t// Convert anything to text\n\t\t\t\"* text\": String,\n\n\t\t\t// Text to html (true = no transformation)\n\t\t\t\"text html\": true,\n\n\t\t\t// Evaluate text as a json expression\n\t\t\t\"text json\": JSON.parse,\n\n\t\t\t// Parse text as xml\n\t\t\t\"text xml\": jQuery.parseXML\n\t\t},\n\n\t\t// For options that shouldn't be deep extended:\n\t\t// you can add your own custom options here if\n\t\t// and when you create one that shouldn't be\n\t\t// deep extended (see ajaxExtend)\n\t\tflatOptions: {\n\t\t\turl: true,\n\t\t\tcontext: true\n\t\t}\n\t},\n\n\t// Creates a full fledged settings object into target\n\t// with both ajaxSettings and settings fields.\n\t// If target is omitted, writes into ajaxSettings.\n\tajaxSetup: function( target, settings ) {\n\t\treturn settings ?\n\n\t\t\t// Building a settings object\n\t\t\tajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :\n\n\t\t\t// Extending ajaxSettings\n\t\t\tajaxExtend( jQuery.ajaxSettings, target );\n\t},\n\n\tajaxPrefilter: addToPrefiltersOrTransports( prefilters ),\n\tajaxTransport: addToPrefiltersOrTransports( transports ),\n\n\t// Main method\n\tajax: function( url, options ) {\n\n\t\t// If url is an object, simulate pre-1.5 signature\n\t\tif ( typeof url === \"object\" ) {\n\t\t\toptions = url;\n\t\t\turl = undefined;\n\t\t}\n\n\t\t// Force options to be an object\n\t\toptions = options || {};\n\n\t\tvar transport,\n\n\t\t\t// URL without anti-cache param\n\t\t\tcacheURL,\n\n\t\t\t// Response headers\n\t\t\tresponseHeadersString,\n\t\t\tresponseHeaders,\n\n\t\t\t// timeout handle\n\t\t\ttimeoutTimer,\n\n\t\t\t// Url cleanup var\n\t\t\turlAnchor,\n\n\t\t\t// Request state (becomes false upon send and true upon completion)\n\t\t\tcompleted,\n\n\t\t\t// To know if global events are to be dispatched\n\t\t\tfireGlobals,\n\n\t\t\t// Loop variable\n\t\t\ti,\n\n\t\t\t// uncached part of the url\n\t\t\tuncached,\n\n\t\t\t// Create the final options object\n\t\t\ts = jQuery.ajaxSetup( {}, options ),\n\n\t\t\t// Callbacks context\n\t\t\tcallbackContext = s.context || s,\n\n\t\t\t// Context for global events is callbackContext if it is a DOM node or jQuery collection\n\t\t\tglobalEventContext = s.context &&\n\t\t\t\t( callbackContext.nodeType || callbackContext.jquery ) ?\n\t\t\t\t\tjQuery( callbackContext ) :\n\t\t\t\t\tjQuery.event,\n\n\t\t\t// Deferreds\n\t\t\tdeferred = jQuery.Deferred(),\n\t\t\tcompleteDeferred = jQuery.Callbacks( \"once memory\" ),\n\n\t\t\t// Status-dependent callbacks\n\t\t\tstatusCode = s.statusCode || {},\n\n\t\t\t// Headers (they are sent all at once)\n\t\t\trequestHeaders = {},\n\t\t\trequestHeadersNames = {},\n\n\t\t\t// Default abort message\n\t\t\tstrAbort = \"canceled\",\n\n\t\t\t// Fake xhr\n\t\t\tjqXHR = {\n\t\t\t\treadyState: 0,\n\n\t\t\t\t// Builds headers hashtable if needed\n\t\t\t\tgetResponseHeader: function( key ) {\n\t\t\t\t\tvar match;\n\t\t\t\t\tif ( completed ) {\n\t\t\t\t\t\tif ( !responseHeaders ) {\n\t\t\t\t\t\t\tresponseHeaders = {};\n\t\t\t\t\t\t\twhile ( ( match = rheaders.exec( responseHeadersString ) ) ) {\n\t\t\t\t\t\t\t\tresponseHeaders[ match[ 1 ].toLowerCase() ] = match[ 2 ];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tmatch = responseHeaders[ key.toLowerCase() ];\n\t\t\t\t\t}\n\t\t\t\t\treturn match == null ? null : match;\n\t\t\t\t},\n\n\t\t\t\t// Raw string\n\t\t\t\tgetAllResponseHeaders: function() {\n\t\t\t\t\treturn completed ? responseHeadersString : null;\n\t\t\t\t},\n\n\t\t\t\t// Caches the header\n\t\t\t\tsetRequestHeader: function( name, value ) {\n\t\t\t\t\tif ( completed == null ) {\n\t\t\t\t\t\tname = requestHeadersNames[ name.toLowerCase() ] =\n\t\t\t\t\t\t\trequestHeadersNames[ name.toLowerCase() ] || name;\n\t\t\t\t\t\trequestHeaders[ name ] = value;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Overrides response content-type header\n\t\t\t\toverrideMimeType: function( type ) {\n\t\t\t\t\tif ( completed == null ) {\n\t\t\t\t\t\ts.mimeType = type;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Status-dependent callbacks\n\t\t\t\tstatusCode: function( map ) {\n\t\t\t\t\tvar code;\n\t\t\t\t\tif ( map ) {\n\t\t\t\t\t\tif ( completed ) {\n\n\t\t\t\t\t\t\t// Execute the appropriate callbacks\n\t\t\t\t\t\t\tjqXHR.always( map[ jqXHR.status ] );\n\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t// Lazy-add the new callbacks in a way that preserves old ones\n\t\t\t\t\t\t\tfor ( code in map ) {\n\t\t\t\t\t\t\t\tstatusCode[ code ] = [ statusCode[ code ], map[ code ] ];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Cancel the request\n\t\t\t\tabort: function( statusText ) {\n\t\t\t\t\tvar finalText = statusText || strAbort;\n\t\t\t\t\tif ( transport ) {\n\t\t\t\t\t\ttransport.abort( finalText );\n\t\t\t\t\t}\n\t\t\t\t\tdone( 0, finalText );\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\t\t\t};\n\n\t\t// Attach deferreds\n\t\tdeferred.promise( jqXHR );\n\n\t\t// Add protocol if not provided (prefilters might expect it)\n\t\t// Handle falsy url in the settings object (#10093: consistency with old signature)\n\t\t// We also use the url parameter if available\n\t\ts.url = ( ( url || s.url || location.href ) + \"\" )\n\t\t\t.replace( rprotocol, location.protocol + \"//\" );\n\n\t\t// Alias method option to type as per ticket #12004\n\t\ts.type = options.method || options.type || s.method || s.type;\n\n\t\t// Extract dataTypes list\n\t\ts.dataTypes = ( s.dataType || \"*\" ).toLowerCase().match( rnothtmlwhite ) || [ \"\" ];\n\n\t\t// A cross-domain request is in order when the origin doesn't match the current origin.\n\t\tif ( s.crossDomain == null ) {\n\t\t\turlAnchor = document.createElement( \"a\" );\n\n\t\t\t// Support: IE <=8 - 11, Edge 12 - 15\n\t\t\t// IE throws exception on accessing the href property if url is malformed,\n\t\t\t// e.g. http://example.com:80x/\n\t\t\ttry {\n\t\t\t\turlAnchor.href = s.url;\n\n\t\t\t\t// Support: IE <=8 - 11 only\n\t\t\t\t// Anchor's host property isn't correctly set when s.url is relative\n\t\t\t\turlAnchor.href = urlAnchor.href;\n\t\t\t\ts.crossDomain = originAnchor.protocol + \"//\" + originAnchor.host !==\n\t\t\t\t\turlAnchor.protocol + \"//\" + urlAnchor.host;\n\t\t\t} catch ( e ) {\n\n\t\t\t\t// If there is an error parsing the URL, assume it is crossDomain,\n\t\t\t\t// it can be rejected by the transport if it is invalid\n\t\t\t\ts.crossDomain = true;\n\t\t\t}\n\t\t}\n\n\t\t// Convert data if not already a string\n\t\tif ( s.data && s.processData && typeof s.data !== \"string\" ) {\n\t\t\ts.data = jQuery.param( s.data, s.traditional );\n\t\t}\n\n\t\t// Apply prefilters\n\t\tinspectPrefiltersOrTransports( prefilters, s, options, jqXHR );\n\n\t\t// If request was aborted inside a prefilter, stop there\n\t\tif ( completed ) {\n\t\t\treturn jqXHR;\n\t\t}\n\n\t\t// We can fire global events as of now if asked to\n\t\t// Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118)\n\t\tfireGlobals = jQuery.event && s.global;\n\n\t\t// Watch for a new set of requests\n\t\tif ( fireGlobals && jQuery.active++ === 0 ) {\n\t\t\tjQuery.event.trigger( \"ajaxStart\" );\n\t\t}\n\n\t\t// Uppercase the type\n\t\ts.type = s.type.toUpperCase();\n\n\t\t// Determine if request has content\n\t\ts.hasContent = !rnoContent.test( s.type );\n\n\t\t// Save the URL in case we're toying with the If-Modified-Since\n\t\t// and/or If-None-Match header later on\n\t\t// Remove hash to simplify url manipulation\n\t\tcacheURL = s.url.replace( rhash, \"\" );\n\n\t\t// More options handling for requests with no content\n\t\tif ( !s.hasContent ) {\n\n\t\t\t// Remember the hash so we can put it back\n\t\t\tuncached = s.url.slice( cacheURL.length );\n\n\t\t\t// If data is available and should be processed, append data to url\n\t\t\tif ( s.data && ( s.processData || typeof s.data === \"string\" ) ) {\n\t\t\t\tcacheURL += ( rquery.test( cacheURL ) ? \"&\" : \"?\" ) + s.data;\n\n\t\t\t\t// #9682: remove data so that it's not used in an eventual retry\n\t\t\t\tdelete s.data;\n\t\t\t}\n\n\t\t\t// Add or update anti-cache param if needed\n\t\t\tif ( s.cache === false ) {\n\t\t\t\tcacheURL = cacheURL.replace( rantiCache, \"$1\" );\n\t\t\t\tuncached = ( rquery.test( cacheURL ) ? \"&\" : \"?\" ) + \"_=\" + ( nonce++ ) + uncached;\n\t\t\t}\n\n\t\t\t// Put hash and anti-cache on the URL that will be requested (gh-1732)\n\t\t\ts.url = cacheURL + uncached;\n\n\t\t// Change '%20' to '+' if this is encoded form body content (gh-2658)\n\t\t} else if ( s.data && s.processData &&\n\t\t\t( s.contentType || \"\" ).indexOf( \"application/x-www-form-urlencoded\" ) === 0 ) {\n\t\t\ts.data = s.data.replace( r20, \"+\" );\n\t\t}\n\n\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\tif ( s.ifModified ) {\n\t\t\tif ( jQuery.lastModified[ cacheURL ] ) {\n\t\t\t\tjqXHR.setRequestHeader( \"If-Modified-Since\", jQuery.lastModified[ cacheURL ] );\n\t\t\t}\n\t\t\tif ( jQuery.etag[ cacheURL ] ) {\n\t\t\t\tjqXHR.setRequestHeader( \"If-None-Match\", jQuery.etag[ cacheURL ] );\n\t\t\t}\n\t\t}\n\n\t\t// Set the correct header, if data is being sent\n\t\tif ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {\n\t\t\tjqXHR.setRequestHeader( \"Content-Type\", s.contentType );\n\t\t}\n\n\t\t// Set the Accepts header for the server, depending on the dataType\n\t\tjqXHR.setRequestHeader(\n\t\t\t\"Accept\",\n\t\t\ts.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ?\n\t\t\t\ts.accepts[ s.dataTypes[ 0 ] ] +\n\t\t\t\t\t( s.dataTypes[ 0 ] !== \"*\" ? \", \" + allTypes + \"; q=0.01\" : \"\" ) :\n\t\t\t\ts.accepts[ \"*\" ]\n\t\t);\n\n\t\t// Check for headers option\n\t\tfor ( i in s.headers ) {\n\t\t\tjqXHR.setRequestHeader( i, s.headers[ i ] );\n\t\t}\n\n\t\t// Allow custom headers/mimetypes and early abort\n\t\tif ( s.beforeSend &&\n\t\t\t( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) {\n\n\t\t\t// Abort if not done already and return\n\t\t\treturn jqXHR.abort();\n\t\t}\n\n\t\t// Aborting is no longer a cancellation\n\t\tstrAbort = \"abort\";\n\n\t\t// Install callbacks on deferreds\n\t\tcompleteDeferred.add( s.complete );\n\t\tjqXHR.done( s.success );\n\t\tjqXHR.fail( s.error );\n\n\t\t// Get transport\n\t\ttransport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );\n\n\t\t// If no transport, we auto-abort\n\t\tif ( !transport ) {\n\t\t\tdone( -1, \"No Transport\" );\n\t\t} else {\n\t\t\tjqXHR.readyState = 1;\n\n\t\t\t// Send global event\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajaxSend\", [ jqXHR, s ] );\n\t\t\t}\n\n\t\t\t// If request was aborted inside ajaxSend, stop there\n\t\t\tif ( completed ) {\n\t\t\t\treturn jqXHR;\n\t\t\t}\n\n\t\t\t// Timeout\n\t\t\tif ( s.async && s.timeout > 0 ) {\n\t\t\t\ttimeoutTimer = window.setTimeout( function() {\n\t\t\t\t\tjqXHR.abort( \"timeout\" );\n\t\t\t\t}, s.timeout );\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tcompleted = false;\n\t\t\t\ttransport.send( requestHeaders, done );\n\t\t\t} catch ( e ) {\n\n\t\t\t\t// Rethrow post-completion exceptions\n\t\t\t\tif ( completed ) {\n\t\t\t\t\tthrow e;\n\t\t\t\t}\n\n\t\t\t\t// Propagate others as results\n\t\t\t\tdone( -1, e );\n\t\t\t}\n\t\t}\n\n\t\t// Callback for when everything is done\n\t\tfunction done( status, nativeStatusText, responses, headers ) {\n\t\t\tvar isSuccess, success, error, response, modified,\n\t\t\t\tstatusText = nativeStatusText;\n\n\t\t\t// Ignore repeat invocations\n\t\t\tif ( completed ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tcompleted = true;\n\n\t\t\t// Clear timeout if it exists\n\t\t\tif ( timeoutTimer ) {\n\t\t\t\twindow.clearTimeout( timeoutTimer );\n\t\t\t}\n\n\t\t\t// Dereference transport for early garbage collection\n\t\t\t// (no matter how long the jqXHR object will be used)\n\t\t\ttransport = undefined;\n\n\t\t\t// Cache response headers\n\t\t\tresponseHeadersString = headers || \"\";\n\n\t\t\t// Set readyState\n\t\t\tjqXHR.readyState = status > 0 ? 4 : 0;\n\n\t\t\t// Determine if successful\n\t\t\tisSuccess = status >= 200 && status < 300 || status === 304;\n\n\t\t\t// Get response data\n\t\t\tif ( responses ) {\n\t\t\t\tresponse = ajaxHandleResponses( s, jqXHR, responses );\n\t\t\t}\n\n\t\t\t// Convert no matter what (that way responseXXX fields are always set)\n\t\t\tresponse = ajaxConvert( s, response, jqXHR, isSuccess );\n\n\t\t\t// If successful, handle type chaining\n\t\t\tif ( isSuccess ) {\n\n\t\t\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\t\t\tif ( s.ifModified ) {\n\t\t\t\t\tmodified = jqXHR.getResponseHeader( \"Last-Modified\" );\n\t\t\t\t\tif ( modified ) {\n\t\t\t\t\t\tjQuery.lastModified[ cacheURL ] = modified;\n\t\t\t\t\t}\n\t\t\t\t\tmodified = jqXHR.getResponseHeader( \"etag\" );\n\t\t\t\t\tif ( modified ) {\n\t\t\t\t\t\tjQuery.etag[ cacheURL ] = modified;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// if no content\n\t\t\t\tif ( status === 204 || s.type === \"HEAD\" ) {\n\t\t\t\t\tstatusText = \"nocontent\";\n\n\t\t\t\t// if not modified\n\t\t\t\t} else if ( status === 304 ) {\n\t\t\t\t\tstatusText = \"notmodified\";\n\n\t\t\t\t// If we have data, let's convert it\n\t\t\t\t} else {\n\t\t\t\t\tstatusText = response.state;\n\t\t\t\t\tsuccess = response.data;\n\t\t\t\t\terror = response.error;\n\t\t\t\t\tisSuccess = !error;\n\t\t\t\t}\n\t\t\t} else {\n\n\t\t\t\t// Extract error from statusText and normalize for non-aborts\n\t\t\t\terror = statusText;\n\t\t\t\tif ( status || !statusText ) {\n\t\t\t\t\tstatusText = \"error\";\n\t\t\t\t\tif ( status < 0 ) {\n\t\t\t\t\t\tstatus = 0;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set data for the fake xhr object\n\t\t\tjqXHR.status = status;\n\t\t\tjqXHR.statusText = ( nativeStatusText || statusText ) + \"\";\n\n\t\t\t// Success/Error\n\t\t\tif ( isSuccess ) {\n\t\t\t\tdeferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );\n\t\t\t} else {\n\t\t\t\tdeferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );\n\t\t\t}\n\n\t\t\t// Status-dependent callbacks\n\t\t\tjqXHR.statusCode( statusCode );\n\t\t\tstatusCode = undefined;\n\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( isSuccess ? \"ajaxSuccess\" : \"ajaxError\",\n\t\t\t\t\t[ jqXHR, s, isSuccess ? success : error ] );\n\t\t\t}\n\n\t\t\t// Complete\n\t\t\tcompleteDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );\n\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajaxComplete\", [ jqXHR, s ] );\n\n\t\t\t\t// Handle the global AJAX counter\n\t\t\t\tif ( !( --jQuery.active ) ) {\n\t\t\t\t\tjQuery.event.trigger( \"ajaxStop\" );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn jqXHR;\n\t},\n\n\tgetJSON: function( url, data, callback ) {\n\t\treturn jQuery.get( url, data, callback, \"json\" );\n\t},\n\n\tgetScript: function( url, callback ) {\n\t\treturn jQuery.get( url, undefined, callback, \"script\" );\n\t}\n} );\n\njQuery.each( [ \"get\", \"post\" ], function( i, method ) {\n\tjQuery[ method ] = function( url, data, callback, type ) {\n\n\t\t// Shift arguments if data argument was omitted\n\t\tif ( isFunction( data ) ) {\n\t\t\ttype = type || callback;\n\t\t\tcallback = data;\n\t\t\tdata = undefined;\n\t\t}\n\n\t\t// The url can be an options object (which then must have .url)\n\t\treturn jQuery.ajax( jQuery.extend( {\n\t\t\turl: url,\n\t\t\ttype: method,\n\t\t\tdataType: type,\n\t\t\tdata: data,\n\t\t\tsuccess: callback\n\t\t}, jQuery.isPlainObject( url ) && url ) );\n\t};\n} );\n\n\njQuery._evalUrl = function( url ) {\n\treturn jQuery.ajax( {\n\t\turl: url,\n\n\t\t// Make this explicit, since user can override this through ajaxSetup (#11264)\n\t\ttype: \"GET\",\n\t\tdataType: \"script\",\n\t\tcache: true,\n\t\tasync: false,\n\t\tglobal: false,\n\t\t\"throws\": true\n\t} );\n};\n\n\njQuery.fn.extend( {\n\twrapAll: function( html ) {\n\t\tvar wrap;\n\n\t\tif ( this[ 0 ] ) {\n\t\t\tif ( isFunction( html ) ) {\n\t\t\t\thtml = html.call( this[ 0 ] );\n\t\t\t}\n\n\t\t\t// The elements to wrap the target around\n\t\t\twrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true );\n\n\t\t\tif ( this[ 0 ].parentNode ) {\n\t\t\t\twrap.insertBefore( this[ 0 ] );\n\t\t\t}\n\n\t\t\twrap.map( function() {\n\t\t\t\tvar elem = this;\n\n\t\t\t\twhile ( elem.firstElementChild ) {\n\t\t\t\t\telem = elem.firstElementChild;\n\t\t\t\t}\n\n\t\t\t\treturn elem;\n\t\t\t} ).append( this );\n\t\t}\n\n\t\treturn this;\n\t},\n\n\twrapInner: function( html ) {\n\t\tif ( isFunction( html ) ) {\n\t\t\treturn this.each( function( i ) {\n\t\t\t\tjQuery( this ).wrapInner( html.call( this, i ) );\n\t\t\t} );\n\t\t}\n\n\t\treturn this.each( function() {\n\t\t\tvar self = jQuery( this ),\n\t\t\t\tcontents = self.contents();\n\n\t\t\tif ( contents.length ) {\n\t\t\t\tcontents.wrapAll( html );\n\n\t\t\t} else {\n\t\t\t\tself.append( html );\n\t\t\t}\n\t\t} );\n\t},\n\n\twrap: function( html ) {\n\t\tvar htmlIsFunction = isFunction( html );\n\n\t\treturn this.each( function( i ) {\n\t\t\tjQuery( this ).wrapAll( htmlIsFunction ? html.call( this, i ) : html );\n\t\t} );\n\t},\n\n\tunwrap: function( selector ) {\n\t\tthis.parent( selector ).not( \"body\" ).each( function() {\n\t\t\tjQuery( this ).replaceWith( this.childNodes );\n\t\t} );\n\t\treturn this;\n\t}\n} );\n\n\njQuery.expr.pseudos.hidden = function( elem ) {\n\treturn !jQuery.expr.pseudos.visible( elem );\n};\njQuery.expr.pseudos.visible = function( elem ) {\n\treturn !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length );\n};\n\n\n\n\njQuery.ajaxSettings.xhr = function() {\n\ttry {\n\t\treturn new window.XMLHttpRequest();\n\t} catch ( e ) {}\n};\n\nvar xhrSuccessStatus = {\n\n\t\t// File protocol always yields status code 0, assume 200\n\t\t0: 200,\n\n\t\t// Support: IE <=9 only\n\t\t// #1450: sometimes IE returns 1223 when it should be 204\n\t\t1223: 204\n\t},\n\txhrSupported = jQuery.ajaxSettings.xhr();\n\nsupport.cors = !!xhrSupported && ( \"withCredentials\" in xhrSupported );\nsupport.ajax = xhrSupported = !!xhrSupported;\n\njQuery.ajaxTransport( function( options ) {\n\tvar callback, errorCallback;\n\n\t// Cross domain only allowed if supported through XMLHttpRequest\n\tif ( support.cors || xhrSupported && !options.crossDomain ) {\n\t\treturn {\n\t\t\tsend: function( headers, complete ) {\n\t\t\t\tvar i,\n\t\t\t\t\txhr = options.xhr();\n\n\t\t\t\txhr.open(\n\t\t\t\t\toptions.type,\n\t\t\t\t\toptions.url,\n\t\t\t\t\toptions.async,\n\t\t\t\t\toptions.username,\n\t\t\t\t\toptions.password\n\t\t\t\t);\n\n\t\t\t\t// Apply custom fields if provided\n\t\t\t\tif ( options.xhrFields ) {\n\t\t\t\t\tfor ( i in options.xhrFields ) {\n\t\t\t\t\t\txhr[ i ] = options.xhrFields[ i ];\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Override mime type if needed\n\t\t\t\tif ( options.mimeType && xhr.overrideMimeType ) {\n\t\t\t\t\txhr.overrideMimeType( options.mimeType );\n\t\t\t\t}\n\n\t\t\t\t// X-Requested-With header\n\t\t\t\t// For cross-domain requests, seeing as conditions for a preflight are\n\t\t\t\t// akin to a jigsaw puzzle, we simply never set it to be sure.\n\t\t\t\t// (it can always be set on a per-request basis or even using ajaxSetup)\n\t\t\t\t// For same-domain requests, won't change header if already provided.\n\t\t\t\tif ( !options.crossDomain && !headers[ \"X-Requested-With\" ] ) {\n\t\t\t\t\theaders[ \"X-Requested-With\" ] = \"XMLHttpRequest\";\n\t\t\t\t}\n\n\t\t\t\t// Set headers\n\t\t\t\tfor ( i in headers ) {\n\t\t\t\t\txhr.setRequestHeader( i, headers[ i ] );\n\t\t\t\t}\n\n\t\t\t\t// Callback\n\t\t\t\tcallback = function( type ) {\n\t\t\t\t\treturn function() {\n\t\t\t\t\t\tif ( callback ) {\n\t\t\t\t\t\t\tcallback = errorCallback = xhr.onload =\n\t\t\t\t\t\t\t\txhr.onerror = xhr.onabort = xhr.ontimeout =\n\t\t\t\t\t\t\t\t\txhr.onreadystatechange = null;\n\n\t\t\t\t\t\t\tif ( type === \"abort\" ) {\n\t\t\t\t\t\t\t\txhr.abort();\n\t\t\t\t\t\t\t} else if ( type === \"error\" ) {\n\n\t\t\t\t\t\t\t\t// Support: IE <=9 only\n\t\t\t\t\t\t\t\t// On a manual native abort, IE9 throws\n\t\t\t\t\t\t\t\t// errors on any property access that is not readyState\n\t\t\t\t\t\t\t\tif ( typeof xhr.status !== \"number\" ) {\n\t\t\t\t\t\t\t\t\tcomplete( 0, \"error\" );\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tcomplete(\n\n\t\t\t\t\t\t\t\t\t\t// File: protocol always yields status 0; see #8605, #14207\n\t\t\t\t\t\t\t\t\t\txhr.status,\n\t\t\t\t\t\t\t\t\t\txhr.statusText\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tcomplete(\n\t\t\t\t\t\t\t\t\txhrSuccessStatus[ xhr.status ] || xhr.status,\n\t\t\t\t\t\t\t\t\txhr.statusText,\n\n\t\t\t\t\t\t\t\t\t// Support: IE <=9 only\n\t\t\t\t\t\t\t\t\t// IE9 has no XHR2 but throws on binary (trac-11426)\n\t\t\t\t\t\t\t\t\t// For XHR2 non-text, let the caller handle it (gh-2498)\n\t\t\t\t\t\t\t\t\t( xhr.responseType || \"text\" ) !== \"text\"  ||\n\t\t\t\t\t\t\t\t\ttypeof xhr.responseText !== \"string\" ?\n\t\t\t\t\t\t\t\t\t\t{ binary: xhr.response } :\n\t\t\t\t\t\t\t\t\t\t{ text: xhr.responseText },\n\t\t\t\t\t\t\t\t\txhr.getAllResponseHeaders()\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\t\t\t\t};\n\n\t\t\t\t// Listen to events\n\t\t\t\txhr.onload = callback();\n\t\t\t\terrorCallback = xhr.onerror = xhr.ontimeout = callback( \"error\" );\n\n\t\t\t\t// Support: IE 9 only\n\t\t\t\t// Use onreadystatechange to replace onabort\n\t\t\t\t// to handle uncaught aborts\n\t\t\t\tif ( xhr.onabort !== undefined ) {\n\t\t\t\t\txhr.onabort = errorCallback;\n\t\t\t\t} else {\n\t\t\t\t\txhr.onreadystatechange = function() {\n\n\t\t\t\t\t\t// Check readyState before timeout as it changes\n\t\t\t\t\t\tif ( xhr.readyState === 4 ) {\n\n\t\t\t\t\t\t\t// Allow onerror to be called first,\n\t\t\t\t\t\t\t// but that will not handle a native abort\n\t\t\t\t\t\t\t// Also, save errorCallback to a variable\n\t\t\t\t\t\t\t// as xhr.onerror cannot be accessed\n\t\t\t\t\t\t\twindow.setTimeout( function() {\n\t\t\t\t\t\t\t\tif ( callback ) {\n\t\t\t\t\t\t\t\t\terrorCallback();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\t// Create the abort callback\n\t\t\t\tcallback = callback( \"abort\" );\n\n\t\t\t\ttry {\n\n\t\t\t\t\t// Do send the request (this may raise an exception)\n\t\t\t\t\txhr.send( options.hasContent && options.data || null );\n\t\t\t\t} catch ( e ) {\n\n\t\t\t\t\t// #14683: Only rethrow if this hasn't been notified as an error yet\n\t\t\t\t\tif ( callback ) {\n\t\t\t\t\t\tthrow e;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tabort: function() {\n\t\t\t\tif ( callback ) {\n\t\t\t\t\tcallback();\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n} );\n\n\n\n\n// Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432)\njQuery.ajaxPrefilter( function( s ) {\n\tif ( s.crossDomain ) {\n\t\ts.contents.script = false;\n\t}\n} );\n\n// Install script dataType\njQuery.ajaxSetup( {\n\taccepts: {\n\t\tscript: \"text/javascript, application/javascript, \" +\n\t\t\t\"application/ecmascript, application/x-ecmascript\"\n\t},\n\tcontents: {\n\t\tscript: /\\b(?:java|ecma)script\\b/\n\t},\n\tconverters: {\n\t\t\"text script\": function( text ) {\n\t\t\tjQuery.globalEval( text );\n\t\t\treturn text;\n\t\t}\n\t}\n} );\n\n// Handle cache's special case and crossDomain\njQuery.ajaxPrefilter( \"script\", function( s ) {\n\tif ( s.cache === undefined ) {\n\t\ts.cache = false;\n\t}\n\tif ( s.crossDomain ) {\n\t\ts.type = \"GET\";\n\t}\n} );\n\n// Bind script tag hack transport\njQuery.ajaxTransport( \"script\", function( s ) {\n\n\t// This transport only deals with cross domain requests\n\tif ( s.crossDomain ) {\n\t\tvar script, callback;\n\t\treturn {\n\t\t\tsend: function( _, complete ) {\n\t\t\t\tscript = jQuery( \"<script>\" ).prop( {\n\t\t\t\t\tcharset: s.scriptCharset,\n\t\t\t\t\tsrc: s.url\n\t\t\t\t} ).on(\n\t\t\t\t\t\"load error\",\n\t\t\t\t\tcallback = function( evt ) {\n\t\t\t\t\t\tscript.remove();\n\t\t\t\t\t\tcallback = null;\n\t\t\t\t\t\tif ( evt ) {\n\t\t\t\t\t\t\tcomplete( evt.type === \"error\" ? 404 : 200, evt.type );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t);\n\n\t\t\t\t// Use native DOM manipulation to avoid our domManip AJAX trickery\n\t\t\t\tdocument.head.appendChild( script[ 0 ] );\n\t\t\t},\n\t\t\tabort: function() {\n\t\t\t\tif ( callback ) {\n\t\t\t\t\tcallback();\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n} );\n\n\n\n\nvar oldCallbacks = [],\n\trjsonp = /(=)\\?(?=&|$)|\\?\\?/;\n\n// Default jsonp settings\njQuery.ajaxSetup( {\n\tjsonp: \"callback\",\n\tjsonpCallback: function() {\n\t\tvar callback = oldCallbacks.pop() || ( jQuery.expando + \"_\" + ( nonce++ ) );\n\t\tthis[ callback ] = true;\n\t\treturn callback;\n\t}\n} );\n\n// Detect, normalize options and install callbacks for jsonp requests\njQuery.ajaxPrefilter( \"json jsonp\", function( s, originalSettings, jqXHR ) {\n\n\tvar callbackName, overwritten, responseContainer,\n\t\tjsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?\n\t\t\t\"url\" :\n\t\t\ttypeof s.data === \"string\" &&\n\t\t\t\t( s.contentType || \"\" )\n\t\t\t\t\t.indexOf( \"application/x-www-form-urlencoded\" ) === 0 &&\n\t\t\t\trjsonp.test( s.data ) && \"data\"\n\t\t);\n\n\t// Handle iff the expected data type is \"jsonp\" or we have a parameter to set\n\tif ( jsonProp || s.dataTypes[ 0 ] === \"jsonp\" ) {\n\n\t\t// Get callback name, remembering preexisting value associated with it\n\t\tcallbackName = s.jsonpCallback = isFunction( s.jsonpCallback ) ?\n\t\t\ts.jsonpCallback() :\n\t\t\ts.jsonpCallback;\n\n\t\t// Insert callback into url or form data\n\t\tif ( jsonProp ) {\n\t\t\ts[ jsonProp ] = s[ jsonProp ].replace( rjsonp, \"$1\" + callbackName );\n\t\t} else if ( s.jsonp !== false ) {\n\t\t\ts.url += ( rquery.test( s.url ) ? \"&\" : \"?\" ) + s.jsonp + \"=\" + callbackName;\n\t\t}\n\n\t\t// Use data converter to retrieve json after script execution\n\t\ts.converters[ \"script json\" ] = function() {\n\t\t\tif ( !responseContainer ) {\n\t\t\t\tjQuery.error( callbackName + \" was not called\" );\n\t\t\t}\n\t\t\treturn responseContainer[ 0 ];\n\t\t};\n\n\t\t// Force json dataType\n\t\ts.dataTypes[ 0 ] = \"json\";\n\n\t\t// Install callback\n\t\toverwritten = window[ callbackName ];\n\t\twindow[ callbackName ] = function() {\n\t\t\tresponseContainer = arguments;\n\t\t};\n\n\t\t// Clean-up function (fires after converters)\n\t\tjqXHR.always( function() {\n\n\t\t\t// If previous value didn't exist - remove it\n\t\t\tif ( overwritten === undefined ) {\n\t\t\t\tjQuery( window ).removeProp( callbackName );\n\n\t\t\t// Otherwise restore preexisting value\n\t\t\t} else {\n\t\t\t\twindow[ callbackName ] = overwritten;\n\t\t\t}\n\n\t\t\t// Save back as free\n\t\t\tif ( s[ callbackName ] ) {\n\n\t\t\t\t// Make sure that re-using the options doesn't screw things around\n\t\t\t\ts.jsonpCallback = originalSettings.jsonpCallback;\n\n\t\t\t\t// Save the callback name for future use\n\t\t\t\toldCallbacks.push( callbackName );\n\t\t\t}\n\n\t\t\t// Call if it was a function and we have a response\n\t\t\tif ( responseContainer && isFunction( overwritten ) ) {\n\t\t\t\toverwritten( responseContainer[ 0 ] );\n\t\t\t}\n\n\t\t\tresponseContainer = overwritten = undefined;\n\t\t} );\n\n\t\t// Delegate to script\n\t\treturn \"script\";\n\t}\n} );\n\n\n\n\n// Support: Safari 8 only\n// In Safari 8 documents created via document.implementation.createHTMLDocument\n// collapse sibling forms: the second one becomes a child of the first one.\n// Because of that, this security measure has to be disabled in Safari 8.\n// https://bugs.webkit.org/show_bug.cgi?id=137337\nsupport.createHTMLDocument = ( function() {\n\tvar body = document.implementation.createHTMLDocument( \"\" ).body;\n\tbody.innerHTML = \"<form></form><form></form>\";\n\treturn body.childNodes.length === 2;\n} )();\n\n\n// Argument \"data\" should be string of html\n// context (optional): If specified, the fragment will be created in this context,\n// defaults to document\n// keepScripts (optional): If true, will include scripts passed in the html string\njQuery.parseHTML = function( data, context, keepScripts ) {\n\tif ( typeof data !== \"string\" ) {\n\t\treturn [];\n\t}\n\tif ( typeof context === \"boolean\" ) {\n\t\tkeepScripts = context;\n\t\tcontext = false;\n\t}\n\n\tvar base, parsed, scripts;\n\n\tif ( !context ) {\n\n\t\t// Stop scripts or inline event handlers from being executed immediately\n\t\t// by using document.implementation\n\t\tif ( support.createHTMLDocument ) {\n\t\t\tcontext = document.implementation.createHTMLDocument( \"\" );\n\n\t\t\t// Set the base href for the created document\n\t\t\t// so any parsed elements with URLs\n\t\t\t// are based on the document's URL (gh-2965)\n\t\t\tbase = context.createElement( \"base\" );\n\t\t\tbase.href = document.location.href;\n\t\t\tcontext.head.appendChild( base );\n\t\t} else {\n\t\t\tcontext = document;\n\t\t}\n\t}\n\n\tparsed = rsingleTag.exec( data );\n\tscripts = !keepScripts && [];\n\n\t// Single tag\n\tif ( parsed ) {\n\t\treturn [ context.createElement( parsed[ 1 ] ) ];\n\t}\n\n\tparsed = buildFragment( [ data ], context, scripts );\n\n\tif ( scripts && scripts.length ) {\n\t\tjQuery( scripts ).remove();\n\t}\n\n\treturn jQuery.merge( [], parsed.childNodes );\n};\n\n\n/**\n * Load a url into a page\n */\njQuery.fn.load = function( url, params, callback ) {\n\tvar selector, type, response,\n\t\tself = this,\n\t\toff = url.indexOf( \" \" );\n\n\tif ( off > -1 ) {\n\t\tselector = stripAndCollapse( url.slice( off ) );\n\t\turl = url.slice( 0, off );\n\t}\n\n\t// If it's a function\n\tif ( isFunction( params ) ) {\n\n\t\t// We assume that it's the callback\n\t\tcallback = params;\n\t\tparams = undefined;\n\n\t// Otherwise, build a param string\n\t} else if ( params && typeof params === \"object\" ) {\n\t\ttype = \"POST\";\n\t}\n\n\t// If we have elements to modify, make the request\n\tif ( self.length > 0 ) {\n\t\tjQuery.ajax( {\n\t\t\turl: url,\n\n\t\t\t// If \"type\" variable is undefined, then \"GET\" method will be used.\n\t\t\t// Make value of this field explicit since\n\t\t\t// user can override it through ajaxSetup method\n\t\t\ttype: type || \"GET\",\n\t\t\tdataType: \"html\",\n\t\t\tdata: params\n\t\t} ).done( function( responseText ) {\n\n\t\t\t// Save response for use in complete callback\n\t\t\tresponse = arguments;\n\n\t\t\tself.html( selector ?\n\n\t\t\t\t// If a selector was specified, locate the right elements in a dummy div\n\t\t\t\t// Exclude scripts to avoid IE 'Permission Denied' errors\n\t\t\t\tjQuery( \"<div>\" ).append( jQuery.parseHTML( responseText ) ).find( selector ) :\n\n\t\t\t\t// Otherwise use the full result\n\t\t\t\tresponseText );\n\n\t\t// If the request succeeds, this function gets \"data\", \"status\", \"jqXHR\"\n\t\t// but they are ignored because response was set above.\n\t\t// If it fails, this function gets \"jqXHR\", \"status\", \"error\"\n\t\t} ).always( callback && function( jqXHR, status ) {\n\t\t\tself.each( function() {\n\t\t\t\tcallback.apply( this, response || [ jqXHR.responseText, status, jqXHR ] );\n\t\t\t} );\n\t\t} );\n\t}\n\n\treturn this;\n};\n\n\n\n\n// Attach a bunch of functions for handling common AJAX events\njQuery.each( [\n\t\"ajaxStart\",\n\t\"ajaxStop\",\n\t\"ajaxComplete\",\n\t\"ajaxError\",\n\t\"ajaxSuccess\",\n\t\"ajaxSend\"\n], function( i, type ) {\n\tjQuery.fn[ type ] = function( fn ) {\n\t\treturn this.on( type, fn );\n\t};\n} );\n\n\n\n\njQuery.expr.pseudos.animated = function( elem ) {\n\treturn jQuery.grep( jQuery.timers, function( fn ) {\n\t\treturn elem === fn.elem;\n\t} ).length;\n};\n\n\n\n\njQuery.offset = {\n\tsetOffset: function( elem, options, i ) {\n\t\tvar curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,\n\t\t\tposition = jQuery.css( elem, \"position\" ),\n\t\t\tcurElem = jQuery( elem ),\n\t\t\tprops = {};\n\n\t\t// Set position first, in-case top/left are set even on static elem\n\t\tif ( position === \"static\" ) {\n\t\t\telem.style.position = \"relative\";\n\t\t}\n\n\t\tcurOffset = curElem.offset();\n\t\tcurCSSTop = jQuery.css( elem, \"top\" );\n\t\tcurCSSLeft = jQuery.css( elem, \"left\" );\n\t\tcalculatePosition = ( position === \"absolute\" || position === \"fixed\" ) &&\n\t\t\t( curCSSTop + curCSSLeft ).indexOf( \"auto\" ) > -1;\n\n\t\t// Need to be able to calculate position if either\n\t\t// top or left is auto and position is either absolute or fixed\n\t\tif ( calculatePosition ) {\n\t\t\tcurPosition = curElem.position();\n\t\t\tcurTop = curPosition.top;\n\t\t\tcurLeft = curPosition.left;\n\n\t\t} else {\n\t\t\tcurTop = parseFloat( curCSSTop ) || 0;\n\t\t\tcurLeft = parseFloat( curCSSLeft ) || 0;\n\t\t}\n\n\t\tif ( isFunction( options ) ) {\n\n\t\t\t// Use jQuery.extend here to allow modification of coordinates argument (gh-1848)\n\t\t\toptions = options.call( elem, i, jQuery.extend( {}, curOffset ) );\n\t\t}\n\n\t\tif ( options.top != null ) {\n\t\t\tprops.top = ( options.top - curOffset.top ) + curTop;\n\t\t}\n\t\tif ( options.left != null ) {\n\t\t\tprops.left = ( options.left - curOffset.left ) + curLeft;\n\t\t}\n\n\t\tif ( \"using\" in options ) {\n\t\t\toptions.using.call( elem, props );\n\n\t\t} else {\n\t\t\tcurElem.css( props );\n\t\t}\n\t}\n};\n\njQuery.fn.extend( {\n\n\t// offset() relates an element's border box to the document origin\n\toffset: function( options ) {\n\n\t\t// Preserve chaining for setter\n\t\tif ( arguments.length ) {\n\t\t\treturn options === undefined ?\n\t\t\t\tthis :\n\t\t\t\tthis.each( function( i ) {\n\t\t\t\t\tjQuery.offset.setOffset( this, options, i );\n\t\t\t\t} );\n\t\t}\n\n\t\tvar rect, win,\n\t\t\telem = this[ 0 ];\n\n\t\tif ( !elem ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Return zeros for disconnected and hidden (display: none) elements (gh-2310)\n\t\t// Support: IE <=11 only\n\t\t// Running getBoundingClientRect on a\n\t\t// disconnected node in IE throws an error\n\t\tif ( !elem.getClientRects().length ) {\n\t\t\treturn { top: 0, left: 0 };\n\t\t}\n\n\t\t// Get document-relative position by adding viewport scroll to viewport-relative gBCR\n\t\trect = elem.getBoundingClientRect();\n\t\twin = elem.ownerDocument.defaultView;\n\t\treturn {\n\t\t\ttop: rect.top + win.pageYOffset,\n\t\t\tleft: rect.left + win.pageXOffset\n\t\t};\n\t},\n\n\t// position() relates an element's margin box to its offset parent's padding box\n\t// This corresponds to the behavior of CSS absolute positioning\n\tposition: function() {\n\t\tif ( !this[ 0 ] ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar offsetParent, offset, doc,\n\t\t\telem = this[ 0 ],\n\t\t\tparentOffset = { top: 0, left: 0 };\n\n\t\t// position:fixed elements are offset from the viewport, which itself always has zero offset\n\t\tif ( jQuery.css( elem, \"position\" ) === \"fixed\" ) {\n\n\t\t\t// Assume position:fixed implies availability of getBoundingClientRect\n\t\t\toffset = elem.getBoundingClientRect();\n\n\t\t} else {\n\t\t\toffset = this.offset();\n\n\t\t\t// Account for the *real* offset parent, which can be the document or its root element\n\t\t\t// when a statically positioned element is identified\n\t\t\tdoc = elem.ownerDocument;\n\t\t\toffsetParent = elem.offsetParent || doc.documentElement;\n\t\t\twhile ( offsetParent &&\n\t\t\t\t( offsetParent === doc.body || offsetParent === doc.documentElement ) &&\n\t\t\t\tjQuery.css( offsetParent, \"position\" ) === \"static\" ) {\n\n\t\t\t\toffsetParent = offsetParent.parentNode;\n\t\t\t}\n\t\t\tif ( offsetParent && offsetParent !== elem && offsetParent.nodeType === 1 ) {\n\n\t\t\t\t// Incorporate borders into its offset, since they are outside its content origin\n\t\t\t\tparentOffset = jQuery( offsetParent ).offset();\n\t\t\t\tparentOffset.top += jQuery.css( offsetParent, \"borderTopWidth\", true );\n\t\t\t\tparentOffset.left += jQuery.css( offsetParent, \"borderLeftWidth\", true );\n\t\t\t}\n\t\t}\n\n\t\t// Subtract parent offsets and element margins\n\t\treturn {\n\t\t\ttop: offset.top - parentOffset.top - jQuery.css( elem, \"marginTop\", true ),\n\t\t\tleft: offset.left - parentOffset.left - jQuery.css( elem, \"marginLeft\", true )\n\t\t};\n\t},\n\n\t// This method will return documentElement in the following cases:\n\t// 1) For the element inside the iframe without offsetParent, this method will return\n\t//    documentElement of the parent window\n\t// 2) For the hidden or detached element\n\t// 3) For body or html element, i.e. in case of the html node - it will return itself\n\t//\n\t// but those exceptions were never presented as a real life use-cases\n\t// and might be considered as more preferable results.\n\t//\n\t// This logic, however, is not guaranteed and can change at any point in the future\n\toffsetParent: function() {\n\t\treturn this.map( function() {\n\t\t\tvar offsetParent = this.offsetParent;\n\n\t\t\twhile ( offsetParent && jQuery.css( offsetParent, \"position\" ) === \"static\" ) {\n\t\t\t\toffsetParent = offsetParent.offsetParent;\n\t\t\t}\n\n\t\t\treturn offsetParent || documentElement;\n\t\t} );\n\t}\n} );\n\n// Create scrollLeft and scrollTop methods\njQuery.each( { scrollLeft: \"pageXOffset\", scrollTop: \"pageYOffset\" }, function( method, prop ) {\n\tvar top = \"pageYOffset\" === prop;\n\n\tjQuery.fn[ method ] = function( val ) {\n\t\treturn access( this, function( elem, method, val ) {\n\n\t\t\t// Coalesce documents and windows\n\t\t\tvar win;\n\t\t\tif ( isWindow( elem ) ) {\n\t\t\t\twin = elem;\n\t\t\t} else if ( elem.nodeType === 9 ) {\n\t\t\t\twin = elem.defaultView;\n\t\t\t}\n\n\t\t\tif ( val === undefined ) {\n\t\t\t\treturn win ? win[ prop ] : elem[ method ];\n\t\t\t}\n\n\t\t\tif ( win ) {\n\t\t\t\twin.scrollTo(\n\t\t\t\t\t!top ? val : win.pageXOffset,\n\t\t\t\t\ttop ? val : win.pageYOffset\n\t\t\t\t);\n\n\t\t\t} else {\n\t\t\t\telem[ method ] = val;\n\t\t\t}\n\t\t}, method, val, arguments.length );\n\t};\n} );\n\n// Support: Safari <=7 - 9.1, Chrome <=37 - 49\n// Add the top/left cssHooks using jQuery.fn.position\n// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084\n// Blink bug: https://bugs.chromium.org/p/chromium/issues/detail?id=589347\n// getComputedStyle returns percent when specified for top/left/bottom/right;\n// rather than make the css module depend on the offset module, just check for it here\njQuery.each( [ \"top\", \"left\" ], function( i, prop ) {\n\tjQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition,\n\t\tfunction( elem, computed ) {\n\t\t\tif ( computed ) {\n\t\t\t\tcomputed = curCSS( elem, prop );\n\n\t\t\t\t// If curCSS returns percentage, fallback to offset\n\t\t\t\treturn rnumnonpx.test( computed ) ?\n\t\t\t\t\tjQuery( elem ).position()[ prop ] + \"px\" :\n\t\t\t\t\tcomputed;\n\t\t\t}\n\t\t}\n\t);\n} );\n\n\n// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods\njQuery.each( { Height: \"height\", Width: \"width\" }, function( name, type ) {\n\tjQuery.each( { padding: \"inner\" + name, content: type, \"\": \"outer\" + name },\n\t\tfunction( defaultExtra, funcName ) {\n\n\t\t// Margin is only for outerHeight, outerWidth\n\t\tjQuery.fn[ funcName ] = function( margin, value ) {\n\t\t\tvar chainable = arguments.length && ( defaultExtra || typeof margin !== \"boolean\" ),\n\t\t\t\textra = defaultExtra || ( margin === true || value === true ? \"margin\" : \"border\" );\n\n\t\t\treturn access( this, function( elem, type, value ) {\n\t\t\t\tvar doc;\n\n\t\t\t\tif ( isWindow( elem ) ) {\n\n\t\t\t\t\t// $( window ).outerWidth/Height return w/h including scrollbars (gh-1729)\n\t\t\t\t\treturn funcName.indexOf( \"outer\" ) === 0 ?\n\t\t\t\t\t\telem[ \"inner\" + name ] :\n\t\t\t\t\t\telem.document.documentElement[ \"client\" + name ];\n\t\t\t\t}\n\n\t\t\t\t// Get document width or height\n\t\t\t\tif ( elem.nodeType === 9 ) {\n\t\t\t\t\tdoc = elem.documentElement;\n\n\t\t\t\t\t// Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height],\n\t\t\t\t\t// whichever is greatest\n\t\t\t\t\treturn Math.max(\n\t\t\t\t\t\telem.body[ \"scroll\" + name ], doc[ \"scroll\" + name ],\n\t\t\t\t\t\telem.body[ \"offset\" + name ], doc[ \"offset\" + name ],\n\t\t\t\t\t\tdoc[ \"client\" + name ]\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\treturn value === undefined ?\n\n\t\t\t\t\t// Get width or height on the element, requesting but not forcing parseFloat\n\t\t\t\t\tjQuery.css( elem, type, extra ) :\n\n\t\t\t\t\t// Set width or height on the element\n\t\t\t\t\tjQuery.style( elem, type, value, extra );\n\t\t\t}, type, chainable ? margin : undefined, chainable );\n\t\t};\n\t} );\n} );\n\n\njQuery.each( ( \"blur focus focusin focusout resize scroll click dblclick \" +\n\t\"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave \" +\n\t\"change select submit keydown keypress keyup contextmenu\" ).split( \" \" ),\n\tfunction( i, name ) {\n\n\t// Handle event binding\n\tjQuery.fn[ name ] = function( data, fn ) {\n\t\treturn arguments.length > 0 ?\n\t\t\tthis.on( name, null, data, fn ) :\n\t\t\tthis.trigger( name );\n\t};\n} );\n\njQuery.fn.extend( {\n\thover: function( fnOver, fnOut ) {\n\t\treturn this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );\n\t}\n} );\n\n\n\n\njQuery.fn.extend( {\n\n\tbind: function( types, data, fn ) {\n\t\treturn this.on( types, null, data, fn );\n\t},\n\tunbind: function( types, fn ) {\n\t\treturn this.off( types, null, fn );\n\t},\n\n\tdelegate: function( selector, types, data, fn ) {\n\t\treturn this.on( types, selector, data, fn );\n\t},\n\tundelegate: function( selector, types, fn ) {\n\n\t\t// ( namespace ) or ( selector, types [, fn] )\n\t\treturn arguments.length === 1 ?\n\t\t\tthis.off( selector, \"**\" ) :\n\t\t\tthis.off( types, selector || \"**\", fn );\n\t}\n} );\n\n// Bind a function to a context, optionally partially applying any\n// arguments.\n// jQuery.proxy is deprecated to promote standards (specifically Function#bind)\n// However, it is not slated for removal any time soon\njQuery.proxy = function( fn, context ) {\n\tvar tmp, args, proxy;\n\n\tif ( typeof context === \"string\" ) {\n\t\ttmp = fn[ context ];\n\t\tcontext = fn;\n\t\tfn = tmp;\n\t}\n\n\t// Quick check to determine if target is callable, in the spec\n\t// this throws a TypeError, but we will just return undefined.\n\tif ( !isFunction( fn ) ) {\n\t\treturn undefined;\n\t}\n\n\t// Simulated bind\n\targs = slice.call( arguments, 2 );\n\tproxy = function() {\n\t\treturn fn.apply( context || this, args.concat( slice.call( arguments ) ) );\n\t};\n\n\t// Set the guid of unique handler to the same of original handler, so it can be removed\n\tproxy.guid = fn.guid = fn.guid || jQuery.guid++;\n\n\treturn proxy;\n};\n\njQuery.holdReady = function( hold ) {\n\tif ( hold ) {\n\t\tjQuery.readyWait++;\n\t} else {\n\t\tjQuery.ready( true );\n\t}\n};\njQuery.isArray = Array.isArray;\njQuery.parseJSON = JSON.parse;\njQuery.nodeName = nodeName;\njQuery.isFunction = isFunction;\njQuery.isWindow = isWindow;\njQuery.camelCase = camelCase;\njQuery.type = toType;\n\njQuery.now = Date.now;\n\njQuery.isNumeric = function( obj ) {\n\n\t// As of jQuery 3.0, isNumeric is limited to\n\t// strings and numbers (primitives or objects)\n\t// that can be coerced to finite numbers (gh-2662)\n\tvar type = jQuery.type( obj );\n\treturn ( type === \"number\" || type === \"string\" ) &&\n\n\t\t// parseFloat NaNs numeric-cast false positives (\"\")\n\t\t// ...but misinterprets leading-number strings, particularly hex literals (\"0x...\")\n\t\t// subtraction forces infinities to NaN\n\t\t!isNaN( obj - parseFloat( obj ) );\n};\n\n\n\n\n// Register as a named AMD module, since jQuery can be concatenated with other\n// files that may use define, but not via a proper concatenation script that\n// understands anonymous AMD modules. A named AMD is safest and most robust\n// way to register. Lowercase jquery is used because AMD module names are\n// derived from file names, and jQuery is normally delivered in a lowercase\n// file name. Do this after creating the global so that if an AMD module wants\n// to call noConflict to hide this version of jQuery, it will work.\n\n// Note that for maximum portability, libraries that are not jQuery should\n// declare themselves as anonymous modules, and avoid setting a global if an\n// AMD loader is present. jQuery is a special case. For more information, see\n// https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon\n\nif ( typeof define === \"function\" && define.amd ) {\n\tdefine( \"jquery\", [], function() {\n\t\treturn jQuery;\n\t} );\n}\n\n\n\n\nvar\n\n\t// Map over jQuery in case of overwrite\n\t_jQuery = window.jQuery,\n\n\t// Map over the $ in case of overwrite\n\t_$ = window.$;\n\njQuery.noConflict = function( deep ) {\n\tif ( window.$ === jQuery ) {\n\t\twindow.$ = _$;\n\t}\n\n\tif ( deep && window.jQuery === jQuery ) {\n\t\twindow.jQuery = _jQuery;\n\t}\n\n\treturn jQuery;\n};\n\n// Expose jQuery and $ identifiers, even in AMD\n// (#7102#comment:10, https://github.com/jquery/jquery/pull/557)\n// and CommonJS for browser emulators (#13566)\nif ( !noGlobal ) {\n\twindow.jQuery = window.$ = jQuery;\n}\n\n\n\n\nreturn jQuery;\n} );", "/*! jQuery UI - v1.12.1 - 2019-01-18\n* http://jqueryui.com\n* Includes: widget.js, position.js, data.js, disable-selection.js, focusable.js, keycode.js, scroll-parent.js, unique-id.js, widgets/draggable.js, widgets/droppable.js, widgets/resizable.js, widgets/selectable.js, widgets/sortable.js, widgets/autocomplete.js, widgets/datepicker.js, widgets/menu.js, widgets/mouse.js, widgets/tooltip.js, effect.js, effects/effect-bounce.js\n* Copyright jQuery Foundation and other contributors; Licensed MIT */\n\n(function( factory ) {\n\tif ( typeof define === \"function\" && define.amd ) {\n\n\t\t// AMD. Register as an anonymous module.\n\t\tdefine([ \"jquery\" ], factory );\n\t} else {\n\n\t\t// Browser globals\n\t\tfactory( jQuery );\n\t}\n}(function( $ ) {\n\n$.ui = $.ui || {};\n\nvar version = $.ui.version = \"1.12.1\";\n\n\n/*!\n * jQuery UI Widget 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Widget\n//>>group: Core\n//>>description: Provides a factory for creating stateful widgets with a common API.\n//>>docs: http://api.jqueryui.com/jQuery.widget/\n//>>demos: http://jqueryui.com/widget/\n\n\n\nvar widgetUuid = 0;\nvar widgetSlice = Array.prototype.slice;\n\n$.cleanData = ( function( orig ) {\n\treturn function( elems ) {\n\t\tvar events, elem, i;\n\t\tfor ( i = 0; ( elem = elems[ i ] ) != null; i++ ) {\n\t\t\ttry {\n\n\t\t\t\t// Only trigger remove when necessary to save time\n\t\t\t\tevents = $._data( elem, \"events\" );\n\t\t\t\tif ( events && events.remove ) {\n\t\t\t\t\t$( elem ).triggerHandler( \"remove\" );\n\t\t\t\t}\n\n\t\t\t// Http://bugs.jquery.com/ticket/8235\n\t\t\t} catch ( e ) {}\n\t\t}\n\t\torig( elems );\n\t};\n} )( $.cleanData );\n\n$.widget = function( name, base, prototype ) {\n\tvar existingConstructor, constructor, basePrototype;\n\n\t// ProxiedPrototype allows the provided prototype to remain unmodified\n\t// so that it can be used as a mixin for multiple widgets (#8876)\n\tvar proxiedPrototype = {};\n\n\tvar namespace = name.split( \".\" )[ 0 ];\n\tname = name.split( \".\" )[ 1 ];\n\tvar fullName = namespace + \"-\" + name;\n\n\tif ( !prototype ) {\n\t\tprototype = base;\n\t\tbase = $.Widget;\n\t}\n\n\tif ( $.isArray( prototype ) ) {\n\t\tprototype = $.extend.apply( null, [ {} ].concat( prototype ) );\n\t}\n\n\t// Create selector for plugin\n\t$.expr[ \":\" ][ fullName.toLowerCase() ] = function( elem ) {\n\t\treturn !!$.data( elem, fullName );\n\t};\n\n\t$[ namespace ] = $[ namespace ] || {};\n\texistingConstructor = $[ namespace ][ name ];\n\tconstructor = $[ namespace ][ name ] = function( options, element ) {\n\n\t\t// Allow instantiation without \"new\" keyword\n\t\tif ( !this._createWidget ) {\n\t\t\treturn new constructor( options, element );\n\t\t}\n\n\t\t// Allow instantiation without initializing for simple inheritance\n\t\t// must use \"new\" keyword (the code above always passes args)\n\t\tif ( arguments.length ) {\n\t\t\tthis._createWidget( options, element );\n\t\t}\n\t};\n\n\t// Extend with the existing constructor to carry over any static properties\n\t$.extend( constructor, existingConstructor, {\n\t\tversion: prototype.version,\n\n\t\t// Copy the object used to create the prototype in case we need to\n\t\t// redefine the widget later\n\t\t_proto: $.extend( {}, prototype ),\n\n\t\t// Track widgets that inherit from this widget in case this widget is\n\t\t// redefined after a widget inherits from it\n\t\t_childConstructors: []\n\t} );\n\n\tbasePrototype = new base();\n\n\t// We need to make the options hash a property directly on the new instance\n\t// otherwise we'll modify the options hash on the prototype that we're\n\t// inheriting from\n\tbasePrototype.options = $.widget.extend( {}, basePrototype.options );\n\t$.each( prototype, function( prop, value ) {\n\t\tif ( !$.isFunction( value ) ) {\n\t\t\tproxiedPrototype[ prop ] = value;\n\t\t\treturn;\n\t\t}\n\t\tproxiedPrototype[ prop ] = ( function() {\n\t\t\tfunction _super() {\n\t\t\t\treturn base.prototype[ prop ].apply( this, arguments );\n\t\t\t}\n\n\t\t\tfunction _superApply( args ) {\n\t\t\t\treturn base.prototype[ prop ].apply( this, args );\n\t\t\t}\n\n\t\t\treturn function() {\n\t\t\t\tvar __super = this._super;\n\t\t\t\tvar __superApply = this._superApply;\n\t\t\t\tvar returnValue;\n\n\t\t\t\tthis._super = _super;\n\t\t\t\tthis._superApply = _superApply;\n\n\t\t\t\treturnValue = value.apply( this, arguments );\n\n\t\t\t\tthis._super = __super;\n\t\t\t\tthis._superApply = __superApply;\n\n\t\t\t\treturn returnValue;\n\t\t\t};\n\t\t} )();\n\t} );\n\tconstructor.prototype = $.widget.extend( basePrototype, {\n\n\t\t// TODO: remove support for widgetEventPrefix\n\t\t// always use the name + a colon as the prefix, e.g., draggable:start\n\t\t// don't prefix for widgets that aren't DOM-based\n\t\twidgetEventPrefix: existingConstructor ? ( basePrototype.widgetEventPrefix || name ) : name\n\t}, proxiedPrototype, {\n\t\tconstructor: constructor,\n\t\tnamespace: namespace,\n\t\twidgetName: name,\n\t\twidgetFullName: fullName\n\t} );\n\n\t// If this widget is being redefined then we need to find all widgets that\n\t// are inheriting from it and redefine all of them so that they inherit from\n\t// the new version of this widget. We're essentially trying to replace one\n\t// level in the prototype chain.\n\tif ( existingConstructor ) {\n\t\t$.each( existingConstructor._childConstructors, function( i, child ) {\n\t\t\tvar childPrototype = child.prototype;\n\n\t\t\t// Redefine the child widget using the same prototype that was\n\t\t\t// originally used, but inherit from the new version of the base\n\t\t\t$.widget( childPrototype.namespace + \".\" + childPrototype.widgetName, constructor,\n\t\t\t\tchild._proto );\n\t\t} );\n\n\t\t// Remove the list of existing child constructors from the old constructor\n\t\t// so the old child constructors can be garbage collected\n\t\tdelete existingConstructor._childConstructors;\n\t} else {\n\t\tbase._childConstructors.push( constructor );\n\t}\n\n\t$.widget.bridge( name, constructor );\n\n\treturn constructor;\n};\n\n$.widget.extend = function( target ) {\n\tvar input = widgetSlice.call( arguments, 1 );\n\tvar inputIndex = 0;\n\tvar inputLength = input.length;\n\tvar key;\n\tvar value;\n\n\tfor ( ; inputIndex < inputLength; inputIndex++ ) {\n\t\tfor ( key in input[ inputIndex ] ) {\n\t\t\tvalue = input[ inputIndex ][ key ];\n\t\t\tif ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) {\n\n\t\t\t\t// Clone objects\n\t\t\t\tif ( $.isPlainObject( value ) ) {\n\t\t\t\t\ttarget[ key ] = $.isPlainObject( target[ key ] ) ?\n\t\t\t\t\t\t$.widget.extend( {}, target[ key ], value ) :\n\n\t\t\t\t\t\t// Don't extend strings, arrays, etc. with objects\n\t\t\t\t\t\t$.widget.extend( {}, value );\n\n\t\t\t\t// Copy everything else by reference\n\t\t\t\t} else {\n\t\t\t\t\ttarget[ key ] = value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn target;\n};\n\n$.widget.bridge = function( name, object ) {\n\tvar fullName = object.prototype.widgetFullName || name;\n\t$.fn[ name ] = function( options ) {\n\t\tvar isMethodCall = typeof options === \"string\";\n\t\tvar args = widgetSlice.call( arguments, 1 );\n\t\tvar returnValue = this;\n\n\t\tif ( isMethodCall ) {\n\n\t\t\t// If this is an empty collection, we need to have the instance method\n\t\t\t// return undefined instead of the jQuery instance\n\t\t\tif ( !this.length && options === \"instance\" ) {\n\t\t\t\treturnValue = undefined;\n\t\t\t} else {\n\t\t\t\tthis.each( function() {\n\t\t\t\t\tvar methodValue;\n\t\t\t\t\tvar instance = $.data( this, fullName );\n\n\t\t\t\t\tif ( options === \"instance\" ) {\n\t\t\t\t\t\treturnValue = instance;\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( !instance ) {\n\t\t\t\t\t\treturn $.error( \"cannot call methods on \" + name +\n\t\t\t\t\t\t\t\" prior to initialization; \" +\n\t\t\t\t\t\t\t\"attempted to call method '\" + options + \"'\" );\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( !$.isFunction( instance[ options ] ) || options.charAt( 0 ) === \"_\" ) {\n\t\t\t\t\t\treturn $.error( \"no such method '\" + options + \"' for \" + name +\n\t\t\t\t\t\t\t\" widget instance\" );\n\t\t\t\t\t}\n\n\t\t\t\t\tmethodValue = instance[ options ].apply( instance, args );\n\n\t\t\t\t\tif ( methodValue !== instance && methodValue !== undefined ) {\n\t\t\t\t\t\treturnValue = methodValue && methodValue.jquery ?\n\t\t\t\t\t\t\treturnValue.pushStack( methodValue.get() ) :\n\t\t\t\t\t\t\tmethodValue;\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t}\n\t\t} else {\n\n\t\t\t// Allow multiple hashes to be passed on init\n\t\t\tif ( args.length ) {\n\t\t\t\toptions = $.widget.extend.apply( null, [ options ].concat( args ) );\n\t\t\t}\n\n\t\t\tthis.each( function() {\n\t\t\t\tvar instance = $.data( this, fullName );\n\t\t\t\tif ( instance ) {\n\t\t\t\t\tinstance.option( options || {} );\n\t\t\t\t\tif ( instance._init ) {\n\t\t\t\t\t\tinstance._init();\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t$.data( this, fullName, new object( options, this ) );\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\n\t\treturn returnValue;\n\t};\n};\n\n$.Widget = function( /* options, element */ ) {};\n$.Widget._childConstructors = [];\n\n$.Widget.prototype = {\n\twidgetName: \"widget\",\n\twidgetEventPrefix: \"\",\n\tdefaultElement: \"<div>\",\n\n\toptions: {\n\t\tclasses: {},\n\t\tdisabled: false,\n\n\t\t// Callbacks\n\t\tcreate: null\n\t},\n\n\t_createWidget: function( options, element ) {\n\t\telement = $( element || this.defaultElement || this )[ 0 ];\n\t\tthis.element = $( element );\n\t\tthis.uuid = widgetUuid++;\n\t\tthis.eventNamespace = \".\" + this.widgetName + this.uuid;\n\n\t\tthis.bindings = $();\n\t\tthis.hoverable = $();\n\t\tthis.focusable = $();\n\t\tthis.classesElementLookup = {};\n\n\t\tif ( element !== this ) {\n\t\t\t$.data( element, this.widgetFullName, this );\n\t\t\tthis._on( true, this.element, {\n\t\t\t\tremove: function( event ) {\n\t\t\t\t\tif ( event.target === element ) {\n\t\t\t\t\t\tthis.destroy();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} );\n\t\t\tthis.document = $( element.style ?\n\n\t\t\t\t// Element within the document\n\t\t\t\telement.ownerDocument :\n\n\t\t\t\t// Element is window or document\n\t\t\t\telement.document || element );\n\t\t\tthis.window = $( this.document[ 0 ].defaultView || this.document[ 0 ].parentWindow );\n\t\t}\n\n\t\tthis.options = $.widget.extend( {},\n\t\t\tthis.options,\n\t\t\tthis._getCreateOptions(),\n\t\t\toptions );\n\n\t\tthis._create();\n\n\t\tif ( this.options.disabled ) {\n\t\t\tthis._setOptionDisabled( this.options.disabled );\n\t\t}\n\n\t\tthis._trigger( \"create\", null, this._getCreateEventData() );\n\t\tthis._init();\n\t},\n\n\t_getCreateOptions: function() {\n\t\treturn {};\n\t},\n\n\t_getCreateEventData: $.noop,\n\n\t_create: $.noop,\n\n\t_init: $.noop,\n\n\tdestroy: function() {\n\t\tvar that = this;\n\n\t\tthis._destroy();\n\t\t$.each( this.classesElementLookup, function( key, value ) {\n\t\t\tthat._removeClass( value, key );\n\t\t} );\n\n\t\t// We can probably remove the unbind calls in 2.0\n\t\t// all event bindings should go through this._on()\n\t\tthis.element\n\t\t\t.off( this.eventNamespace )\n\t\t\t.removeData( this.widgetFullName );\n\t\tthis.widget()\n\t\t\t.off( this.eventNamespace )\n\t\t\t.removeAttr( \"aria-disabled\" );\n\n\t\t// Clean up events and states\n\t\tthis.bindings.off( this.eventNamespace );\n\t},\n\n\t_destroy: $.noop,\n\n\twidget: function() {\n\t\treturn this.element;\n\t},\n\n\toption: function( key, value ) {\n\t\tvar options = key;\n\t\tvar parts;\n\t\tvar curOption;\n\t\tvar i;\n\n\t\tif ( arguments.length === 0 ) {\n\n\t\t\t// Don't return a reference to the internal hash\n\t\t\treturn $.widget.extend( {}, this.options );\n\t\t}\n\n\t\tif ( typeof key === \"string\" ) {\n\n\t\t\t// Handle nested keys, e.g., \"foo.bar\" => { foo: { bar: ___ } }\n\t\t\toptions = {};\n\t\t\tparts = key.split( \".\" );\n\t\t\tkey = parts.shift();\n\t\t\tif ( parts.length ) {\n\t\t\t\tcurOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );\n\t\t\t\tfor ( i = 0; i < parts.length - 1; i++ ) {\n\t\t\t\t\tcurOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};\n\t\t\t\t\tcurOption = curOption[ parts[ i ] ];\n\t\t\t\t}\n\t\t\t\tkey = parts.pop();\n\t\t\t\tif ( arguments.length === 1 ) {\n\t\t\t\t\treturn curOption[ key ] === undefined ? null : curOption[ key ];\n\t\t\t\t}\n\t\t\t\tcurOption[ key ] = value;\n\t\t\t} else {\n\t\t\t\tif ( arguments.length === 1 ) {\n\t\t\t\t\treturn this.options[ key ] === undefined ? null : this.options[ key ];\n\t\t\t\t}\n\t\t\t\toptions[ key ] = value;\n\t\t\t}\n\t\t}\n\n\t\tthis._setOptions( options );\n\n\t\treturn this;\n\t},\n\n\t_setOptions: function( options ) {\n\t\tvar key;\n\n\t\tfor ( key in options ) {\n\t\t\tthis._setOption( key, options[ key ] );\n\t\t}\n\n\t\treturn this;\n\t},\n\n\t_setOption: function( key, value ) {\n\t\tif ( key === \"classes\" ) {\n\t\t\tthis._setOptionClasses( value );\n\t\t}\n\n\t\tthis.options[ key ] = value;\n\n\t\tif ( key === \"disabled\" ) {\n\t\t\tthis._setOptionDisabled( value );\n\t\t}\n\n\t\treturn this;\n\t},\n\n\t_setOptionClasses: function( value ) {\n\t\tvar classKey, elements, currentElements;\n\n\t\tfor ( classKey in value ) {\n\t\t\tcurrentElements = this.classesElementLookup[ classKey ];\n\t\t\tif ( value[ classKey ] === this.options.classes[ classKey ] ||\n\t\t\t\t\t!currentElements ||\n\t\t\t\t\t!currentElements.length ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// We are doing this to create a new jQuery object because the _removeClass() call\n\t\t\t// on the next line is going to destroy the reference to the current elements being\n\t\t\t// tracked. We need to save a copy of this collection so that we can add the new classes\n\t\t\t// below.\n\t\t\telements = $( currentElements.get() );\n\t\t\tthis._removeClass( currentElements, classKey );\n\n\t\t\t// We don't use _addClass() here, because that uses this.options.classes\n\t\t\t// for generating the string of classes. We want to use the value passed in from\n\t\t\t// _setOption(), this is the new value of the classes option which was passed to\n\t\t\t// _setOption(). We pass this value directly to _classes().\n\t\t\telements.addClass( this._classes( {\n\t\t\t\telement: elements,\n\t\t\t\tkeys: classKey,\n\t\t\t\tclasses: value,\n\t\t\t\tadd: true\n\t\t\t} ) );\n\t\t}\n\t},\n\n\t_setOptionDisabled: function( value ) {\n\t\tthis._toggleClass( this.widget(), this.widgetFullName + \"-disabled\", null, !!value );\n\n\t\t// If the widget is becoming disabled, then nothing is interactive\n\t\tif ( value ) {\n\t\t\tthis._removeClass( this.hoverable, null, \"ui-state-hover\" );\n\t\t\tthis._removeClass( this.focusable, null, \"ui-state-focus\" );\n\t\t}\n\t},\n\n\tenable: function() {\n\t\treturn this._setOptions( { disabled: false } );\n\t},\n\n\tdisable: function() {\n\t\treturn this._setOptions( { disabled: true } );\n\t},\n\n\t_classes: function( options ) {\n\t\tvar full = [];\n\t\tvar that = this;\n\n\t\toptions = $.extend( {\n\t\t\telement: this.element,\n\t\t\tclasses: this.options.classes || {}\n\t\t}, options );\n\n\t\tfunction processClassString( classes, checkOption ) {\n\t\t\tvar current, i;\n\t\t\tfor ( i = 0; i < classes.length; i++ ) {\n\t\t\t\tcurrent = that.classesElementLookup[ classes[ i ] ] || $();\n\t\t\t\tif ( options.add ) {\n\t\t\t\t\tcurrent = $( $.unique( current.get().concat( options.element.get() ) ) );\n\t\t\t\t} else {\n\t\t\t\t\tcurrent = $( current.not( options.element ).get() );\n\t\t\t\t}\n\t\t\t\tthat.classesElementLookup[ classes[ i ] ] = current;\n\t\t\t\tfull.push( classes[ i ] );\n\t\t\t\tif ( checkOption && options.classes[ classes[ i ] ] ) {\n\t\t\t\t\tfull.push( options.classes[ classes[ i ] ] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tthis._on( options.element, {\n\t\t\t\"remove\": \"_untrackClassesElement\"\n\t\t} );\n\n\t\tif ( options.keys ) {\n\t\t\tprocessClassString( options.keys.match( /\\S+/g ) || [], true );\n\t\t}\n\t\tif ( options.extra ) {\n\t\t\tprocessClassString( options.extra.match( /\\S+/g ) || [] );\n\t\t}\n\n\t\treturn full.join( \" \" );\n\t},\n\n\t_untrackClassesElement: function( event ) {\n\t\tvar that = this;\n\t\t$.each( that.classesElementLookup, function( key, value ) {\n\t\t\tif ( $.inArray( event.target, value ) !== -1 ) {\n\t\t\t\tthat.classesElementLookup[ key ] = $( value.not( event.target ).get() );\n\t\t\t}\n\t\t} );\n\t},\n\n\t_removeClass: function( element, keys, extra ) {\n\t\treturn this._toggleClass( element, keys, extra, false );\n\t},\n\n\t_addClass: function( element, keys, extra ) {\n\t\treturn this._toggleClass( element, keys, extra, true );\n\t},\n\n\t_toggleClass: function( element, keys, extra, add ) {\n\t\tadd = ( typeof add === \"boolean\" ) ? add : extra;\n\t\tvar shift = ( typeof element === \"string\" || element === null ),\n\t\t\toptions = {\n\t\t\t\textra: shift ? keys : extra,\n\t\t\t\tkeys: shift ? element : keys,\n\t\t\t\telement: shift ? this.element : element,\n\t\t\t\tadd: add\n\t\t\t};\n\t\toptions.element.toggleClass( this._classes( options ), add );\n\t\treturn this;\n\t},\n\n\t_on: function( suppressDisabledCheck, element, handlers ) {\n\t\tvar delegateElement;\n\t\tvar instance = this;\n\n\t\t// No suppressDisabledCheck flag, shuffle arguments\n\t\tif ( typeof suppressDisabledCheck !== \"boolean\" ) {\n\t\t\thandlers = element;\n\t\t\telement = suppressDisabledCheck;\n\t\t\tsuppressDisabledCheck = false;\n\t\t}\n\n\t\t// No element argument, shuffle and use this.element\n\t\tif ( !handlers ) {\n\t\t\thandlers = element;\n\t\t\telement = this.element;\n\t\t\tdelegateElement = this.widget();\n\t\t} else {\n\t\t\telement = delegateElement = $( element );\n\t\t\tthis.bindings = this.bindings.add( element );\n\t\t}\n\n\t\t$.each( handlers, function( event, handler ) {\n\t\t\tfunction handlerProxy() {\n\n\t\t\t\t// Allow widgets to customize the disabled handling\n\t\t\t\t// - disabled as an array instead of boolean\n\t\t\t\t// - disabled class as method for disabling individual parts\n\t\t\t\tif ( !suppressDisabledCheck &&\n\t\t\t\t\t\t( instance.options.disabled === true ||\n\t\t\t\t\t\t$( this ).hasClass( \"ui-state-disabled\" ) ) ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\treturn ( typeof handler === \"string\" ? instance[ handler ] : handler )\n\t\t\t\t\t.apply( instance, arguments );\n\t\t\t}\n\n\t\t\t// Copy the guid so direct unbinding works\n\t\t\tif ( typeof handler !== \"string\" ) {\n\t\t\t\thandlerProxy.guid = handler.guid =\n\t\t\t\t\thandler.guid || handlerProxy.guid || $.guid++;\n\t\t\t}\n\n\t\t\tvar match = event.match( /^([\\w:-]*)\\s*(.*)$/ );\n\t\t\tvar eventName = match[ 1 ] + instance.eventNamespace;\n\t\t\tvar selector = match[ 2 ];\n\n\t\t\tif ( selector ) {\n\t\t\t\tdelegateElement.on( eventName, selector, handlerProxy );\n\t\t\t} else {\n\t\t\t\telement.on( eventName, handlerProxy );\n\t\t\t}\n\t\t} );\n\t},\n\n\t_off: function( element, eventName ) {\n\t\teventName = ( eventName || \"\" ).split( \" \" ).join( this.eventNamespace + \" \" ) +\n\t\t\tthis.eventNamespace;\n\t\telement.off( eventName ).off( eventName );\n\n\t\t// Clear the stack to avoid memory leaks (#10056)\n\t\tthis.bindings = $( this.bindings.not( element ).get() );\n\t\tthis.focusable = $( this.focusable.not( element ).get() );\n\t\tthis.hoverable = $( this.hoverable.not( element ).get() );\n\t},\n\n\t_delay: function( handler, delay ) {\n\t\tfunction handlerProxy() {\n\t\t\treturn ( typeof handler === \"string\" ? instance[ handler ] : handler )\n\t\t\t\t.apply( instance, arguments );\n\t\t}\n\t\tvar instance = this;\n\t\treturn setTimeout( handlerProxy, delay || 0 );\n\t},\n\n\t_hoverable: function( element ) {\n\t\tthis.hoverable = this.hoverable.add( element );\n\t\tthis._on( element, {\n\t\t\tmouseenter: function( event ) {\n\t\t\t\tthis._addClass( $( event.currentTarget ), null, \"ui-state-hover\" );\n\t\t\t},\n\t\t\tmouseleave: function( event ) {\n\t\t\t\tthis._removeClass( $( event.currentTarget ), null, \"ui-state-hover\" );\n\t\t\t}\n\t\t} );\n\t},\n\n\t_focusable: function( element ) {\n\t\tthis.focusable = this.focusable.add( element );\n\t\tthis._on( element, {\n\t\t\tfocusin: function( event ) {\n\t\t\t\tthis._addClass( $( event.currentTarget ), null, \"ui-state-focus\" );\n\t\t\t},\n\t\t\tfocusout: function( event ) {\n\t\t\t\tthis._removeClass( $( event.currentTarget ), null, \"ui-state-focus\" );\n\t\t\t}\n\t\t} );\n\t},\n\n\t_trigger: function( type, event, data ) {\n\t\tvar prop, orig;\n\t\tvar callback = this.options[ type ];\n\n\t\tdata = data || {};\n\t\tevent = $.Event( event );\n\t\tevent.type = ( type === this.widgetEventPrefix ?\n\t\t\ttype :\n\t\t\tthis.widgetEventPrefix + type ).toLowerCase();\n\n\t\t// The original event may come from any element\n\t\t// so we need to reset the target on the new event\n\t\tevent.target = this.element[ 0 ];\n\n\t\t// Copy original event properties over to the new event\n\t\torig = event.originalEvent;\n\t\tif ( orig ) {\n\t\t\tfor ( prop in orig ) {\n\t\t\t\tif ( !( prop in event ) ) {\n\t\t\t\t\tevent[ prop ] = orig[ prop ];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tthis.element.trigger( event, data );\n\t\treturn !( $.isFunction( callback ) &&\n\t\t\tcallback.apply( this.element[ 0 ], [ event ].concat( data ) ) === false ||\n\t\t\tevent.isDefaultPrevented() );\n\t}\n};\n\n$.each( { show: \"fadeIn\", hide: \"fadeOut\" }, function( method, defaultEffect ) {\n\t$.Widget.prototype[ \"_\" + method ] = function( element, options, callback ) {\n\t\tif ( typeof options === \"string\" ) {\n\t\t\toptions = { effect: options };\n\t\t}\n\n\t\tvar hasOptions;\n\t\tvar effectName = !options ?\n\t\t\tmethod :\n\t\t\toptions === true || typeof options === \"number\" ?\n\t\t\t\tdefaultEffect :\n\t\t\t\toptions.effect || defaultEffect;\n\n\t\toptions = options || {};\n\t\tif ( typeof options === \"number\" ) {\n\t\t\toptions = { duration: options };\n\t\t}\n\n\t\thasOptions = !$.isEmptyObject( options );\n\t\toptions.complete = callback;\n\n\t\tif ( options.delay ) {\n\t\t\telement.delay( options.delay );\n\t\t}\n\n\t\tif ( hasOptions && $.effects && $.effects.effect[ effectName ] ) {\n\t\t\telement[ method ]( options );\n\t\t} else if ( effectName !== method && element[ effectName ] ) {\n\t\t\telement[ effectName ]( options.duration, options.easing, callback );\n\t\t} else {\n\t\t\telement.queue( function( next ) {\n\t\t\t\t$( this )[ method ]();\n\t\t\t\tif ( callback ) {\n\t\t\t\t\tcallback.call( element[ 0 ] );\n\t\t\t\t}\n\t\t\t\tnext();\n\t\t\t} );\n\t\t}\n\t};\n} );\n\nvar widget = $.widget;\n\n\n/*!\n * jQuery UI Position 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n *\n * http://api.jqueryui.com/position/\n */\n\n//>>label: Position\n//>>group: Core\n//>>description: Positions elements relative to other elements.\n//>>docs: http://api.jqueryui.com/position/\n//>>demos: http://jqueryui.com/position/\n\n\n( function() {\nvar cachedScrollbarWidth,\n\tmax = Math.max,\n\tabs = Math.abs,\n\trhorizontal = /left|center|right/,\n\trvertical = /top|center|bottom/,\n\troffset = /[\\+\\-]\\d+(\\.[\\d]+)?%?/,\n\trposition = /^\\w+/,\n\trpercent = /%$/,\n\t_position = $.fn.position;\n\nfunction getOffsets( offsets, width, height ) {\n\treturn [\n\t\tparseFloat( offsets[ 0 ] ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ),\n\t\tparseFloat( offsets[ 1 ] ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 )\n\t];\n}\n\nfunction parseCss( element, property ) {\n\treturn parseInt( $.css( element, property ), 10 ) || 0;\n}\n\nfunction getDimensions( elem ) {\n\tvar raw = elem[ 0 ];\n\tif ( raw.nodeType === 9 ) {\n\t\treturn {\n\t\t\twidth: elem.width(),\n\t\t\theight: elem.height(),\n\t\t\toffset: { top: 0, left: 0 }\n\t\t};\n\t}\n\tif ( $.isWindow( raw ) ) {\n\t\treturn {\n\t\t\twidth: elem.width(),\n\t\t\theight: elem.height(),\n\t\t\toffset: { top: elem.scrollTop(), left: elem.scrollLeft() }\n\t\t};\n\t}\n\tif ( raw.preventDefault ) {\n\t\treturn {\n\t\t\twidth: 0,\n\t\t\theight: 0,\n\t\t\toffset: { top: raw.pageY, left: raw.pageX }\n\t\t};\n\t}\n\treturn {\n\t\twidth: elem.outerWidth(),\n\t\theight: elem.outerHeight(),\n\t\toffset: elem.offset()\n\t};\n}\n\n$.position = {\n\tscrollbarWidth: function() {\n\t\tif ( cachedScrollbarWidth !== undefined ) {\n\t\t\treturn cachedScrollbarWidth;\n\t\t}\n\t\tvar w1, w2,\n\t\t\tdiv = $( \"<div \" +\n\t\t\t\t\"style='display:block;position:absolute;width:50px;height:50px;overflow:hidden;'>\" +\n\t\t\t\t\"<div style='height:100px;width:auto;'></div></div>\" ),\n\t\t\tinnerDiv = div.children()[ 0 ];\n\n\t\t$( \"body\" ).append( div );\n\t\tw1 = innerDiv.offsetWidth;\n\t\tdiv.css( \"overflow\", \"scroll\" );\n\n\t\tw2 = innerDiv.offsetWidth;\n\n\t\tif ( w1 === w2 ) {\n\t\t\tw2 = div[ 0 ].clientWidth;\n\t\t}\n\n\t\tdiv.remove();\n\n\t\treturn ( cachedScrollbarWidth = w1 - w2 );\n\t},\n\tgetScrollInfo: function( within ) {\n\t\tvar overflowX = within.isWindow || within.isDocument ? \"\" :\n\t\t\t\twithin.element.css( \"overflow-x\" ),\n\t\t\toverflowY = within.isWindow || within.isDocument ? \"\" :\n\t\t\t\twithin.element.css( \"overflow-y\" ),\n\t\t\thasOverflowX = overflowX === \"scroll\" ||\n\t\t\t\t( overflowX === \"auto\" && within.width < within.element[ 0 ].scrollWidth ),\n\t\t\thasOverflowY = overflowY === \"scroll\" ||\n\t\t\t\t( overflowY === \"auto\" && within.height < within.element[ 0 ].scrollHeight );\n\t\treturn {\n\t\t\twidth: hasOverflowY ? $.position.scrollbarWidth() : 0,\n\t\t\theight: hasOverflowX ? $.position.scrollbarWidth() : 0\n\t\t};\n\t},\n\tgetWithinInfo: function( element ) {\n\t\tvar withinElement = $( element || window ),\n\t\t\tisWindow = $.isWindow( withinElement[ 0 ] ),\n\t\t\tisDocument = !!withinElement[ 0 ] && withinElement[ 0 ].nodeType === 9,\n\t\t\thasOffset = !isWindow && !isDocument;\n\t\treturn {\n\t\t\telement: withinElement,\n\t\t\tisWindow: isWindow,\n\t\t\tisDocument: isDocument,\n\t\t\toffset: hasOffset ? $( element ).offset() : { left: 0, top: 0 },\n\t\t\tscrollLeft: withinElement.scrollLeft(),\n\t\t\tscrollTop: withinElement.scrollTop(),\n\t\t\twidth: withinElement.outerWidth(),\n\t\t\theight: withinElement.outerHeight()\n\t\t};\n\t}\n};\n\n$.fn.position = function( options ) {\n\tif ( !options || !options.of ) {\n\t\treturn _position.apply( this, arguments );\n\t}\n\n\t// Make a copy, we don't want to modify arguments\n\toptions = $.extend( {}, options );\n\n\tvar atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions,\n\t\ttarget = $( options.of ),\n\t\twithin = $.position.getWithinInfo( options.within ),\n\t\tscrollInfo = $.position.getScrollInfo( within ),\n\t\tcollision = ( options.collision || \"flip\" ).split( \" \" ),\n\t\toffsets = {};\n\n\tdimensions = getDimensions( target );\n\tif ( target[ 0 ].preventDefault ) {\n\n\t\t// Force left top to allow flipping\n\t\toptions.at = \"left top\";\n\t}\n\ttargetWidth = dimensions.width;\n\ttargetHeight = dimensions.height;\n\ttargetOffset = dimensions.offset;\n\n\t// Clone to reuse original targetOffset later\n\tbasePosition = $.extend( {}, targetOffset );\n\n\t// Force my and at to have valid horizontal and vertical positions\n\t// if a value is missing or invalid, it will be converted to center\n\t$.each( [ \"my\", \"at\" ], function() {\n\t\tvar pos = ( options[ this ] || \"\" ).split( \" \" ),\n\t\t\thorizontalOffset,\n\t\t\tverticalOffset;\n\n\t\tif ( pos.length === 1 ) {\n\t\t\tpos = rhorizontal.test( pos[ 0 ] ) ?\n\t\t\t\tpos.concat( [ \"center\" ] ) :\n\t\t\t\trvertical.test( pos[ 0 ] ) ?\n\t\t\t\t\t[ \"center\" ].concat( pos ) :\n\t\t\t\t\t[ \"center\", \"center\" ];\n\t\t}\n\t\tpos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : \"center\";\n\t\tpos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : \"center\";\n\n\t\t// Calculate offsets\n\t\thorizontalOffset = roffset.exec( pos[ 0 ] );\n\t\tverticalOffset = roffset.exec( pos[ 1 ] );\n\t\toffsets[ this ] = [\n\t\t\thorizontalOffset ? horizontalOffset[ 0 ] : 0,\n\t\t\tverticalOffset ? verticalOffset[ 0 ] : 0\n\t\t];\n\n\t\t// Reduce to just the positions without the offsets\n\t\toptions[ this ] = [\n\t\t\trposition.exec( pos[ 0 ] )[ 0 ],\n\t\t\trposition.exec( pos[ 1 ] )[ 0 ]\n\t\t];\n\t} );\n\n\t// Normalize collision option\n\tif ( collision.length === 1 ) {\n\t\tcollision[ 1 ] = collision[ 0 ];\n\t}\n\n\tif ( options.at[ 0 ] === \"right\" ) {\n\t\tbasePosition.left += targetWidth;\n\t} else if ( options.at[ 0 ] === \"center\" ) {\n\t\tbasePosition.left += targetWidth / 2;\n\t}\n\n\tif ( options.at[ 1 ] === \"bottom\" ) {\n\t\tbasePosition.top += targetHeight;\n\t} else if ( options.at[ 1 ] === \"center\" ) {\n\t\tbasePosition.top += targetHeight / 2;\n\t}\n\n\tatOffset = getOffsets( offsets.at, targetWidth, targetHeight );\n\tbasePosition.left += atOffset[ 0 ];\n\tbasePosition.top += atOffset[ 1 ];\n\n\treturn this.each( function() {\n\t\tvar collisionPosition, using,\n\t\t\telem = $( this ),\n\t\t\telemWidth = elem.outerWidth(),\n\t\t\telemHeight = elem.outerHeight(),\n\t\t\tmarginLeft = parseCss( this, \"marginLeft\" ),\n\t\t\tmarginTop = parseCss( this, \"marginTop\" ),\n\t\t\tcollisionWidth = elemWidth + marginLeft + parseCss( this, \"marginRight\" ) +\n\t\t\t\tscrollInfo.width,\n\t\t\tcollisionHeight = elemHeight + marginTop + parseCss( this, \"marginBottom\" ) +\n\t\t\t\tscrollInfo.height,\n\t\t\tposition = $.extend( {}, basePosition ),\n\t\t\tmyOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() );\n\n\t\tif ( options.my[ 0 ] === \"right\" ) {\n\t\t\tposition.left -= elemWidth;\n\t\t} else if ( options.my[ 0 ] === \"center\" ) {\n\t\t\tposition.left -= elemWidth / 2;\n\t\t}\n\n\t\tif ( options.my[ 1 ] === \"bottom\" ) {\n\t\t\tposition.top -= elemHeight;\n\t\t} else if ( options.my[ 1 ] === \"center\" ) {\n\t\t\tposition.top -= elemHeight / 2;\n\t\t}\n\n\t\tposition.left += myOffset[ 0 ];\n\t\tposition.top += myOffset[ 1 ];\n\n\t\tcollisionPosition = {\n\t\t\tmarginLeft: marginLeft,\n\t\t\tmarginTop: marginTop\n\t\t};\n\n\t\t$.each( [ \"left\", \"top\" ], function( i, dir ) {\n\t\t\tif ( $.ui.position[ collision[ i ] ] ) {\n\t\t\t\t$.ui.position[ collision[ i ] ][ dir ]( position, {\n\t\t\t\t\ttargetWidth: targetWidth,\n\t\t\t\t\ttargetHeight: targetHeight,\n\t\t\t\t\telemWidth: elemWidth,\n\t\t\t\t\telemHeight: elemHeight,\n\t\t\t\t\tcollisionPosition: collisionPosition,\n\t\t\t\t\tcollisionWidth: collisionWidth,\n\t\t\t\t\tcollisionHeight: collisionHeight,\n\t\t\t\t\toffset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ],\n\t\t\t\t\tmy: options.my,\n\t\t\t\t\tat: options.at,\n\t\t\t\t\twithin: within,\n\t\t\t\t\telem: elem\n\t\t\t\t} );\n\t\t\t}\n\t\t} );\n\n\t\tif ( options.using ) {\n\n\t\t\t// Adds feedback as second argument to using callback, if present\n\t\t\tusing = function( props ) {\n\t\t\t\tvar left = targetOffset.left - position.left,\n\t\t\t\t\tright = left + targetWidth - elemWidth,\n\t\t\t\t\ttop = targetOffset.top - position.top,\n\t\t\t\t\tbottom = top + targetHeight - elemHeight,\n\t\t\t\t\tfeedback = {\n\t\t\t\t\t\ttarget: {\n\t\t\t\t\t\t\telement: target,\n\t\t\t\t\t\t\tleft: targetOffset.left,\n\t\t\t\t\t\t\ttop: targetOffset.top,\n\t\t\t\t\t\t\twidth: targetWidth,\n\t\t\t\t\t\t\theight: targetHeight\n\t\t\t\t\t\t},\n\t\t\t\t\t\telement: {\n\t\t\t\t\t\t\telement: elem,\n\t\t\t\t\t\t\tleft: position.left,\n\t\t\t\t\t\t\ttop: position.top,\n\t\t\t\t\t\t\twidth: elemWidth,\n\t\t\t\t\t\t\theight: elemHeight\n\t\t\t\t\t\t},\n\t\t\t\t\t\thorizontal: right < 0 ? \"left\" : left > 0 ? \"right\" : \"center\",\n\t\t\t\t\t\tvertical: bottom < 0 ? \"top\" : top > 0 ? \"bottom\" : \"middle\"\n\t\t\t\t\t};\n\t\t\t\tif ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) {\n\t\t\t\t\tfeedback.horizontal = \"center\";\n\t\t\t\t}\n\t\t\t\tif ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) {\n\t\t\t\t\tfeedback.vertical = \"middle\";\n\t\t\t\t}\n\t\t\t\tif ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) {\n\t\t\t\t\tfeedback.important = \"horizontal\";\n\t\t\t\t} else {\n\t\t\t\t\tfeedback.important = \"vertical\";\n\t\t\t\t}\n\t\t\t\toptions.using.call( this, props, feedback );\n\t\t\t};\n\t\t}\n\n\t\telem.offset( $.extend( position, { using: using } ) );\n\t} );\n};\n\n$.ui.position = {\n\tfit: {\n\t\tleft: function( position, data ) {\n\t\t\tvar within = data.within,\n\t\t\t\twithinOffset = within.isWindow ? within.scrollLeft : within.offset.left,\n\t\t\t\touterWidth = within.width,\n\t\t\t\tcollisionPosLeft = position.left - data.collisionPosition.marginLeft,\n\t\t\t\toverLeft = withinOffset - collisionPosLeft,\n\t\t\t\toverRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset,\n\t\t\t\tnewOverRight;\n\n\t\t\t// Element is wider than within\n\t\t\tif ( data.collisionWidth > outerWidth ) {\n\n\t\t\t\t// Element is initially over the left side of within\n\t\t\t\tif ( overLeft > 0 && overRight <= 0 ) {\n\t\t\t\t\tnewOverRight = position.left + overLeft + data.collisionWidth - outerWidth -\n\t\t\t\t\t\twithinOffset;\n\t\t\t\t\tposition.left += overLeft - newOverRight;\n\n\t\t\t\t// Element is initially over right side of within\n\t\t\t\t} else if ( overRight > 0 && overLeft <= 0 ) {\n\t\t\t\t\tposition.left = withinOffset;\n\n\t\t\t\t// Element is initially over both left and right sides of within\n\t\t\t\t} else {\n\t\t\t\t\tif ( overLeft > overRight ) {\n\t\t\t\t\t\tposition.left = withinOffset + outerWidth - data.collisionWidth;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tposition.left = withinOffset;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t// Too far left -> align with left edge\n\t\t\t} else if ( overLeft > 0 ) {\n\t\t\t\tposition.left += overLeft;\n\n\t\t\t// Too far right -> align with right edge\n\t\t\t} else if ( overRight > 0 ) {\n\t\t\t\tposition.left -= overRight;\n\n\t\t\t// Adjust based on position and margin\n\t\t\t} else {\n\t\t\t\tposition.left = max( position.left - collisionPosLeft, position.left );\n\t\t\t}\n\t\t},\n\t\ttop: function( position, data ) {\n\t\t\tvar within = data.within,\n\t\t\t\twithinOffset = within.isWindow ? within.scrollTop : within.offset.top,\n\t\t\t\touterHeight = data.within.height,\n\t\t\t\tcollisionPosTop = position.top - data.collisionPosition.marginTop,\n\t\t\t\toverTop = withinOffset - collisionPosTop,\n\t\t\t\toverBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset,\n\t\t\t\tnewOverBottom;\n\n\t\t\t// Element is taller than within\n\t\t\tif ( data.collisionHeight > outerHeight ) {\n\n\t\t\t\t// Element is initially over the top of within\n\t\t\t\tif ( overTop > 0 && overBottom <= 0 ) {\n\t\t\t\t\tnewOverBottom = position.top + overTop + data.collisionHeight - outerHeight -\n\t\t\t\t\t\twithinOffset;\n\t\t\t\t\tposition.top += overTop - newOverBottom;\n\n\t\t\t\t// Element is initially over bottom of within\n\t\t\t\t} else if ( overBottom > 0 && overTop <= 0 ) {\n\t\t\t\t\tposition.top = withinOffset;\n\n\t\t\t\t// Element is initially over both top and bottom of within\n\t\t\t\t} else {\n\t\t\t\t\tif ( overTop > overBottom ) {\n\t\t\t\t\t\tposition.top = withinOffset + outerHeight - data.collisionHeight;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tposition.top = withinOffset;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t// Too far up -> align with top\n\t\t\t} else if ( overTop > 0 ) {\n\t\t\t\tposition.top += overTop;\n\n\t\t\t// Too far down -> align with bottom edge\n\t\t\t} else if ( overBottom > 0 ) {\n\t\t\t\tposition.top -= overBottom;\n\n\t\t\t// Adjust based on position and margin\n\t\t\t} else {\n\t\t\t\tposition.top = max( position.top - collisionPosTop, position.top );\n\t\t\t}\n\t\t}\n\t},\n\tflip: {\n\t\tleft: function( position, data ) {\n\t\t\tvar within = data.within,\n\t\t\t\twithinOffset = within.offset.left + within.scrollLeft,\n\t\t\t\touterWidth = within.width,\n\t\t\t\toffsetLeft = within.isWindow ? within.scrollLeft : within.offset.left,\n\t\t\t\tcollisionPosLeft = position.left - data.collisionPosition.marginLeft,\n\t\t\t\toverLeft = collisionPosLeft - offsetLeft,\n\t\t\t\toverRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft,\n\t\t\t\tmyOffset = data.my[ 0 ] === \"left\" ?\n\t\t\t\t\t-data.elemWidth :\n\t\t\t\t\tdata.my[ 0 ] === \"right\" ?\n\t\t\t\t\t\tdata.elemWidth :\n\t\t\t\t\t\t0,\n\t\t\t\tatOffset = data.at[ 0 ] === \"left\" ?\n\t\t\t\t\tdata.targetWidth :\n\t\t\t\t\tdata.at[ 0 ] === \"right\" ?\n\t\t\t\t\t\t-data.targetWidth :\n\t\t\t\t\t\t0,\n\t\t\t\toffset = -2 * data.offset[ 0 ],\n\t\t\t\tnewOverRight,\n\t\t\t\tnewOverLeft;\n\n\t\t\tif ( overLeft < 0 ) {\n\t\t\t\tnewOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth -\n\t\t\t\t\touterWidth - withinOffset;\n\t\t\t\tif ( newOverRight < 0 || newOverRight < abs( overLeft ) ) {\n\t\t\t\t\tposition.left += myOffset + atOffset + offset;\n\t\t\t\t}\n\t\t\t} else if ( overRight > 0 ) {\n\t\t\t\tnewOverLeft = position.left - data.collisionPosition.marginLeft + myOffset +\n\t\t\t\t\tatOffset + offset - offsetLeft;\n\t\t\t\tif ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) {\n\t\t\t\t\tposition.left += myOffset + atOffset + offset;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\ttop: function( position, data ) {\n\t\t\tvar within = data.within,\n\t\t\t\twithinOffset = within.offset.top + within.scrollTop,\n\t\t\t\touterHeight = within.height,\n\t\t\t\toffsetTop = within.isWindow ? within.scrollTop : within.offset.top,\n\t\t\t\tcollisionPosTop = position.top - data.collisionPosition.marginTop,\n\t\t\t\toverTop = collisionPosTop - offsetTop,\n\t\t\t\toverBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop,\n\t\t\t\ttop = data.my[ 1 ] === \"top\",\n\t\t\t\tmyOffset = top ?\n\t\t\t\t\t-data.elemHeight :\n\t\t\t\t\tdata.my[ 1 ] === \"bottom\" ?\n\t\t\t\t\t\tdata.elemHeight :\n\t\t\t\t\t\t0,\n\t\t\t\tatOffset = data.at[ 1 ] === \"top\" ?\n\t\t\t\t\tdata.targetHeight :\n\t\t\t\t\tdata.at[ 1 ] === \"bottom\" ?\n\t\t\t\t\t\t-data.targetHeight :\n\t\t\t\t\t\t0,\n\t\t\t\toffset = -2 * data.offset[ 1 ],\n\t\t\t\tnewOverTop,\n\t\t\t\tnewOverBottom;\n\t\t\tif ( overTop < 0 ) {\n\t\t\t\tnewOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight -\n\t\t\t\t\touterHeight - withinOffset;\n\t\t\t\tif ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) {\n\t\t\t\t\tposition.top += myOffset + atOffset + offset;\n\t\t\t\t}\n\t\t\t} else if ( overBottom > 0 ) {\n\t\t\t\tnewOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset +\n\t\t\t\t\toffset - offsetTop;\n\t\t\t\tif ( newOverTop > 0 || abs( newOverTop ) < overBottom ) {\n\t\t\t\t\tposition.top += myOffset + atOffset + offset;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\tflipfit: {\n\t\tleft: function() {\n\t\t\t$.ui.position.flip.left.apply( this, arguments );\n\t\t\t$.ui.position.fit.left.apply( this, arguments );\n\t\t},\n\t\ttop: function() {\n\t\t\t$.ui.position.flip.top.apply( this, arguments );\n\t\t\t$.ui.position.fit.top.apply( this, arguments );\n\t\t}\n\t}\n};\n\n} )();\n\nvar position = $.ui.position;\n\n\n/*!\n * jQuery UI :data 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: :data Selector\n//>>group: Core\n//>>description: Selects elements which have data stored under the specified key.\n//>>docs: http://api.jqueryui.com/data-selector/\n\n\nvar data = $.extend( $.expr[ \":\" ], {\n\tdata: $.expr.createPseudo ?\n\t\t$.expr.createPseudo( function( dataName ) {\n\t\t\treturn function( elem ) {\n\t\t\t\treturn !!$.data( elem, dataName );\n\t\t\t};\n\t\t} ) :\n\n\t\t// Support: jQuery <1.8\n\t\tfunction( elem, i, match ) {\n\t\t\treturn !!$.data( elem, match[ 3 ] );\n\t\t}\n} );\n\n/*!\n * jQuery UI Disable Selection 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: disableSelection\n//>>group: Core\n//>>description: Disable selection of text content within the set of matched elements.\n//>>docs: http://api.jqueryui.com/disableSelection/\n\n// This file is deprecated\n\n\nvar disableSelection = $.fn.extend( {\n\tdisableSelection: ( function() {\n\t\tvar eventType = \"onselectstart\" in document.createElement( \"div\" ) ?\n\t\t\t\"selectstart\" :\n\t\t\t\"mousedown\";\n\n\t\treturn function() {\n\t\t\treturn this.on( eventType + \".ui-disableSelection\", function( event ) {\n\t\t\t\tevent.preventDefault();\n\t\t\t} );\n\t\t};\n\t} )(),\n\n\tenableSelection: function() {\n\t\treturn this.off( \".ui-disableSelection\" );\n\t}\n} );\n\n\n/*!\n * jQuery UI Focusable 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: :focusable Selector\n//>>group: Core\n//>>description: Selects elements which can be focused.\n//>>docs: http://api.jqueryui.com/focusable-selector/\n\n\n\n// Selectors\n$.ui.focusable = function( element, hasTabindex ) {\n\tvar map, mapName, img, focusableIfVisible, fieldset,\n\t\tnodeName = element.nodeName.toLowerCase();\n\n\tif ( \"area\" === nodeName ) {\n\t\tmap = element.parentNode;\n\t\tmapName = map.name;\n\t\tif ( !element.href || !mapName || map.nodeName.toLowerCase() !== \"map\" ) {\n\t\t\treturn false;\n\t\t}\n\t\timg = $( \"img[usemap='#\" + mapName + \"']\" );\n\t\treturn img.length > 0 && img.is( \":visible\" );\n\t}\n\n\tif ( /^(input|select|textarea|button|object)$/.test( nodeName ) ) {\n\t\tfocusableIfVisible = !element.disabled;\n\n\t\tif ( focusableIfVisible ) {\n\n\t\t\t// Form controls within a disabled fieldset are disabled.\n\t\t\t// However, controls within the fieldset's legend do not get disabled.\n\t\t\t// Since controls generally aren't placed inside legends, we skip\n\t\t\t// this portion of the check.\n\t\t\tfieldset = $( element ).closest( \"fieldset\" )[ 0 ];\n\t\t\tif ( fieldset ) {\n\t\t\t\tfocusableIfVisible = !fieldset.disabled;\n\t\t\t}\n\t\t}\n\t} else if ( \"a\" === nodeName ) {\n\t\tfocusableIfVisible = element.href || hasTabindex;\n\t} else {\n\t\tfocusableIfVisible = hasTabindex;\n\t}\n\n\treturn focusableIfVisible && $( element ).is( \":visible\" ) && visible( $( element ) );\n};\n\n// Support: IE 8 only\n// IE 8 doesn't resolve inherit to visible/hidden for computed values\nfunction visible( element ) {\n\tvar visibility = element.css( \"visibility\" );\n\twhile ( visibility === \"inherit\" ) {\n\t\telement = element.parent();\n\t\tvisibility = element.css( \"visibility\" );\n\t}\n\treturn visibility !== \"hidden\";\n}\n\n$.extend( $.expr[ \":\" ], {\n\tfocusable: function( element ) {\n\t\treturn $.ui.focusable( element, $.attr( element, \"tabindex\" ) != null );\n\t}\n} );\n\nvar focusable = $.ui.focusable;\n\n\n/*!\n * jQuery UI Keycode 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Keycode\n//>>group: Core\n//>>description: Provide keycodes as keynames\n//>>docs: http://api.jqueryui.com/jQuery.ui.keyCode/\n\n\nvar keycode = $.ui.keyCode = {\n\tBACKSPACE: 8,\n\tCOMMA: 188,\n\tDELETE: 46,\n\tDOWN: 40,\n\tEND: 35,\n\tENTER: 13,\n\tESCAPE: 27,\n\tHOME: 36,\n\tLEFT: 37,\n\tPAGE_DOWN: 34,\n\tPAGE_UP: 33,\n\tPERIOD: 190,\n\tRIGHT: 39,\n\tSPACE: 32,\n\tTAB: 9,\n\tUP: 38\n};\n\n\n/*!\n * jQuery UI Scroll Parent 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: scrollParent\n//>>group: Core\n//>>description: Get the closest ancestor element that is scrollable.\n//>>docs: http://api.jqueryui.com/scrollParent/\n\n\n\nvar scrollParent = $.fn.scrollParent = function( includeHidden ) {\n\tvar position = this.css( \"position\" ),\n\t\texcludeStaticParent = position === \"absolute\",\n\t\toverflowRegex = includeHidden ? /(auto|scroll|hidden)/ : /(auto|scroll)/,\n\t\tscrollParent = this.parents().filter( function() {\n\t\t\tvar parent = $( this );\n\t\t\tif ( excludeStaticParent && parent.css( \"position\" ) === \"static\" ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\treturn overflowRegex.test( parent.css( \"overflow\" ) + parent.css( \"overflow-y\" ) +\n\t\t\t\tparent.css( \"overflow-x\" ) );\n\t\t} ).eq( 0 );\n\n\treturn position === \"fixed\" || !scrollParent.length ?\n\t\t$( this[ 0 ].ownerDocument || document ) :\n\t\tscrollParent;\n};\n\n\n/*!\n * jQuery UI Unique ID 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: uniqueId\n//>>group: Core\n//>>description: Functions to generate and remove uniqueId's\n//>>docs: http://api.jqueryui.com/uniqueId/\n\n\n\nvar uniqueId = $.fn.extend( {\n\tuniqueId: ( function() {\n\t\tvar uuid = 0;\n\n\t\treturn function() {\n\t\t\treturn this.each( function() {\n\t\t\t\tif ( !this.id ) {\n\t\t\t\t\tthis.id = \"ui-id-\" + ( ++uuid );\n\t\t\t\t}\n\t\t\t} );\n\t\t};\n\t} )(),\n\n\tremoveUniqueId: function() {\n\t\treturn this.each( function() {\n\t\t\tif ( /^ui-id-\\d+$/.test( this.id ) ) {\n\t\t\t\t$( this ).removeAttr( \"id\" );\n\t\t\t}\n\t\t} );\n\t}\n} );\n\n\n\n\n// This file is deprecated\nvar ie = $.ui.ie = !!/msie [\\w.]+/.exec( navigator.userAgent.toLowerCase() );\n\n/*!\n * jQuery UI Mouse 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Mouse\n//>>group: Widgets\n//>>description: Abstracts mouse-based interactions to assist in creating certain widgets.\n//>>docs: http://api.jqueryui.com/mouse/\n\n\n\nvar mouseHandled = false;\n$( document ).on( \"mouseup\", function() {\n\tmouseHandled = false;\n} );\n\nvar widgetsMouse = $.widget( \"ui.mouse\", {\n\tversion: \"1.12.1\",\n\toptions: {\n\t\tcancel: \"input, textarea, button, select, option\",\n\t\tdistance: 1,\n\t\tdelay: 0\n\t},\n\t_mouseInit: function() {\n\t\tvar that = this;\n\n\t\tthis.element\n\t\t\t.on( \"mousedown.\" + this.widgetName, function( event ) {\n\t\t\t\treturn that._mouseDown( event );\n\t\t\t} )\n\t\t\t.on( \"click.\" + this.widgetName, function( event ) {\n\t\t\t\tif ( true === $.data( event.target, that.widgetName + \".preventClickEvent\" ) ) {\n\t\t\t\t\t$.removeData( event.target, that.widgetName + \".preventClickEvent\" );\n\t\t\t\t\tevent.stopImmediatePropagation();\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t} );\n\n\t\tthis.started = false;\n\t},\n\n\t// TODO: make sure destroying one instance of mouse doesn't mess with\n\t// other instances of mouse\n\t_mouseDestroy: function() {\n\t\tthis.element.off( \".\" + this.widgetName );\n\t\tif ( this._mouseMoveDelegate ) {\n\t\t\tthis.document\n\t\t\t\t.off( \"mousemove.\" + this.widgetName, this._mouseMoveDelegate )\n\t\t\t\t.off( \"mouseup.\" + this.widgetName, this._mouseUpDelegate );\n\t\t}\n\t},\n\n\t_mouseDown: function( event ) {\n\n\t\t// don't let more than one widget handle mouseStart\n\t\tif ( mouseHandled ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis._mouseMoved = false;\n\n\t\t// We may have missed mouseup (out of window)\n\t\t( this._mouseStarted && this._mouseUp( event ) );\n\n\t\tthis._mouseDownEvent = event;\n\n\t\tvar that = this,\n\t\t\tbtnIsLeft = ( event.which === 1 ),\n\n\t\t\t// event.target.nodeName works around a bug in IE 8 with\n\t\t\t// disabled inputs (#7620)\n\t\t\telIsCancel = ( typeof this.options.cancel === \"string\" && event.target.nodeName ?\n\t\t\t\t$( event.target ).closest( this.options.cancel ).length : false );\n\t\tif ( !btnIsLeft || elIsCancel || !this._mouseCapture( event ) ) {\n\t\t\treturn true;\n\t\t}\n\n\t\tthis.mouseDelayMet = !this.options.delay;\n\t\tif ( !this.mouseDelayMet ) {\n\t\t\tthis._mouseDelayTimer = setTimeout( function() {\n\t\t\t\tthat.mouseDelayMet = true;\n\t\t\t}, this.options.delay );\n\t\t}\n\n\t\tif ( this._mouseDistanceMet( event ) && this._mouseDelayMet( event ) ) {\n\t\t\tthis._mouseStarted = ( this._mouseStart( event ) !== false );\n\t\t\tif ( !this._mouseStarted ) {\n\t\t\t\tevent.preventDefault();\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\t// Click event may never have fired (Gecko & Opera)\n\t\tif ( true === $.data( event.target, this.widgetName + \".preventClickEvent\" ) ) {\n\t\t\t$.removeData( event.target, this.widgetName + \".preventClickEvent\" );\n\t\t}\n\n\t\t// These delegates are required to keep context\n\t\tthis._mouseMoveDelegate = function( event ) {\n\t\t\treturn that._mouseMove( event );\n\t\t};\n\t\tthis._mouseUpDelegate = function( event ) {\n\t\t\treturn that._mouseUp( event );\n\t\t};\n\n\t\tthis.document\n\t\t\t.on( \"mousemove.\" + this.widgetName, this._mouseMoveDelegate )\n\t\t\t.on( \"mouseup.\" + this.widgetName, this._mouseUpDelegate );\n\n\t\tevent.preventDefault();\n\n\t\tmouseHandled = true;\n\t\treturn true;\n\t},\n\n\t_mouseMove: function( event ) {\n\n\t\t// Only check for mouseups outside the document if you've moved inside the document\n\t\t// at least once. This prevents the firing of mouseup in the case of IE<9, which will\n\t\t// fire a mousemove event if content is placed under the cursor. See #7778\n\t\t// Support: IE <9\n\t\tif ( this._mouseMoved ) {\n\n\t\t\t// IE mouseup check - mouseup happened when mouse was out of window\n\t\t\tif ( $.ui.ie && ( !document.documentMode || document.documentMode < 9 ) &&\n\t\t\t\t\t!event.button ) {\n\t\t\t\treturn this._mouseUp( event );\n\n\t\t\t// Iframe mouseup check - mouseup occurred in another document\n\t\t\t} else if ( !event.which ) {\n\n\t\t\t\t// Support: Safari <=8 - 9\n\t\t\t\t// Safari sets which to 0 if you press any of the following keys\n\t\t\t\t// during a drag (#14461)\n\t\t\t\tif ( event.originalEvent.altKey || event.originalEvent.ctrlKey ||\n\t\t\t\t\t\tevent.originalEvent.metaKey || event.originalEvent.shiftKey ) {\n\t\t\t\t\tthis.ignoreMissingWhich = true;\n\t\t\t\t} else if ( !this.ignoreMissingWhich ) {\n\t\t\t\t\treturn this._mouseUp( event );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif ( event.which || event.button ) {\n\t\t\tthis._mouseMoved = true;\n\t\t}\n\n\t\tif ( this._mouseStarted ) {\n\t\t\tthis._mouseDrag( event );\n\t\t\treturn event.preventDefault();\n\t\t}\n\n\t\tif ( this._mouseDistanceMet( event ) && this._mouseDelayMet( event ) ) {\n\t\t\tthis._mouseStarted =\n\t\t\t\t( this._mouseStart( this._mouseDownEvent, event ) !== false );\n\t\t\t( this._mouseStarted ? this._mouseDrag( event ) : this._mouseUp( event ) );\n\t\t}\n\n\t\treturn !this._mouseStarted;\n\t},\n\n\t_mouseUp: function( event ) {\n\t\tthis.document\n\t\t\t.off( \"mousemove.\" + this.widgetName, this._mouseMoveDelegate )\n\t\t\t.off( \"mouseup.\" + this.widgetName, this._mouseUpDelegate );\n\n\t\tif ( this._mouseStarted ) {\n\t\t\tthis._mouseStarted = false;\n\n\t\t\tif ( event.target === this._mouseDownEvent.target ) {\n\t\t\t\t$.data( event.target, this.widgetName + \".preventClickEvent\", true );\n\t\t\t}\n\n\t\t\tthis._mouseStop( event );\n\t\t}\n\n\t\tif ( this._mouseDelayTimer ) {\n\t\t\tclearTimeout( this._mouseDelayTimer );\n\t\t\tdelete this._mouseDelayTimer;\n\t\t}\n\n\t\tthis.ignoreMissingWhich = false;\n\t\tmouseHandled = false;\n\t\tevent.preventDefault();\n\t},\n\n\t_mouseDistanceMet: function( event ) {\n\t\treturn ( Math.max(\n\t\t\t\tMath.abs( this._mouseDownEvent.pageX - event.pageX ),\n\t\t\t\tMath.abs( this._mouseDownEvent.pageY - event.pageY )\n\t\t\t) >= this.options.distance\n\t\t);\n\t},\n\n\t_mouseDelayMet: function( /* event */ ) {\n\t\treturn this.mouseDelayMet;\n\t},\n\n\t// These are placeholder methods, to be overridden by extending plugin\n\t_mouseStart: function( /* event */ ) {},\n\t_mouseDrag: function( /* event */ ) {},\n\t_mouseStop: function( /* event */ ) {},\n\t_mouseCapture: function( /* event */ ) { return true; }\n} );\n\n\n\n\n// $.ui.plugin is deprecated. Use $.widget() extensions instead.\nvar plugin = $.ui.plugin = {\n\tadd: function( module, option, set ) {\n\t\tvar i,\n\t\t\tproto = $.ui[ module ].prototype;\n\t\tfor ( i in set ) {\n\t\t\tproto.plugins[ i ] = proto.plugins[ i ] || [];\n\t\t\tproto.plugins[ i ].push( [ option, set[ i ] ] );\n\t\t}\n\t},\n\tcall: function( instance, name, args, allowDisconnected ) {\n\t\tvar i,\n\t\t\tset = instance.plugins[ name ];\n\n\t\tif ( !set ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( !allowDisconnected && ( !instance.element[ 0 ].parentNode ||\n\t\t\t\tinstance.element[ 0 ].parentNode.nodeType === 11 ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tfor ( i = 0; i < set.length; i++ ) {\n\t\t\tif ( instance.options[ set[ i ][ 0 ] ] ) {\n\t\t\t\tset[ i ][ 1 ].apply( instance.element, args );\n\t\t\t}\n\t\t}\n\t}\n};\n\n\n\nvar safeActiveElement = $.ui.safeActiveElement = function( document ) {\n\tvar activeElement;\n\n\t// Support: IE 9 only\n\t// IE9 throws an \"Unspecified error\" accessing document.activeElement from an <iframe>\n\ttry {\n\t\tactiveElement = document.activeElement;\n\t} catch ( error ) {\n\t\tactiveElement = document.body;\n\t}\n\n\t// Support: IE 9 - 11 only\n\t// IE may return null instead of an element\n\t// Interestingly, this only seems to occur when NOT in an iframe\n\tif ( !activeElement ) {\n\t\tactiveElement = document.body;\n\t}\n\n\t// Support: IE 11 only\n\t// IE11 returns a seemingly empty object in some cases when accessing\n\t// document.activeElement from an <iframe>\n\tif ( !activeElement.nodeName ) {\n\t\tactiveElement = document.body;\n\t}\n\n\treturn activeElement;\n};\n\n\n\nvar safeBlur = $.ui.safeBlur = function( element ) {\n\n\t// Support: IE9 - 10 only\n\t// If the <body> is blurred, IE will switch windows, see #9420\n\tif ( element && element.nodeName.toLowerCase() !== \"body\" ) {\n\t\t$( element ).trigger( \"blur\" );\n\t}\n};\n\n\n/*!\n * jQuery UI Draggable 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Draggable\n//>>group: Interactions\n//>>description: Enables dragging functionality for any element.\n//>>docs: http://api.jqueryui.com/draggable/\n//>>demos: http://jqueryui.com/draggable/\n//>>css.structure: ../../themes/base/draggable.css\n\n\n\n$.widget( \"ui.draggable\", $.ui.mouse, {\n\tversion: \"1.12.1\",\n\twidgetEventPrefix: \"drag\",\n\toptions: {\n\t\taddClasses: true,\n\t\tappendTo: \"parent\",\n\t\taxis: false,\n\t\tconnectToSortable: false,\n\t\tcontainment: false,\n\t\tcursor: \"auto\",\n\t\tcursorAt: false,\n\t\tgrid: false,\n\t\thandle: false,\n\t\thelper: \"original\",\n\t\tiframeFix: false,\n\t\topacity: false,\n\t\trefreshPositions: false,\n\t\trevert: false,\n\t\trevertDuration: 500,\n\t\tscope: \"default\",\n\t\tscroll: true,\n\t\tscrollSensitivity: 20,\n\t\tscrollSpeed: 20,\n\t\tsnap: false,\n\t\tsnapMode: \"both\",\n\t\tsnapTolerance: 20,\n\t\tstack: false,\n\t\tzIndex: false,\n\n\t\t// Callbacks\n\t\tdrag: null,\n\t\tstart: null,\n\t\tstop: null\n\t},\n\t_create: function() {\n\n\t\tif ( this.options.helper === \"original\" ) {\n\t\t\tthis._setPositionRelative();\n\t\t}\n\t\tif ( this.options.addClasses ) {\n\t\t\tthis._addClass( \"ui-draggable\" );\n\t\t}\n\t\tthis._setHandleClassName();\n\n\t\tthis._mouseInit();\n\t},\n\n\t_setOption: function( key, value ) {\n\t\tthis._super( key, value );\n\t\tif ( key === \"handle\" ) {\n\t\t\tthis._removeHandleClassName();\n\t\t\tthis._setHandleClassName();\n\t\t}\n\t},\n\n\t_destroy: function() {\n\t\tif ( ( this.helper || this.element ).is( \".ui-draggable-dragging\" ) ) {\n\t\t\tthis.destroyOnClear = true;\n\t\t\treturn;\n\t\t}\n\t\tthis._removeHandleClassName();\n\t\tthis._mouseDestroy();\n\t},\n\n\t_mouseCapture: function( event ) {\n\t\tvar o = this.options;\n\n\t\t// Among others, prevent a drag on a resizable-handle\n\t\tif ( this.helper || o.disabled ||\n\t\t\t\t$( event.target ).closest( \".ui-resizable-handle\" ).length > 0 ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t//Quit if we're not on a valid handle\n\t\tthis.handle = this._getHandle( event );\n\t\tif ( !this.handle ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tthis._blurActiveElement( event );\n\n\t\tthis._blockFrames( o.iframeFix === true ? \"iframe\" : o.iframeFix );\n\n\t\treturn true;\n\n\t},\n\n\t_blockFrames: function( selector ) {\n\t\tthis.iframeBlocks = this.document.find( selector ).map( function() {\n\t\t\tvar iframe = $( this );\n\n\t\t\treturn $( \"<div>\" )\n\t\t\t\t.css( \"position\", \"absolute\" )\n\t\t\t\t.appendTo( iframe.parent() )\n\t\t\t\t.outerWidth( iframe.outerWidth() )\n\t\t\t\t.outerHeight( iframe.outerHeight() )\n\t\t\t\t.offset( iframe.offset() )[ 0 ];\n\t\t} );\n\t},\n\n\t_unblockFrames: function() {\n\t\tif ( this.iframeBlocks ) {\n\t\t\tthis.iframeBlocks.remove();\n\t\t\tdelete this.iframeBlocks;\n\t\t}\n\t},\n\n\t_blurActiveElement: function( event ) {\n\t\tvar activeElement = $.ui.safeActiveElement( this.document[ 0 ] ),\n\t\t\ttarget = $( event.target );\n\n\t\t// Don't blur if the event occurred on an element that is within\n\t\t// the currently focused element\n\t\t// See #10527, #12472\n\t\tif ( target.closest( activeElement ).length ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Blur any element that currently has focus, see #4261\n\t\t$.ui.safeBlur( activeElement );\n\t},\n\n\t_mouseStart: function( event ) {\n\n\t\tvar o = this.options;\n\n\t\t//Create and append the visible helper\n\t\tthis.helper = this._createHelper( event );\n\n\t\tthis._addClass( this.helper, \"ui-draggable-dragging\" );\n\n\t\t//Cache the helper size\n\t\tthis._cacheHelperProportions();\n\n\t\t//If ddmanager is used for droppables, set the global draggable\n\t\tif ( $.ui.ddmanager ) {\n\t\t\t$.ui.ddmanager.current = this;\n\t\t}\n\n\t\t/*\n\t\t * - Position generation -\n\t\t * This block generates everything position related - it's the core of draggables.\n\t\t */\n\n\t\t//Cache the margins of the original element\n\t\tthis._cacheMargins();\n\n\t\t//Store the helper's css position\n\t\tthis.cssPosition = this.helper.css( \"position\" );\n\t\tthis.scrollParent = this.helper.scrollParent( true );\n\t\tthis.offsetParent = this.helper.offsetParent();\n\t\tthis.hasFixedAncestor = this.helper.parents().filter( function() {\n\t\t\t\treturn $( this ).css( \"position\" ) === \"fixed\";\n\t\t\t} ).length > 0;\n\n\t\t//The element's absolute position on the page minus margins\n\t\tthis.positionAbs = this.element.offset();\n\t\tthis._refreshOffsets( event );\n\n\t\t//Generate the original position\n\t\tthis.originalPosition = this.position = this._generatePosition( event, false );\n\t\tthis.originalPageX = event.pageX;\n\t\tthis.originalPageY = event.pageY;\n\n\t\t//Adjust the mouse offset relative to the helper if \"cursorAt\" is supplied\n\t\t( o.cursorAt && this._adjustOffsetFromHelper( o.cursorAt ) );\n\n\t\t//Set a containment if given in the options\n\t\tthis._setContainment();\n\n\t\t//Trigger event + callbacks\n\t\tif ( this._trigger( \"start\", event ) === false ) {\n\t\t\tthis._clear();\n\t\t\treturn false;\n\t\t}\n\n\t\t//Recache the helper size\n\t\tthis._cacheHelperProportions();\n\n\t\t//Prepare the droppable offsets\n\t\tif ( $.ui.ddmanager && !o.dropBehaviour ) {\n\t\t\t$.ui.ddmanager.prepareOffsets( this, event );\n\t\t}\n\n\t\t// Execute the drag once - this causes the helper not to be visible before getting its\n\t\t// correct position\n\t\tthis._mouseDrag( event, true );\n\n\t\t// If the ddmanager is used for droppables, inform the manager that dragging has started\n\t\t// (see #5003)\n\t\tif ( $.ui.ddmanager ) {\n\t\t\t$.ui.ddmanager.dragStart( this, event );\n\t\t}\n\n\t\treturn true;\n\t},\n\n\t_refreshOffsets: function( event ) {\n\t\tthis.offset = {\n\t\t\ttop: this.positionAbs.top - this.margins.top,\n\t\t\tleft: this.positionAbs.left - this.margins.left,\n\t\t\tscroll: false,\n\t\t\tparent: this._getParentOffset(),\n\t\t\trelative: this._getRelativeOffset()\n\t\t};\n\n\t\tthis.offset.click = {\n\t\t\tleft: event.pageX - this.offset.left,\n\t\t\ttop: event.pageY - this.offset.top\n\t\t};\n\t},\n\n\t_mouseDrag: function( event, noPropagation ) {\n\n\t\t// reset any necessary cached properties (see #5009)\n\t\tif ( this.hasFixedAncestor ) {\n\t\t\tthis.offset.parent = this._getParentOffset();\n\t\t}\n\n\t\t//Compute the helpers position\n\t\tthis.position = this._generatePosition( event, true );\n\t\tthis.positionAbs = this._convertPositionTo( \"absolute\" );\n\n\t\t//Call plugins and callbacks and use the resulting position if something is returned\n\t\tif ( !noPropagation ) {\n\t\t\tvar ui = this._uiHash();\n\t\t\tif ( this._trigger( \"drag\", event, ui ) === false ) {\n\t\t\t\tthis._mouseUp( new $.Event( \"mouseup\", event ) );\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tthis.position = ui.position;\n\t\t}\n\n\t\tthis.helper[ 0 ].style.left = this.position.left + \"px\";\n\t\tthis.helper[ 0 ].style.top = this.position.top + \"px\";\n\n\t\tif ( $.ui.ddmanager ) {\n\t\t\t$.ui.ddmanager.drag( this, event );\n\t\t}\n\n\t\treturn false;\n\t},\n\n\t_mouseStop: function( event ) {\n\n\t\t//If we are using droppables, inform the manager about the drop\n\t\tvar that = this,\n\t\t\tdropped = false;\n\t\tif ( $.ui.ddmanager && !this.options.dropBehaviour ) {\n\t\t\tdropped = $.ui.ddmanager.drop( this, event );\n\t\t}\n\n\t\t//if a drop comes from outside (a sortable)\n\t\tif ( this.dropped ) {\n\t\t\tdropped = this.dropped;\n\t\t\tthis.dropped = false;\n\t\t}\n\n\t\tif ( ( this.options.revert === \"invalid\" && !dropped ) ||\n\t\t\t\t( this.options.revert === \"valid\" && dropped ) ||\n\t\t\t\tthis.options.revert === true || ( $.isFunction( this.options.revert ) &&\n\t\t\t\tthis.options.revert.call( this.element, dropped ) )\n\t\t) {\n\t\t\t$( this.helper ).animate(\n\t\t\t\tthis.originalPosition,\n\t\t\t\tparseInt( this.options.revertDuration, 10 ),\n\t\t\t\tfunction() {\n\t\t\t\t\tif ( that._trigger( \"stop\", event ) !== false ) {\n\t\t\t\t\t\tthat._clear();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t);\n\t\t} else {\n\t\t\tif ( this._trigger( \"stop\", event ) !== false ) {\n\t\t\t\tthis._clear();\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t},\n\n\t_mouseUp: function( event ) {\n\t\tthis._unblockFrames();\n\n\t\t// If the ddmanager is used for droppables, inform the manager that dragging has stopped\n\t\t// (see #5003)\n\t\tif ( $.ui.ddmanager ) {\n\t\t\t$.ui.ddmanager.dragStop( this, event );\n\t\t}\n\n\t\t// Only need to focus if the event occurred on the draggable itself, see #10527\n\t\tif ( this.handleElement.is( event.target ) ) {\n\n\t\t\t// The interaction is over; whether or not the click resulted in a drag,\n\t\t\t// focus the element\n\t\t\tthis.element.trigger( \"focus\" );\n\t\t}\n\n\t\treturn $.ui.mouse.prototype._mouseUp.call( this, event );\n\t},\n\n\tcancel: function() {\n\n\t\tif ( this.helper.is( \".ui-draggable-dragging\" ) ) {\n\t\t\tthis._mouseUp( new $.Event( \"mouseup\", { target: this.element[ 0 ] } ) );\n\t\t} else {\n\t\t\tthis._clear();\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\t_getHandle: function( event ) {\n\t\treturn this.options.handle ?\n\t\t\t!!$( event.target ).closest( this.element.find( this.options.handle ) ).length :\n\t\t\ttrue;\n\t},\n\n\t_setHandleClassName: function() {\n\t\tthis.handleElement = this.options.handle ?\n\t\t\tthis.element.find( this.options.handle ) : this.element;\n\t\tthis._addClass( this.handleElement, \"ui-draggable-handle\" );\n\t},\n\n\t_removeHandleClassName: function() {\n\t\tthis._removeClass( this.handleElement, \"ui-draggable-handle\" );\n\t},\n\n\t_createHelper: function( event ) {\n\n\t\tvar o = this.options,\n\t\t\thelperIsFunction = $.isFunction( o.helper ),\n\t\t\thelper = helperIsFunction ?\n\t\t\t\t$( o.helper.apply( this.element[ 0 ], [ event ] ) ) :\n\t\t\t\t( o.helper === \"clone\" ?\n\t\t\t\t\tthis.element.clone().removeAttr( \"id\" ) :\n\t\t\t\t\tthis.element );\n\n\t\tif ( !helper.parents( \"body\" ).length ) {\n\t\t\thelper.appendTo( ( o.appendTo === \"parent\" ?\n\t\t\t\tthis.element[ 0 ].parentNode :\n\t\t\t\to.appendTo ) );\n\t\t}\n\n\t\t// Http://bugs.jqueryui.com/ticket/9446\n\t\t// a helper function can return the original element\n\t\t// which wouldn't have been set to relative in _create\n\t\tif ( helperIsFunction && helper[ 0 ] === this.element[ 0 ] ) {\n\t\t\tthis._setPositionRelative();\n\t\t}\n\n\t\tif ( helper[ 0 ] !== this.element[ 0 ] &&\n\t\t\t\t!( /(fixed|absolute)/ ).test( helper.css( \"position\" ) ) ) {\n\t\t\thelper.css( \"position\", \"absolute\" );\n\t\t}\n\n\t\treturn helper;\n\n\t},\n\n\t_setPositionRelative: function() {\n\t\tif ( !( /^(?:r|a|f)/ ).test( this.element.css( \"position\" ) ) ) {\n\t\t\tthis.element[ 0 ].style.position = \"relative\";\n\t\t}\n\t},\n\n\t_adjustOffsetFromHelper: function( obj ) {\n\t\tif ( typeof obj === \"string\" ) {\n\t\t\tobj = obj.split( \" \" );\n\t\t}\n\t\tif ( $.isArray( obj ) ) {\n\t\t\tobj = { left: +obj[ 0 ], top: +obj[ 1 ] || 0 };\n\t\t}\n\t\tif ( \"left\" in obj ) {\n\t\t\tthis.offset.click.left = obj.left + this.margins.left;\n\t\t}\n\t\tif ( \"right\" in obj ) {\n\t\t\tthis.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;\n\t\t}\n\t\tif ( \"top\" in obj ) {\n\t\t\tthis.offset.click.top = obj.top + this.margins.top;\n\t\t}\n\t\tif ( \"bottom\" in obj ) {\n\t\t\tthis.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;\n\t\t}\n\t},\n\n\t_isRootNode: function( element ) {\n\t\treturn ( /(html|body)/i ).test( element.tagName ) || element === this.document[ 0 ];\n\t},\n\n\t_getParentOffset: function() {\n\n\t\t//Get the offsetParent and cache its position\n\t\tvar po = this.offsetParent.offset(),\n\t\t\tdocument = this.document[ 0 ];\n\n\t\t// This is a special case where we need to modify a offset calculated on start, since the\n\t\t// following happened:\n\t\t// 1. The position of the helper is absolute, so it's position is calculated based on the\n\t\t// next positioned parent\n\t\t// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't\n\t\t// the document, which means that the scroll is included in the initial calculation of the\n\t\t// offset of the parent, and never recalculated upon drag\n\t\tif ( this.cssPosition === \"absolute\" && this.scrollParent[ 0 ] !== document &&\n\t\t\t\t$.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) {\n\t\t\tpo.left += this.scrollParent.scrollLeft();\n\t\t\tpo.top += this.scrollParent.scrollTop();\n\t\t}\n\n\t\tif ( this._isRootNode( this.offsetParent[ 0 ] ) ) {\n\t\t\tpo = { top: 0, left: 0 };\n\t\t}\n\n\t\treturn {\n\t\t\ttop: po.top + ( parseInt( this.offsetParent.css( \"borderTopWidth\" ), 10 ) || 0 ),\n\t\t\tleft: po.left + ( parseInt( this.offsetParent.css( \"borderLeftWidth\" ), 10 ) || 0 )\n\t\t};\n\n\t},\n\n\t_getRelativeOffset: function() {\n\t\tif ( this.cssPosition !== \"relative\" ) {\n\t\t\treturn { top: 0, left: 0 };\n\t\t}\n\n\t\tvar p = this.element.position(),\n\t\t\tscrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] );\n\n\t\treturn {\n\t\t\ttop: p.top - ( parseInt( this.helper.css( \"top\" ), 10 ) || 0 ) +\n\t\t\t\t( !scrollIsRootNode ? this.scrollParent.scrollTop() : 0 ),\n\t\t\tleft: p.left - ( parseInt( this.helper.css( \"left\" ), 10 ) || 0 ) +\n\t\t\t\t( !scrollIsRootNode ? this.scrollParent.scrollLeft() : 0 )\n\t\t};\n\n\t},\n\n\t_cacheMargins: function() {\n\t\tthis.margins = {\n\t\t\tleft: ( parseInt( this.element.css( \"marginLeft\" ), 10 ) || 0 ),\n\t\t\ttop: ( parseInt( this.element.css( \"marginTop\" ), 10 ) || 0 ),\n\t\t\tright: ( parseInt( this.element.css( \"marginRight\" ), 10 ) || 0 ),\n\t\t\tbottom: ( parseInt( this.element.css( \"marginBottom\" ), 10 ) || 0 )\n\t\t};\n\t},\n\n\t_cacheHelperProportions: function() {\n\t\tthis.helperProportions = {\n\t\t\twidth: this.helper.outerWidth(),\n\t\t\theight: this.helper.outerHeight()\n\t\t};\n\t},\n\n\t_setContainment: function() {\n\n\t\tvar isUserScrollable, c, ce,\n\t\t\to = this.options,\n\t\t\tdocument = this.document[ 0 ];\n\n\t\tthis.relativeContainer = null;\n\n\t\tif ( !o.containment ) {\n\t\t\tthis.containment = null;\n\t\t\treturn;\n\t\t}\n\n\t\tif ( o.containment === \"window\" ) {\n\t\t\tthis.containment = [\n\t\t\t\t$( window ).scrollLeft() - this.offset.relative.left - this.offset.parent.left,\n\t\t\t\t$( window ).scrollTop() - this.offset.relative.top - this.offset.parent.top,\n\t\t\t\t$( window ).scrollLeft() + $( window ).width() -\n\t\t\t\t\tthis.helperProportions.width - this.margins.left,\n\t\t\t\t$( window ).scrollTop() +\n\t\t\t\t\t( $( window ).height() || document.body.parentNode.scrollHeight ) -\n\t\t\t\t\tthis.helperProportions.height - this.margins.top\n\t\t\t];\n\t\t\treturn;\n\t\t}\n\n\t\tif ( o.containment === \"document\" ) {\n\t\t\tthis.containment = [\n\t\t\t\t0,\n\t\t\t\t0,\n\t\t\t\t$( document ).width() - this.helperProportions.width - this.margins.left,\n\t\t\t\t( $( document ).height() || document.body.parentNode.scrollHeight ) -\n\t\t\t\t\tthis.helperProportions.height - this.margins.top\n\t\t\t];\n\t\t\treturn;\n\t\t}\n\n\t\tif ( o.containment.constructor === Array ) {\n\t\t\tthis.containment = o.containment;\n\t\t\treturn;\n\t\t}\n\n\t\tif ( o.containment === \"parent\" ) {\n\t\t\to.containment = this.helper[ 0 ].parentNode;\n\t\t}\n\n\t\tc = $( o.containment );\n\t\tce = c[ 0 ];\n\n\t\tif ( !ce ) {\n\t\t\treturn;\n\t\t}\n\n\t\tisUserScrollable = /(scroll|auto)/.test( c.css( \"overflow\" ) );\n\n\t\tthis.containment = [\n\t\t\t( parseInt( c.css( \"borderLeftWidth\" ), 10 ) || 0 ) +\n\t\t\t\t( parseInt( c.css( \"paddingLeft\" ), 10 ) || 0 ),\n\t\t\t( parseInt( c.css( \"borderTopWidth\" ), 10 ) || 0 ) +\n\t\t\t\t( parseInt( c.css( \"paddingTop\" ), 10 ) || 0 ),\n\t\t\t( isUserScrollable ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) -\n\t\t\t\t( parseInt( c.css( \"borderRightWidth\" ), 10 ) || 0 ) -\n\t\t\t\t( parseInt( c.css( \"paddingRight\" ), 10 ) || 0 ) -\n\t\t\t\tthis.helperProportions.width -\n\t\t\t\tthis.margins.left -\n\t\t\t\tthis.margins.right,\n\t\t\t( isUserScrollable ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) -\n\t\t\t\t( parseInt( c.css( \"borderBottomWidth\" ), 10 ) || 0 ) -\n\t\t\t\t( parseInt( c.css( \"paddingBottom\" ), 10 ) || 0 ) -\n\t\t\t\tthis.helperProportions.height -\n\t\t\t\tthis.margins.top -\n\t\t\t\tthis.margins.bottom\n\t\t];\n\t\tthis.relativeContainer = c;\n\t},\n\n\t_convertPositionTo: function( d, pos ) {\n\n\t\tif ( !pos ) {\n\t\t\tpos = this.position;\n\t\t}\n\n\t\tvar mod = d === \"absolute\" ? 1 : -1,\n\t\t\tscrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] );\n\n\t\treturn {\n\t\t\ttop: (\n\n\t\t\t\t// The absolute mouse position\n\t\t\t\tpos.top\t+\n\n\t\t\t\t// Only for relative positioned nodes: Relative offset from element to offset parent\n\t\t\t\tthis.offset.relative.top * mod +\n\n\t\t\t\t// The offsetParent's offset without borders (offset + border)\n\t\t\t\tthis.offset.parent.top * mod -\n\t\t\t\t( ( this.cssPosition === \"fixed\" ?\n\t\t\t\t\t-this.offset.scroll.top :\n\t\t\t\t\t( scrollIsRootNode ? 0 : this.offset.scroll.top ) ) * mod )\n\t\t\t),\n\t\t\tleft: (\n\n\t\t\t\t// The absolute mouse position\n\t\t\t\tpos.left +\n\n\t\t\t\t// Only for relative positioned nodes: Relative offset from element to offset parent\n\t\t\t\tthis.offset.relative.left * mod +\n\n\t\t\t\t// The offsetParent's offset without borders (offset + border)\n\t\t\t\tthis.offset.parent.left * mod\t-\n\t\t\t\t( ( this.cssPosition === \"fixed\" ?\n\t\t\t\t\t-this.offset.scroll.left :\n\t\t\t\t\t( scrollIsRootNode ? 0 : this.offset.scroll.left ) ) * mod )\n\t\t\t)\n\t\t};\n\n\t},\n\n\t_generatePosition: function( event, constrainPosition ) {\n\n\t\tvar containment, co, top, left,\n\t\t\to = this.options,\n\t\t\tscrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] ),\n\t\t\tpageX = event.pageX,\n\t\t\tpageY = event.pageY;\n\n\t\t// Cache the scroll\n\t\tif ( !scrollIsRootNode || !this.offset.scroll ) {\n\t\t\tthis.offset.scroll = {\n\t\t\t\ttop: this.scrollParent.scrollTop(),\n\t\t\t\tleft: this.scrollParent.scrollLeft()\n\t\t\t};\n\t\t}\n\n\t\t/*\n\t\t * - Position constraining -\n\t\t * Constrain the position to a mix of grid, containment.\n\t\t */\n\n\t\t// If we are not dragging yet, we won't check for options\n\t\tif ( constrainPosition ) {\n\t\t\tif ( this.containment ) {\n\t\t\t\tif ( this.relativeContainer ) {\n\t\t\t\t\tco = this.relativeContainer.offset();\n\t\t\t\t\tcontainment = [\n\t\t\t\t\t\tthis.containment[ 0 ] + co.left,\n\t\t\t\t\t\tthis.containment[ 1 ] + co.top,\n\t\t\t\t\t\tthis.containment[ 2 ] + co.left,\n\t\t\t\t\t\tthis.containment[ 3 ] + co.top\n\t\t\t\t\t];\n\t\t\t\t} else {\n\t\t\t\t\tcontainment = this.containment;\n\t\t\t\t}\n\n\t\t\t\tif ( event.pageX - this.offset.click.left < containment[ 0 ] ) {\n\t\t\t\t\tpageX = containment[ 0 ] + this.offset.click.left;\n\t\t\t\t}\n\t\t\t\tif ( event.pageY - this.offset.click.top < containment[ 1 ] ) {\n\t\t\t\t\tpageY = containment[ 1 ] + this.offset.click.top;\n\t\t\t\t}\n\t\t\t\tif ( event.pageX - this.offset.click.left > containment[ 2 ] ) {\n\t\t\t\t\tpageX = containment[ 2 ] + this.offset.click.left;\n\t\t\t\t}\n\t\t\t\tif ( event.pageY - this.offset.click.top > containment[ 3 ] ) {\n\t\t\t\t\tpageY = containment[ 3 ] + this.offset.click.top;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( o.grid ) {\n\n\t\t\t\t//Check for grid elements set to 0 to prevent divide by 0 error causing invalid\n\t\t\t\t// argument errors in IE (see ticket #6950)\n\t\t\t\ttop = o.grid[ 1 ] ? this.originalPageY + Math.round( ( pageY -\n\t\t\t\t\tthis.originalPageY ) / o.grid[ 1 ] ) * o.grid[ 1 ] : this.originalPageY;\n\t\t\t\tpageY = containment ? ( ( top - this.offset.click.top >= containment[ 1 ] ||\n\t\t\t\t\ttop - this.offset.click.top > containment[ 3 ] ) ?\n\t\t\t\t\t\ttop :\n\t\t\t\t\t\t( ( top - this.offset.click.top >= containment[ 1 ] ) ?\n\t\t\t\t\t\t\ttop - o.grid[ 1 ] : top + o.grid[ 1 ] ) ) : top;\n\n\t\t\t\tleft = o.grid[ 0 ] ? this.originalPageX +\n\t\t\t\t\tMath.round( ( pageX - this.originalPageX ) / o.grid[ 0 ] ) * o.grid[ 0 ] :\n\t\t\t\t\tthis.originalPageX;\n\t\t\t\tpageX = containment ? ( ( left - this.offset.click.left >= containment[ 0 ] ||\n\t\t\t\t\tleft - this.offset.click.left > containment[ 2 ] ) ?\n\t\t\t\t\t\tleft :\n\t\t\t\t\t\t( ( left - this.offset.click.left >= containment[ 0 ] ) ?\n\t\t\t\t\t\t\tleft - o.grid[ 0 ] : left + o.grid[ 0 ] ) ) : left;\n\t\t\t}\n\n\t\t\tif ( o.axis === \"y\" ) {\n\t\t\t\tpageX = this.originalPageX;\n\t\t\t}\n\n\t\t\tif ( o.axis === \"x\" ) {\n\t\t\t\tpageY = this.originalPageY;\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\ttop: (\n\n\t\t\t\t// The absolute mouse position\n\t\t\t\tpageY -\n\n\t\t\t\t// Click offset (relative to the element)\n\t\t\t\tthis.offset.click.top -\n\n\t\t\t\t// Only for relative positioned nodes: Relative offset from element to offset parent\n\t\t\t\tthis.offset.relative.top -\n\n\t\t\t\t// The offsetParent's offset without borders (offset + border)\n\t\t\t\tthis.offset.parent.top +\n\t\t\t\t( this.cssPosition === \"fixed\" ?\n\t\t\t\t\t-this.offset.scroll.top :\n\t\t\t\t\t( scrollIsRootNode ? 0 : this.offset.scroll.top ) )\n\t\t\t),\n\t\t\tleft: (\n\n\t\t\t\t// The absolute mouse position\n\t\t\t\tpageX -\n\n\t\t\t\t// Click offset (relative to the element)\n\t\t\t\tthis.offset.click.left -\n\n\t\t\t\t// Only for relative positioned nodes: Relative offset from element to offset parent\n\t\t\t\tthis.offset.relative.left -\n\n\t\t\t\t// The offsetParent's offset without borders (offset + border)\n\t\t\t\tthis.offset.parent.left +\n\t\t\t\t( this.cssPosition === \"fixed\" ?\n\t\t\t\t\t-this.offset.scroll.left :\n\t\t\t\t\t( scrollIsRootNode ? 0 : this.offset.scroll.left ) )\n\t\t\t)\n\t\t};\n\n\t},\n\n\t_clear: function() {\n\t\tthis._removeClass( this.helper, \"ui-draggable-dragging\" );\n\t\tif ( this.helper[ 0 ] !== this.element[ 0 ] && !this.cancelHelperRemoval ) {\n\t\t\tthis.helper.remove();\n\t\t}\n\t\tthis.helper = null;\n\t\tthis.cancelHelperRemoval = false;\n\t\tif ( this.destroyOnClear ) {\n\t\t\tthis.destroy();\n\t\t}\n\t},\n\n\t// From now on bulk stuff - mainly helpers\n\n\t_trigger: function( type, event, ui ) {\n\t\tui = ui || this._uiHash();\n\t\t$.ui.plugin.call( this, type, [ event, ui, this ], true );\n\n\t\t// Absolute position and offset (see #6884 ) have to be recalculated after plugins\n\t\tif ( /^(drag|start|stop)/.test( type ) ) {\n\t\t\tthis.positionAbs = this._convertPositionTo( \"absolute\" );\n\t\t\tui.offset = this.positionAbs;\n\t\t}\n\t\treturn $.Widget.prototype._trigger.call( this, type, event, ui );\n\t},\n\n\tplugins: {},\n\n\t_uiHash: function() {\n\t\treturn {\n\t\t\thelper: this.helper,\n\t\t\tposition: this.position,\n\t\t\toriginalPosition: this.originalPosition,\n\t\t\toffset: this.positionAbs\n\t\t};\n\t}\n\n} );\n\n$.ui.plugin.add( \"draggable\", \"connectToSortable\", {\n\tstart: function( event, ui, draggable ) {\n\t\tvar uiSortable = $.extend( {}, ui, {\n\t\t\titem: draggable.element\n\t\t} );\n\n\t\tdraggable.sortables = [];\n\t\t$( draggable.options.connectToSortable ).each( function() {\n\t\t\tvar sortable = $( this ).sortable( \"instance\" );\n\n\t\t\tif ( sortable && !sortable.options.disabled ) {\n\t\t\t\tdraggable.sortables.push( sortable );\n\n\t\t\t\t// RefreshPositions is called at drag start to refresh the containerCache\n\t\t\t\t// which is used in drag. This ensures it's initialized and synchronized\n\t\t\t\t// with any changes that might have happened on the page since initialization.\n\t\t\t\tsortable.refreshPositions();\n\t\t\t\tsortable._trigger( \"activate\", event, uiSortable );\n\t\t\t}\n\t\t} );\n\t},\n\tstop: function( event, ui, draggable ) {\n\t\tvar uiSortable = $.extend( {}, ui, {\n\t\t\titem: draggable.element\n\t\t} );\n\n\t\tdraggable.cancelHelperRemoval = false;\n\n\t\t$.each( draggable.sortables, function() {\n\t\t\tvar sortable = this;\n\n\t\t\tif ( sortable.isOver ) {\n\t\t\t\tsortable.isOver = 0;\n\n\t\t\t\t// Allow this sortable to handle removing the helper\n\t\t\t\tdraggable.cancelHelperRemoval = true;\n\t\t\t\tsortable.cancelHelperRemoval = false;\n\n\t\t\t\t// Use _storedCSS To restore properties in the sortable,\n\t\t\t\t// as this also handles revert (#9675) since the draggable\n\t\t\t\t// may have modified them in unexpected ways (#8809)\n\t\t\t\tsortable._storedCSS = {\n\t\t\t\t\tposition: sortable.placeholder.css( \"position\" ),\n\t\t\t\t\ttop: sortable.placeholder.css( \"top\" ),\n\t\t\t\t\tleft: sortable.placeholder.css( \"left\" )\n\t\t\t\t};\n\n\t\t\t\tsortable._mouseStop( event );\n\n\t\t\t\t// Once drag has ended, the sortable should return to using\n\t\t\t\t// its original helper, not the shared helper from draggable\n\t\t\t\tsortable.options.helper = sortable.options._helper;\n\t\t\t} else {\n\n\t\t\t\t// Prevent this Sortable from removing the helper.\n\t\t\t\t// However, don't set the draggable to remove the helper\n\t\t\t\t// either as another connected Sortable may yet handle the removal.\n\t\t\t\tsortable.cancelHelperRemoval = true;\n\n\t\t\t\tsortable._trigger( \"deactivate\", event, uiSortable );\n\t\t\t}\n\t\t} );\n\t},\n\tdrag: function( event, ui, draggable ) {\n\t\t$.each( draggable.sortables, function() {\n\t\t\tvar innermostIntersecting = false,\n\t\t\t\tsortable = this;\n\n\t\t\t// Copy over variables that sortable's _intersectsWith uses\n\t\t\tsortable.positionAbs = draggable.positionAbs;\n\t\t\tsortable.helperProportions = draggable.helperProportions;\n\t\t\tsortable.offset.click = draggable.offset.click;\n\n\t\t\tif ( sortable._intersectsWith( sortable.containerCache ) ) {\n\t\t\t\tinnermostIntersecting = true;\n\n\t\t\t\t$.each( draggable.sortables, function() {\n\n\t\t\t\t\t// Copy over variables that sortable's _intersectsWith uses\n\t\t\t\t\tthis.positionAbs = draggable.positionAbs;\n\t\t\t\t\tthis.helperProportions = draggable.helperProportions;\n\t\t\t\t\tthis.offset.click = draggable.offset.click;\n\n\t\t\t\t\tif ( this !== sortable &&\n\t\t\t\t\t\t\tthis._intersectsWith( this.containerCache ) &&\n\t\t\t\t\t\t\t$.contains( sortable.element[ 0 ], this.element[ 0 ] ) ) {\n\t\t\t\t\t\tinnermostIntersecting = false;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn innermostIntersecting;\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\tif ( innermostIntersecting ) {\n\n\t\t\t\t// If it intersects, we use a little isOver variable and set it once,\n\t\t\t\t// so that the move-in stuff gets fired only once.\n\t\t\t\tif ( !sortable.isOver ) {\n\t\t\t\t\tsortable.isOver = 1;\n\n\t\t\t\t\t// Store draggable's parent in case we need to reappend to it later.\n\t\t\t\t\tdraggable._parent = ui.helper.parent();\n\n\t\t\t\t\tsortable.currentItem = ui.helper\n\t\t\t\t\t\t.appendTo( sortable.element )\n\t\t\t\t\t\t.data( \"ui-sortable-item\", true );\n\n\t\t\t\t\t// Store helper option to later restore it\n\t\t\t\t\tsortable.options._helper = sortable.options.helper;\n\n\t\t\t\t\tsortable.options.helper = function() {\n\t\t\t\t\t\treturn ui.helper[ 0 ];\n\t\t\t\t\t};\n\n\t\t\t\t\t// Fire the start events of the sortable with our passed browser event,\n\t\t\t\t\t// and our own helper (so it doesn't create a new one)\n\t\t\t\t\tevent.target = sortable.currentItem[ 0 ];\n\t\t\t\t\tsortable._mouseCapture( event, true );\n\t\t\t\t\tsortable._mouseStart( event, true, true );\n\n\t\t\t\t\t// Because the browser event is way off the new appended portlet,\n\t\t\t\t\t// modify necessary variables to reflect the changes\n\t\t\t\t\tsortable.offset.click.top = draggable.offset.click.top;\n\t\t\t\t\tsortable.offset.click.left = draggable.offset.click.left;\n\t\t\t\t\tsortable.offset.parent.left -= draggable.offset.parent.left -\n\t\t\t\t\t\tsortable.offset.parent.left;\n\t\t\t\t\tsortable.offset.parent.top -= draggable.offset.parent.top -\n\t\t\t\t\t\tsortable.offset.parent.top;\n\n\t\t\t\t\tdraggable._trigger( \"toSortable\", event );\n\n\t\t\t\t\t// Inform draggable that the helper is in a valid drop zone,\n\t\t\t\t\t// used solely in the revert option to handle \"valid/invalid\".\n\t\t\t\t\tdraggable.dropped = sortable.element;\n\n\t\t\t\t\t// Need to refreshPositions of all sortables in the case that\n\t\t\t\t\t// adding to one sortable changes the location of the other sortables (#9675)\n\t\t\t\t\t$.each( draggable.sortables, function() {\n\t\t\t\t\t\tthis.refreshPositions();\n\t\t\t\t\t} );\n\n\t\t\t\t\t// Hack so receive/update callbacks work (mostly)\n\t\t\t\t\tdraggable.currentItem = draggable.element;\n\t\t\t\t\tsortable.fromOutside = draggable;\n\t\t\t\t}\n\n\t\t\t\tif ( sortable.currentItem ) {\n\t\t\t\t\tsortable._mouseDrag( event );\n\n\t\t\t\t\t// Copy the sortable's position because the draggable's can potentially reflect\n\t\t\t\t\t// a relative position, while sortable is always absolute, which the dragged\n\t\t\t\t\t// element has now become. (#8809)\n\t\t\t\t\tui.position = sortable.position;\n\t\t\t\t}\n\t\t\t} else {\n\n\t\t\t\t// If it doesn't intersect with the sortable, and it intersected before,\n\t\t\t\t// we fake the drag stop of the sortable, but make sure it doesn't remove\n\t\t\t\t// the helper by using cancelHelperRemoval.\n\t\t\t\tif ( sortable.isOver ) {\n\n\t\t\t\t\tsortable.isOver = 0;\n\t\t\t\t\tsortable.cancelHelperRemoval = true;\n\n\t\t\t\t\t// Calling sortable's mouseStop would trigger a revert,\n\t\t\t\t\t// so revert must be temporarily false until after mouseStop is called.\n\t\t\t\t\tsortable.options._revert = sortable.options.revert;\n\t\t\t\t\tsortable.options.revert = false;\n\n\t\t\t\t\tsortable._trigger( \"out\", event, sortable._uiHash( sortable ) );\n\t\t\t\t\tsortable._mouseStop( event, true );\n\n\t\t\t\t\t// Restore sortable behaviors that were modfied\n\t\t\t\t\t// when the draggable entered the sortable area (#9481)\n\t\t\t\t\tsortable.options.revert = sortable.options._revert;\n\t\t\t\t\tsortable.options.helper = sortable.options._helper;\n\n\t\t\t\t\tif ( sortable.placeholder ) {\n\t\t\t\t\t\tsortable.placeholder.remove();\n\t\t\t\t\t}\n\n\t\t\t\t\t// Restore and recalculate the draggable's offset considering the sortable\n\t\t\t\t\t// may have modified them in unexpected ways. (#8809, #10669)\n\t\t\t\t\tui.helper.appendTo( draggable._parent );\n\t\t\t\t\tdraggable._refreshOffsets( event );\n\t\t\t\t\tui.position = draggable._generatePosition( event, true );\n\n\t\t\t\t\tdraggable._trigger( \"fromSortable\", event );\n\n\t\t\t\t\t// Inform draggable that the helper is no longer in a valid drop zone\n\t\t\t\t\tdraggable.dropped = false;\n\n\t\t\t\t\t// Need to refreshPositions of all sortables just in case removing\n\t\t\t\t\t// from one sortable changes the location of other sortables (#9675)\n\t\t\t\t\t$.each( draggable.sortables, function() {\n\t\t\t\t\t\tthis.refreshPositions();\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\t}\n} );\n\n$.ui.plugin.add( \"draggable\", \"cursor\", {\n\tstart: function( event, ui, instance ) {\n\t\tvar t = $( \"body\" ),\n\t\t\to = instance.options;\n\n\t\tif ( t.css( \"cursor\" ) ) {\n\t\t\to._cursor = t.css( \"cursor\" );\n\t\t}\n\t\tt.css( \"cursor\", o.cursor );\n\t},\n\tstop: function( event, ui, instance ) {\n\t\tvar o = instance.options;\n\t\tif ( o._cursor ) {\n\t\t\t$( \"body\" ).css( \"cursor\", o._cursor );\n\t\t}\n\t}\n} );\n\n$.ui.plugin.add( \"draggable\", \"opacity\", {\n\tstart: function( event, ui, instance ) {\n\t\tvar t = $( ui.helper ),\n\t\t\to = instance.options;\n\t\tif ( t.css( \"opacity\" ) ) {\n\t\t\to._opacity = t.css( \"opacity\" );\n\t\t}\n\t\tt.css( \"opacity\", o.opacity );\n\t},\n\tstop: function( event, ui, instance ) {\n\t\tvar o = instance.options;\n\t\tif ( o._opacity ) {\n\t\t\t$( ui.helper ).css( \"opacity\", o._opacity );\n\t\t}\n\t}\n} );\n\n$.ui.plugin.add( \"draggable\", \"scroll\", {\n\tstart: function( event, ui, i ) {\n\t\tif ( !i.scrollParentNotHidden ) {\n\t\t\ti.scrollParentNotHidden = i.helper.scrollParent( false );\n\t\t}\n\n\t\tif ( i.scrollParentNotHidden[ 0 ] !== i.document[ 0 ] &&\n\t\t\t\ti.scrollParentNotHidden[ 0 ].tagName !== \"HTML\" ) {\n\t\t\ti.overflowOffset = i.scrollParentNotHidden.offset();\n\t\t}\n\t},\n\tdrag: function( event, ui, i  ) {\n\n\t\tvar o = i.options,\n\t\t\tscrolled = false,\n\t\t\tscrollParent = i.scrollParentNotHidden[ 0 ],\n\t\t\tdocument = i.document[ 0 ];\n\n\t\tif ( scrollParent !== document && scrollParent.tagName !== \"HTML\" ) {\n\t\t\tif ( !o.axis || o.axis !== \"x\" ) {\n\t\t\t\tif ( ( i.overflowOffset.top + scrollParent.offsetHeight ) - event.pageY <\n\t\t\t\t\t\to.scrollSensitivity ) {\n\t\t\t\t\tscrollParent.scrollTop = scrolled = scrollParent.scrollTop + o.scrollSpeed;\n\t\t\t\t} else if ( event.pageY - i.overflowOffset.top < o.scrollSensitivity ) {\n\t\t\t\t\tscrollParent.scrollTop = scrolled = scrollParent.scrollTop - o.scrollSpeed;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( !o.axis || o.axis !== \"y\" ) {\n\t\t\t\tif ( ( i.overflowOffset.left + scrollParent.offsetWidth ) - event.pageX <\n\t\t\t\t\t\to.scrollSensitivity ) {\n\t\t\t\t\tscrollParent.scrollLeft = scrolled = scrollParent.scrollLeft + o.scrollSpeed;\n\t\t\t\t} else if ( event.pageX - i.overflowOffset.left < o.scrollSensitivity ) {\n\t\t\t\t\tscrollParent.scrollLeft = scrolled = scrollParent.scrollLeft - o.scrollSpeed;\n\t\t\t\t}\n\t\t\t}\n\n\t\t} else {\n\n\t\t\tif ( !o.axis || o.axis !== \"x\" ) {\n\t\t\t\tif ( event.pageY - $( document ).scrollTop() < o.scrollSensitivity ) {\n\t\t\t\t\tscrolled = $( document ).scrollTop( $( document ).scrollTop() - o.scrollSpeed );\n\t\t\t\t} else if ( $( window ).height() - ( event.pageY - $( document ).scrollTop() ) <\n\t\t\t\t\t\to.scrollSensitivity ) {\n\t\t\t\t\tscrolled = $( document ).scrollTop( $( document ).scrollTop() + o.scrollSpeed );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( !o.axis || o.axis !== \"y\" ) {\n\t\t\t\tif ( event.pageX - $( document ).scrollLeft() < o.scrollSensitivity ) {\n\t\t\t\t\tscrolled = $( document ).scrollLeft(\n\t\t\t\t\t\t$( document ).scrollLeft() - o.scrollSpeed\n\t\t\t\t\t);\n\t\t\t\t} else if ( $( window ).width() - ( event.pageX - $( document ).scrollLeft() ) <\n\t\t\t\t\t\to.scrollSensitivity ) {\n\t\t\t\t\tscrolled = $( document ).scrollLeft(\n\t\t\t\t\t\t$( document ).scrollLeft() + o.scrollSpeed\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t}\n\n\t\tif ( scrolled !== false && $.ui.ddmanager && !o.dropBehaviour ) {\n\t\t\t$.ui.ddmanager.prepareOffsets( i, event );\n\t\t}\n\n\t}\n} );\n\n$.ui.plugin.add( \"draggable\", \"snap\", {\n\tstart: function( event, ui, i ) {\n\n\t\tvar o = i.options;\n\n\t\ti.snapElements = [];\n\n\t\t$( o.snap.constructor !== String ? ( o.snap.items || \":data(ui-draggable)\" ) : o.snap )\n\t\t\t.each( function() {\n\t\t\t\tvar $t = $( this ),\n\t\t\t\t\t$o = $t.offset();\n\t\t\t\tif ( this !== i.element[ 0 ] ) {\n\t\t\t\t\ti.snapElements.push( {\n\t\t\t\t\t\titem: this,\n\t\t\t\t\t\twidth: $t.outerWidth(), height: $t.outerHeight(),\n\t\t\t\t\t\ttop: $o.top, left: $o.left\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t} );\n\n\t},\n\tdrag: function( event, ui, inst ) {\n\n\t\tvar ts, bs, ls, rs, l, r, t, b, i, first,\n\t\t\to = inst.options,\n\t\t\td = o.snapTolerance,\n\t\t\tx1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,\n\t\t\ty1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;\n\n\t\tfor ( i = inst.snapElements.length - 1; i >= 0; i-- ) {\n\n\t\t\tl = inst.snapElements[ i ].left - inst.margins.left;\n\t\t\tr = l + inst.snapElements[ i ].width;\n\t\t\tt = inst.snapElements[ i ].top - inst.margins.top;\n\t\t\tb = t + inst.snapElements[ i ].height;\n\n\t\t\tif ( x2 < l - d || x1 > r + d || y2 < t - d || y1 > b + d ||\n\t\t\t\t\t!$.contains( inst.snapElements[ i ].item.ownerDocument,\n\t\t\t\t\tinst.snapElements[ i ].item ) ) {\n\t\t\t\tif ( inst.snapElements[ i ].snapping ) {\n\t\t\t\t\t( inst.options.snap.release &&\n\t\t\t\t\t\tinst.options.snap.release.call(\n\t\t\t\t\t\t\tinst.element,\n\t\t\t\t\t\t\tevent,\n\t\t\t\t\t\t\t$.extend( inst._uiHash(), { snapItem: inst.snapElements[ i ].item } )\n\t\t\t\t\t\t) );\n\t\t\t\t}\n\t\t\t\tinst.snapElements[ i ].snapping = false;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif ( o.snapMode !== \"inner\" ) {\n\t\t\t\tts = Math.abs( t - y2 ) <= d;\n\t\t\t\tbs = Math.abs( b - y1 ) <= d;\n\t\t\t\tls = Math.abs( l - x2 ) <= d;\n\t\t\t\trs = Math.abs( r - x1 ) <= d;\n\t\t\t\tif ( ts ) {\n\t\t\t\t\tui.position.top = inst._convertPositionTo( \"relative\", {\n\t\t\t\t\t\ttop: t - inst.helperProportions.height,\n\t\t\t\t\t\tleft: 0\n\t\t\t\t\t} ).top;\n\t\t\t\t}\n\t\t\t\tif ( bs ) {\n\t\t\t\t\tui.position.top = inst._convertPositionTo( \"relative\", {\n\t\t\t\t\t\ttop: b,\n\t\t\t\t\t\tleft: 0\n\t\t\t\t\t} ).top;\n\t\t\t\t}\n\t\t\t\tif ( ls ) {\n\t\t\t\t\tui.position.left = inst._convertPositionTo( \"relative\", {\n\t\t\t\t\t\ttop: 0,\n\t\t\t\t\t\tleft: l - inst.helperProportions.width\n\t\t\t\t\t} ).left;\n\t\t\t\t}\n\t\t\t\tif ( rs ) {\n\t\t\t\t\tui.position.left = inst._convertPositionTo( \"relative\", {\n\t\t\t\t\t\ttop: 0,\n\t\t\t\t\t\tleft: r\n\t\t\t\t\t} ).left;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfirst = ( ts || bs || ls || rs );\n\n\t\t\tif ( o.snapMode !== \"outer\" ) {\n\t\t\t\tts = Math.abs( t - y1 ) <= d;\n\t\t\t\tbs = Math.abs( b - y2 ) <= d;\n\t\t\t\tls = Math.abs( l - x1 ) <= d;\n\t\t\t\trs = Math.abs( r - x2 ) <= d;\n\t\t\t\tif ( ts ) {\n\t\t\t\t\tui.position.top = inst._convertPositionTo( \"relative\", {\n\t\t\t\t\t\ttop: t,\n\t\t\t\t\t\tleft: 0\n\t\t\t\t\t} ).top;\n\t\t\t\t}\n\t\t\t\tif ( bs ) {\n\t\t\t\t\tui.position.top = inst._convertPositionTo( \"relative\", {\n\t\t\t\t\t\ttop: b - inst.helperProportions.height,\n\t\t\t\t\t\tleft: 0\n\t\t\t\t\t} ).top;\n\t\t\t\t}\n\t\t\t\tif ( ls ) {\n\t\t\t\t\tui.position.left = inst._convertPositionTo( \"relative\", {\n\t\t\t\t\t\ttop: 0,\n\t\t\t\t\t\tleft: l\n\t\t\t\t\t} ).left;\n\t\t\t\t}\n\t\t\t\tif ( rs ) {\n\t\t\t\t\tui.position.left = inst._convertPositionTo( \"relative\", {\n\t\t\t\t\t\ttop: 0,\n\t\t\t\t\t\tleft: r - inst.helperProportions.width\n\t\t\t\t\t} ).left;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( !inst.snapElements[ i ].snapping && ( ts || bs || ls || rs || first ) ) {\n\t\t\t\t( inst.options.snap.snap &&\n\t\t\t\t\tinst.options.snap.snap.call(\n\t\t\t\t\t\tinst.element,\n\t\t\t\t\t\tevent,\n\t\t\t\t\t\t$.extend( inst._uiHash(), {\n\t\t\t\t\t\t\tsnapItem: inst.snapElements[ i ].item\n\t\t\t\t\t\t} ) ) );\n\t\t\t}\n\t\t\tinst.snapElements[ i ].snapping = ( ts || bs || ls || rs || first );\n\n\t\t}\n\n\t}\n} );\n\n$.ui.plugin.add( \"draggable\", \"stack\", {\n\tstart: function( event, ui, instance ) {\n\t\tvar min,\n\t\t\to = instance.options,\n\t\t\tgroup = $.makeArray( $( o.stack ) ).sort( function( a, b ) {\n\t\t\t\treturn ( parseInt( $( a ).css( \"zIndex\" ), 10 ) || 0 ) -\n\t\t\t\t\t( parseInt( $( b ).css( \"zIndex\" ), 10 ) || 0 );\n\t\t\t} );\n\n\t\tif ( !group.length ) { return; }\n\n\t\tmin = parseInt( $( group[ 0 ] ).css( \"zIndex\" ), 10 ) || 0;\n\t\t$( group ).each( function( i ) {\n\t\t\t$( this ).css( \"zIndex\", min + i );\n\t\t} );\n\t\tthis.css( \"zIndex\", ( min + group.length ) );\n\t}\n} );\n\n$.ui.plugin.add( \"draggable\", \"zIndex\", {\n\tstart: function( event, ui, instance ) {\n\t\tvar t = $( ui.helper ),\n\t\t\to = instance.options;\n\n\t\tif ( t.css( \"zIndex\" ) ) {\n\t\t\to._zIndex = t.css( \"zIndex\" );\n\t\t}\n\t\tt.css( \"zIndex\", o.zIndex );\n\t},\n\tstop: function( event, ui, instance ) {\n\t\tvar o = instance.options;\n\n\t\tif ( o._zIndex ) {\n\t\t\t$( ui.helper ).css( \"zIndex\", o._zIndex );\n\t\t}\n\t}\n} );\n\nvar widgetsDraggable = $.ui.draggable;\n\n\n/*!\n * jQuery UI Droppable 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Droppable\n//>>group: Interactions\n//>>description: Enables drop targets for draggable elements.\n//>>docs: http://api.jqueryui.com/droppable/\n//>>demos: http://jqueryui.com/droppable/\n\n\n\n$.widget( \"ui.droppable\", {\n\tversion: \"1.12.1\",\n\twidgetEventPrefix: \"drop\",\n\toptions: {\n\t\taccept: \"*\",\n\t\taddClasses: true,\n\t\tgreedy: false,\n\t\tscope: \"default\",\n\t\ttolerance: \"intersect\",\n\n\t\t// Callbacks\n\t\tactivate: null,\n\t\tdeactivate: null,\n\t\tdrop: null,\n\t\tout: null,\n\t\tover: null\n\t},\n\t_create: function() {\n\n\t\tvar proportions,\n\t\t\to = this.options,\n\t\t\taccept = o.accept;\n\n\t\tthis.isover = false;\n\t\tthis.isout = true;\n\n\t\tthis.accept = $.isFunction( accept ) ? accept : function( d ) {\n\t\t\treturn d.is( accept );\n\t\t};\n\n\t\tthis.proportions = function( /* valueToWrite */ ) {\n\t\t\tif ( arguments.length ) {\n\n\t\t\t\t// Store the droppable's proportions\n\t\t\t\tproportions = arguments[ 0 ];\n\t\t\t} else {\n\n\t\t\t\t// Retrieve or derive the droppable's proportions\n\t\t\t\treturn proportions ?\n\t\t\t\t\tproportions :\n\t\t\t\t\tproportions = {\n\t\t\t\t\t\twidth: this.element[ 0 ].offsetWidth,\n\t\t\t\t\t\theight: this.element[ 0 ].offsetHeight\n\t\t\t\t\t};\n\t\t\t}\n\t\t};\n\n\t\tthis._addToManager( o.scope );\n\n\t\to.addClasses && this._addClass( \"ui-droppable\" );\n\n\t},\n\n\t_addToManager: function( scope ) {\n\n\t\t// Add the reference and positions to the manager\n\t\t$.ui.ddmanager.droppables[ scope ] = $.ui.ddmanager.droppables[ scope ] || [];\n\t\t$.ui.ddmanager.droppables[ scope ].push( this );\n\t},\n\n\t_splice: function( drop ) {\n\t\tvar i = 0;\n\t\tfor ( ; i < drop.length; i++ ) {\n\t\t\tif ( drop[ i ] === this ) {\n\t\t\t\tdrop.splice( i, 1 );\n\t\t\t}\n\t\t}\n\t},\n\n\t_destroy: function() {\n\t\tvar drop = $.ui.ddmanager.droppables[ this.options.scope ];\n\n\t\tthis._splice( drop );\n\t},\n\n\t_setOption: function( key, value ) {\n\n\t\tif ( key === \"accept\" ) {\n\t\t\tthis.accept = $.isFunction( value ) ? value : function( d ) {\n\t\t\t\treturn d.is( value );\n\t\t\t};\n\t\t} else if ( key === \"scope\" ) {\n\t\t\tvar drop = $.ui.ddmanager.droppables[ this.options.scope ];\n\n\t\t\tthis._splice( drop );\n\t\t\tthis._addToManager( value );\n\t\t}\n\n\t\tthis._super( key, value );\n\t},\n\n\t_activate: function( event ) {\n\t\tvar draggable = $.ui.ddmanager.current;\n\n\t\tthis._addActiveClass();\n\t\tif ( draggable ) {\n\t\t\tthis._trigger( \"activate\", event, this.ui( draggable ) );\n\t\t}\n\t},\n\n\t_deactivate: function( event ) {\n\t\tvar draggable = $.ui.ddmanager.current;\n\n\t\tthis._removeActiveClass();\n\t\tif ( draggable ) {\n\t\t\tthis._trigger( \"deactivate\", event, this.ui( draggable ) );\n\t\t}\n\t},\n\n\t_over: function( event ) {\n\n\t\tvar draggable = $.ui.ddmanager.current;\n\n\t\t// Bail if draggable and droppable are same element\n\t\tif ( !draggable || ( draggable.currentItem ||\n\t\t\t\tdraggable.element )[ 0 ] === this.element[ 0 ] ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( this.accept.call( this.element[ 0 ], ( draggable.currentItem ||\n\t\t\t\tdraggable.element ) ) ) {\n\t\t\tthis._addHoverClass();\n\t\t\tthis._trigger( \"over\", event, this.ui( draggable ) );\n\t\t}\n\n\t},\n\n\t_out: function( event ) {\n\n\t\tvar draggable = $.ui.ddmanager.current;\n\n\t\t// Bail if draggable and droppable are same element\n\t\tif ( !draggable || ( draggable.currentItem ||\n\t\t\t\tdraggable.element )[ 0 ] === this.element[ 0 ] ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( this.accept.call( this.element[ 0 ], ( draggable.currentItem ||\n\t\t\t\tdraggable.element ) ) ) {\n\t\t\tthis._removeHoverClass();\n\t\t\tthis._trigger( \"out\", event, this.ui( draggable ) );\n\t\t}\n\n\t},\n\n\t_drop: function( event, custom ) {\n\n\t\tvar draggable = custom || $.ui.ddmanager.current,\n\t\t\tchildrenIntersection = false;\n\n\t\t// Bail if draggable and droppable are same element\n\t\tif ( !draggable || ( draggable.currentItem ||\n\t\t\t\tdraggable.element )[ 0 ] === this.element[ 0 ] ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tthis.element\n\t\t\t.find( \":data(ui-droppable)\" )\n\t\t\t.not( \".ui-draggable-dragging\" )\n\t\t\t.each( function() {\n\t\t\t\tvar inst = $( this ).droppable( \"instance\" );\n\t\t\t\tif (\n\t\t\t\t\tinst.options.greedy &&\n\t\t\t\t\t!inst.options.disabled &&\n\t\t\t\t\tinst.options.scope === draggable.options.scope &&\n\t\t\t\t\tinst.accept.call(\n\t\t\t\t\t\tinst.element[ 0 ], ( draggable.currentItem || draggable.element )\n\t\t\t\t\t) &&\n\t\t\t\t\tintersect(\n\t\t\t\t\t\tdraggable,\n\t\t\t\t\t\t$.extend( inst, { offset: inst.element.offset() } ),\n\t\t\t\t\t\tinst.options.tolerance, event\n\t\t\t\t\t)\n\t\t\t\t) {\n\t\t\t\t\tchildrenIntersection = true;\n\t\t\t\t\treturn false; }\n\t\t\t} );\n\t\tif ( childrenIntersection ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif ( this.accept.call( this.element[ 0 ],\n\t\t\t\t( draggable.currentItem || draggable.element ) ) ) {\n\t\t\tthis._removeActiveClass();\n\t\t\tthis._removeHoverClass();\n\n\t\t\tthis._trigger( \"drop\", event, this.ui( draggable ) );\n\t\t\treturn this.element;\n\t\t}\n\n\t\treturn false;\n\n\t},\n\n\tui: function( c ) {\n\t\treturn {\n\t\t\tdraggable: ( c.currentItem || c.element ),\n\t\t\thelper: c.helper,\n\t\t\tposition: c.position,\n\t\t\toffset: c.positionAbs\n\t\t};\n\t},\n\n\t// Extension points just to make backcompat sane and avoid duplicating logic\n\t// TODO: Remove in 1.13 along with call to it below\n\t_addHoverClass: function() {\n\t\tthis._addClass( \"ui-droppable-hover\" );\n\t},\n\n\t_removeHoverClass: function() {\n\t\tthis._removeClass( \"ui-droppable-hover\" );\n\t},\n\n\t_addActiveClass: function() {\n\t\tthis._addClass( \"ui-droppable-active\" );\n\t},\n\n\t_removeActiveClass: function() {\n\t\tthis._removeClass( \"ui-droppable-active\" );\n\t}\n} );\n\nvar intersect = $.ui.intersect = ( function() {\n\tfunction isOverAxis( x, reference, size ) {\n\t\treturn ( x >= reference ) && ( x < ( reference + size ) );\n\t}\n\n\treturn function( draggable, droppable, toleranceMode, event ) {\n\n\t\tif ( !droppable.offset ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tvar x1 = ( draggable.positionAbs ||\n\t\t\t\tdraggable.position.absolute ).left + draggable.margins.left,\n\t\t\ty1 = ( draggable.positionAbs ||\n\t\t\t\tdraggable.position.absolute ).top + draggable.margins.top,\n\t\t\tx2 = x1 + draggable.helperProportions.width,\n\t\t\ty2 = y1 + draggable.helperProportions.height,\n\t\t\tl = droppable.offset.left,\n\t\t\tt = droppable.offset.top,\n\t\t\tr = l + droppable.proportions().width,\n\t\t\tb = t + droppable.proportions().height;\n\n\t\tswitch ( toleranceMode ) {\n\t\tcase \"fit\":\n\t\t\treturn ( l <= x1 && x2 <= r && t <= y1 && y2 <= b );\n\t\tcase \"intersect\":\n\t\t\treturn ( l < x1 + ( draggable.helperProportions.width / 2 ) && // Right Half\n\t\t\t\tx2 - ( draggable.helperProportions.width / 2 ) < r && // Left Half\n\t\t\t\tt < y1 + ( draggable.helperProportions.height / 2 ) && // Bottom Half\n\t\t\t\ty2 - ( draggable.helperProportions.height / 2 ) < b ); // Top Half\n\t\tcase \"pointer\":\n\t\t\treturn isOverAxis( event.pageY, t, droppable.proportions().height ) &&\n\t\t\t\tisOverAxis( event.pageX, l, droppable.proportions().width );\n\t\tcase \"touch\":\n\t\t\treturn (\n\t\t\t\t( y1 >= t && y1 <= b ) || // Top edge touching\n\t\t\t\t( y2 >= t && y2 <= b ) || // Bottom edge touching\n\t\t\t\t( y1 < t && y2 > b ) // Surrounded vertically\n\t\t\t) && (\n\t\t\t\t( x1 >= l && x1 <= r ) || // Left edge touching\n\t\t\t\t( x2 >= l && x2 <= r ) || // Right edge touching\n\t\t\t\t( x1 < l && x2 > r ) // Surrounded horizontally\n\t\t\t);\n\t\tdefault:\n\t\t\treturn false;\n\t\t}\n\t};\n} )();\n\n/*\n\tThis manager tracks offsets of draggables and droppables\n*/\n$.ui.ddmanager = {\n\tcurrent: null,\n\tdroppables: { \"default\": [] },\n\tprepareOffsets: function( t, event ) {\n\n\t\tvar i, j,\n\t\t\tm = $.ui.ddmanager.droppables[ t.options.scope ] || [],\n\t\t\ttype = event ? event.type : null, // workaround for #2317\n\t\t\tlist = ( t.currentItem || t.element ).find( \":data(ui-droppable)\" ).addBack();\n\n\t\tdroppablesLoop: for ( i = 0; i < m.length; i++ ) {\n\n\t\t\t// No disabled and non-accepted\n\t\t\tif ( m[ i ].options.disabled || ( t && !m[ i ].accept.call( m[ i ].element[ 0 ],\n\t\t\t\t\t( t.currentItem || t.element ) ) ) ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Filter out elements in the current dragged item\n\t\t\tfor ( j = 0; j < list.length; j++ ) {\n\t\t\t\tif ( list[ j ] === m[ i ].element[ 0 ] ) {\n\t\t\t\t\tm[ i ].proportions().height = 0;\n\t\t\t\t\tcontinue droppablesLoop;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tm[ i ].visible = m[ i ].element.css( \"display\" ) !== \"none\";\n\t\t\tif ( !m[ i ].visible ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Activate the droppable if used directly from draggables\n\t\t\tif ( type === \"mousedown\" ) {\n\t\t\t\tm[ i ]._activate.call( m[ i ], event );\n\t\t\t}\n\n\t\t\tm[ i ].offset = m[ i ].element.offset();\n\t\t\tm[ i ].proportions( {\n\t\t\t\twidth: m[ i ].element[ 0 ].offsetWidth,\n\t\t\t\theight: m[ i ].element[ 0 ].offsetHeight\n\t\t\t} );\n\n\t\t}\n\n\t},\n\tdrop: function( draggable, event ) {\n\n\t\tvar dropped = false;\n\n\t\t// Create a copy of the droppables in case the list changes during the drop (#9116)\n\t\t$.each( ( $.ui.ddmanager.droppables[ draggable.options.scope ] || [] ).slice(), function() {\n\n\t\t\tif ( !this.options ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif ( !this.options.disabled && this.visible &&\n\t\t\t\t\tintersect( draggable, this, this.options.tolerance, event ) ) {\n\t\t\t\tdropped = this._drop.call( this, event ) || dropped;\n\t\t\t}\n\n\t\t\tif ( !this.options.disabled && this.visible && this.accept.call( this.element[ 0 ],\n\t\t\t\t\t( draggable.currentItem || draggable.element ) ) ) {\n\t\t\t\tthis.isout = true;\n\t\t\t\tthis.isover = false;\n\t\t\t\tthis._deactivate.call( this, event );\n\t\t\t}\n\n\t\t} );\n\t\treturn dropped;\n\n\t},\n\tdragStart: function( draggable, event ) {\n\n\t\t// Listen for scrolling so that if the dragging causes scrolling the position of the\n\t\t// droppables can be recalculated (see #5003)\n\t\tdraggable.element.parentsUntil( \"body\" ).on( \"scroll.droppable\", function() {\n\t\t\tif ( !draggable.options.refreshPositions ) {\n\t\t\t\t$.ui.ddmanager.prepareOffsets( draggable, event );\n\t\t\t}\n\t\t} );\n\t},\n\tdrag: function( draggable, event ) {\n\n\t\t// If you have a highly dynamic page, you might try this option. It renders positions\n\t\t// every time you move the mouse.\n\t\tif ( draggable.options.refreshPositions ) {\n\t\t\t$.ui.ddmanager.prepareOffsets( draggable, event );\n\t\t}\n\n\t\t// Run through all droppables and check their positions based on specific tolerance options\n\t\t$.each( $.ui.ddmanager.droppables[ draggable.options.scope ] || [], function() {\n\n\t\t\tif ( this.options.disabled || this.greedyChild || !this.visible ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tvar parentInstance, scope, parent,\n\t\t\t\tintersects = intersect( draggable, this, this.options.tolerance, event ),\n\t\t\t\tc = !intersects && this.isover ?\n\t\t\t\t\t\"isout\" :\n\t\t\t\t\t( intersects && !this.isover ? \"isover\" : null );\n\t\t\tif ( !c ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( this.options.greedy ) {\n\n\t\t\t\t// find droppable parents with same scope\n\t\t\t\tscope = this.options.scope;\n\t\t\t\tparent = this.element.parents( \":data(ui-droppable)\" ).filter( function() {\n\t\t\t\t\treturn $( this ).droppable( \"instance\" ).options.scope === scope;\n\t\t\t\t} );\n\n\t\t\t\tif ( parent.length ) {\n\t\t\t\t\tparentInstance = $( parent[ 0 ] ).droppable( \"instance\" );\n\t\t\t\t\tparentInstance.greedyChild = ( c === \"isover\" );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// We just moved into a greedy child\n\t\t\tif ( parentInstance && c === \"isover\" ) {\n\t\t\t\tparentInstance.isover = false;\n\t\t\t\tparentInstance.isout = true;\n\t\t\t\tparentInstance._out.call( parentInstance, event );\n\t\t\t}\n\n\t\t\tthis[ c ] = true;\n\t\t\tthis[ c === \"isout\" ? \"isover\" : \"isout\" ] = false;\n\t\t\tthis[ c === \"isover\" ? \"_over\" : \"_out\" ].call( this, event );\n\n\t\t\t// We just moved out of a greedy child\n\t\t\tif ( parentInstance && c === \"isout\" ) {\n\t\t\t\tparentInstance.isout = false;\n\t\t\t\tparentInstance.isover = true;\n\t\t\t\tparentInstance._over.call( parentInstance, event );\n\t\t\t}\n\t\t} );\n\n\t},\n\tdragStop: function( draggable, event ) {\n\t\tdraggable.element.parentsUntil( \"body\" ).off( \"scroll.droppable\" );\n\n\t\t// Call prepareOffsets one final time since IE does not fire return scroll events when\n\t\t// overflow was caused by drag (see #5003)\n\t\tif ( !draggable.options.refreshPositions ) {\n\t\t\t$.ui.ddmanager.prepareOffsets( draggable, event );\n\t\t}\n\t}\n};\n\n// DEPRECATED\n// TODO: switch return back to widget declaration at top of file when this is removed\nif ( $.uiBackCompat !== false ) {\n\n\t// Backcompat for activeClass and hoverClass options\n\t$.widget( \"ui.droppable\", $.ui.droppable, {\n\t\toptions: {\n\t\t\thoverClass: false,\n\t\t\tactiveClass: false\n\t\t},\n\t\t_addActiveClass: function() {\n\t\t\tthis._super();\n\t\t\tif ( this.options.activeClass ) {\n\t\t\t\tthis.element.addClass( this.options.activeClass );\n\t\t\t}\n\t\t},\n\t\t_removeActiveClass: function() {\n\t\t\tthis._super();\n\t\t\tif ( this.options.activeClass ) {\n\t\t\t\tthis.element.removeClass( this.options.activeClass );\n\t\t\t}\n\t\t},\n\t\t_addHoverClass: function() {\n\t\t\tthis._super();\n\t\t\tif ( this.options.hoverClass ) {\n\t\t\t\tthis.element.addClass( this.options.hoverClass );\n\t\t\t}\n\t\t},\n\t\t_removeHoverClass: function() {\n\t\t\tthis._super();\n\t\t\tif ( this.options.hoverClass ) {\n\t\t\t\tthis.element.removeClass( this.options.hoverClass );\n\t\t\t}\n\t\t}\n\t} );\n}\n\nvar widgetsDroppable = $.ui.droppable;\n\n\n/*!\n * jQuery UI Resizable 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Resizable\n//>>group: Interactions\n//>>description: Enables resize functionality for any element.\n//>>docs: http://api.jqueryui.com/resizable/\n//>>demos: http://jqueryui.com/resizable/\n//>>css.structure: ../../themes/base/core.css\n//>>css.structure: ../../themes/base/resizable.css\n//>>css.theme: ../../themes/base/theme.css\n\n\n\n$.widget( \"ui.resizable\", $.ui.mouse, {\n\tversion: \"1.12.1\",\n\twidgetEventPrefix: \"resize\",\n\toptions: {\n\t\talsoResize: false,\n\t\tanimate: false,\n\t\tanimateDuration: \"slow\",\n\t\tanimateEasing: \"swing\",\n\t\taspectRatio: false,\n\t\tautoHide: false,\n\t\tclasses: {\n\t\t\t\"ui-resizable-se\": \"ui-icon ui-icon-gripsmall-diagonal-se\"\n\t\t},\n\t\tcontainment: false,\n\t\tghost: false,\n\t\tgrid: false,\n\t\thandles: \"e,s,se\",\n\t\thelper: false,\n\t\tmaxHeight: null,\n\t\tmaxWidth: null,\n\t\tminHeight: 10,\n\t\tminWidth: 10,\n\n\t\t// See #7960\n\t\tzIndex: 90,\n\n\t\todoo_isRTL: false,\n\n\t\t// Callbacks\n\t\tresize: null,\n\t\tstart: null,\n\t\tstop: null\n\t},\n\n\t_num: function( value ) {\n\t\treturn parseFloat( value ) || 0;\n\t},\n\n\t_isNumber: function( value ) {\n\t\treturn !isNaN( parseFloat( value ) );\n\t},\n\n\t_hasScroll: function( el, a ) {\n\n\t\tif ( $( el ).css( \"overflow\" ) === \"hidden\" ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tvar scroll = ( a && a === \"left\" ) ? \"scrollLeft\" : \"scrollTop\",\n\t\t\thas = false;\n\n\t\tif ( el[ scroll ] > 0 ) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// TODO: determine which cases actually cause this to happen\n\t\t// if the element doesn't have the scroll set, see if it's possible to\n\t\t// set the scroll\n\t\tel[ scroll ] = 1;\n\t\thas = ( el[ scroll ] > 0 );\n\t\tel[ scroll ] = 0;\n\t\treturn has;\n\t},\n\n\t_create: function() {\n\n\t\tvar margins,\n\t\t\to = this.options,\n\t\t\tthat = this;\n\t\tthis._addClass( \"ui-resizable\" );\n\n\t\t$.extend( this, {\n\t\t\t_aspectRatio: !!( o.aspectRatio ),\n\t\t\taspectRatio: o.aspectRatio,\n\t\t\toriginalElement: this.element,\n\t\t\t_proportionallyResizeElements: [],\n\t\t\t_helper: o.helper || o.ghost || o.animate ? o.helper || \"ui-resizable-helper\" : null\n\t\t} );\n\n\t\t// Wrap the element if it cannot hold child nodes\n\t\tif ( this.element[ 0 ].nodeName.match( /^(canvas|textarea|input|select|button|img)$/i ) ) {\n\n\t\t\tthis.element.wrap(\n\t\t\t\t$( \"<div class='ui-wrapper' style='overflow: hidden;'></div>\" ).css( {\n\t\t\t\t\tposition: this.element.css( \"position\" ),\n\t\t\t\t\twidth: this.element.outerWidth(),\n\t\t\t\t\theight: this.element.outerHeight(),\n\t\t\t\t\ttop: this.element.css( \"top\" ),\n\t\t\t\t\tleft: this.element.css( \"left\" )\n\t\t\t\t} )\n\t\t\t);\n\n\t\t\tthis.element = this.element.parent().data(\n\t\t\t\t\"ui-resizable\", this.element.resizable( \"instance\" )\n\t\t\t);\n\n\t\t\tthis.elementIsWrapper = true;\n\n\t\t\tmargins = {\n\t\t\t\tmarginTop: this.originalElement.css( \"marginTop\" ),\n\t\t\t\tmarginRight: this.originalElement.css( \"marginRight\" ),\n\t\t\t\tmarginBottom: this.originalElement.css( \"marginBottom\" ),\n\t\t\t\tmarginLeft: this.originalElement.css( \"marginLeft\" )\n\t\t\t};\n\n\t\t\tthis.element.css( margins );\n\t\t\tthis.originalElement.css( \"margin\", 0 );\n\n\t\t\t// support: Safari\n\t\t\t// Prevent Safari textarea resize\n\t\t\tthis.originalResizeStyle = this.originalElement.css( \"resize\" );\n\t\t\tthis.originalElement.css( \"resize\", \"none\" );\n\n\t\t\tthis._proportionallyResizeElements.push( this.originalElement.css( {\n\t\t\t\tposition: \"static\",\n\t\t\t\tzoom: 1,\n\t\t\t\tdisplay: \"block\"\n\t\t\t} ) );\n\n\t\t\t// Support: IE9\n\t\t\t// avoid IE jump (hard set the margin)\n\t\t\tthis.originalElement.css( margins );\n\n\t\t\tthis._proportionallyResize();\n\t\t}\n\n\t\tthis._setupHandles();\n\n\t\tif ( o.autoHide ) {\n\t\t\t$( this.element )\n\t\t\t\t.on( \"mouseenter\", function() {\n\t\t\t\t\tif ( o.disabled ) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tthat._removeClass( \"ui-resizable-autohide\" );\n\t\t\t\t\tthat._handles.show();\n\t\t\t\t} )\n\t\t\t\t.on( \"mouseleave\", function() {\n\t\t\t\t\tif ( o.disabled ) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif ( !that.resizing ) {\n\t\t\t\t\t\tthat._addClass( \"ui-resizable-autohide\" );\n\t\t\t\t\t\tthat._handles.hide();\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t}\n\n\t\tthis._mouseInit();\n\t},\n\n\t_destroy: function() {\n\n\t\tthis._mouseDestroy();\n\n\t\tvar wrapper,\n\t\t\t_destroy = function( exp ) {\n\t\t\t\t$( exp )\n\t\t\t\t\t.removeData( \"resizable\" )\n\t\t\t\t\t.removeData( \"ui-resizable\" )\n\t\t\t\t\t.off( \".resizable\" )\n\t\t\t\t\t.find( \".ui-resizable-handle\" )\n\t\t\t\t\t\t.remove();\n\t\t\t};\n\n\t\t// TODO: Unwrap at same DOM position\n\t\tif ( this.elementIsWrapper ) {\n\t\t\t_destroy( this.element );\n\t\t\twrapper = this.element;\n\t\t\tthis.originalElement.css( {\n\t\t\t\tposition: wrapper.css( \"position\" ),\n\t\t\t\twidth: wrapper.outerWidth(),\n\t\t\t\theight: wrapper.outerHeight(),\n\t\t\t\ttop: wrapper.css( \"top\" ),\n\t\t\t\tleft: wrapper.css( \"left\" )\n\t\t\t} ).insertAfter( wrapper );\n\t\t\twrapper.remove();\n\t\t}\n\n\t\tthis.originalElement.css( \"resize\", this.originalResizeStyle );\n\t\t_destroy( this.originalElement );\n\n\t\treturn this;\n\t},\n\n\t_setOption: function( key, value ) {\n\t\tthis._super( key, value );\n\n\t\tswitch ( key ) {\n\t\tcase \"handles\":\n\t\t\tthis._removeHandles();\n\t\t\tthis._setupHandles();\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\t},\n\n\t_setupHandles: function() {\n\t\tvar o = this.options, handle, i, n, hname, axis, that = this;\n\t\tthis.handles = o.handles ||\n\t\t\t( !$( \".ui-resizable-handle\", this.element ).length ?\n\t\t\t\t\"e,s,se\" : {\n\t\t\t\t\tn: \".ui-resizable-n\",\n\t\t\t\t\te: \".ui-resizable-e\",\n\t\t\t\t\ts: \".ui-resizable-s\",\n\t\t\t\t\tw: \".ui-resizable-w\",\n\t\t\t\t\tse: \".ui-resizable-se\",\n\t\t\t\t\tsw: \".ui-resizable-sw\",\n\t\t\t\t\tne: \".ui-resizable-ne\",\n\t\t\t\t\tnw: \".ui-resizable-nw\"\n\t\t\t\t} );\n\n\t\tthis._handles = $();\n\t\tif ( this.handles.constructor === String ) {\n\n\t\t\tif ( this.handles === \"all\" ) {\n\t\t\t\tthis.handles = \"n,e,s,w,se,sw,ne,nw\";\n\t\t\t}\n\n\t\t\tn = this.handles.split( \",\" );\n\t\t\tthis.handles = {};\n\n\t\t\tfor ( i = 0; i < n.length; i++ ) {\n\n\t\t\t\thandle = $.trim( n[ i ] );\n\t\t\t\thname = \"ui-resizable-\" + handle;\n\t\t\t\taxis = $( \"<div>\" );\n\t\t\t\tthis._addClass( axis, \"ui-resizable-handle \" + hname );\n\n\t\t\t\taxis.css( { zIndex: o.zIndex } );\n\n\t\t\t\tthis.handles[ handle ] = \".ui-resizable-\" + handle;\n\t\t\t\tthis.element.append( axis );\n\t\t\t}\n\n\t\t}\n\n\t\tthis._renderAxis = function( target ) {\n\n\t\t\tvar i, axis, padPos, padWrapper;\n\n\t\t\ttarget = target || this.element;\n\n\t\t\tfor ( i in this.handles ) {\n\n\t\t\t\tif ( this.handles[ i ].constructor === String ) {\n\t\t\t\t\tthis.handles[ i ] = this.element.children( this.handles[ i ] ).first().show();\n\t\t\t\t} else if ( this.handles[ i ].jquery || this.handles[ i ].nodeType ) {\n\t\t\t\t\tthis.handles[ i ] = $( this.handles[ i ] );\n\t\t\t\t\tthis._on( this.handles[ i ], { \"mousedown\": that._mouseDown } );\n\t\t\t\t}\n\n\t\t\t\tif ( this.elementIsWrapper &&\n\t\t\t\t\t\tthis.originalElement[ 0 ]\n\t\t\t\t\t\t\t.nodeName\n\t\t\t\t\t\t\t.match( /^(textarea|input|select|button)$/i ) ) {\n\t\t\t\t\taxis = $( this.handles[ i ], this.element );\n\n\t\t\t\t\tpadWrapper = /sw|ne|nw|se|n|s/.test( i ) ?\n\t\t\t\t\t\taxis.outerHeight() :\n\t\t\t\t\t\taxis.outerWidth();\n\n\t\t\t\t\tpadPos = [ \"padding\",\n\t\t\t\t\t\t/ne|nw|n/.test( i ) ? \"Top\" :\n\t\t\t\t\t\t/se|sw|s/.test( i ) ? \"Bottom\" :\n\t\t\t\t\t\t/^e$/.test( i ) ? \"Right\" : \"Left\" ].join( \"\" );\n\n\t\t\t\t\ttarget.css( padPos, padWrapper );\n\n\t\t\t\t\tthis._proportionallyResize();\n\t\t\t\t}\n\n\t\t\t\tthis._handles = this._handles.add( this.handles[ i ] );\n\t\t\t}\n\t\t};\n\n\t\t// TODO: make renderAxis a prototype function\n\t\tthis._renderAxis( this.element );\n\n\t\tthis._handles = this._handles.add( this.element.find( \".ui-resizable-handle\" ) );\n\t\tthis._handles.disableSelection();\n\n\t\tthis._handles.on( \"mouseover\", function() {\n\t\t\tif ( !that.resizing ) {\n\t\t\t\tif ( this.className ) {\n\t\t\t\t\taxis = this.className.match( /ui-resizable-(se|sw|ne|nw|n|e|s|w)/i );\n\t\t\t\t}\n\t\t\t\tthat.axis = axis && axis[ 1 ] ? axis[ 1 ] : \"se\";\n\t\t\t}\n\t\t} );\n\n\t\tif ( o.autoHide ) {\n\t\t\tthis._handles.hide();\n\t\t\tthis._addClass( \"ui-resizable-autohide\" );\n\t\t}\n\t},\n\n\t_removeHandles: function() {\n\t\tthis._handles.remove();\n\t},\n\n\t_mouseCapture: function( event ) {\n\t\tvar i, handle,\n\t\t\tcapture = false;\n\n\t\tfor ( i in this.handles ) {\n\t\t\thandle = $( this.handles[ i ] )[ 0 ];\n\t\t\tif ( handle === event.target || $.contains( handle, event.target ) ) {\n\t\t\t\tcapture = true;\n\t\t\t}\n\t\t}\n\n\t\treturn !this.options.disabled && capture;\n\t},\n\n\t_mouseStart: function( event ) {\n\n\t\tvar curleft, curtop, cursor,\n\t\t\to = this.options,\n\t\t\tel = this.element;\n\n\t\tthis.resizing = true;\n\n\t\tthis._renderProxy();\n\n\t\tcurleft = this._num( this.helper.css( \"left\" ) );\n\t\tcurtop = this._num( this.helper.css( \"top\" ) );\n\n\t\tif ( o.containment ) {\n\t\t\tcurleft += $( o.containment ).scrollLeft() || 0;\n\t\t\tcurtop += $( o.containment ).scrollTop() || 0;\n\t\t}\n\n\t\tthis.offset = this.helper.offset();\n\t\tthis.position = { left: curleft, top: curtop };\n\n\t\tthis.size = this._helper ? {\n\t\t\t\twidth: this.helper.width(),\n\t\t\t\theight: this.helper.height()\n\t\t\t} : {\n\t\t\t\twidth: el.width(),\n\t\t\t\theight: el.height()\n\t\t\t};\n\n\t\tthis.originalSize = this._helper ? {\n\t\t\t\twidth: el.outerWidth(),\n\t\t\t\theight: el.outerHeight()\n\t\t\t} : {\n\t\t\t\twidth: el.width(),\n\t\t\t\theight: el.height()\n\t\t\t};\n\n\t\tthis.sizeDiff = {\n\t\t\twidth: el.outerWidth() - el.width(),\n\t\t\theight: el.outerHeight() - el.height()\n\t\t};\n\n\t\tthis.originalPosition = { left: curleft, top: curtop };\n\t\tthis.originalMousePosition = { left: event.pageX, top: event.pageY };\n\n\t\tthis.aspectRatio = ( typeof o.aspectRatio === \"number\" ) ?\n\t\t\to.aspectRatio :\n\t\t\t( ( this.originalSize.width / this.originalSize.height ) || 1 );\n\n\t\tcursor = $( \".ui-resizable-\" + this.axis ).css( \"cursor\" );\n\t\t$( \"body\" ).css( \"cursor\", cursor === \"auto\" ? this.axis + \"-resize\" : cursor );\n\n\t\tthis._addClass( \"ui-resizable-resizing\" );\n\t\tthis._propagate( \"start\", event );\n\t\treturn true;\n\t},\n\n\t_mouseDrag: function( event ) {\n\n\t\tvar data, props,\n\t\t\tsmp = this.originalMousePosition,\n\t\t\ta = this.axis,\n\t\t\tdx = ( event.pageX - smp.left ) || 0,\n\t\t\tdy = ( event.pageY - smp.top ) || 0,\n\t\t\ttrigger = this._change[ a ];\n\t\tdx = this.options.odoo_isRTL ? -dx : dx;\n\n\t\tthis._updatePrevProperties();\n\n\t\tif ( !trigger ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tdata = trigger.apply( this, [ event, dx, dy ] );\n\n\t\tthis._updateVirtualBoundaries( event.shiftKey );\n\t\tif ( this._aspectRatio || event.shiftKey ) {\n\t\t\tdata = this._updateRatio( data, event );\n\t\t}\n\n\t\tdata = this._respectSize( data, event );\n\n\t\tthis._updateCache( data );\n\n\t\tthis._propagate( \"resize\", event );\n\n\t\tprops = this._applyChanges();\n\n\t\tif ( !this._helper && this._proportionallyResizeElements.length ) {\n\t\t\tthis._proportionallyResize();\n\t\t}\n\n\t\tif ( !$.isEmptyObject( props ) ) {\n\t\t\tthis._updatePrevProperties();\n\t\t\tthis._trigger( \"resize\", event, this.ui() );\n\t\t\tthis._applyChanges();\n\t\t}\n\n\t\treturn false;\n\t},\n\n\t_mouseStop: function( event ) {\n\n\t\tthis.resizing = false;\n\t\tvar pr, ista, soffseth, soffsetw, s, left, top,\n\t\t\to = this.options, that = this;\n\n\t\tif ( this._helper ) {\n\n\t\t\tpr = this._proportionallyResizeElements;\n\t\t\tista = pr.length && ( /textarea/i ).test( pr[ 0 ].nodeName );\n\t\t\tsoffseth = ista && this._hasScroll( pr[ 0 ], \"left\" ) ? 0 : that.sizeDiff.height;\n\t\t\tsoffsetw = ista ? 0 : that.sizeDiff.width;\n\n\t\t\ts = {\n\t\t\t\twidth: ( that.helper.width()  - soffsetw ),\n\t\t\t\theight: ( that.helper.height() - soffseth )\n\t\t\t};\n\t\t\tleft = ( parseFloat( that.element.css( \"left\" ) ) +\n\t\t\t\t( that.position.left - that.originalPosition.left ) ) || null;\n\t\t\ttop = ( parseFloat( that.element.css( \"top\" ) ) +\n\t\t\t\t( that.position.top - that.originalPosition.top ) ) || null;\n\n\t\t\tif ( !o.animate ) {\n\t\t\t\tthis.element.css( $.extend( s, { top: top, left: left } ) );\n\t\t\t}\n\n\t\t\tthat.helper.height( that.size.height );\n\t\t\tthat.helper.width( that.size.width );\n\n\t\t\tif ( this._helper && !o.animate ) {\n\t\t\t\tthis._proportionallyResize();\n\t\t\t}\n\t\t}\n\n\t\t$( \"body\" ).css( \"cursor\", \"auto\" );\n\n\t\tthis._removeClass( \"ui-resizable-resizing\" );\n\n\t\tthis._propagate( \"stop\", event );\n\n\t\tif ( this._helper ) {\n\t\t\tthis.helper.remove();\n\t\t}\n\n\t\treturn false;\n\n\t},\n\n\t_updatePrevProperties: function() {\n\t\tthis.prevPosition = {\n\t\t\ttop: this.position.top,\n\t\t\tleft: this.position.left\n\t\t};\n\t\tthis.prevSize = {\n\t\t\twidth: this.size.width,\n\t\t\theight: this.size.height\n\t\t};\n\t},\n\n\t_applyChanges: function() {\n\t\tvar props = {};\n\n\t\tif ( this.position.top !== this.prevPosition.top ) {\n\t\t\tprops.top = this.position.top + \"px\";\n\t\t}\n\t\tif ( this.position.left !== this.prevPosition.left ) {\n\t\t\tprops.left = this.position.left + \"px\";\n\t\t}\n\t\tif ( this.size.width !== this.prevSize.width ) {\n\t\t\tprops.width = this.size.width + \"px\";\n\t\t}\n\t\tif ( this.size.height !== this.prevSize.height ) {\n\t\t\tprops.height = this.size.height + \"px\";\n\t\t}\n\n\t\tthis.helper.css( props );\n\n\t\treturn props;\n\t},\n\n\t_updateVirtualBoundaries: function( forceAspectRatio ) {\n\t\tvar pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b,\n\t\t\to = this.options;\n\n\t\tb = {\n\t\t\tminWidth: this._isNumber( o.minWidth ) ? o.minWidth : 0,\n\t\t\tmaxWidth: this._isNumber( o.maxWidth ) ? o.maxWidth : Infinity,\n\t\t\tminHeight: this._isNumber( o.minHeight ) ? o.minHeight : 0,\n\t\t\tmaxHeight: this._isNumber( o.maxHeight ) ? o.maxHeight : Infinity\n\t\t};\n\n\t\tif ( this._aspectRatio || forceAspectRatio ) {\n\t\t\tpMinWidth = b.minHeight * this.aspectRatio;\n\t\t\tpMinHeight = b.minWidth / this.aspectRatio;\n\t\t\tpMaxWidth = b.maxHeight * this.aspectRatio;\n\t\t\tpMaxHeight = b.maxWidth / this.aspectRatio;\n\n\t\t\tif ( pMinWidth > b.minWidth ) {\n\t\t\t\tb.minWidth = pMinWidth;\n\t\t\t}\n\t\t\tif ( pMinHeight > b.minHeight ) {\n\t\t\t\tb.minHeight = pMinHeight;\n\t\t\t}\n\t\t\tif ( pMaxWidth < b.maxWidth ) {\n\t\t\t\tb.maxWidth = pMaxWidth;\n\t\t\t}\n\t\t\tif ( pMaxHeight < b.maxHeight ) {\n\t\t\t\tb.maxHeight = pMaxHeight;\n\t\t\t}\n\t\t}\n\t\tthis._vBoundaries = b;\n\t},\n\n\t_updateCache: function( data ) {\n\t\tthis.offset = this.helper.offset();\n\t\tif ( this._isNumber( data.left ) ) {\n\t\t\tthis.position.left = data.left;\n\t\t}\n\t\tif ( this._isNumber( data.top ) ) {\n\t\t\tthis.position.top = data.top;\n\t\t}\n\t\tif ( this._isNumber( data.height ) ) {\n\t\t\tthis.size.height = data.height;\n\t\t}\n\t\tif ( this._isNumber( data.width ) ) {\n\t\t\tthis.size.width = data.width;\n\t\t}\n\t},\n\n\t_updateRatio: function( data ) {\n\n\t\tvar cpos = this.position,\n\t\t\tcsize = this.size,\n\t\t\ta = this.axis;\n\n\t\tif ( this._isNumber( data.height ) ) {\n\t\t\tdata.width = ( data.height * this.aspectRatio );\n\t\t} else if ( this._isNumber( data.width ) ) {\n\t\t\tdata.height = ( data.width / this.aspectRatio );\n\t\t}\n\n\t\tif ( a === \"sw\" ) {\n\t\t\tdata.left = cpos.left + ( csize.width - data.width );\n\t\t\tdata.top = null;\n\t\t}\n\t\tif ( a === \"nw\" ) {\n\t\t\tdata.top = cpos.top + ( csize.height - data.height );\n\t\t\tdata.left = cpos.left + ( csize.width - data.width );\n\t\t}\n\n\t\treturn data;\n\t},\n\n\t_respectSize: function( data ) {\n\n\t\tvar o = this._vBoundaries,\n\t\t\ta = this.axis,\n\t\t\tismaxw = this._isNumber( data.width ) && o.maxWidth && ( o.maxWidth < data.width ),\n\t\t\tismaxh = this._isNumber( data.height ) && o.maxHeight && ( o.maxHeight < data.height ),\n\t\t\tisminw = this._isNumber( data.width ) && o.minWidth && ( o.minWidth > data.width ),\n\t\t\tisminh = this._isNumber( data.height ) && o.minHeight && ( o.minHeight > data.height ),\n\t\t\tdw = this.originalPosition.left + this.originalSize.width,\n\t\t\tdh = this.originalPosition.top + this.originalSize.height,\n\t\t\tcw = /sw|nw|w/.test( a ), ch = /nw|ne|n/.test( a );\n\t\tif ( isminw ) {\n\t\t\tdata.width = o.minWidth;\n\t\t}\n\t\tif ( isminh ) {\n\t\t\tdata.height = o.minHeight;\n\t\t}\n\t\tif ( ismaxw ) {\n\t\t\tdata.width = o.maxWidth;\n\t\t}\n\t\tif ( ismaxh ) {\n\t\t\tdata.height = o.maxHeight;\n\t\t}\n\n\t\tif ( isminw && cw ) {\n\t\t\tdata.left = dw - o.minWidth;\n\t\t}\n\t\tif ( ismaxw && cw ) {\n\t\t\tdata.left = dw - o.maxWidth;\n\t\t}\n\t\tif ( isminh && ch ) {\n\t\t\tdata.top = dh - o.minHeight;\n\t\t}\n\t\tif ( ismaxh && ch ) {\n\t\t\tdata.top = dh - o.maxHeight;\n\t\t}\n\n\t\t// Fixing jump error on top/left - bug #2330\n\t\tif ( !data.width && !data.height && !data.left && data.top ) {\n\t\t\tdata.top = null;\n\t\t} else if ( !data.width && !data.height && !data.top && data.left ) {\n\t\t\tdata.left = null;\n\t\t}\n\n\t\treturn data;\n\t},\n\n\t_getPaddingPlusBorderDimensions: function( element ) {\n\t\tvar i = 0,\n\t\t\twidths = [],\n\t\t\tborders = [\n\t\t\t\telement.css( \"borderTopWidth\" ),\n\t\t\t\telement.css( \"borderRightWidth\" ),\n\t\t\t\telement.css( \"borderBottomWidth\" ),\n\t\t\t\telement.css( \"borderLeftWidth\" )\n\t\t\t],\n\t\t\tpaddings = [\n\t\t\t\telement.css( \"paddingTop\" ),\n\t\t\t\telement.css( \"paddingRight\" ),\n\t\t\t\telement.css( \"paddingBottom\" ),\n\t\t\t\telement.css( \"paddingLeft\" )\n\t\t\t];\n\n\t\tfor ( ; i < 4; i++ ) {\n\t\t\twidths[ i ] = ( parseFloat( borders[ i ] ) || 0 );\n\t\t\twidths[ i ] += ( parseFloat( paddings[ i ] ) || 0 );\n\t\t}\n\n\t\treturn {\n\t\t\theight: widths[ 0 ] + widths[ 2 ],\n\t\t\twidth: widths[ 1 ] + widths[ 3 ]\n\t\t};\n\t},\n\n\t_proportionallyResize: function() {\n\n\t\tif ( !this._proportionallyResizeElements.length ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar prel,\n\t\t\ti = 0,\n\t\t\telement = this.helper || this.element;\n\n\t\tfor ( ; i < this._proportionallyResizeElements.length; i++ ) {\n\n\t\t\tprel = this._proportionallyResizeElements[ i ];\n\n\t\t\t// TODO: Seems like a bug to cache this.outerDimensions\n\t\t\t// considering that we are in a loop.\n\t\t\tif ( !this.outerDimensions ) {\n\t\t\t\tthis.outerDimensions = this._getPaddingPlusBorderDimensions( prel );\n\t\t\t}\n\n\t\t\tprel.css( {\n\t\t\t\theight: ( element.height() - this.outerDimensions.height ) || 0,\n\t\t\t\twidth: ( element.width() - this.outerDimensions.width ) || 0\n\t\t\t} );\n\n\t\t}\n\n\t},\n\n\t_renderProxy: function() {\n\n\t\tvar el = this.element, o = this.options;\n\t\tthis.elementOffset = el.offset();\n\n\t\tif ( this._helper ) {\n\n\t\t\tthis.helper = this.helper || $( \"<div style='overflow:hidden;'></div>\" );\n\n\t\t\tthis._addClass( this.helper, this._helper );\n\t\t\tthis.helper.css( {\n\t\t\t\twidth: this.element.outerWidth(),\n\t\t\t\theight: this.element.outerHeight(),\n\t\t\t\tposition: \"absolute\",\n\t\t\t\tleft: this.elementOffset.left + \"px\",\n\t\t\t\ttop: this.elementOffset.top + \"px\",\n\t\t\t\tzIndex: ++o.zIndex //TODO: Don't modify option\n\t\t\t} );\n\n\t\t\tthis.helper\n\t\t\t\t.appendTo( \"body\" )\n\t\t\t\t.disableSelection();\n\n\t\t} else {\n\t\t\tthis.helper = this.element;\n\t\t}\n\n\t},\n\n\t_change: {\n\t\te: function( event, dx ) {\n\t\t\treturn { width: this.originalSize.width + dx };\n\t\t},\n\t\tw: function( event, dx ) {\n\t\t\tvar cs = this.originalSize, sp = this.originalPosition;\n\t\t\treturn { left: sp.left + dx, width: cs.width - dx };\n\t\t},\n\t\tn: function( event, dx, dy ) {\n\t\t\tvar cs = this.originalSize, sp = this.originalPosition;\n\t\t\treturn { top: sp.top + dy, height: cs.height - dy };\n\t\t},\n\t\ts: function( event, dx, dy ) {\n\t\t\treturn { height: this.originalSize.height + dy };\n\t\t},\n\t\tse: function( event, dx, dy ) {\n\t\t\treturn $.extend( this._change.s.apply( this, arguments ),\n\t\t\t\tthis._change.e.apply( this, [ event, dx, dy ] ) );\n\t\t},\n\t\tsw: function( event, dx, dy ) {\n\t\t\treturn $.extend( this._change.s.apply( this, arguments ),\n\t\t\t\tthis._change.w.apply( this, [ event, dx, dy ] ) );\n\t\t},\n\t\tne: function( event, dx, dy ) {\n\t\t\treturn $.extend( this._change.n.apply( this, arguments ),\n\t\t\t\tthis._change.e.apply( this, [ event, dx, dy ] ) );\n\t\t},\n\t\tnw: function( event, dx, dy ) {\n\t\t\treturn $.extend( this._change.n.apply( this, arguments ),\n\t\t\t\tthis._change.w.apply( this, [ event, dx, dy ] ) );\n\t\t}\n\t},\n\n\t_propagate: function( n, event ) {\n\t\t$.ui.plugin.call( this, n, [ event, this.ui() ] );\n\t\t( n !== \"resize\" && this._trigger( n, event, this.ui() ) );\n\t},\n\n\tplugins: {},\n\n\tui: function() {\n\t\treturn {\n\t\t\toriginalElement: this.originalElement,\n\t\t\telement: this.element,\n\t\t\thelper: this.helper,\n\t\t\tposition: this.position,\n\t\t\tsize: this.size,\n\t\t\toriginalSize: this.originalSize,\n\t\t\toriginalPosition: this.originalPosition\n\t\t};\n\t}\n\n} );\n\n/*\n * Resizable Extensions\n */\n\n$.ui.plugin.add( \"resizable\", \"animate\", {\n\n\tstop: function( event ) {\n\t\tvar that = $( this ).resizable( \"instance\" ),\n\t\t\to = that.options,\n\t\t\tpr = that._proportionallyResizeElements,\n\t\t\tista = pr.length && ( /textarea/i ).test( pr[ 0 ].nodeName ),\n\t\t\tsoffseth = ista && that._hasScroll( pr[ 0 ], \"left\" ) ? 0 : that.sizeDiff.height,\n\t\t\tsoffsetw = ista ? 0 : that.sizeDiff.width,\n\t\t\tstyle = {\n\t\t\t\twidth: ( that.size.width - soffsetw ),\n\t\t\t\theight: ( that.size.height - soffseth )\n\t\t\t},\n\t\t\tleft = ( parseFloat( that.element.css( \"left\" ) ) +\n\t\t\t\t( that.position.left - that.originalPosition.left ) ) || null,\n\t\t\ttop = ( parseFloat( that.element.css( \"top\" ) ) +\n\t\t\t\t( that.position.top - that.originalPosition.top ) ) || null;\n\n\t\tthat.element.animate(\n\t\t\t$.extend( style, top && left ? { top: top, left: left } : {} ), {\n\t\t\t\tduration: o.animateDuration,\n\t\t\t\teasing: o.animateEasing,\n\t\t\t\tstep: function() {\n\n\t\t\t\t\tvar data = {\n\t\t\t\t\t\twidth: parseFloat( that.element.css( \"width\" ) ),\n\t\t\t\t\t\theight: parseFloat( that.element.css( \"height\" ) ),\n\t\t\t\t\t\ttop: parseFloat( that.element.css( \"top\" ) ),\n\t\t\t\t\t\tleft: parseFloat( that.element.css( \"left\" ) )\n\t\t\t\t\t};\n\n\t\t\t\t\tif ( pr && pr.length ) {\n\t\t\t\t\t\t$( pr[ 0 ] ).css( { width: data.width, height: data.height } );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Propagating resize, and updating values for each animation step\n\t\t\t\t\tthat._updateCache( data );\n\t\t\t\t\tthat._propagate( \"resize\", event );\n\n\t\t\t\t}\n\t\t\t}\n\t\t);\n\t}\n\n} );\n\n$.ui.plugin.add( \"resizable\", \"containment\", {\n\n\tstart: function() {\n\t\tvar element, p, co, ch, cw, width, height,\n\t\t\tthat = $( this ).resizable( \"instance\" ),\n\t\t\to = that.options,\n\t\t\tel = that.element,\n\t\t\toc = o.containment,\n\t\t\tce = ( oc instanceof $ ) ?\n\t\t\t\toc.get( 0 ) :\n\t\t\t\t( /parent/.test( oc ) ) ? el.parent().get( 0 ) : oc;\n\n\t\tif ( !ce ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthat.containerElement = $( ce );\n\n\t\tif ( /document/.test( oc ) || oc === document ) {\n\t\t\tthat.containerOffset = {\n\t\t\t\tleft: 0,\n\t\t\t\ttop: 0\n\t\t\t};\n\t\t\tthat.containerPosition = {\n\t\t\t\tleft: 0,\n\t\t\t\ttop: 0\n\t\t\t};\n\n\t\t\tthat.parentData = {\n\t\t\t\telement: $( document ),\n\t\t\t\tleft: 0,\n\t\t\t\ttop: 0,\n\t\t\t\twidth: $( document ).width(),\n\t\t\t\theight: $( document ).height() || document.body.parentNode.scrollHeight\n\t\t\t};\n\t\t} else {\n\t\t\telement = $( ce );\n\t\t\tp = [];\n\t\t\t$( [ \"Top\", \"Right\", \"Left\", \"Bottom\" ] ).each( function( i, name ) {\n\t\t\t\tp[ i ] = that._num( element.css( \"padding\" + name ) );\n\t\t\t} );\n\n\t\t\tthat.containerOffset = element.offset();\n\t\t\tthat.containerPosition = element.position();\n\t\t\tthat.containerSize = {\n\t\t\t\theight: ( element.innerHeight() - p[ 3 ] ),\n\t\t\t\twidth: ( element.innerWidth() - p[ 1 ] )\n\t\t\t};\n\n\t\t\tco = that.containerOffset;\n\t\t\tch = that.containerSize.height;\n\t\t\tcw = that.containerSize.width;\n\t\t\twidth = ( that._hasScroll ( ce, \"left\" ) ? ce.scrollWidth : cw );\n\t\t\theight = ( that._hasScroll ( ce ) ? ce.scrollHeight : ch ) ;\n\n\t\t\tthat.parentData = {\n\t\t\t\telement: ce,\n\t\t\t\tleft: co.left,\n\t\t\t\ttop: co.top,\n\t\t\t\twidth: width,\n\t\t\t\theight: height\n\t\t\t};\n\t\t}\n\t},\n\n\tresize: function( event ) {\n\t\tvar woset, hoset, isParent, isOffsetRelative,\n\t\t\tthat = $( this ).resizable( \"instance\" ),\n\t\t\to = that.options,\n\t\t\tco = that.containerOffset,\n\t\t\tcp = that.position,\n\t\t\tpRatio = that._aspectRatio || event.shiftKey,\n\t\t\tcop = {\n\t\t\t\ttop: 0,\n\t\t\t\tleft: 0\n\t\t\t},\n\t\t\tce = that.containerElement,\n\t\t\tcontinueResize = true;\n\n\t\tif ( ce[ 0 ] !== document && ( /static/ ).test( ce.css( \"position\" ) ) ) {\n\t\t\tcop = co;\n\t\t}\n\n\t\tif ( cp.left < ( that._helper ? co.left : 0 ) ) {\n\t\t\tthat.size.width = that.size.width +\n\t\t\t\t( that._helper ?\n\t\t\t\t\t( that.position.left - co.left ) :\n\t\t\t\t\t( that.position.left - cop.left ) );\n\n\t\t\tif ( pRatio ) {\n\t\t\t\tthat.size.height = that.size.width / that.aspectRatio;\n\t\t\t\tcontinueResize = false;\n\t\t\t}\n\t\t\tthat.position.left = o.helper ? co.left : 0;\n\t\t}\n\n\t\tif ( cp.top < ( that._helper ? co.top : 0 ) ) {\n\t\t\tthat.size.height = that.size.height +\n\t\t\t\t( that._helper ?\n\t\t\t\t\t( that.position.top - co.top ) :\n\t\t\t\t\tthat.position.top );\n\n\t\t\tif ( pRatio ) {\n\t\t\t\tthat.size.width = that.size.height * that.aspectRatio;\n\t\t\t\tcontinueResize = false;\n\t\t\t}\n\t\t\tthat.position.top = that._helper ? co.top : 0;\n\t\t}\n\n\t\tisParent = that.containerElement.get( 0 ) === that.element.parent().get( 0 );\n\t\tisOffsetRelative = /relative|absolute/.test( that.containerElement.css( \"position\" ) );\n\n\t\tif ( isParent && isOffsetRelative ) {\n\t\t\tthat.offset.left = that.parentData.left + that.position.left;\n\t\t\tthat.offset.top = that.parentData.top + that.position.top;\n\t\t} else {\n\t\t\tthat.offset.left = that.element.offset().left;\n\t\t\tthat.offset.top = that.element.offset().top;\n\t\t}\n\n\t\twoset = Math.abs( that.sizeDiff.width +\n\t\t\t( that._helper ?\n\t\t\t\tthat.offset.left - cop.left :\n\t\t\t\t( that.offset.left - co.left ) ) );\n\n\t\thoset = Math.abs( that.sizeDiff.height +\n\t\t\t( that._helper ?\n\t\t\t\tthat.offset.top - cop.top :\n\t\t\t\t( that.offset.top - co.top ) ) );\n\n\t\tif ( woset + that.size.width >= that.parentData.width ) {\n\t\t\tthat.size.width = that.parentData.width - woset;\n\t\t\tif ( pRatio ) {\n\t\t\t\tthat.size.height = that.size.width / that.aspectRatio;\n\t\t\t\tcontinueResize = false;\n\t\t\t}\n\t\t}\n\n\t\tif ( hoset + that.size.height >= that.parentData.height ) {\n\t\t\tthat.size.height = that.parentData.height - hoset;\n\t\t\tif ( pRatio ) {\n\t\t\t\tthat.size.width = that.size.height * that.aspectRatio;\n\t\t\t\tcontinueResize = false;\n\t\t\t}\n\t\t}\n\n\t\tif ( !continueResize ) {\n\t\t\tthat.position.left = that.prevPosition.left;\n\t\t\tthat.position.top = that.prevPosition.top;\n\t\t\tthat.size.width = that.prevSize.width;\n\t\t\tthat.size.height = that.prevSize.height;\n\t\t}\n\t},\n\n\tstop: function() {\n\t\tvar that = $( this ).resizable( \"instance\" ),\n\t\t\to = that.options,\n\t\t\tco = that.containerOffset,\n\t\t\tcop = that.containerPosition,\n\t\t\tce = that.containerElement,\n\t\t\thelper = $( that.helper ),\n\t\t\tho = helper.offset(),\n\t\t\tw = helper.outerWidth() - that.sizeDiff.width,\n\t\t\th = helper.outerHeight() - that.sizeDiff.height;\n\n\t\tif ( that._helper && !o.animate && ( /relative/ ).test( ce.css( \"position\" ) ) ) {\n\t\t\t$( this ).css( {\n\t\t\t\tleft: ho.left - cop.left - co.left,\n\t\t\t\twidth: w,\n\t\t\t\theight: h\n\t\t\t} );\n\t\t}\n\n\t\tif ( that._helper && !o.animate && ( /static/ ).test( ce.css( \"position\" ) ) ) {\n\t\t\t$( this ).css( {\n\t\t\t\tleft: ho.left - cop.left - co.left,\n\t\t\t\twidth: w,\n\t\t\t\theight: h\n\t\t\t} );\n\t\t}\n\t}\n} );\n\n$.ui.plugin.add( \"resizable\", \"alsoResize\", {\n\n\tstart: function() {\n\t\tvar that = $( this ).resizable( \"instance\" ),\n\t\t\to = that.options;\n\n\t\t$( o.alsoResize ).each( function() {\n\t\t\tvar el = $( this );\n\t\t\tel.data( \"ui-resizable-alsoresize\", {\n\t\t\t\twidth: parseFloat( el.width() ), height: parseFloat( el.height() ),\n\t\t\t\tleft: parseFloat( el.css( \"left\" ) ), top: parseFloat( el.css( \"top\" ) )\n\t\t\t} );\n\t\t} );\n\t},\n\n\tresize: function( event, ui ) {\n\t\tvar that = $( this ).resizable( \"instance\" ),\n\t\t\to = that.options,\n\t\t\tos = that.originalSize,\n\t\t\top = that.originalPosition,\n\t\t\tdelta = {\n\t\t\t\theight: ( that.size.height - os.height ) || 0,\n\t\t\t\twidth: ( that.size.width - os.width ) || 0,\n\t\t\t\ttop: ( that.position.top - op.top ) || 0,\n\t\t\t\tleft: ( that.position.left - op.left ) || 0\n\t\t\t};\n\n\t\t\t$( o.alsoResize ).each( function() {\n\t\t\t\tvar el = $( this ), start = $( this ).data( \"ui-resizable-alsoresize\" ), style = {},\n\t\t\t\t\tcss = el.parents( ui.originalElement[ 0 ] ).length ?\n\t\t\t\t\t\t\t[ \"width\", \"height\" ] :\n\t\t\t\t\t\t\t[ \"width\", \"height\", \"top\", \"left\" ];\n\n\t\t\t\t$.each( css, function( i, prop ) {\n\t\t\t\t\tvar sum = ( start[ prop ] || 0 ) + ( delta[ prop ] || 0 );\n\t\t\t\t\tif ( sum && sum >= 0 ) {\n\t\t\t\t\t\tstyle[ prop ] = sum || null;\n\t\t\t\t\t}\n\t\t\t\t} );\n\n\t\t\t\tel.css( style );\n\t\t\t} );\n\t},\n\n\tstop: function() {\n\t\t$( this ).removeData( \"ui-resizable-alsoresize\" );\n\t}\n} );\n\n$.ui.plugin.add( \"resizable\", \"ghost\", {\n\n\tstart: function() {\n\n\t\tvar that = $( this ).resizable( \"instance\" ), cs = that.size;\n\n\t\tthat.ghost = that.originalElement.clone();\n\t\tthat.ghost.css( {\n\t\t\topacity: 0.25,\n\t\t\tdisplay: \"block\",\n\t\t\tposition: \"relative\",\n\t\t\theight: cs.height,\n\t\t\twidth: cs.width,\n\t\t\tmargin: 0,\n\t\t\tleft: 0,\n\t\t\ttop: 0\n\t\t} );\n\n\t\tthat._addClass( that.ghost, \"ui-resizable-ghost\" );\n\n\t\t// DEPRECATED\n\t\t// TODO: remove after 1.12\n\t\tif ( $.uiBackCompat !== false && typeof that.options.ghost === \"string\" ) {\n\n\t\t\t// Ghost option\n\t\t\tthat.ghost.addClass( this.options.ghost );\n\t\t}\n\n\t\tthat.ghost.appendTo( that.helper );\n\n\t},\n\n\tresize: function() {\n\t\tvar that = $( this ).resizable( \"instance\" );\n\t\tif ( that.ghost ) {\n\t\t\tthat.ghost.css( {\n\t\t\t\tposition: \"relative\",\n\t\t\t\theight: that.size.height,\n\t\t\t\twidth: that.size.width\n\t\t\t} );\n\t\t}\n\t},\n\n\tstop: function() {\n\t\tvar that = $( this ).resizable( \"instance\" );\n\t\tif ( that.ghost && that.helper ) {\n\t\t\tthat.helper.get( 0 ).removeChild( that.ghost.get( 0 ) );\n\t\t}\n\t}\n\n} );\n\n$.ui.plugin.add( \"resizable\", \"grid\", {\n\n\tresize: function() {\n\t\tvar outerDimensions,\n\t\t\tthat = $( this ).resizable( \"instance\" ),\n\t\t\to = that.options,\n\t\t\tcs = that.size,\n\t\t\tos = that.originalSize,\n\t\t\top = that.originalPosition,\n\t\t\ta = that.axis,\n\t\t\tgrid = typeof o.grid === \"number\" ? [ o.grid, o.grid ] : o.grid,\n\t\t\tgridX = ( grid[ 0 ] || 1 ),\n\t\t\tgridY = ( grid[ 1 ] || 1 ),\n\t\t\tox = Math.round( ( cs.width - os.width ) / gridX ) * gridX,\n\t\t\toy = Math.round( ( cs.height - os.height ) / gridY ) * gridY,\n\t\t\tnewWidth = os.width + ox,\n\t\t\tnewHeight = os.height + oy,\n\t\t\tisMaxWidth = o.maxWidth && ( o.maxWidth < newWidth ),\n\t\t\tisMaxHeight = o.maxHeight && ( o.maxHeight < newHeight ),\n\t\t\tisMinWidth = o.minWidth && ( o.minWidth > newWidth ),\n\t\t\tisMinHeight = o.minHeight && ( o.minHeight > newHeight );\n\n\t\to.grid = grid;\n\n\t\tif ( isMinWidth ) {\n\t\t\tnewWidth += gridX;\n\t\t}\n\t\tif ( isMinHeight ) {\n\t\t\tnewHeight += gridY;\n\t\t}\n\t\tif ( isMaxWidth ) {\n\t\t\tnewWidth -= gridX;\n\t\t}\n\t\tif ( isMaxHeight ) {\n\t\t\tnewHeight -= gridY;\n\t\t}\n\n\t\tif ( /^(se|s|e)$/.test( a ) ) {\n\t\t\tthat.size.width = newWidth;\n\t\t\tthat.size.height = newHeight;\n\t\t} else if ( /^(ne)$/.test( a ) ) {\n\t\t\tthat.size.width = newWidth;\n\t\t\tthat.size.height = newHeight;\n\t\t\tthat.position.top = op.top - oy;\n\t\t} else if ( /^(sw)$/.test( a ) ) {\n\t\t\tthat.size.width = newWidth;\n\t\t\tthat.size.height = newHeight;\n\t\t\tthat.position.left = op.left - ox;\n\t\t} else {\n\t\t\tif ( newHeight - gridY <= 0 || newWidth - gridX <= 0 ) {\n\t\t\t\touterDimensions = that._getPaddingPlusBorderDimensions( this );\n\t\t\t}\n\n\t\t\tif ( newHeight - gridY > 0 ) {\n\t\t\t\tthat.size.height = newHeight;\n\t\t\t\tthat.position.top = op.top - oy;\n\t\t\t} else {\n\t\t\t\tnewHeight = gridY - outerDimensions.height;\n\t\t\t\tthat.size.height = newHeight;\n\t\t\t\tthat.position.top = op.top + os.height - newHeight;\n\t\t\t}\n\t\t\tif ( newWidth - gridX > 0 ) {\n\t\t\t\tthat.size.width = newWidth;\n\t\t\t\tif (that.options.odoo_isRTL) {\n\t\t\t\t\tthat.position.left = op.left + ox;\n\t\t\t\t} else {\n\t\t\t\t\tthat.position.left = op.left - ox;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tnewWidth = gridX - outerDimensions.width;\n\t\t\t\tthat.size.width = newWidth;\n\t\t\t\tif (that.options.odoo_isRTL) {\n\t\t\t\t\tthat.position.left = op.left - os.width + newWidth;\n\t\t\t\t} else {\n\t\t\t\t\tthat.position.left = op.left + os.width - newWidth;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n} );\n\nvar widgetsResizable = $.ui.resizable;\n\n\n/*!\n * jQuery UI Selectable 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Selectable\n//>>group: Interactions\n//>>description: Allows groups of elements to be selected with the mouse.\n//>>docs: http://api.jqueryui.com/selectable/\n//>>demos: http://jqueryui.com/selectable/\n//>>css.structure: ../../themes/base/selectable.css\n\n\n\nvar widgetsSelectable = $.widget( \"ui.selectable\", $.ui.mouse, {\n\tversion: \"1.12.1\",\n\toptions: {\n\t\tappendTo: \"body\",\n\t\tautoRefresh: true,\n\t\tdistance: 0,\n\t\tfilter: \"*\",\n\t\ttolerance: \"touch\",\n\n\t\t// Callbacks\n\t\tselected: null,\n\t\tselecting: null,\n\t\tstart: null,\n\t\tstop: null,\n\t\tunselected: null,\n\t\tunselecting: null\n\t},\n\t_create: function() {\n\t\tvar that = this;\n\n\t\tthis._addClass( \"ui-selectable\" );\n\n\t\tthis.dragged = false;\n\n\t\t// Cache selectee children based on filter\n\t\tthis.refresh = function() {\n\t\t\tthat.elementPos = $( that.element[ 0 ] ).offset();\n\t\t\tthat.selectees = $( that.options.filter, that.element[ 0 ] );\n\t\t\tthat._addClass( that.selectees, \"ui-selectee\" );\n\t\t\tthat.selectees.each( function() {\n\t\t\t\tvar $this = $( this ),\n\t\t\t\t\tselecteeOffset = $this.offset(),\n\t\t\t\t\tpos = {\n\t\t\t\t\t\tleft: selecteeOffset.left - that.elementPos.left,\n\t\t\t\t\t\ttop: selecteeOffset.top - that.elementPos.top\n\t\t\t\t\t};\n\t\t\t\t$.data( this, \"selectable-item\", {\n\t\t\t\t\telement: this,\n\t\t\t\t\t$element: $this,\n\t\t\t\t\tleft: pos.left,\n\t\t\t\t\ttop: pos.top,\n\t\t\t\t\tright: pos.left + $this.outerWidth(),\n\t\t\t\t\tbottom: pos.top + $this.outerHeight(),\n\t\t\t\t\tstartselected: false,\n\t\t\t\t\tselected: $this.hasClass( \"ui-selected\" ),\n\t\t\t\t\tselecting: $this.hasClass( \"ui-selecting\" ),\n\t\t\t\t\tunselecting: $this.hasClass( \"ui-unselecting\" )\n\t\t\t\t} );\n\t\t\t} );\n\t\t};\n\t\tthis.refresh();\n\n\t\tthis._mouseInit();\n\n\t\tthis.helper = $( \"<div>\" );\n\t\tthis._addClass( this.helper, \"ui-selectable-helper\" );\n\t},\n\n\t_destroy: function() {\n\t\tthis.selectees.removeData( \"selectable-item\" );\n\t\tthis._mouseDestroy();\n\t},\n\n\t_mouseStart: function( event ) {\n\t\tvar that = this,\n\t\t\toptions = this.options;\n\n\t\tthis.opos = [ event.pageX, event.pageY ];\n\t\tthis.elementPos = $( this.element[ 0 ] ).offset();\n\n\t\tif ( this.options.disabled ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.selectees = $( options.filter, this.element[ 0 ] );\n\n\t\tthis._trigger( \"start\", event );\n\n\t\t$( options.appendTo ).append( this.helper );\n\n\t\t// position helper (lasso)\n\t\tthis.helper.css( {\n\t\t\t\"left\": event.pageX,\n\t\t\t\"top\": event.pageY,\n\t\t\t\"width\": 0,\n\t\t\t\"height\": 0\n\t\t} );\n\n\t\tif ( options.autoRefresh ) {\n\t\t\tthis.refresh();\n\t\t}\n\n\t\tthis.selectees.filter( \".ui-selected\" ).each( function() {\n\t\t\tvar selectee = $.data( this, \"selectable-item\" );\n\t\t\tselectee.startselected = true;\n\t\t\tif ( !event.metaKey && !event.ctrlKey ) {\n\t\t\t\tthat._removeClass( selectee.$element, \"ui-selected\" );\n\t\t\t\tselectee.selected = false;\n\t\t\t\tthat._addClass( selectee.$element, \"ui-unselecting\" );\n\t\t\t\tselectee.unselecting = true;\n\n\t\t\t\t// selectable UNSELECTING callback\n\t\t\t\tthat._trigger( \"unselecting\", event, {\n\t\t\t\t\tunselecting: selectee.element\n\t\t\t\t} );\n\t\t\t}\n\t\t} );\n\n\t\t$( event.target ).parents().addBack().each( function() {\n\t\t\tvar doSelect,\n\t\t\t\tselectee = $.data( this, \"selectable-item\" );\n\t\t\tif ( selectee ) {\n\t\t\t\tdoSelect = ( !event.metaKey && !event.ctrlKey ) ||\n\t\t\t\t\t!selectee.$element.hasClass( \"ui-selected\" );\n\t\t\t\tthat._removeClass( selectee.$element, doSelect ? \"ui-unselecting\" : \"ui-selected\" )\n\t\t\t\t\t._addClass( selectee.$element, doSelect ? \"ui-selecting\" : \"ui-unselecting\" );\n\t\t\t\tselectee.unselecting = !doSelect;\n\t\t\t\tselectee.selecting = doSelect;\n\t\t\t\tselectee.selected = doSelect;\n\n\t\t\t\t// selectable (UN)SELECTING callback\n\t\t\t\tif ( doSelect ) {\n\t\t\t\t\tthat._trigger( \"selecting\", event, {\n\t\t\t\t\t\tselecting: selectee.element\n\t\t\t\t\t} );\n\t\t\t\t} else {\n\t\t\t\t\tthat._trigger( \"unselecting\", event, {\n\t\t\t\t\t\tunselecting: selectee.element\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}\n\t\t} );\n\n\t},\n\n\t_mouseDrag: function( event ) {\n\n\t\tthis.dragged = true;\n\n\t\tif ( this.options.disabled ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar tmp,\n\t\t\tthat = this,\n\t\t\toptions = this.options,\n\t\t\tx1 = this.opos[ 0 ],\n\t\t\ty1 = this.opos[ 1 ],\n\t\t\tx2 = event.pageX,\n\t\t\ty2 = event.pageY;\n\n\t\tif ( x1 > x2 ) { tmp = x2; x2 = x1; x1 = tmp; }\n\t\tif ( y1 > y2 ) { tmp = y2; y2 = y1; y1 = tmp; }\n\t\tthis.helper.css( { left: x1, top: y1, width: x2 - x1, height: y2 - y1 } );\n\n\t\tthis.selectees.each( function() {\n\t\t\tvar selectee = $.data( this, \"selectable-item\" ),\n\t\t\t\thit = false,\n\t\t\t\toffset = {};\n\n\t\t\t//prevent helper from being selected if appendTo: selectable\n\t\t\tif ( !selectee || selectee.element === that.element[ 0 ] ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\toffset.left   = selectee.left   + that.elementPos.left;\n\t\t\toffset.right  = selectee.right  + that.elementPos.left;\n\t\t\toffset.top    = selectee.top    + that.elementPos.top;\n\t\t\toffset.bottom = selectee.bottom + that.elementPos.top;\n\n\t\t\tif ( options.tolerance === \"touch\" ) {\n\t\t\t\thit = ( !( offset.left > x2 || offset.right < x1 || offset.top > y2 ||\n                    offset.bottom < y1 ) );\n\t\t\t} else if ( options.tolerance === \"fit\" ) {\n\t\t\t\thit = ( offset.left > x1 && offset.right < x2 && offset.top > y1 &&\n                    offset.bottom < y2 );\n\t\t\t}\n\n\t\t\tif ( hit ) {\n\n\t\t\t\t// SELECT\n\t\t\t\tif ( selectee.selected ) {\n\t\t\t\t\tthat._removeClass( selectee.$element, \"ui-selected\" );\n\t\t\t\t\tselectee.selected = false;\n\t\t\t\t}\n\t\t\t\tif ( selectee.unselecting ) {\n\t\t\t\t\tthat._removeClass( selectee.$element, \"ui-unselecting\" );\n\t\t\t\t\tselectee.unselecting = false;\n\t\t\t\t}\n\t\t\t\tif ( !selectee.selecting ) {\n\t\t\t\t\tthat._addClass( selectee.$element, \"ui-selecting\" );\n\t\t\t\t\tselectee.selecting = true;\n\n\t\t\t\t\t// selectable SELECTING callback\n\t\t\t\t\tthat._trigger( \"selecting\", event, {\n\t\t\t\t\t\tselecting: selectee.element\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t} else {\n\n\t\t\t\t// UNSELECT\n\t\t\t\tif ( selectee.selecting ) {\n\t\t\t\t\tif ( ( event.metaKey || event.ctrlKey ) && selectee.startselected ) {\n\t\t\t\t\t\tthat._removeClass( selectee.$element, \"ui-selecting\" );\n\t\t\t\t\t\tselectee.selecting = false;\n\t\t\t\t\t\tthat._addClass( selectee.$element, \"ui-selected\" );\n\t\t\t\t\t\tselectee.selected = true;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthat._removeClass( selectee.$element, \"ui-selecting\" );\n\t\t\t\t\t\tselectee.selecting = false;\n\t\t\t\t\t\tif ( selectee.startselected ) {\n\t\t\t\t\t\t\tthat._addClass( selectee.$element, \"ui-unselecting\" );\n\t\t\t\t\t\t\tselectee.unselecting = true;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// selectable UNSELECTING callback\n\t\t\t\t\t\tthat._trigger( \"unselecting\", event, {\n\t\t\t\t\t\t\tunselecting: selectee.element\n\t\t\t\t\t\t} );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif ( selectee.selected ) {\n\t\t\t\t\tif ( !event.metaKey && !event.ctrlKey && !selectee.startselected ) {\n\t\t\t\t\t\tthat._removeClass( selectee.$element, \"ui-selected\" );\n\t\t\t\t\t\tselectee.selected = false;\n\n\t\t\t\t\t\tthat._addClass( selectee.$element, \"ui-unselecting\" );\n\t\t\t\t\t\tselectee.unselecting = true;\n\n\t\t\t\t\t\t// selectable UNSELECTING callback\n\t\t\t\t\t\tthat._trigger( \"unselecting\", event, {\n\t\t\t\t\t\t\tunselecting: selectee.element\n\t\t\t\t\t\t} );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\n\t\treturn false;\n\t},\n\n\t_mouseStop: function( event ) {\n\t\tvar that = this;\n\n\t\tthis.dragged = false;\n\n\t\t$( \".ui-unselecting\", this.element[ 0 ] ).each( function() {\n\t\t\tvar selectee = $.data( this, \"selectable-item\" );\n\t\t\tthat._removeClass( selectee.$element, \"ui-unselecting\" );\n\t\t\tselectee.unselecting = false;\n\t\t\tselectee.startselected = false;\n\t\t\tthat._trigger( \"unselected\", event, {\n\t\t\t\tunselected: selectee.element\n\t\t\t} );\n\t\t} );\n\t\t$( \".ui-selecting\", this.element[ 0 ] ).each( function() {\n\t\t\tvar selectee = $.data( this, \"selectable-item\" );\n\t\t\tthat._removeClass( selectee.$element, \"ui-selecting\" )\n\t\t\t\t._addClass( selectee.$element, \"ui-selected\" );\n\t\t\tselectee.selecting = false;\n\t\t\tselectee.selected = true;\n\t\t\tselectee.startselected = true;\n\t\t\tthat._trigger( \"selected\", event, {\n\t\t\t\tselected: selectee.element\n\t\t\t} );\n\t\t} );\n\t\tthis._trigger( \"stop\", event );\n\n\t\tthis.helper.remove();\n\n\t\treturn false;\n\t}\n\n} );\n\n\n/*!\n * jQuery UI Sortable 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Sortable\n//>>group: Interactions\n//>>description: Enables items in a list to be sorted using the mouse.\n//>>docs: http://api.jqueryui.com/sortable/\n//>>demos: http://jqueryui.com/sortable/\n//>>css.structure: ../../themes/base/sortable.css\n\n\n\nvar widgetsSortable = $.widget( \"ui.sortable\", $.ui.mouse, {\n\tversion: \"1.12.1\",\n\twidgetEventPrefix: \"sort\",\n\tready: false,\n\toptions: {\n\t\tappendTo: \"parent\",\n\t\taxis: false,\n\t\tconnectWith: false,\n\t\tcontainment: false,\n\t\tcursor: \"auto\",\n\t\tcursorAt: false,\n\t\tdropOnEmpty: true,\n\t\tforcePlaceholderSize: false,\n\t\tforceHelperSize: false,\n\t\tgrid: false,\n\t\thandle: false,\n\t\thelper: \"original\",\n\t\titems: \"> *\",\n\t\topacity: false,\n\t\tplaceholder: false,\n\t\trevert: false,\n\t\tscroll: true,\n\t\tscrollSensitivity: 20,\n\t\tscrollSpeed: 20,\n\t\tscope: \"default\",\n\t\ttolerance: \"intersect\",\n\t\tzIndex: 1000,\n\n\t\t// Callbacks\n\t\tactivate: null,\n\t\tbeforeStop: null,\n\t\tchange: null,\n\t\tdeactivate: null,\n\t\tout: null,\n\t\tover: null,\n\t\treceive: null,\n\t\tremove: null,\n\t\tsort: null,\n\t\tstart: null,\n\t\tstop: null,\n\t\tupdate: null\n\t},\n\n\t_isOverAxis: function( x, reference, size ) {\n\t\treturn ( x >= reference ) && ( x < ( reference + size ) );\n\t},\n\n\t_isFloating: function( item ) {\n\t\treturn ( /left|right/ ).test( item.css( \"float\" ) ) ||\n\t\t\t( /inline|table-cell/ ).test( item.css( \"display\" ) );\n\t},\n\n\t_create: function() {\n\t\tthis.containerCache = {};\n\t\tthis._addClass( \"ui-sortable\" );\n\n\t\t//Get the items\n\t\tthis.refresh();\n\n\t\t//Let's determine the parent's offset\n\t\tthis.offset = this.element.offset();\n\n\t\t//Initialize mouse events for interaction\n\t\tthis._mouseInit();\n\n\t\tthis._setHandleClassName();\n\n\t\t//We're ready to go\n\t\tthis.ready = true;\n\n\t},\n\n\t_setOption: function( key, value ) {\n\t\tthis._super( key, value );\n\n\t\tif ( key === \"handle\" ) {\n\t\t\tthis._setHandleClassName();\n\t\t}\n\t},\n\n\t_setHandleClassName: function() {\n\t\tvar that = this;\n\t\tthis._removeClass( this.element.find( \".ui-sortable-handle\" ), \"ui-sortable-handle\" );\n\t\t$.each( this.items, function() {\n\t\t\tthat._addClass(\n\t\t\t\tthis.instance.options.handle ?\n\t\t\t\t\tthis.item.find( this.instance.options.handle ) :\n\t\t\t\t\tthis.item,\n\t\t\t\t\"ui-sortable-handle\"\n\t\t\t);\n\t\t} );\n\t},\n\n\t_destroy: function() {\n\t\tthis._mouseDestroy();\n\n\t\tfor ( var i = this.items.length - 1; i >= 0; i-- ) {\n\t\t\tthis.items[ i ].item.removeData( this.widgetName + \"-item\" );\n\t\t}\n\n\t\treturn this;\n\t},\n\n\t_mouseCapture: function( event, overrideHandle ) {\n\t\tvar currentItem = null,\n\t\t\tvalidHandle = false,\n\t\t\tthat = this;\n\n\t\tif ( this.reverting ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif ( this.options.disabled || this.options.type === \"static\" ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t//We have to refresh the items data once first\n\t\tthis._refreshItems( event );\n\n\t\t//Find out if the clicked node (or one of its parents) is a actual item in this.items\n\t\t$( event.target ).parents().each( function() {\n\t\t\tif ( $.data( this, that.widgetName + \"-item\" ) === that ) {\n\t\t\t\tcurrentItem = $( this );\n\t\t\t\treturn false;\n\t\t\t}\n\t\t} );\n\t\tif ( $.data( event.target, that.widgetName + \"-item\" ) === that ) {\n\t\t\tcurrentItem = $( event.target );\n\t\t}\n\n\t\tif ( !currentItem ) {\n\t\t\treturn false;\n\t\t}\n\t\tif ( this.options.handle && !overrideHandle ) {\n\t\t\t$( this.options.handle, currentItem ).find( \"*\" ).addBack().each( function() {\n\t\t\t\tif ( this === event.target ) {\n\t\t\t\t\tvalidHandle = true;\n\t\t\t\t}\n\t\t\t} );\n\t\t\tif ( !validHandle ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\tthis.currentItem = currentItem;\n\t\tthis._removeCurrentsFromItems();\n\t\treturn true;\n\n\t},\n\n\t_mouseStart: function( event, overrideHandle, noActivation ) {\n\n\t\tvar i, body,\n\t\t\to = this.options;\n\n\t\tthis.currentContainer = this;\n\n\t\t//We only need to call refreshPositions, because the refreshItems call has been moved to\n\t\t// mouseCapture\n\t\tthis.refreshPositions();\n\n\t\t//Create and append the visible helper\n\t\tthis.helper = this._createHelper( event );\n\n\t\t//Cache the helper size\n\t\tthis._cacheHelperProportions();\n\n\t\t/*\n\t\t * - Position generation -\n\t\t * This block generates everything position related - it's the core of draggables.\n\t\t */\n\n\t\t//Cache the margins of the original element\n\t\tthis._cacheMargins();\n\n\t\t//Get the next scrolling parent\n\t\tthis.scrollParent = this.helper.scrollParent();\n\n\t\t//The element's absolute position on the page minus margins\n\t\tthis.offset = this.currentItem.offset();\n\t\tthis.offset = {\n\t\t\ttop: this.offset.top - this.margins.top,\n\t\t\tleft: this.offset.left - this.margins.left\n\t\t};\n\n\t\t$.extend( this.offset, {\n\t\t\tclick: { //Where the click happened, relative to the element\n\t\t\t\tleft: event.pageX - this.offset.left,\n\t\t\t\ttop: event.pageY - this.offset.top\n\t\t\t},\n\t\t\tparent: this._getParentOffset(),\n\n\t\t\t// This is a relative to absolute position minus the actual position calculation -\n\t\t\t// only used for relative positioned helper\n\t\t\trelative: this._getRelativeOffset()\n\t\t} );\n\n\t\t// Only after we got the offset, we can change the helper's position to absolute\n\t\t// TODO: Still need to figure out a way to make relative sorting possible\n\t\tthis.helper.css( \"position\", \"absolute\" );\n\t\tthis.cssPosition = this.helper.css( \"position\" );\n\n\t\t//Generate the original position\n\t\tthis.originalPosition = this._generatePosition( event );\n\t\tthis.originalPageX = event.pageX;\n\t\tthis.originalPageY = event.pageY;\n\n\t\t//Adjust the mouse offset relative to the helper if \"cursorAt\" is supplied\n\t\t( o.cursorAt && this._adjustOffsetFromHelper( o.cursorAt ) );\n\n\t\t//Cache the former DOM position\n\t\tthis.domPosition = {\n\t\t\tprev: this.currentItem.prev()[ 0 ],\n\t\t\tparent: this.currentItem.parent()[ 0 ]\n\t\t};\n\n\t\t// If the helper is not the original, hide the original so it's not playing any role during\n\t\t// the drag, won't cause anything bad this way\n\t\tif ( this.helper[ 0 ] !== this.currentItem[ 0 ] ) {\n\t\t\tthis.currentItem.hide();\n\t\t}\n\n\t\t//Create the placeholder\n\t\tthis._createPlaceholder();\n\n\t\t//Set a containment if given in the options\n\t\tif ( o.containment ) {\n\t\t\tthis._setContainment();\n\t\t}\n\n\t\tif ( o.cursor && o.cursor !== \"auto\" ) { // cursor option\n\t\t\tbody = this.document.find( \"body\" );\n\n\t\t\t// Support: IE\n\t\t\tthis.storedCursor = body.css( \"cursor\" );\n\t\t\tbody.css( \"cursor\", o.cursor );\n\n\t\t\tthis.storedStylesheet =\n\t\t\t\t$( \"<style>*{ cursor: \" + o.cursor + \" !important; }</style>\" ).appendTo( body );\n\t\t}\n\n\t\tif ( o.opacity ) { // opacity option\n\t\t\tif ( this.helper.css( \"opacity\" ) ) {\n\t\t\t\tthis._storedOpacity = this.helper.css( \"opacity\" );\n\t\t\t}\n\t\t\tthis.helper.css( \"opacity\", o.opacity );\n\t\t}\n\n\t\tif ( o.zIndex ) { // zIndex option\n\t\t\tif ( this.helper.css( \"zIndex\" ) ) {\n\t\t\t\tthis._storedZIndex = this.helper.css( \"zIndex\" );\n\t\t\t}\n\t\t\tthis.helper.css( \"zIndex\", o.zIndex );\n\t\t}\n\n\t\t//Prepare scrolling\n\t\tif ( this.scrollParent[ 0 ] !== this.document[ 0 ] &&\n\t\t\t\tthis.scrollParent[ 0 ].tagName !== \"HTML\" ) {\n\t\t\tthis.overflowOffset = this.scrollParent.offset();\n\t\t}\n\n\t\t//Call callbacks\n\t\tthis._trigger( \"start\", event, this._uiHash() );\n\n\t\t//Recache the helper size\n\t\tif ( !this._preserveHelperProportions ) {\n\t\t\tthis._cacheHelperProportions();\n\t\t}\n\n\t\t//Post \"activate\" events to possible containers\n\t\tif ( !noActivation ) {\n\t\t\tfor ( i = this.containers.length - 1; i >= 0; i-- ) {\n\t\t\t\tthis.containers[ i ]._trigger( \"activate\", event, this._uiHash( this ) );\n\t\t\t}\n\t\t}\n\n\t\t//Prepare possible droppables\n\t\tif ( $.ui.ddmanager ) {\n\t\t\t$.ui.ddmanager.current = this;\n\t\t}\n\n\t\tif ( $.ui.ddmanager && !o.dropBehaviour ) {\n\t\t\t$.ui.ddmanager.prepareOffsets( this, event );\n\t\t}\n\n\t\tthis.dragging = true;\n\n\t\tthis._addClass( this.helper, \"ui-sortable-helper\" );\n\n\t\t// Execute the drag once - this causes the helper not to be visiblebefore getting its\n\t\t// correct position\n\t\tthis._mouseDrag( event );\n\t\treturn true;\n\n\t},\n\n\t_mouseDrag: function( event ) {\n\t\tvar i, item, itemElement, intersection,\n\t\t\to = this.options,\n\t\t\tscrolled = false;\n\n\t\t//Compute the helpers position\n\t\tthis.position = this._generatePosition( event );\n\t\tthis.positionAbs = this._convertPositionTo( \"absolute\" );\n\n\t\tif ( !this.lastPositionAbs ) {\n\t\t\tthis.lastPositionAbs = this.positionAbs;\n\t\t}\n\n\t\t//Do scrolling\n\t\tif ( this.options.scroll ) {\n\t\t\tif ( this.scrollParent[ 0 ] !== this.document[ 0 ] &&\n\t\t\t\t\tthis.scrollParent[ 0 ].tagName !== \"HTML\" ) {\n\n\t\t\t\tif ( ( this.overflowOffset.top + this.scrollParent[ 0 ].offsetHeight ) -\n\t\t\t\t\t\tevent.pageY < o.scrollSensitivity ) {\n\t\t\t\t\tthis.scrollParent[ 0 ].scrollTop =\n\t\t\t\t\t\tscrolled = this.scrollParent[ 0 ].scrollTop + o.scrollSpeed;\n\t\t\t\t} else if ( event.pageY - this.overflowOffset.top < o.scrollSensitivity ) {\n\t\t\t\t\tthis.scrollParent[ 0 ].scrollTop =\n\t\t\t\t\t\tscrolled = this.scrollParent[ 0 ].scrollTop - o.scrollSpeed;\n\t\t\t\t}\n\n\t\t\t\tif ( ( this.overflowOffset.left + this.scrollParent[ 0 ].offsetWidth ) -\n\t\t\t\t\t\tevent.pageX < o.scrollSensitivity ) {\n\t\t\t\t\tthis.scrollParent[ 0 ].scrollLeft = scrolled =\n\t\t\t\t\t\tthis.scrollParent[ 0 ].scrollLeft + o.scrollSpeed;\n\t\t\t\t} else if ( event.pageX - this.overflowOffset.left < o.scrollSensitivity ) {\n\t\t\t\t\tthis.scrollParent[ 0 ].scrollLeft = scrolled =\n\t\t\t\t\t\tthis.scrollParent[ 0 ].scrollLeft - o.scrollSpeed;\n\t\t\t\t}\n\n\t\t\t} else {\n\n\t\t\t\tif ( event.pageY - this.document.scrollTop() < o.scrollSensitivity ) {\n\t\t\t\t\tscrolled = this.document.scrollTop( this.document.scrollTop() - o.scrollSpeed );\n\t\t\t\t} else if ( this.window.height() - ( event.pageY - this.document.scrollTop() ) <\n\t\t\t\t\t\to.scrollSensitivity ) {\n\t\t\t\t\tscrolled = this.document.scrollTop( this.document.scrollTop() + o.scrollSpeed );\n\t\t\t\t}\n\n\t\t\t\tif ( event.pageX - this.document.scrollLeft() < o.scrollSensitivity ) {\n\t\t\t\t\tscrolled = this.document.scrollLeft(\n\t\t\t\t\t\tthis.document.scrollLeft() - o.scrollSpeed\n\t\t\t\t\t);\n\t\t\t\t} else if ( this.window.width() - ( event.pageX - this.document.scrollLeft() ) <\n\t\t\t\t\t\to.scrollSensitivity ) {\n\t\t\t\t\tscrolled = this.document.scrollLeft(\n\t\t\t\t\t\tthis.document.scrollLeft() + o.scrollSpeed\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tif ( scrolled !== false && $.ui.ddmanager && !o.dropBehaviour ) {\n\t\t\t\t$.ui.ddmanager.prepareOffsets( this, event );\n\t\t\t}\n\t\t}\n\n\t\t//Regenerate the absolute position used for position checks\n\t\tthis.positionAbs = this._convertPositionTo( \"absolute\" );\n\n\t\t//Set the helper position\n\t\tif ( !this.options.axis || this.options.axis !== \"y\" ) {\n\t\t\tthis.helper[ 0 ].style.left = this.position.left + \"px\";\n\t\t}\n\t\tif ( !this.options.axis || this.options.axis !== \"x\" ) {\n\t\t\tthis.helper[ 0 ].style.top = this.position.top + \"px\";\n\t\t}\n\n\t\t//Rearrange\n\t\tfor ( i = this.items.length - 1; i >= 0; i-- ) {\n\n\t\t\t//Cache variables and intersection, continue if no intersection\n\t\t\titem = this.items[ i ];\n\t\t\titemElement = item.item[ 0 ];\n\t\t\tintersection = this._intersectsWithPointer( item );\n\t\t\tif ( !intersection ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Only put the placeholder inside the current Container, skip all\n\t\t\t// items from other containers. This works because when moving\n\t\t\t// an item from one container to another the\n\t\t\t// currentContainer is switched before the placeholder is moved.\n\t\t\t//\n\t\t\t// Without this, moving items in \"sub-sortables\" can cause\n\t\t\t// the placeholder to jitter between the outer and inner container.\n\t\t\tif ( item.instance !== this.currentContainer ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Cannot intersect with itself\n\t\t\t// no useless actions that have been done before\n\t\t\t// no action if the item moved is the parent of the item checked\n\t\t\tif ( itemElement !== this.currentItem[ 0 ] &&\n\t\t\t\tthis.placeholder[ intersection === 1 ? \"next\" : \"prev\" ]()[ 0 ] !== itemElement &&\n\t\t\t\t!$.contains( this.placeholder[ 0 ], itemElement ) &&\n\t\t\t\t( this.options.type === \"semi-dynamic\" ?\n\t\t\t\t\t!$.contains( this.element[ 0 ], itemElement ) :\n\t\t\t\t\ttrue\n\t\t\t\t)\n\t\t\t) {\n\n\t\t\t\tthis.direction = intersection === 1 ? \"down\" : \"up\";\n\n\t\t\t\tif ( this.options.tolerance === \"pointer\" || this._intersectsWithSides( item ) ) {\n\t\t\t\t\tthis._rearrange( event, item );\n\t\t\t\t} else {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tthis._trigger( \"change\", event, this._uiHash() );\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t//Post events to containers\n\t\tthis._contactContainers( event );\n\n\t\t//Interconnect with droppables\n\t\tif ( $.ui.ddmanager ) {\n\t\t\t$.ui.ddmanager.drag( this, event );\n\t\t}\n\n\t\t//Call callbacks\n\t\tthis._trigger( \"sort\", event, this._uiHash() );\n\n\t\tthis.lastPositionAbs = this.positionAbs;\n\t\treturn false;\n\n\t},\n\n\t_mouseStop: function( event, noPropagation ) {\n\n\t\tif ( !event ) {\n\t\t\treturn;\n\t\t}\n\n\t\t//If we are using droppables, inform the manager about the drop\n\t\tif ( $.ui.ddmanager && !this.options.dropBehaviour ) {\n\t\t\t$.ui.ddmanager.drop( this, event );\n\t\t}\n\n\t\tif ( this.options.revert ) {\n\t\t\tvar that = this,\n\t\t\t\tcur = this.placeholder.offset(),\n\t\t\t\taxis = this.options.axis,\n\t\t\t\tanimation = {};\n\n\t\t\tif ( !axis || axis === \"x\" ) {\n\t\t\t\tanimation.left = cur.left - this.offset.parent.left - this.margins.left +\n\t\t\t\t\t( this.offsetParent[ 0 ] === this.document[ 0 ].body ?\n\t\t\t\t\t\t0 :\n\t\t\t\t\t\tthis.offsetParent[ 0 ].scrollLeft\n\t\t\t\t\t);\n\t\t\t}\n\t\t\tif ( !axis || axis === \"y\" ) {\n\t\t\t\tanimation.top = cur.top - this.offset.parent.top - this.margins.top +\n\t\t\t\t\t( this.offsetParent[ 0 ] === this.document[ 0 ].body ?\n\t\t\t\t\t\t0 :\n\t\t\t\t\t\tthis.offsetParent[ 0 ].scrollTop\n\t\t\t\t\t);\n\t\t\t}\n\t\t\tthis.reverting = true;\n\t\t\t$( this.helper ).animate(\n\t\t\t\tanimation,\n\t\t\t\tparseInt( this.options.revert, 10 ) || 500,\n\t\t\t\tfunction() {\n\t\t\t\t\tthat._clear( event );\n\t\t\t\t}\n\t\t\t);\n\t\t} else {\n\t\t\tthis._clear( event, noPropagation );\n\t\t}\n\n\t\treturn false;\n\n\t},\n\n\tcancel: function() {\n\n\t\tif ( this.dragging ) {\n\n\t\t\tthis._mouseUp( new $.Event( \"mouseup\", { target: null } ) );\n\n\t\t\tif ( this.options.helper === \"original\" ) {\n\t\t\t\tthis.currentItem.css( this._storedCSS );\n\t\t\t\tthis._removeClass( this.currentItem, \"ui-sortable-helper\" );\n\t\t\t} else {\n\t\t\t\tthis.currentItem.show();\n\t\t\t}\n\n\t\t\t//Post deactivating events to containers\n\t\t\tfor ( var i = this.containers.length - 1; i >= 0; i-- ) {\n\t\t\t\tthis.containers[ i ]._trigger( \"deactivate\", null, this._uiHash( this ) );\n\t\t\t\tif ( this.containers[ i ].containerCache.over ) {\n\t\t\t\t\tthis.containers[ i ]._trigger( \"out\", null, this._uiHash( this ) );\n\t\t\t\t\tthis.containers[ i ].containerCache.over = 0;\n\t\t\t\t}\n\t\t\t}\n\n\t\t}\n\n\t\tif ( this.placeholder ) {\n\n\t\t\t//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately,\n\t\t\t// it unbinds ALL events from the original node!\n\t\t\tif ( this.placeholder[ 0 ].parentNode ) {\n\t\t\t\tthis.placeholder[ 0 ].parentNode.removeChild( this.placeholder[ 0 ] );\n\t\t\t}\n\t\t\tif ( this.options.helper !== \"original\" && this.helper &&\n\t\t\t\t\tthis.helper[ 0 ].parentNode ) {\n\t\t\t\tthis.helper.remove();\n\t\t\t}\n\n\t\t\t$.extend( this, {\n\t\t\t\thelper: null,\n\t\t\t\tdragging: false,\n\t\t\t\treverting: false,\n\t\t\t\t_noFinalSort: null\n\t\t\t} );\n\n\t\t\tif ( this.domPosition.prev ) {\n\t\t\t\t$( this.domPosition.prev ).after( this.currentItem );\n\t\t\t} else {\n\t\t\t\t$( this.domPosition.parent ).prepend( this.currentItem );\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\tserialize: function( o ) {\n\n\t\tvar items = this._getItemsAsjQuery( o && o.connected ),\n\t\t\tstr = [];\n\t\to = o || {};\n\n\t\t$( items ).each( function() {\n\t\t\tvar res = ( $( o.item || this ).attr( o.attribute || \"id\" ) || \"\" )\n\t\t\t\t.match( o.expression || ( /(.+)[\\-=_](.+)/ ) );\n\t\t\tif ( res ) {\n\t\t\t\tstr.push(\n\t\t\t\t\t( o.key || res[ 1 ] + \"[]\" ) +\n\t\t\t\t\t\"=\" + ( o.key && o.expression ? res[ 1 ] : res[ 2 ] ) );\n\t\t\t}\n\t\t} );\n\n\t\tif ( !str.length && o.key ) {\n\t\t\tstr.push( o.key + \"=\" );\n\t\t}\n\n\t\treturn str.join( \"&\" );\n\n\t},\n\n\ttoArray: function( o ) {\n\n\t\tvar items = this._getItemsAsjQuery( o && o.connected ),\n\t\t\tret = [];\n\n\t\to = o || {};\n\n\t\titems.each( function() {\n\t\t\tret.push( $( o.item || this ).attr( o.attribute || \"id\" ) || \"\" );\n\t\t} );\n\t\treturn ret;\n\n\t},\n\n\t/* Be careful with the following core functions */\n\t_intersectsWith: function( item ) {\n\n\t\tvar x1 = this.positionAbs.left,\n\t\t\tx2 = x1 + this.helperProportions.width,\n\t\t\ty1 = this.positionAbs.top,\n\t\t\ty2 = y1 + this.helperProportions.height,\n\t\t\tl = item.left,\n\t\t\tr = l + item.width,\n\t\t\tt = item.top,\n\t\t\tb = t + item.height,\n\t\t\tdyClick = this.offset.click.top,\n\t\t\tdxClick = this.offset.click.left,\n\t\t\tisOverElementHeight = ( this.options.axis === \"x\" ) || ( ( y1 + dyClick ) > t &&\n\t\t\t\t( y1 + dyClick ) < b ),\n\t\t\tisOverElementWidth = ( this.options.axis === \"y\" ) || ( ( x1 + dxClick ) > l &&\n\t\t\t\t( x1 + dxClick ) < r ),\n\t\t\tisOverElement = isOverElementHeight && isOverElementWidth;\n\n\t\tif ( this.options.tolerance === \"pointer\" ||\n\t\t\tthis.options.forcePointerForContainers ||\n\t\t\t( this.options.tolerance !== \"pointer\" &&\n\t\t\t\tthis.helperProportions[ this.floating ? \"width\" : \"height\" ] >\n\t\t\t\titem[ this.floating ? \"width\" : \"height\" ] )\n\t\t) {\n\t\t\treturn isOverElement;\n\t\t} else {\n\n\t\t\treturn ( l < x1 + ( this.helperProportions.width / 2 ) && // Right Half\n\t\t\t\tx2 - ( this.helperProportions.width / 2 ) < r && // Left Half\n\t\t\t\tt < y1 + ( this.helperProportions.height / 2 ) && // Bottom Half\n\t\t\t\ty2 - ( this.helperProportions.height / 2 ) < b ); // Top Half\n\n\t\t}\n\t},\n\n\t_intersectsWithPointer: function( item ) {\n\t\tvar verticalDirection, horizontalDirection,\n\t\t\tisOverElementHeight = ( this.options.axis === \"x\" ) ||\n\t\t\t\tthis._isOverAxis(\n\t\t\t\t\tthis.positionAbs.top + this.offset.click.top, item.top, item.height ),\n\t\t\tisOverElementWidth = ( this.options.axis === \"y\" ) ||\n\t\t\t\tthis._isOverAxis(\n\t\t\t\t\tthis.positionAbs.left + this.offset.click.left, item.left, item.width ),\n\t\t\tisOverElement = isOverElementHeight && isOverElementWidth;\n\n\t\tif ( !isOverElement ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tverticalDirection = this._getDragVerticalDirection();\n\t\thorizontalDirection = this._getDragHorizontalDirection();\n\n\t\treturn this.floating ?\n\t\t\t( ( horizontalDirection === \"right\" || verticalDirection === \"down\" ) ? 2 : 1 )\n\t\t\t: ( verticalDirection && ( verticalDirection === \"down\" ? 2 : 1 ) );\n\n\t},\n\n\t_intersectsWithSides: function( item ) {\n\n\t\tvar isOverBottomHalf = this._isOverAxis( this.positionAbs.top +\n\t\t\t\tthis.offset.click.top, item.top + ( item.height / 2 ), item.height ),\n\t\t\tisOverRightHalf = this._isOverAxis( this.positionAbs.left +\n\t\t\t\tthis.offset.click.left, item.left + ( item.width / 2 ), item.width ),\n\t\t\tverticalDirection = this._getDragVerticalDirection(),\n\t\t\thorizontalDirection = this._getDragHorizontalDirection();\n\n\t\tif ( this.floating && horizontalDirection ) {\n\t\t\treturn ( ( horizontalDirection === \"right\" && isOverRightHalf ) ||\n\t\t\t\t( horizontalDirection === \"left\" && !isOverRightHalf ) );\n\t\t} else {\n\t\t\treturn verticalDirection && ( ( verticalDirection === \"down\" && isOverBottomHalf ) ||\n\t\t\t\t( verticalDirection === \"up\" && !isOverBottomHalf ) );\n\t\t}\n\n\t},\n\n\t_getDragVerticalDirection: function() {\n\t\tvar delta = this.positionAbs.top - this.lastPositionAbs.top;\n\t\treturn delta !== 0 && ( delta > 0 ? \"down\" : \"up\" );\n\t},\n\n\t_getDragHorizontalDirection: function() {\n\t\tvar delta = this.positionAbs.left - this.lastPositionAbs.left;\n\t\treturn delta !== 0 && ( delta > 0 ? \"right\" : \"left\" );\n\t},\n\n\trefresh: function( event ) {\n\t\tthis._refreshItems( event );\n\t\tthis._setHandleClassName();\n\t\tthis.refreshPositions();\n\t\treturn this;\n\t},\n\n\t_connectWith: function() {\n\t\tvar options = this.options;\n\t\treturn options.connectWith.constructor === String ?\n\t\t\t[ options.connectWith ] :\n\t\t\toptions.connectWith;\n\t},\n\n\t_getItemsAsjQuery: function( connected ) {\n\n\t\tvar i, j, cur, inst,\n\t\t\titems = [],\n\t\t\tqueries = [],\n\t\t\tconnectWith = this._connectWith();\n\n\t\tif ( connectWith && connected ) {\n\t\t\tfor ( i = connectWith.length - 1; i >= 0; i-- ) {\n\t\t\t\tcur = $( connectWith[ i ], this.document[ 0 ] );\n\t\t\t\tfor ( j = cur.length - 1; j >= 0; j-- ) {\n\t\t\t\t\tinst = $.data( cur[ j ], this.widgetFullName );\n\t\t\t\t\tif ( inst && inst !== this && !inst.options.disabled ) {\n\t\t\t\t\t\tqueries.push( [ $.isFunction( inst.options.items ) ?\n\t\t\t\t\t\t\tinst.options.items.call( inst.element ) :\n\t\t\t\t\t\t\t$( inst.options.items, inst.element )\n\t\t\t\t\t\t\t\t.not( \".ui-sortable-helper\" )\n\t\t\t\t\t\t\t\t.not( \".ui-sortable-placeholder\" ), inst ] );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tqueries.push( [ $.isFunction( this.options.items ) ?\n\t\t\tthis.options.items\n\t\t\t\t.call( this.element, null, { options: this.options, item: this.currentItem } ) :\n\t\t\t$( this.options.items, this.element )\n\t\t\t\t.not( \".ui-sortable-helper\" )\n\t\t\t\t.not( \".ui-sortable-placeholder\" ), this ] );\n\n\t\tfunction addItems() {\n\t\t\titems.push( this );\n\t\t}\n\t\tfor ( i = queries.length - 1; i >= 0; i-- ) {\n\t\t\tqueries[ i ][ 0 ].each( addItems );\n\t\t}\n\n\t\treturn $( items );\n\n\t},\n\n\t_removeCurrentsFromItems: function() {\n\n\t\tvar list = this.currentItem.find( \":data(\" + this.widgetName + \"-item)\" );\n\n\t\tthis.items = $.grep( this.items, function( item ) {\n\t\t\tfor ( var j = 0; j < list.length; j++ ) {\n\t\t\t\tif ( list[ j ] === item.item[ 0 ] ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t} );\n\n\t},\n\n\t_refreshItems: function( event ) {\n\n\t\tthis.items = [];\n\t\tthis.containers = [ this ];\n\n\t\tvar i, j, cur, inst, targetData, _queries, item, queriesLength,\n\t\t\titems = this.items,\n\t\t\tqueries = [ [ $.isFunction( this.options.items ) ?\n\t\t\t\tthis.options.items.call( this.element[ 0 ], event, { item: this.currentItem } ) :\n\t\t\t\t$( this.options.items, this.element ), this ] ],\n\t\t\tconnectWith = this._connectWith();\n\n\t\t//Shouldn't be run the first time through due to massive slow-down\n\t\tif ( connectWith && this.ready ) {\n\t\t\tfor ( i = connectWith.length - 1; i >= 0; i-- ) {\n\t\t\t\tcur = $( connectWith[ i ], this.document[ 0 ] );\n\t\t\t\tfor ( j = cur.length - 1; j >= 0; j-- ) {\n\t\t\t\t\tinst = $.data( cur[ j ], this.widgetFullName );\n\t\t\t\t\tif ( inst && inst !== this && !inst.options.disabled ) {\n\t\t\t\t\t\tqueries.push( [ $.isFunction( inst.options.items ) ?\n\t\t\t\t\t\t\tinst.options.items\n\t\t\t\t\t\t\t\t.call( inst.element[ 0 ], event, { item: this.currentItem } ) :\n\t\t\t\t\t\t\t$( inst.options.items, inst.element ), inst ] );\n\t\t\t\t\t\tthis.containers.push( inst );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfor ( i = queries.length - 1; i >= 0; i-- ) {\n\t\t\ttargetData = queries[ i ][ 1 ];\n\t\t\t_queries = queries[ i ][ 0 ];\n\n\t\t\tfor ( j = 0, queriesLength = _queries.length; j < queriesLength; j++ ) {\n\t\t\t\titem = $( _queries[ j ] );\n\n\t\t\t\t// Data for target checking (mouse manager)\n\t\t\t\titem.data( this.widgetName + \"-item\", targetData );\n\n\t\t\t\titems.push( {\n\t\t\t\t\titem: item,\n\t\t\t\t\tinstance: targetData,\n\t\t\t\t\twidth: 0, height: 0,\n\t\t\t\t\tleft: 0, top: 0\n\t\t\t\t} );\n\t\t\t}\n\t\t}\n\n\t},\n\n\trefreshPositions: function( fast ) {\n\n\t\t// Determine whether items are being displayed horizontally\n\t\tthis.floating = this.items.length ?\n\t\t\tthis.options.axis === \"x\" || this._isFloating( this.items[ 0 ].item ) :\n\t\t\tfalse;\n\n\t\t//This has to be redone because due to the item being moved out/into the offsetParent,\n\t\t// the offsetParent's position will change\n\t\tif ( this.offsetParent && this.helper ) {\n\t\t\tthis.offset.parent = this._getParentOffset();\n\t\t}\n\n\t\tvar i, item, t, p;\n\n\t\tfor ( i = this.items.length - 1; i >= 0; i-- ) {\n\t\t\titem = this.items[ i ];\n\n\t\t\t//We ignore calculating positions of all connected containers when we're not over them\n\t\t\tif ( item.instance !== this.currentContainer && this.currentContainer &&\n\t\t\t\t\titem.item[ 0 ] !== this.currentItem[ 0 ] ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tt = this.options.toleranceElement ?\n\t\t\t\t$( this.options.toleranceElement, item.item ) :\n\t\t\t\titem.item;\n\n\t\t\tif ( !fast ) {\n\t\t\t\titem.width = t.outerWidth();\n\t\t\t\titem.height = t.outerHeight();\n\t\t\t}\n\n\t\t\tp = t.offset();\n\t\t\titem.left = p.left;\n\t\t\titem.top = p.top;\n\t\t}\n\n\t\tif ( this.options.custom && this.options.custom.refreshContainers ) {\n\t\t\tthis.options.custom.refreshContainers.call( this );\n\t\t} else {\n\t\t\tfor ( i = this.containers.length - 1; i >= 0; i-- ) {\n\t\t\t\tp = this.containers[ i ].element.offset();\n\t\t\t\tthis.containers[ i ].containerCache.left = p.left;\n\t\t\t\tthis.containers[ i ].containerCache.top = p.top;\n\t\t\t\tthis.containers[ i ].containerCache.width =\n\t\t\t\t\tthis.containers[ i ].element.outerWidth();\n\t\t\t\tthis.containers[ i ].containerCache.height =\n\t\t\t\t\tthis.containers[ i ].element.outerHeight();\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\t_createPlaceholder: function( that ) {\n\t\tthat = that || this;\n\t\tvar className,\n\t\t\to = that.options;\n\n\t\tif ( !o.placeholder || o.placeholder.constructor === String ) {\n\t\t\tclassName = o.placeholder;\n\t\t\to.placeholder = {\n\t\t\t\telement: function() {\n\n\t\t\t\t\tvar nodeName = that.currentItem[ 0 ].nodeName.toLowerCase(),\n\t\t\t\t\t\telement = $( \"<\" + nodeName + \">\", that.document[ 0 ] );\n\n\t\t\t\t\t\tthat._addClass( element, \"ui-sortable-placeholder\",\n\t\t\t\t\t\t\t\tclassName || that.currentItem[ 0 ].className )\n\t\t\t\t\t\t\t._removeClass( element, \"ui-sortable-helper\" );\n\n\t\t\t\t\tif ( nodeName === \"tbody\" ) {\n\t\t\t\t\t\tthat._createTrPlaceholder(\n\t\t\t\t\t\t\tthat.currentItem.find( \"tr\" ).eq( 0 ),\n\t\t\t\t\t\t\t$( \"<tr>\", that.document[ 0 ] ).appendTo( element )\n\t\t\t\t\t\t);\n\t\t\t\t\t} else if ( nodeName === \"tr\" ) {\n\t\t\t\t\t\tthat._createTrPlaceholder( that.currentItem, element );\n\t\t\t\t\t} else if ( nodeName === \"img\" ) {\n\t\t\t\t\t\telement.attr( \"src\", that.currentItem.attr( \"src\" ) );\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( !className ) {\n\t\t\t\t\t\telement.css( \"visibility\", \"hidden\" );\n\t\t\t\t\t}\n\n\t\t\t\t\treturn element;\n\t\t\t\t},\n\t\t\t\tupdate: function( container, p ) {\n\n\t\t\t\t\t// 1. If a className is set as 'placeholder option, we don't force sizes -\n\t\t\t\t\t// the class is responsible for that\n\t\t\t\t\t// 2. The option 'forcePlaceholderSize can be enabled to force it even if a\n\t\t\t\t\t// class name is specified\n\t\t\t\t\tif ( className && !o.forcePlaceholderSize ) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\t//If the element doesn't have a actual height by itself (without styles coming\n\t\t\t\t\t// from a stylesheet), it receives the inline height from the dragged item\n\t\t\t\t\tif ( !p.height() ) {\n\t\t\t\t\t\tp.height(\n\t\t\t\t\t\t\tthat.currentItem.innerHeight() -\n\t\t\t\t\t\t\tparseInt( that.currentItem.css( \"paddingTop\" ) || 0, 10 ) -\n\t\t\t\t\t\t\tparseInt( that.currentItem.css( \"paddingBottom\" ) || 0, 10 ) );\n\t\t\t\t\t}\n\t\t\t\t\tif ( !p.width() ) {\n\t\t\t\t\t\tp.width(\n\t\t\t\t\t\t\tthat.currentItem.innerWidth() -\n\t\t\t\t\t\t\tparseInt( that.currentItem.css( \"paddingLeft\" ) || 0, 10 ) -\n\t\t\t\t\t\t\tparseInt( that.currentItem.css( \"paddingRight\" ) || 0, 10 ) );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\n\t\t//Create the placeholder\n\t\tthat.placeholder = $( o.placeholder.element.call( that.element, that.currentItem ) );\n\n\t\t//Append it after the actual current item\n\t\tthat.currentItem.after( that.placeholder );\n\n\t\t//Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)\n\t\to.placeholder.update( that, that.placeholder );\n\n\t},\n\n\t_createTrPlaceholder: function( sourceTr, targetTr ) {\n\t\tvar that = this;\n\n\t\tsourceTr.children().each( function() {\n\t\t\t$( \"<td>&#160;</td>\", that.document[ 0 ] )\n\t\t\t\t.attr( \"colspan\", $( this ).attr( \"colspan\" ) || 1 )\n\t\t\t\t.appendTo( targetTr );\n\t\t} );\n\t},\n\n\t_contactContainers: function( event ) {\n\t\tvar i, j, dist, itemWithLeastDistance, posProperty, sizeProperty, cur, nearBottom,\n\t\t\tfloating, axis,\n\t\t\tinnermostContainer = null,\n\t\t\tinnermostIndex = null;\n\n\t\t// Get innermost container that intersects with item\n\t\tfor ( i = this.containers.length - 1; i >= 0; i-- ) {\n\n\t\t\t// Never consider a container that's located within the item itself\n\t\t\tif ( $.contains( this.currentItem[ 0 ], this.containers[ i ].element[ 0 ] ) ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif ( this._intersectsWith( this.containers[ i ].containerCache ) ) {\n\n\t\t\t\t// If we've already found a container and it's more \"inner\" than this, then continue\n\t\t\t\tif ( innermostContainer &&\n\t\t\t\t\t\t$.contains(\n\t\t\t\t\t\t\tthis.containers[ i ].element[ 0 ],\n\t\t\t\t\t\t\tinnermostContainer.element[ 0 ] ) ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tinnermostContainer = this.containers[ i ];\n\t\t\t\tinnermostIndex = i;\n\n\t\t\t} else {\n\n\t\t\t\t// container doesn't intersect. trigger \"out\" event if necessary\n\t\t\t\tif ( this.containers[ i ].containerCache.over ) {\n\t\t\t\t\tthis.containers[ i ]._trigger( \"out\", event, this._uiHash( this ) );\n\t\t\t\t\tthis.containers[ i ].containerCache.over = 0;\n\t\t\t\t}\n\t\t\t}\n\n\t\t}\n\n\t\t// If no intersecting containers found, return\n\t\tif ( !innermostContainer ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Move the item into the container if it's not there already\n\t\tif ( this.containers.length === 1 ) {\n\t\t\tif ( !this.containers[ innermostIndex ].containerCache.over ) {\n\t\t\t\tthis.containers[ innermostIndex ]._trigger( \"over\", event, this._uiHash( this ) );\n\t\t\t\tthis.containers[ innermostIndex ].containerCache.over = 1;\n\t\t\t}\n\t\t} else {\n\n\t\t\t// When entering a new container, we will find the item with the least distance and\n\t\t\t// append our item near it\n\t\t\tdist = 10000;\n\t\t\titemWithLeastDistance = null;\n\t\t\tfloating = innermostContainer.floating || this._isFloating( this.currentItem );\n\t\t\tposProperty = floating ? \"left\" : \"top\";\n\t\t\tsizeProperty = floating ? \"width\" : \"height\";\n\t\t\taxis = floating ? \"pageX\" : \"pageY\";\n\n\t\t\tfor ( j = this.items.length - 1; j >= 0; j-- ) {\n\t\t\t\tif ( !$.contains(\n\t\t\t\t\t\tthis.containers[ innermostIndex ].element[ 0 ], this.items[ j ].item[ 0 ] )\n\t\t\t\t) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif ( this.items[ j ].item[ 0 ] === this.currentItem[ 0 ] ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tcur = this.items[ j ].item.offset()[ posProperty ];\n\t\t\t\tnearBottom = false;\n\t\t\t\tif ( event[ axis ] - cur > this.items[ j ][ sizeProperty ] / 2 ) {\n\t\t\t\t\tnearBottom = true;\n\t\t\t\t}\n\n\t\t\t\tif ( Math.abs( event[ axis ] - cur ) < dist ) {\n\t\t\t\t\tdist = Math.abs( event[ axis ] - cur );\n\t\t\t\t\titemWithLeastDistance = this.items[ j ];\n\t\t\t\t\tthis.direction = nearBottom ? \"up\" : \"down\";\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t//Check if dropOnEmpty is enabled\n\t\t\tif ( !itemWithLeastDistance && !this.options.dropOnEmpty ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( this.currentContainer === this.containers[ innermostIndex ] ) {\n\t\t\t\tif ( !this.currentContainer.containerCache.over ) {\n\t\t\t\t\tthis.containers[ innermostIndex ]._trigger( \"over\", event, this._uiHash() );\n\t\t\t\t\tthis.currentContainer.containerCache.over = 1;\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\titemWithLeastDistance ?\n\t\t\t\tthis._rearrange( event, itemWithLeastDistance, null, true ) :\n\t\t\t\tthis._rearrange( event, null, this.containers[ innermostIndex ].element, true );\n\t\t\tthis._trigger( \"change\", event, this._uiHash() );\n\t\t\tthis.containers[ innermostIndex ]._trigger( \"change\", event, this._uiHash( this ) );\n\t\t\tthis.currentContainer = this.containers[ innermostIndex ];\n\n\t\t\t//Update the placeholder\n\t\t\tthis.options.placeholder.update( this.currentContainer, this.placeholder );\n\n\t\t\tthis.containers[ innermostIndex ]._trigger( \"over\", event, this._uiHash( this ) );\n\t\t\tthis.containers[ innermostIndex ].containerCache.over = 1;\n\t\t}\n\n\t},\n\n\t_createHelper: function( event ) {\n\n\t\tvar o = this.options,\n\t\t\thelper = $.isFunction( o.helper ) ?\n\t\t\t\t$( o.helper.apply( this.element[ 0 ], [ event, this.currentItem ] ) ) :\n\t\t\t\t( o.helper === \"clone\" ? this.currentItem.clone() : this.currentItem );\n\n\t\t//Add the helper to the DOM if that didn't happen already\n\t\tif ( !helper.parents( \"body\" ).length ) {\n\t\t\t$( o.appendTo !== \"parent\" ?\n\t\t\t\to.appendTo :\n\t\t\t\tthis.currentItem[ 0 ].parentNode )[ 0 ].appendChild( helper[ 0 ] );\n\t\t}\n\n\t\tif ( helper[ 0 ] === this.currentItem[ 0 ] ) {\n\t\t\tthis._storedCSS = {\n\t\t\t\twidth: this.currentItem[ 0 ].style.width,\n\t\t\t\theight: this.currentItem[ 0 ].style.height,\n\t\t\t\tposition: this.currentItem.css( \"position\" ),\n\t\t\t\ttop: this.currentItem.css( \"top\" ),\n\t\t\t\tleft: this.currentItem.css( \"left\" )\n\t\t\t};\n\t\t}\n\n\t\tif ( !helper[ 0 ].style.width || o.forceHelperSize ) {\n\t\t\thelper.width( this.currentItem.width() );\n\t\t}\n\t\tif ( !helper[ 0 ].style.height || o.forceHelperSize ) {\n\t\t\thelper.height( this.currentItem.height() );\n\t\t}\n\n\t\treturn helper;\n\n\t},\n\n\t_adjustOffsetFromHelper: function( obj ) {\n\t\tif ( typeof obj === \"string\" ) {\n\t\t\tobj = obj.split( \" \" );\n\t\t}\n\t\tif ( $.isArray( obj ) ) {\n\t\t\tobj = { left: +obj[ 0 ], top: +obj[ 1 ] || 0 };\n\t\t}\n\t\tif ( \"left\" in obj ) {\n\t\t\tthis.offset.click.left = obj.left + this.margins.left;\n\t\t}\n\t\tif ( \"right\" in obj ) {\n\t\t\tthis.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;\n\t\t}\n\t\tif ( \"top\" in obj ) {\n\t\t\tthis.offset.click.top = obj.top + this.margins.top;\n\t\t}\n\t\tif ( \"bottom\" in obj ) {\n\t\t\tthis.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;\n\t\t}\n\t},\n\n\t_getParentOffset: function() {\n\n\t\t//Get the offsetParent and cache its position\n\t\tthis.offsetParent = this.helper.offsetParent();\n\t\tvar po = this.offsetParent.offset();\n\n\t\t// This is a special case where we need to modify a offset calculated on start, since the\n\t\t// following happened:\n\t\t// 1. The position of the helper is absolute, so it's position is calculated based on the\n\t\t// next positioned parent\n\t\t// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't\n\t\t// the document, which means that the scroll is included in the initial calculation of the\n\t\t// offset of the parent, and never recalculated upon drag\n\t\tif ( this.cssPosition === \"absolute\" && this.scrollParent[ 0 ] !== this.document[ 0 ] &&\n\t\t\t\t$.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) {\n\t\t\tpo.left += this.scrollParent.scrollLeft();\n\t\t\tpo.top += this.scrollParent.scrollTop();\n\t\t}\n\n\t\t// This needs to be actually done for all browsers, since pageX/pageY includes this\n\t\t// information with an ugly IE fix\n\t\tif ( this.offsetParent[ 0 ] === this.document[ 0 ].body ||\n\t\t\t\t( this.offsetParent[ 0 ].tagName &&\n\t\t\t\tthis.offsetParent[ 0 ].tagName.toLowerCase() === \"html\" && $.ui.ie ) ) {\n\t\t\tpo = { top: 0, left: 0 };\n\t\t}\n\n\t\treturn {\n\t\t\ttop: po.top + ( parseInt( this.offsetParent.css( \"borderTopWidth\" ), 10 ) || 0 ),\n\t\t\tleft: po.left + ( parseInt( this.offsetParent.css( \"borderLeftWidth\" ), 10 ) || 0 )\n\t\t};\n\n\t},\n\n\t_getRelativeOffset: function() {\n\n\t\tif ( this.cssPosition === \"relative\" ) {\n\t\t\tvar p = this.currentItem.position();\n\t\t\treturn {\n\t\t\t\ttop: p.top - ( parseInt( this.helper.css( \"top\" ), 10 ) || 0 ) +\n\t\t\t\t\tthis.scrollParent.scrollTop(),\n\t\t\t\tleft: p.left - ( parseInt( this.helper.css( \"left\" ), 10 ) || 0 ) +\n\t\t\t\t\tthis.scrollParent.scrollLeft()\n\t\t\t};\n\t\t} else {\n\t\t\treturn { top: 0, left: 0 };\n\t\t}\n\n\t},\n\n\t_cacheMargins: function() {\n\t\tthis.margins = {\n\t\t\tleft: ( parseInt( this.currentItem.css( \"marginLeft\" ), 10 ) || 0 ),\n\t\t\ttop: ( parseInt( this.currentItem.css( \"marginTop\" ), 10 ) || 0 )\n\t\t};\n\t},\n\n\t_cacheHelperProportions: function() {\n\t\tthis.helperProportions = {\n\t\t\twidth: this.helper.outerWidth(),\n\t\t\theight: this.helper.outerHeight()\n\t\t};\n\t},\n\n\t_setContainment: function() {\n\n\t\tvar ce, co, over,\n\t\t\to = this.options;\n\t\tif ( o.containment === \"parent\" ) {\n\t\t\to.containment = this.helper[ 0 ].parentNode;\n\t\t}\n\t\tif ( o.containment === \"document\" || o.containment === \"window\" ) {\n\t\t\tthis.containment = [\n\t\t\t\t0 - this.offset.relative.left - this.offset.parent.left,\n\t\t\t\t0 - this.offset.relative.top - this.offset.parent.top,\n\t\t\t\to.containment === \"document\" ?\n\t\t\t\t\tthis.document.width() :\n\t\t\t\t\tthis.window.width() - this.helperProportions.width - this.margins.left,\n\t\t\t\t( o.containment === \"document\" ?\n\t\t\t\t\t( this.document.height() || document.body.parentNode.scrollHeight ) :\n\t\t\t\t\tthis.window.height() || this.document[ 0 ].body.parentNode.scrollHeight\n\t\t\t\t) - this.helperProportions.height - this.margins.top\n\t\t\t];\n\t\t}\n\n\t\tif ( !( /^(document|window|parent)$/ ).test( o.containment ) ) {\n\t\t\tce = $( o.containment )[ 0 ];\n\t\t\tco = $( o.containment ).offset();\n\t\t\tover = ( $( ce ).css( \"overflow\" ) !== \"hidden\" );\n\n\t\t\tthis.containment = [\n\t\t\t\tco.left + ( parseInt( $( ce ).css( \"borderLeftWidth\" ), 10 ) || 0 ) +\n\t\t\t\t\t( parseInt( $( ce ).css( \"paddingLeft\" ), 10 ) || 0 ) - this.margins.left,\n\t\t\t\tco.top + ( parseInt( $( ce ).css( \"borderTopWidth\" ), 10 ) || 0 ) +\n\t\t\t\t\t( parseInt( $( ce ).css( \"paddingTop\" ), 10 ) || 0 ) - this.margins.top,\n\t\t\t\tco.left + ( over ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) -\n\t\t\t\t\t( parseInt( $( ce ).css( \"borderLeftWidth\" ), 10 ) || 0 ) -\n\t\t\t\t\t( parseInt( $( ce ).css( \"paddingRight\" ), 10 ) || 0 ) -\n\t\t\t\t\tthis.helperProportions.width - this.margins.left,\n\t\t\t\tco.top + ( over ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) -\n\t\t\t\t\t( parseInt( $( ce ).css( \"borderTopWidth\" ), 10 ) || 0 ) -\n\t\t\t\t\t( parseInt( $( ce ).css( \"paddingBottom\" ), 10 ) || 0 ) -\n\t\t\t\t\tthis.helperProportions.height - this.margins.top\n\t\t\t];\n\t\t}\n\n\t},\n\n\t_convertPositionTo: function( d, pos ) {\n\n\t\tif ( !pos ) {\n\t\t\tpos = this.position;\n\t\t}\n\t\tvar mod = d === \"absolute\" ? 1 : -1,\n\t\t\tscroll = this.cssPosition === \"absolute\" &&\n\t\t\t\t!( this.scrollParent[ 0 ] !== this.document[ 0 ] &&\n\t\t\t\t$.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ?\n\t\t\t\t\tthis.offsetParent :\n\t\t\t\t\tthis.scrollParent,\n\t\t\tscrollIsRootNode = ( /(html|body)/i ).test( scroll[ 0 ].tagName );\n\n\t\treturn {\n\t\t\ttop: (\n\n\t\t\t\t// The absolute mouse position\n\t\t\t\tpos.top\t+\n\n\t\t\t\t// Only for relative positioned nodes: Relative offset from element to offset parent\n\t\t\t\tthis.offset.relative.top * mod +\n\n\t\t\t\t// The offsetParent's offset without borders (offset + border)\n\t\t\t\tthis.offset.parent.top * mod -\n\t\t\t\t( ( this.cssPosition === \"fixed\" ?\n\t\t\t\t\t-this.scrollParent.scrollTop() :\n\t\t\t\t\t( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod )\n\t\t\t),\n\t\t\tleft: (\n\n\t\t\t\t// The absolute mouse position\n\t\t\t\tpos.left +\n\n\t\t\t\t// Only for relative positioned nodes: Relative offset from element to offset parent\n\t\t\t\tthis.offset.relative.left * mod +\n\n\t\t\t\t// The offsetParent's offset without borders (offset + border)\n\t\t\t\tthis.offset.parent.left * mod\t-\n\t\t\t\t( ( this.cssPosition === \"fixed\" ?\n\t\t\t\t\t-this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 :\n\t\t\t\t\tscroll.scrollLeft() ) * mod )\n\t\t\t)\n\t\t};\n\n\t},\n\n\t_generatePosition: function( event ) {\n\n\t\tvar top, left,\n\t\t\to = this.options,\n\t\t\tpageX = event.pageX,\n\t\t\tpageY = event.pageY,\n\t\t\tscroll = this.cssPosition === \"absolute\" &&\n\t\t\t\t!( this.scrollParent[ 0 ] !== this.document[ 0 ] &&\n\t\t\t\t$.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ?\n\t\t\t\t\tthis.offsetParent :\n\t\t\t\t\tthis.scrollParent,\n\t\t\t\tscrollIsRootNode = ( /(html|body)/i ).test( scroll[ 0 ].tagName );\n\n\t\t// This is another very weird special case that only happens for relative elements:\n\t\t// 1. If the css position is relative\n\t\t// 2. and the scroll parent is the document or similar to the offset parent\n\t\t// we have to refresh the relative offset during the scroll so there are no jumps\n\t\tif ( this.cssPosition === \"relative\" && !( this.scrollParent[ 0 ] !== this.document[ 0 ] &&\n\t\t\t\tthis.scrollParent[ 0 ] !== this.offsetParent[ 0 ] ) ) {\n\t\t\tthis.offset.relative = this._getRelativeOffset();\n\t\t}\n\n\t\t/*\n\t\t * - Position constraining -\n\t\t * Constrain the position to a mix of grid, containment.\n\t\t */\n\n\t\tif ( this.originalPosition ) { //If we are not dragging yet, we won't check for options\n\n\t\t\tif ( this.containment ) {\n\t\t\t\tif ( event.pageX - this.offset.click.left < this.containment[ 0 ] ) {\n\t\t\t\t\tpageX = this.containment[ 0 ] + this.offset.click.left;\n\t\t\t\t}\n\t\t\t\tif ( event.pageY - this.offset.click.top < this.containment[ 1 ] ) {\n\t\t\t\t\tpageY = this.containment[ 1 ] + this.offset.click.top;\n\t\t\t\t}\n\t\t\t\tif ( event.pageX - this.offset.click.left > this.containment[ 2 ] ) {\n\t\t\t\t\tpageX = this.containment[ 2 ] + this.offset.click.left;\n\t\t\t\t}\n\t\t\t\tif ( event.pageY - this.offset.click.top > this.containment[ 3 ] ) {\n\t\t\t\t\tpageY = this.containment[ 3 ] + this.offset.click.top;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( o.grid ) {\n\t\t\t\ttop = this.originalPageY + Math.round( ( pageY - this.originalPageY ) /\n\t\t\t\t\to.grid[ 1 ] ) * o.grid[ 1 ];\n\t\t\t\tpageY = this.containment ?\n\t\t\t\t\t( ( top - this.offset.click.top >= this.containment[ 1 ] &&\n\t\t\t\t\t\ttop - this.offset.click.top <= this.containment[ 3 ] ) ?\n\t\t\t\t\t\t\ttop :\n\t\t\t\t\t\t\t( ( top - this.offset.click.top >= this.containment[ 1 ] ) ?\n\t\t\t\t\t\t\t\ttop - o.grid[ 1 ] : top + o.grid[ 1 ] ) ) :\n\t\t\t\t\t\t\t\ttop;\n\n\t\t\t\tleft = this.originalPageX + Math.round( ( pageX - this.originalPageX ) /\n\t\t\t\t\to.grid[ 0 ] ) * o.grid[ 0 ];\n\t\t\t\tpageX = this.containment ?\n\t\t\t\t\t( ( left - this.offset.click.left >= this.containment[ 0 ] &&\n\t\t\t\t\t\tleft - this.offset.click.left <= this.containment[ 2 ] ) ?\n\t\t\t\t\t\t\tleft :\n\t\t\t\t\t\t\t( ( left - this.offset.click.left >= this.containment[ 0 ] ) ?\n\t\t\t\t\t\t\t\tleft - o.grid[ 0 ] : left + o.grid[ 0 ] ) ) :\n\t\t\t\t\t\t\t\tleft;\n\t\t\t}\n\n\t\t}\n\n\t\treturn {\n\t\t\ttop: (\n\n\t\t\t\t// The absolute mouse position\n\t\t\t\tpageY -\n\n\t\t\t\t// Click offset (relative to the element)\n\t\t\t\tthis.offset.click.top -\n\n\t\t\t\t// Only for relative positioned nodes: Relative offset from element to offset parent\n\t\t\t\tthis.offset.relative.top -\n\n\t\t\t\t// The offsetParent's offset without borders (offset + border)\n\t\t\t\tthis.offset.parent.top +\n\t\t\t\t( ( this.cssPosition === \"fixed\" ?\n\t\t\t\t\t-this.scrollParent.scrollTop() :\n\t\t\t\t\t( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) )\n\t\t\t),\n\t\t\tleft: (\n\n\t\t\t\t// The absolute mouse position\n\t\t\t\tpageX -\n\n\t\t\t\t// Click offset (relative to the element)\n\t\t\t\tthis.offset.click.left -\n\n\t\t\t\t// Only for relative positioned nodes: Relative offset from element to offset parent\n\t\t\t\tthis.offset.relative.left -\n\n\t\t\t\t// The offsetParent's offset without borders (offset + border)\n\t\t\t\tthis.offset.parent.left +\n\t\t\t\t( ( this.cssPosition === \"fixed\" ?\n\t\t\t\t\t-this.scrollParent.scrollLeft() :\n\t\t\t\t\tscrollIsRootNode ? 0 : scroll.scrollLeft() ) )\n\t\t\t)\n\t\t};\n\n\t},\n\n\t_rearrange: function( event, i, a, hardRefresh ) {\n\n\t\ta ? a[ 0 ].appendChild( this.placeholder[ 0 ] ) :\n\t\t\ti.item[ 0 ].parentNode.insertBefore( this.placeholder[ 0 ],\n\t\t\t\t( this.direction === \"down\" ? i.item[ 0 ] : i.item[ 0 ].nextSibling ) );\n\n\t\t//Various things done here to improve the performance:\n\t\t// 1. we create a setTimeout, that calls refreshPositions\n\t\t// 2. on the instance, we have a counter variable, that get's higher after every append\n\t\t// 3. on the local scope, we copy the counter variable, and check in the timeout,\n\t\t// if it's still the same\n\t\t// 4. this lets only the last addition to the timeout stack through\n\t\tthis.counter = this.counter ? ++this.counter : 1;\n\t\tvar counter = this.counter;\n\n\t\tthis._delay( function() {\n\t\t\tif ( counter === this.counter ) {\n\n\t\t\t\t//Precompute after each DOM insertion, NOT on mousemove\n\t\t\t\tthis.refreshPositions( !hardRefresh );\n\t\t\t}\n\t\t} );\n\n\t},\n\n\t_clear: function( event, noPropagation ) {\n\n\t\tthis.reverting = false;\n\n\t\t// We delay all events that have to be triggered to after the point where the placeholder\n\t\t// has been removed and everything else normalized again\n\t\tvar i,\n\t\t\tdelayedTriggers = [];\n\n\t\t// We first have to update the dom position of the actual currentItem\n\t\t// Note: don't do it if the current item is already removed (by a user), or it gets\n\t\t// reappended (see #4088)\n\t\tif ( !this._noFinalSort && this.currentItem.parent().length ) {\n\t\t\tthis.placeholder.before( this.currentItem );\n\t\t}\n\t\tthis._noFinalSort = null;\n\n\t\tif ( this.helper[ 0 ] === this.currentItem[ 0 ] ) {\n\t\t\tfor ( i in this._storedCSS ) {\n\t\t\t\tif ( this._storedCSS[ i ] === \"auto\" || this._storedCSS[ i ] === \"static\" ) {\n\t\t\t\t\tthis._storedCSS[ i ] = \"\";\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.currentItem.css( this._storedCSS );\n\t\t\tthis._removeClass( this.currentItem, \"ui-sortable-helper\" );\n\t\t} else {\n\t\t\tthis.currentItem.show();\n\t\t}\n\n\t\tif ( this.fromOutside && !noPropagation ) {\n\t\t\tdelayedTriggers.push( function( event ) {\n\t\t\t\tthis._trigger( \"receive\", event, this._uiHash( this.fromOutside ) );\n\t\t\t} );\n\t\t}\n\t\tif ( ( this.fromOutside ||\n\t\t\t\tthis.domPosition.prev !==\n\t\t\t\tthis.currentItem.prev().not( \".ui-sortable-helper\" )[ 0 ] ||\n\t\t\t\tthis.domPosition.parent !== this.currentItem.parent()[ 0 ] ) && !noPropagation ) {\n\n\t\t\t// Trigger update callback if the DOM position has changed\n\t\t\tdelayedTriggers.push( function( event ) {\n\t\t\t\tthis._trigger( \"update\", event, this._uiHash() );\n\t\t\t} );\n\t\t}\n\n\t\t// Check if the items Container has Changed and trigger appropriate\n\t\t// events.\n\t\tif ( this !== this.currentContainer ) {\n\t\t\tif ( !noPropagation ) {\n\t\t\t\tdelayedTriggers.push( function( event ) {\n\t\t\t\t\tthis._trigger( \"remove\", event, this._uiHash() );\n\t\t\t\t} );\n\t\t\t\tdelayedTriggers.push( ( function( c ) {\n\t\t\t\t\treturn function( event ) {\n\t\t\t\t\t\tc._trigger( \"receive\", event, this._uiHash( this ) );\n\t\t\t\t\t};\n\t\t\t\t} ).call( this, this.currentContainer ) );\n\t\t\t\tdelayedTriggers.push( ( function( c ) {\n\t\t\t\t\treturn function( event ) {\n\t\t\t\t\t\tc._trigger( \"update\", event, this._uiHash( this ) );\n\t\t\t\t\t};\n\t\t\t\t} ).call( this, this.currentContainer ) );\n\t\t\t}\n\t\t}\n\n\t\t//Post events to containers\n\t\tfunction delayEvent( type, instance, container ) {\n\t\t\treturn function( event ) {\n\t\t\t\tcontainer._trigger( type, event, instance._uiHash( instance ) );\n\t\t\t};\n\t\t}\n\t\tfor ( i = this.containers.length - 1; i >= 0; i-- ) {\n\t\t\tif ( !noPropagation ) {\n\t\t\t\tdelayedTriggers.push( delayEvent( \"deactivate\", this, this.containers[ i ] ) );\n\t\t\t}\n\t\t\tif ( this.containers[ i ].containerCache.over ) {\n\t\t\t\tdelayedTriggers.push( delayEvent( \"out\", this, this.containers[ i ] ) );\n\t\t\t\tthis.containers[ i ].containerCache.over = 0;\n\t\t\t}\n\t\t}\n\n\t\t//Do what was originally in plugins\n\t\tif ( this.storedCursor ) {\n\t\t\tthis.document.find( \"body\" ).css( \"cursor\", this.storedCursor );\n\t\t\tthis.storedStylesheet.remove();\n\t\t}\n\t\tif ( this._storedOpacity ) {\n\t\t\tthis.helper.css( \"opacity\", this._storedOpacity );\n\t\t}\n\t\tif ( this._storedZIndex ) {\n\t\t\tthis.helper.css( \"zIndex\", this._storedZIndex === \"auto\" ? \"\" : this._storedZIndex );\n\t\t}\n\n\t\tthis.dragging = false;\n\n\t\tif ( !noPropagation ) {\n\t\t\tthis._trigger( \"beforeStop\", event, this._uiHash() );\n\t\t}\n\n\t\t//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately,\n\t\t// it unbinds ALL events from the original node!\n\t\tthis.placeholder[ 0 ].parentNode.removeChild( this.placeholder[ 0 ] );\n\n\t\tif ( !this.cancelHelperRemoval ) {\n\t\t\tif ( this.helper[ 0 ] !== this.currentItem[ 0 ] ) {\n\t\t\t\tthis.helper.remove();\n\t\t\t}\n\t\t\tthis.helper = null;\n\t\t}\n\n\t\tif ( !noPropagation ) {\n\t\t\tfor ( i = 0; i < delayedTriggers.length; i++ ) {\n\n\t\t\t\t// Trigger all delayed events\n\t\t\t\tdelayedTriggers[ i ].call( this, event );\n\t\t\t}\n\t\t\tthis._trigger( \"stop\", event, this._uiHash() );\n\t\t}\n\n\t\tthis.fromOutside = false;\n\t\treturn !this.cancelHelperRemoval;\n\n\t},\n\n\t_trigger: function() {\n\t\tif ( $.Widget.prototype._trigger.apply( this, arguments ) === false ) {\n\t\t\tthis.cancel();\n\t\t}\n\t},\n\n\t_uiHash: function( _inst ) {\n\t\tvar inst = _inst || this;\n\t\treturn {\n\t\t\thelper: inst.helper,\n\t\t\tplaceholder: inst.placeholder || $( [] ),\n\t\t\tposition: inst.position,\n\t\t\toriginalPosition: inst.originalPosition,\n\t\t\toffset: inst.positionAbs,\n\t\t\titem: inst.currentItem,\n\t\t\tsender: _inst ? _inst.element : null\n\t\t};\n\t}\n\n} );\n\n\n/*!\n * jQuery UI Menu 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Menu\n//>>group: Widgets\n//>>description: Creates nestable menus.\n//>>docs: http://api.jqueryui.com/menu/\n//>>demos: http://jqueryui.com/menu/\n//>>css.structure: ../../themes/base/core.css\n//>>css.structure: ../../themes/base/menu.css\n//>>css.theme: ../../themes/base/theme.css\n\n\n\nvar widgetsMenu = $.widget( \"ui.menu\", {\n\tversion: \"1.12.1\",\n\tdefaultElement: \"<ul>\",\n\tdelay: 300,\n\toptions: {\n\t\ticons: {\n\t\t\tsubmenu: \"ui-icon-caret-1-e\"\n\t\t},\n\t\titems: \"> *\",\n\t\tmenus: \"ul\",\n\t\tposition: {\n\t\t\tmy: \"left top\",\n\t\t\tat: \"right top\"\n\t\t},\n\t\trole: \"menu\",\n\n\t\t// Callbacks\n\t\tblur: null,\n\t\tfocus: null,\n\t\tselect: null\n\t},\n\n\t_create: function() {\n\t\tthis.activeMenu = this.element;\n\n\t\t// Flag used to prevent firing of the click handler\n\t\t// as the event bubbles up through nested menus\n\t\tthis.mouseHandled = false;\n\t\tthis.element\n\t\t\t.uniqueId()\n\t\t\t.attr( {\n\t\t\t\trole: this.options.role,\n\t\t\t\ttabIndex: 0\n\t\t\t} );\n\n\t\tthis._addClass( \"ui-menu\", \"ui-widget ui-widget-content\" );\n\t\tthis._on( {\n\n\t\t\t// Prevent focus from sticking to links inside menu after clicking\n\t\t\t// them (focus should always stay on UL during navigation).\n\t\t\t\"mousedown .ui-menu-item\": function( event ) {\n\t\t\t\tevent.preventDefault();\n\t\t\t},\n\t\t\t\"click .ui-menu-item\": function( event ) {\n\t\t\t\tvar target = $( event.target );\n\t\t\t\tvar active = $( $.ui.safeActiveElement( this.document[ 0 ] ) );\n\t\t\t\tif ( !this.mouseHandled && target.not( \".ui-state-disabled\" ).length ) {\n\t\t\t\t\tthis.select( event );\n\n\t\t\t\t\t// Only set the mouseHandled flag if the event will bubble, see #9469.\n\t\t\t\t\tif ( !event.isPropagationStopped() ) {\n\t\t\t\t\t\tthis.mouseHandled = true;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Open submenu on click\n\t\t\t\t\tif ( target.has( \".ui-menu\" ).length ) {\n\t\t\t\t\t\tthis.expand( event );\n\t\t\t\t\t} else if ( !this.element.is( \":focus\" ) &&\n\t\t\t\t\t\t\tactive.closest( \".ui-menu\" ).length ) {\n\n\t\t\t\t\t\t// Redirect focus to the menu\n\t\t\t\t\t\tthis.element.trigger( \"focus\", [ true ] );\n\n\t\t\t\t\t\t// If the active item is on the top level, let it stay active.\n\t\t\t\t\t\t// Otherwise, blur the active item since it is no longer visible.\n\t\t\t\t\t\tif ( this.active && this.active.parents( \".ui-menu\" ).length === 1 ) {\n\t\t\t\t\t\t\tclearTimeout( this.timer );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"mouseenter .ui-menu-item\": function( event ) {\n\n\t\t\t\t// Ignore mouse events while typeahead is active, see #10458.\n\t\t\t\t// Prevents focusing the wrong item when typeahead causes a scroll while the mouse\n\t\t\t\t// is over an item in the menu\n\t\t\t\tif ( this.previousFilter ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tvar actualTarget = $( event.target ).closest( \".ui-menu-item\" ),\n\t\t\t\t\ttarget = $( event.currentTarget );\n\n\t\t\t\t// Ignore bubbled events on parent items, see #11641\n\t\t\t\tif ( actualTarget[ 0 ] !== target[ 0 ] ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// Remove ui-state-active class from siblings of the newly focused menu item\n\t\t\t\t// to avoid a jump caused by adjacent elements both having a class with a border\n\t\t\t\tthis._removeClass( target.siblings().children( \".ui-state-active\" ),\n\t\t\t\t\tnull, \"ui-state-active\" );\n\t\t\t\tthis.focus( event, target );\n\t\t\t},\n\t\t\tmouseleave: \"collapseAll\",\n\t\t\t\"mouseleave .ui-menu\": \"collapseAll\",\n\t\t\tfocus: function( event, keepActiveItem ) {\n\n\t\t\t\t// If there's already an active item, keep it active\n\t\t\t\t// If not, activate the first item\n\t\t\t\tvar item = this.active || this.element.find( this.options.items ).eq( 0 );\n\n\t\t\t\tif ( !keepActiveItem ) {\n\t\t\t\t\tthis.focus( event, item );\n\t\t\t\t}\n\t\t\t},\n\t\t\tblur: function( event ) {\n\t\t\t\tthis._delay( function() {\n\t\t\t\t\tvar notContained = !$.contains(\n\t\t\t\t\t\tthis.element[ 0 ],\n\t\t\t\t\t\t$.ui.safeActiveElement( this.document[ 0 ] )\n\t\t\t\t\t);\n\t\t\t\t\tif ( notContained ) {\n\t\t\t\t\t\tthis.collapseAll( event );\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t},\n\t\t\tkeydown: \"_keydown\"\n\t\t} );\n\n\t\tthis.refresh();\n\n\t\t// Clicks outside of a menu collapse any open menus\n\t\tthis._on( this.document, {\n\t\t\tclick: function( event ) {\n\t\t\t\tif ( this._closeOnDocumentClick( event ) ) {\n\t\t\t\t\tthis.collapseAll( event );\n\t\t\t\t}\n\n\t\t\t\t// Reset the mouseHandled flag\n\t\t\t\tthis.mouseHandled = false;\n\t\t\t}\n\t\t} );\n\t},\n\n\t_destroy: function() {\n\t\tvar items = this.element.find( \".ui-menu-item\" )\n\t\t\t\t.removeAttr( \"role aria-disabled\" ),\n\t\t\tsubmenus = items.children( \".ui-menu-item-wrapper\" )\n\t\t\t\t.removeUniqueId()\n\t\t\t\t.removeAttr( \"tabIndex role aria-haspopup\" );\n\n\t\t// Destroy (sub)menus\n\t\tthis.element\n\t\t\t.removeAttr( \"aria-activedescendant\" )\n\t\t\t.find( \".ui-menu\" ).addBack()\n\t\t\t\t.removeAttr( \"role aria-labelledby aria-expanded aria-hidden aria-disabled \" +\n\t\t\t\t\t\"tabIndex\" )\n\t\t\t\t.removeUniqueId()\n\t\t\t\t.show();\n\n\t\tsubmenus.children().each( function() {\n\t\t\tvar elem = $( this );\n\t\t\tif ( elem.data( \"ui-menu-submenu-caret\" ) ) {\n\t\t\t\telem.remove();\n\t\t\t}\n\t\t} );\n\t},\n\n\t_keydown: function( event ) {\n\t\tvar match, prev, character, skip,\n\t\t\tpreventDefault = true;\n\n\t\tswitch ( event.keyCode ) {\n\t\tcase $.ui.keyCode.PAGE_UP:\n\t\t\tthis.previousPage( event );\n\t\t\tbreak;\n\t\tcase $.ui.keyCode.PAGE_DOWN:\n\t\t\tthis.nextPage( event );\n\t\t\tbreak;\n\t\tcase $.ui.keyCode.HOME:\n\t\t\tthis._move( \"first\", \"first\", event );\n\t\t\tbreak;\n\t\tcase $.ui.keyCode.END:\n\t\t\tthis._move( \"last\", \"last\", event );\n\t\t\tbreak;\n\t\tcase $.ui.keyCode.UP:\n\t\t\tthis.previous( event );\n\t\t\tbreak;\n\t\tcase $.ui.keyCode.DOWN:\n\t\t\tthis.next( event );\n\t\t\tbreak;\n\t\tcase $.ui.keyCode.LEFT:\n\t\t\tthis.collapse( event );\n\t\t\tbreak;\n\t\tcase $.ui.keyCode.RIGHT:\n\t\t\tif ( this.active && !this.active.is( \".ui-state-disabled\" ) ) {\n\t\t\t\tthis.expand( event );\n\t\t\t}\n\t\t\tbreak;\n\t\tcase $.ui.keyCode.ENTER:\n\t\tcase $.ui.keyCode.SPACE:\n\t\t\tthis._activate( event );\n\t\t\tbreak;\n\t\tcase $.ui.keyCode.ESCAPE:\n\t\t\tthis.collapse( event );\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tpreventDefault = false;\n\t\t\tprev = this.previousFilter || \"\";\n\t\t\tskip = false;\n\n\t\t\t// Support number pad values\n\t\t\tcharacter = event.keyCode >= 96 && event.keyCode <= 105 ?\n\t\t\t\t( event.keyCode - 96 ).toString() : String.fromCharCode( event.keyCode );\n\n\t\t\tclearTimeout( this.filterTimer );\n\n\t\t\tif ( character === prev ) {\n\t\t\t\tskip = true;\n\t\t\t} else {\n\t\t\t\tcharacter = prev + character;\n\t\t\t}\n\n\t\t\tmatch = this._filterMenuItems( character );\n\t\t\tmatch = skip && match.index( this.active.next() ) !== -1 ?\n\t\t\t\tthis.active.nextAll( \".ui-menu-item\" ) :\n\t\t\t\tmatch;\n\n\t\t\t// If no matches on the current filter, reset to the last character pressed\n\t\t\t// to move down the menu to the first item that starts with that character\n\t\t\tif ( !match.length ) {\n\t\t\t\tcharacter = String.fromCharCode( event.keyCode );\n\t\t\t\tmatch = this._filterMenuItems( character );\n\t\t\t}\n\n\t\t\tif ( match.length ) {\n\t\t\t\tthis.focus( event, match );\n\t\t\t\tthis.previousFilter = character;\n\t\t\t\tthis.filterTimer = this._delay( function() {\n\t\t\t\t\tdelete this.previousFilter;\n\t\t\t\t}, 1000 );\n\t\t\t} else {\n\t\t\t\tdelete this.previousFilter;\n\t\t\t}\n\t\t}\n\n\t\tif ( preventDefault ) {\n\t\t\tevent.preventDefault();\n\t\t}\n\t},\n\n\t_activate: function( event ) {\n\t\tif ( this.active && !this.active.is( \".ui-state-disabled\" ) ) {\n\t\t\tif ( this.active.children( \"[aria-haspopup='true']\" ).length ) {\n\t\t\t\tthis.expand( event );\n\t\t\t} else {\n\t\t\t\tthis.select( event );\n\t\t\t}\n\t\t}\n\t},\n\n\trefresh: function() {\n\t\tvar menus, items, newSubmenus, newItems, newWrappers,\n\t\t\tthat = this,\n\t\t\ticon = this.options.icons.submenu,\n\t\t\tsubmenus = this.element.find( this.options.menus );\n\n\t\tthis._toggleClass( \"ui-menu-icons\", null, !!this.element.find( \".ui-icon\" ).length );\n\n\t\t// Initialize nested menus\n\t\tnewSubmenus = submenus.filter( \":not(.ui-menu)\" )\n\t\t\t.hide()\n\t\t\t.attr( {\n\t\t\t\trole: this.options.role,\n\t\t\t\t\"aria-hidden\": \"true\",\n\t\t\t\t\"aria-expanded\": \"false\"\n\t\t\t} )\n\t\t\t.each( function() {\n\t\t\t\tvar menu = $( this ),\n\t\t\t\t\titem = menu.prev(),\n\t\t\t\t\tsubmenuCaret = $( \"<span>\" ).data( \"ui-menu-submenu-caret\", true );\n\n\t\t\t\tthat._addClass( submenuCaret, \"ui-menu-icon\", \"ui-icon \" + icon );\n\t\t\t\titem\n\t\t\t\t\t.attr( \"aria-haspopup\", \"true\" )\n\t\t\t\t\t.prepend( submenuCaret );\n\t\t\t\tmenu.attr( \"aria-labelledby\", item.attr( \"id\" ) );\n\t\t\t} );\n\n\t\tthis._addClass( newSubmenus, \"ui-menu\", \"ui-widget ui-widget-content ui-front\" );\n\n\t\tmenus = submenus.add( this.element );\n\t\titems = menus.find( this.options.items );\n\n\t\t// Initialize menu-items containing spaces and/or dashes only as dividers\n\t\titems.not( \".ui-menu-item\" ).each( function() {\n\t\t\tvar item = $( this );\n\t\t\tif ( that._isDivider( item ) ) {\n\t\t\t\tthat._addClass( item, \"ui-menu-divider\", \"ui-widget-content\" );\n\t\t\t}\n\t\t} );\n\n\t\t// Don't refresh list items that are already adapted\n\t\tnewItems = items.not( \".ui-menu-item, .ui-menu-divider\" );\n\t\tnewWrappers = newItems.children()\n\t\t\t.not( \".ui-menu\" )\n\t\t\t\t.uniqueId()\n\t\t\t\t.attr( {\n\t\t\t\t\ttabIndex: -1,\n\t\t\t\t\trole: this._itemRole()\n\t\t\t\t} );\n\t\tthis._addClass( newItems, \"ui-menu-item\" )\n\t\t\t._addClass( newWrappers, \"ui-menu-item-wrapper\" );\n\n\t\t// Add aria-disabled attribute to any disabled menu item\n\t\titems.filter( \".ui-state-disabled\" ).attr( \"aria-disabled\", \"true\" );\n\n\t\t// If the active item has been removed, blur the menu\n\t\tif ( this.active && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {\n\t\t\tthis.blur();\n\t\t}\n\t},\n\n\t_itemRole: function() {\n\t\treturn {\n\t\t\tmenu: \"menuitem\",\n\t\t\tlistbox: \"option\"\n\t\t}[ this.options.role ];\n\t},\n\n\t_setOption: function( key, value ) {\n\t\tif ( key === \"icons\" ) {\n\t\t\tvar icons = this.element.find( \".ui-menu-icon\" );\n\t\t\tthis._removeClass( icons, null, this.options.icons.submenu )\n\t\t\t\t._addClass( icons, null, value.submenu );\n\t\t}\n\t\tthis._super( key, value );\n\t},\n\n\t_setOptionDisabled: function( value ) {\n\t\tthis._super( value );\n\n\t\tthis.element.attr( \"aria-disabled\", String( value ) );\n\t\tthis._toggleClass( null, \"ui-state-disabled\", !!value );\n\t},\n\n\tfocus: function( event, item ) {\n\t\tvar nested, focused, activeParent;\n\t\tthis.blur( event, event && event.type === \"focus\" );\n\n\t\tthis._scrollIntoView( item );\n\n\t\tthis.active = item.first();\n\n\t\tfocused = this.active.children( \".ui-menu-item-wrapper\" );\n\t\tthis._addClass( focused, null, \"ui-state-active\" );\n\n\t\t// Only update aria-activedescendant if there's a role\n\t\t// otherwise we assume focus is managed elsewhere\n\t\tif ( this.options.role ) {\n\t\t\tthis.element.attr( \"aria-activedescendant\", focused.attr( \"id\" ) );\n\t\t}\n\n\t\t// Highlight active parent menu item, if any\n\t\tactiveParent = this.active\n\t\t\t.parent()\n\t\t\t\t.closest( \".ui-menu-item\" )\n\t\t\t\t\t.children( \".ui-menu-item-wrapper\" );\n\t\tthis._addClass( activeParent, null, \"ui-state-active\" );\n\n\t\tif ( event && event.type === \"keydown\" ) {\n\t\t\tthis._close();\n\t\t} else {\n\t\t\tthis.timer = this._delay( function() {\n\t\t\t\tthis._close();\n\t\t\t}, this.delay );\n\t\t}\n\n\t\tnested = item.children( \".ui-menu\" );\n\t\tif ( nested.length && event && ( /^mouse/.test( event.type ) ) ) {\n\t\t\tthis._startOpening( nested );\n\t\t}\n\t\tthis.activeMenu = item.parent();\n\n\t\tthis._trigger( \"focus\", event, { item: item } );\n\t},\n\n\t_scrollIntoView: function( item ) {\n\t\tvar borderTop, paddingTop, offset, scroll, elementHeight, itemHeight;\n\t\tif ( this._hasScroll() ) {\n\t\t\tborderTop = parseFloat( $.css( this.activeMenu[ 0 ], \"borderTopWidth\" ) ) || 0;\n\t\t\tpaddingTop = parseFloat( $.css( this.activeMenu[ 0 ], \"paddingTop\" ) ) || 0;\n\t\t\toffset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop;\n\t\t\tscroll = this.activeMenu.scrollTop();\n\t\t\telementHeight = this.activeMenu.height();\n\t\t\titemHeight = item.outerHeight();\n\n\t\t\tif ( offset < 0 ) {\n\t\t\t\tthis.activeMenu.scrollTop( scroll + offset );\n\t\t\t} else if ( offset + itemHeight > elementHeight ) {\n\t\t\t\tthis.activeMenu.scrollTop( scroll + offset - elementHeight + itemHeight );\n\t\t\t}\n\t\t}\n\t},\n\n\tblur: function( event, fromFocus ) {\n\t\tif ( !fromFocus ) {\n\t\t\tclearTimeout( this.timer );\n\t\t}\n\n\t\tif ( !this.active ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis._removeClass( this.active.children( \".ui-menu-item-wrapper\" ),\n\t\t\tnull, \"ui-state-active\" );\n\n\t\tthis._trigger( \"blur\", event, { item: this.active } );\n\t\tthis.active = null;\n\t},\n\n\t_startOpening: function( submenu ) {\n\t\tclearTimeout( this.timer );\n\n\t\t// Don't open if already open fixes a Firefox bug that caused a .5 pixel\n\t\t// shift in the submenu position when mousing over the caret icon\n\t\tif ( submenu.attr( \"aria-hidden\" ) !== \"true\" ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.timer = this._delay( function() {\n\t\t\tthis._close();\n\t\t\tthis._open( submenu );\n\t\t}, this.delay );\n\t},\n\n\t_open: function( submenu ) {\n\t\tvar position = $.extend( {\n\t\t\tof: this.active\n\t\t}, this.options.position );\n\n\t\tclearTimeout( this.timer );\n\t\tthis.element.find( \".ui-menu\" ).not( submenu.parents( \".ui-menu\" ) )\n\t\t\t.hide()\n\t\t\t.attr( \"aria-hidden\", \"true\" );\n\n\t\tsubmenu\n\t\t\t.show()\n\t\t\t.removeAttr( \"aria-hidden\" )\n\t\t\t.attr( \"aria-expanded\", \"true\" )\n\t\t\t.position( position );\n\t},\n\n\tcollapseAll: function( event, all ) {\n\t\tclearTimeout( this.timer );\n\t\tthis.timer = this._delay( function() {\n\n\t\t\t// If we were passed an event, look for the submenu that contains the event\n\t\t\tvar currentMenu = all ? this.element :\n\t\t\t\t$( event && event.target ).closest( this.element.find( \".ui-menu\" ) );\n\n\t\t\t// If we found no valid submenu ancestor, use the main menu to close all\n\t\t\t// sub menus anyway\n\t\t\tif ( !currentMenu.length ) {\n\t\t\t\tcurrentMenu = this.element;\n\t\t\t}\n\n\t\t\tthis._close( currentMenu );\n\n\t\t\tthis.blur( event );\n\n\t\t\t// Work around active item staying active after menu is blurred\n\t\t\tthis._removeClass( currentMenu.find( \".ui-state-active\" ), null, \"ui-state-active\" );\n\n\t\t\tthis.activeMenu = currentMenu;\n\t\t}, this.delay );\n\t},\n\n\t// With no arguments, closes the currently active menu - if nothing is active\n\t// it closes all menus.  If passed an argument, it will search for menus BELOW\n\t_close: function( startMenu ) {\n\t\tif ( !startMenu ) {\n\t\t\tstartMenu = this.active ? this.active.parent() : this.element;\n\t\t}\n\n\t\tstartMenu.find( \".ui-menu\" )\n\t\t\t.hide()\n\t\t\t.attr( \"aria-hidden\", \"true\" )\n\t\t\t.attr( \"aria-expanded\", \"false\" );\n\t},\n\n\t_closeOnDocumentClick: function( event ) {\n\t\treturn !$( event.target ).closest( \".ui-menu\" ).length;\n\t},\n\n\t_isDivider: function( item ) {\n\n\t\t// Match hyphen, em dash, en dash\n\t\treturn !/[^\\-\\u2014\\u2013\\s]/.test( item.text() );\n\t},\n\n\tcollapse: function( event ) {\n\t\tvar newItem = this.active &&\n\t\t\tthis.active.parent().closest( \".ui-menu-item\", this.element );\n\t\tif ( newItem && newItem.length ) {\n\t\t\tthis._close();\n\t\t\tthis.focus( event, newItem );\n\t\t}\n\t},\n\n\texpand: function( event ) {\n\t\tvar newItem = this.active &&\n\t\t\tthis.active\n\t\t\t\t.children( \".ui-menu \" )\n\t\t\t\t\t.find( this.options.items )\n\t\t\t\t\t\t.first();\n\n\t\tif ( newItem && newItem.length ) {\n\t\t\tthis._open( newItem.parent() );\n\n\t\t\t// Delay so Firefox will not hide activedescendant change in expanding submenu from AT\n\t\t\tthis._delay( function() {\n\t\t\t\tthis.focus( event, newItem );\n\t\t\t} );\n\t\t}\n\t},\n\n\tnext: function( event ) {\n\t\tthis._move( \"next\", \"first\", event );\n\t},\n\n\tprevious: function( event ) {\n\t\tthis._move( \"prev\", \"last\", event );\n\t},\n\n\tisFirstItem: function() {\n\t\treturn this.active && !this.active.prevAll( \".ui-menu-item\" ).length;\n\t},\n\n\tisLastItem: function() {\n\t\treturn this.active && !this.active.nextAll( \".ui-menu-item\" ).length;\n\t},\n\n\t_move: function( direction, filter, event ) {\n\t\tvar next;\n\t\tif ( this.active ) {\n\t\t\tif ( direction === \"first\" || direction === \"last\" ) {\n\t\t\t\tnext = this.active\n\t\t\t\t\t[ direction === \"first\" ? \"prevAll\" : \"nextAll\" ]( \".ui-menu-item\" )\n\t\t\t\t\t.eq( -1 );\n\t\t\t} else {\n\t\t\t\tnext = this.active\n\t\t\t\t\t[ direction + \"All\" ]( \".ui-menu-item\" )\n\t\t\t\t\t.eq( 0 );\n\t\t\t}\n\t\t}\n\t\tif ( !next || !next.length || !this.active ) {\n\t\t\tnext = this.activeMenu.find( this.options.items )[ filter ]();\n\t\t}\n\n\t\tthis.focus( event, next );\n\t},\n\n\tnextPage: function( event ) {\n\t\tvar item, base, height;\n\n\t\tif ( !this.active ) {\n\t\t\tthis.next( event );\n\t\t\treturn;\n\t\t}\n\t\tif ( this.isLastItem() ) {\n\t\t\treturn;\n\t\t}\n\t\tif ( this._hasScroll() ) {\n\t\t\tbase = this.active.offset().top;\n\t\t\theight = this.element.height();\n\t\t\tthis.active.nextAll( \".ui-menu-item\" ).each( function() {\n\t\t\t\titem = $( this );\n\t\t\t\treturn item.offset().top - base - height < 0;\n\t\t\t} );\n\n\t\t\tthis.focus( event, item );\n\t\t} else {\n\t\t\tthis.focus( event, this.activeMenu.find( this.options.items )\n\t\t\t\t[ !this.active ? \"first\" : \"last\" ]() );\n\t\t}\n\t},\n\n\tpreviousPage: function( event ) {\n\t\tvar item, base, height;\n\t\tif ( !this.active ) {\n\t\t\tthis.next( event );\n\t\t\treturn;\n\t\t}\n\t\tif ( this.isFirstItem() ) {\n\t\t\treturn;\n\t\t}\n\t\tif ( this._hasScroll() ) {\n\t\t\tbase = this.active.offset().top;\n\t\t\theight = this.element.height();\n\t\t\tthis.active.prevAll( \".ui-menu-item\" ).each( function() {\n\t\t\t\titem = $( this );\n\t\t\t\treturn item.offset().top - base + height > 0;\n\t\t\t} );\n\n\t\t\tthis.focus( event, item );\n\t\t} else {\n\t\t\tthis.focus( event, this.activeMenu.find( this.options.items ).first() );\n\t\t}\n\t},\n\n\t_hasScroll: function() {\n\t\treturn this.element.outerHeight() < this.element.prop( \"scrollHeight\" );\n\t},\n\n\tselect: function( event ) {\n\n\t\t// TODO: It should never be possible to not have an active item at this\n\t\t// point, but the tests don't trigger mouseenter before click.\n\t\tthis.active = this.active || $( event.target ).closest( \".ui-menu-item\" );\n\t\tvar ui = { item: this.active };\n\t\tif ( !this.active.has( \".ui-menu\" ).length ) {\n\t\t\tthis.collapseAll( event, true );\n\t\t}\n\t\tthis._trigger( \"select\", event, ui );\n\t},\n\n\t_filterMenuItems: function( character ) {\n\t\tvar escapedCharacter = character.replace( /[\\-\\[\\]{}()*+?.,\\\\\\^$|#\\s]/g, \"\\\\$&\" ),\n\t\t\tregex = new RegExp( \"^\" + escapedCharacter, \"i\" );\n\n\t\treturn this.activeMenu\n\t\t\t.find( this.options.items )\n\n\t\t\t\t// Only match on items, not dividers or other content (#10571)\n\t\t\t\t.filter( \".ui-menu-item\" )\n\t\t\t\t\t.filter( function() {\n\t\t\t\t\t\treturn regex.test(\n\t\t\t\t\t\t\t$.trim( $( this ).children( \".ui-menu-item-wrapper\" ).text() ) );\n\t\t\t\t\t} );\n\t}\n} );\n\n\n/*!\n * jQuery UI Autocomplete 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Autocomplete\n//>>group: Widgets\n//>>description: Lists suggested words as the user is typing.\n//>>docs: http://api.jqueryui.com/autocomplete/\n//>>demos: http://jqueryui.com/autocomplete/\n//>>css.structure: ../../themes/base/core.css\n//>>css.structure: ../../themes/base/autocomplete.css\n//>>css.theme: ../../themes/base/theme.css\n\n\n\n$.widget( \"ui.autocomplete\", {\n\tversion: \"1.12.1\",\n\tdefaultElement: \"<input>\",\n\toptions: {\n\t\tappendTo: null,\n\t\tautoFocus: false,\n\t\tdelay: 300,\n\t\tminLength: 1,\n\t\tposition: {\n\t\t\tmy: \"left top\",\n\t\t\tat: \"left bottom\",\n\t\t\tcollision: \"none\"\n\t\t},\n\t\tsource: null,\n\n\t\t// Callbacks\n\t\tchange: null,\n\t\tclose: null,\n\t\tfocus: null,\n\t\topen: null,\n\t\tresponse: null,\n\t\tsearch: null,\n\t\tselect: null\n\t},\n\n\trequestIndex: 0,\n\tpending: 0,\n\n\t_create: function() {\n\n\t\t// Some browsers only repeat keydown events, not keypress events,\n\t\t// so we use the suppressKeyPress flag to determine if we've already\n\t\t// handled the keydown event. #7269\n\t\t// Unfortunately the code for & in keypress is the same as the up arrow,\n\t\t// so we use the suppressKeyPressRepeat flag to avoid handling keypress\n\t\t// events when we know the keydown event was used to modify the\n\t\t// search term. #7799\n\t\tvar suppressKeyPress, suppressKeyPressRepeat, suppressInput,\n\t\t\tnodeName = this.element[ 0 ].nodeName.toLowerCase(),\n\t\t\tisTextarea = nodeName === \"textarea\",\n\t\t\tisInput = nodeName === \"input\";\n\n\t\t// Textareas are always multi-line\n\t\t// Inputs are always single-line, even if inside a contentEditable element\n\t\t// IE also treats inputs as contentEditable\n\t\t// All other element types are determined by whether or not they're contentEditable\n\t\tthis.isMultiLine = isTextarea || !isInput && this._isContentEditable( this.element );\n\n\t\tthis.valueMethod = this.element[ isTextarea || isInput ? \"val\" : \"text\" ];\n\t\tthis.isNewMenu = true;\n\n\t\tthis._addClass( \"ui-autocomplete-input\" );\n\t\tthis.element.attr( \"autocomplete\", \"off\" );\n\n\t\tthis._on( this.element, {\n\t\t\tkeydown: function( event ) {\n\t\t\t\tif ( this.element.prop( \"readOnly\" ) ) {\n\t\t\t\t\tsuppressKeyPress = true;\n\t\t\t\t\tsuppressInput = true;\n\t\t\t\t\tsuppressKeyPressRepeat = true;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tsuppressKeyPress = false;\n\t\t\t\tsuppressInput = false;\n\t\t\t\tsuppressKeyPressRepeat = false;\n\t\t\t\tvar keyCode = $.ui.keyCode;\n\t\t\t\tswitch ( event.keyCode ) {\n\t\t\t\tcase keyCode.PAGE_UP:\n\t\t\t\t\tsuppressKeyPress = true;\n\t\t\t\t\tthis._move( \"previousPage\", event );\n\t\t\t\t\tbreak;\n\t\t\t\tcase keyCode.PAGE_DOWN:\n\t\t\t\t\tsuppressKeyPress = true;\n\t\t\t\t\tthis._move( \"nextPage\", event );\n\t\t\t\t\tbreak;\n\t\t\t\tcase keyCode.UP:\n\t\t\t\t\tsuppressKeyPress = true;\n\t\t\t\t\tthis._keyEvent( \"previous\", event );\n\t\t\t\t\tbreak;\n\t\t\t\tcase keyCode.DOWN:\n\t\t\t\t\tsuppressKeyPress = true;\n\t\t\t\t\tthis._keyEvent( \"next\", event );\n\t\t\t\t\tbreak;\n\t\t\t\tcase keyCode.ENTER:\n\n\t\t\t\t\t// when menu is open and has focus\n\t\t\t\t\tif ( this.menu.active ) {\n\n\t\t\t\t\t\t// #6055 - Opera still allows the keypress to occur\n\t\t\t\t\t\t// which causes forms to submit\n\t\t\t\t\t\tsuppressKeyPress = true;\n\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\tthis.menu.select( event );\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase keyCode.TAB:\n\t\t\t\t\tif ( this.menu.active ) {\n\t\t\t\t\t\tthis.menu.select( event );\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase keyCode.ESCAPE:\n\t\t\t\t\tif ( this.menu.element.is( \":visible\" ) ) {\n\t\t\t\t\t\tif ( !this.isMultiLine ) {\n\t\t\t\t\t\t\tthis._value( this.term );\n\t\t\t\t\t\t}\n\t\t\t\t\t\tthis.close( event );\n\n\t\t\t\t\t\t// Different browsers have different default behavior for escape\n\t\t\t\t\t\t// Single press can mean undo or clear\n\t\t\t\t\t\t// Double press in IE means clear the whole form\n\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tsuppressKeyPressRepeat = true;\n\n\t\t\t\t\t// search timeout should be triggered before the input value is changed\n\t\t\t\t\tthis._searchTimeout( event );\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t},\n\t\t\tkeypress: function( event ) {\n\t\t\t\tif ( suppressKeyPress ) {\n\t\t\t\t\tsuppressKeyPress = false;\n\t\t\t\t\tif ( !this.isMultiLine || this.menu.element.is( \":visible\" ) ) {\n\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif ( suppressKeyPressRepeat ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// Replicate some key handlers to allow them to repeat in Firefox and Opera\n\t\t\t\tvar keyCode = $.ui.keyCode;\n\t\t\t\tswitch ( event.keyCode ) {\n\t\t\t\tcase keyCode.PAGE_UP:\n\t\t\t\t\tthis._move( \"previousPage\", event );\n\t\t\t\t\tbreak;\n\t\t\t\tcase keyCode.PAGE_DOWN:\n\t\t\t\t\tthis._move( \"nextPage\", event );\n\t\t\t\t\tbreak;\n\t\t\t\tcase keyCode.UP:\n\t\t\t\t\tthis._keyEvent( \"previous\", event );\n\t\t\t\t\tbreak;\n\t\t\t\tcase keyCode.DOWN:\n\t\t\t\t\tthis._keyEvent( \"next\", event );\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t},\n\t\t\tinput: function( event ) {\n\t\t\t\tif ( suppressInput ) {\n\t\t\t\t\tsuppressInput = false;\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tthis._searchTimeout( event );\n\t\t\t},\n\t\t\tfocus: function() {\n\t\t\t\tthis.selectedItem = null;\n\t\t\t\tthis.previous = this._value();\n\t\t\t},\n\t\t\tblur: function( event ) {\n\t\t\t\tif ( this.cancelBlur ) {\n\t\t\t\t\tdelete this.cancelBlur;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tclearTimeout( this.searching );\n\t\t\t\tthis.close( event );\n\t\t\t\tthis._change( event );\n\t\t\t}\n\t\t} );\n\n\t\tthis._initSource();\n\t\tthis.menu = $( \"<ul>\" )\n\t\t\t.appendTo( this._appendTo() )\n\t\t\t.menu( {\n\n\t\t\t\t// disable ARIA support, the live region takes care of that\n\t\t\t\trole: null\n\t\t\t} )\n\t\t\t.hide()\n\t\t\t.menu( \"instance\" );\n\n\t\tthis._addClass( this.menu.element, \"ui-autocomplete\", \"ui-front\" );\n\t\tthis._on( this.menu.element, {\n\t\t\tmousedown: function( event ) {\n\n\t\t\t\t// prevent moving focus out of the text field\n\t\t\t\tevent.preventDefault();\n\n\t\t\t\t// IE doesn't prevent moving focus even with event.preventDefault()\n\t\t\t\t// so we set a flag to know when we should ignore the blur event\n\t\t\t\tthis.cancelBlur = true;\n\t\t\t\tthis._delay( function() {\n\t\t\t\t\tdelete this.cancelBlur;\n\n\t\t\t\t\t// Support: IE 8 only\n\t\t\t\t\t// Right clicking a menu item or selecting text from the menu items will\n\t\t\t\t\t// result in focus moving out of the input. However, we've already received\n\t\t\t\t\t// and ignored the blur event because of the cancelBlur flag set above. So\n\t\t\t\t\t// we restore focus to ensure that the menu closes properly based on the user's\n\t\t\t\t\t// next actions.\n\t\t\t\t\tif ( this.element[ 0 ] !== $.ui.safeActiveElement( this.document[ 0 ] ) ) {\n\t\t\t\t\t\tthis.element.trigger( \"focus\" );\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t},\n\t\t\tmenufocus: function( event, ui ) {\n\t\t\t\tvar label, item;\n\n\t\t\t\t// support: Firefox\n\t\t\t\t// Prevent accidental activation of menu items in Firefox (#7024 #9118)\n\t\t\t\tif ( this.isNewMenu ) {\n\t\t\t\t\tthis.isNewMenu = false;\n\t\t\t\t\tif ( event.originalEvent && /^mouse/.test( event.originalEvent.type ) ) {\n\t\t\t\t\t\tthis.menu.blur();\n\n\t\t\t\t\t\tthis.document.one( \"mousemove\", function() {\n\t\t\t\t\t\t\t$( event.target ).trigger( event.originalEvent );\n\t\t\t\t\t\t} );\n\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\titem = ui.item.data( \"ui-autocomplete-item\" );\n\t\t\t\tif ( false !== this._trigger( \"focus\", event, { item: item } ) ) {\n\n\t\t\t\t\t// use value to match what will end up in the input, if it was a key event\n\t\t\t\t\tif ( event.originalEvent && /^key/.test( event.originalEvent.type ) ) {\n\t\t\t\t\t\tthis._value( item.value );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Announce the value in the liveRegion\n\t\t\t\tlabel = ui.item.attr( \"aria-label\" ) || item.value;\n\t\t\t\tif ( label && $.trim( label ).length ) {\n\t\t\t\t\tthis.liveRegion.children().hide();\n\t\t\t\t\t$( \"<div>\" ).text( label ).appendTo( this.liveRegion );\n\t\t\t\t}\n\t\t\t},\n\t\t\tmenuselect: function( event, ui ) {\n\t\t\t\tvar item = ui.item.data( \"ui-autocomplete-item\" ),\n\t\t\t\t\tprevious = this.previous;\n\n\t\t\t\t// Only trigger when focus was lost (click on menu)\n\t\t\t\tif ( this.element[ 0 ] !== $.ui.safeActiveElement( this.document[ 0 ] ) ) {\n\t\t\t\t\tthis.element.trigger( \"focus\" );\n\t\t\t\t\tthis.previous = previous;\n\n\t\t\t\t\t// #6109 - IE triggers two focus events and the second\n\t\t\t\t\t// is asynchronous, so we need to reset the previous\n\t\t\t\t\t// term synchronously and asynchronously :-(\n\t\t\t\t\tthis._delay( function() {\n\t\t\t\t\t\tthis.previous = previous;\n\t\t\t\t\t\tthis.selectedItem = item;\n\t\t\t\t\t} );\n\t\t\t\t}\n\n\t\t\t\tif ( false !== this._trigger( \"select\", event, { item: item } ) ) {\n\t\t\t\t\tthis._value( item.value );\n\t\t\t\t}\n\n\t\t\t\t// reset the term after the select event\n\t\t\t\t// this allows custom select handling to work properly\n\t\t\t\tthis.term = this._value();\n\n\t\t\t\tthis.close( event );\n\t\t\t\tthis.selectedItem = item;\n\t\t\t}\n\t\t} );\n\n\t\tthis.liveRegion = $( \"<div>\", {\n\t\t\trole: \"status\",\n\t\t\t\"aria-live\": \"assertive\",\n\t\t\t\"aria-relevant\": \"additions\"\n\t\t} )\n\t\t\t.appendTo( this.document[ 0 ].body );\n\n\t\tthis._addClass( this.liveRegion, null, \"ui-helper-hidden-accessible\" );\n\n\t\t// Turning off autocomplete prevents the browser from remembering the\n\t\t// value when navigating through history, so we re-enable autocomplete\n\t\t// if the page is unloaded before the widget is destroyed. #7790\n\t\tthis._on( this.window, {\n\t\t\tbeforeunload: function() {\n\t\t\t\tthis.element.removeAttr( \"autocomplete\" );\n\t\t\t}\n\t\t} );\n\t},\n\n\t_destroy: function() {\n\t\tclearTimeout( this.searching );\n\t\tthis.element.removeAttr( \"autocomplete\" );\n\t\tthis.menu.element.remove();\n\t\tthis.liveRegion.remove();\n\t},\n\n\t_setOption: function( key, value ) {\n\t\tthis._super( key, value );\n\t\tif ( key === \"source\" ) {\n\t\t\tthis._initSource();\n\t\t}\n\t\tif ( key === \"appendTo\" ) {\n\t\t\tthis.menu.element.appendTo( this._appendTo() );\n\t\t}\n\t\tif ( key === \"disabled\" && value && this.xhr ) {\n\t\t\tthis.xhr.abort();\n\t\t}\n\t},\n\n\t_isEventTargetInWidget: function( event ) {\n\t\tvar menuElement = this.menu.element[ 0 ];\n\n\t\treturn event.target === this.element[ 0 ] ||\n\t\t\tevent.target === menuElement ||\n\t\t\t$.contains( menuElement, event.target );\n\t},\n\n\t_closeOnClickOutside: function( event ) {\n\t\tif ( !this._isEventTargetInWidget( event ) ) {\n\t\t\tthis.close();\n\t\t}\n\t},\n\n\t_appendTo: function() {\n\t\tvar element = this.options.appendTo;\n\n\t\tif ( element ) {\n\t\t\telement = element.jquery || element.nodeType ?\n\t\t\t\t$( element ) :\n\t\t\t\tthis.document.find( element ).eq( 0 );\n\t\t}\n\n\t\tif ( !element || !element[ 0 ] ) {\n\t\t\telement = this.element.closest( \".ui-front, dialog\" );\n\t\t}\n\n\t\tif ( !element.length ) {\n\t\t\telement = this.document[ 0 ].body;\n\t\t}\n\n\t\treturn element;\n\t},\n\n\t_initSource: function() {\n\t\tvar array, url,\n\t\t\tthat = this;\n\t\tif ( $.isArray( this.options.source ) ) {\n\t\t\tarray = this.options.source;\n\t\t\tthis.source = function( request, response ) {\n\t\t\t\tresponse( $.ui.autocomplete.filter( array, request.term ) );\n\t\t\t};\n\t\t} else if ( typeof this.options.source === \"string\" ) {\n\t\t\turl = this.options.source;\n\t\t\tthis.source = function( request, response ) {\n\t\t\t\tif ( that.xhr ) {\n\t\t\t\t\tthat.xhr.abort();\n\t\t\t\t}\n\t\t\t\tthat.xhr = $.ajax( {\n\t\t\t\t\turl: url,\n\t\t\t\t\tdata: request,\n\t\t\t\t\tdataType: \"json\",\n\t\t\t\t\tsuccess: function( data ) {\n\t\t\t\t\t\tresponse( data );\n\t\t\t\t\t},\n\t\t\t\t\terror: function() {\n\t\t\t\t\t\tresponse( [] );\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t};\n\t\t} else {\n\t\t\tthis.source = this.options.source;\n\t\t}\n\t},\n\n\t_searchTimeout: function( event ) {\n\t\tclearTimeout( this.searching );\n\t\tthis.searching = this._delay( function() {\n\n\t\t\t// Search if the value has changed, or if the user retypes the same value (see #7434)\n\t\t\tvar equalValues = this.term === this._value(),\n\t\t\t\tmenuVisible = this.menu.element.is( \":visible\" ),\n\t\t\t\tmodifierKey = event.altKey || event.ctrlKey || event.metaKey || event.shiftKey;\n\n\t\t\tif ( !equalValues || ( equalValues && !menuVisible && !modifierKey ) ) {\n\t\t\t\tthis.selectedItem = null;\n\t\t\t\tthis.search( null, event );\n\t\t\t}\n\t\t}, this.options.delay );\n\t},\n\n\tsearch: function( value, event ) {\n\t\tvalue = value != null ? value : this._value();\n\n\t\t// Always save the actual value, not the one passed as an argument\n\t\tthis.term = this._value();\n\n\t\tif ( value.length < this.options.minLength ) {\n\t\t\treturn this.close( event );\n\t\t}\n\n\t\tif ( this._trigger( \"search\", event ) === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\treturn this._search( value );\n\t},\n\n\t_search: function( value ) {\n\t\tthis.pending++;\n\t\tthis._addClass( \"ui-autocomplete-loading\" );\n\t\tthis.cancelSearch = false;\n\n\t\tthis.source( { term: value }, this._response() );\n\t},\n\n\t_response: function() {\n\t\tvar index = ++this.requestIndex;\n\n\t\treturn $.proxy( function( content ) {\n\t\t\tif ( index === this.requestIndex ) {\n\t\t\t\tthis.__response( content );\n\t\t\t}\n\n\t\t\tthis.pending--;\n\t\t\tif ( !this.pending ) {\n\t\t\t\tthis._removeClass( \"ui-autocomplete-loading\" );\n\t\t\t}\n\t\t}, this );\n\t},\n\n\t__response: function( content ) {\n\t\tif ( content ) {\n\t\t\tcontent = this._normalize( content );\n\t\t}\n\t\tthis._trigger( \"response\", null, { content: content } );\n\t\tif ( !this.options.disabled && content && content.length && !this.cancelSearch ) {\n\t\t\tthis._suggest( content );\n\t\t\tthis._trigger( \"open\" );\n\t\t} else {\n\n\t\t\t// use ._close() instead of .close() so we don't cancel future searches\n\t\t\tthis._close();\n\t\t}\n\t},\n\n\tclose: function( event ) {\n\t\tthis.cancelSearch = true;\n\t\tthis._close( event );\n\t},\n\n\t_close: function( event ) {\n\n\t\t// Remove the handler that closes the menu on outside clicks\n\t\tthis._off( this.document, \"mousedown\" );\n\n\t\tif ( this.menu.element.is( \":visible\" ) ) {\n\t\t\tthis.menu.element.hide();\n\t\t\tthis.menu.blur();\n\t\t\tthis.isNewMenu = true;\n\t\t\tthis._trigger( \"close\", event );\n\t\t}\n\t},\n\n\t_change: function( event ) {\n\t\tif ( this.previous !== this._value() ) {\n\t\t\tthis._trigger( \"change\", event, { item: this.selectedItem } );\n\t\t}\n\t},\n\n\t_normalize: function( items ) {\n\n\t\t// assume all items have the right format when the first item is complete\n\t\tif ( items.length && items[ 0 ].label && items[ 0 ].value ) {\n\t\t\treturn items;\n\t\t}\n\t\treturn $.map( items, function( item ) {\n\t\t\tif ( typeof item === \"string\" ) {\n\t\t\t\treturn {\n\t\t\t\t\tlabel: item,\n\t\t\t\t\tvalue: item\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn $.extend( {}, item, {\n\t\t\t\tlabel: item.label || item.value,\n\t\t\t\tvalue: item.value || item.label\n\t\t\t} );\n\t\t} );\n\t},\n\n\t_suggest: function( items ) {\n\t\tvar ul = this.menu.element.empty();\n\t\tthis._renderMenu( ul, items );\n\t\tthis.isNewMenu = true;\n\t\tthis.menu.refresh();\n\n\t\t// Size and position menu\n\t\tul.show();\n\t\tthis._resizeMenu();\n\t\tul.position( $.extend( {\n\t\t\tof: this.element\n\t\t}, this.options.position ) );\n\n\t\tif ( this.options.autoFocus ) {\n\t\t\tthis.menu.next();\n\t\t}\n\n\t\t// Listen for interactions outside of the widget (#6642)\n\t\tthis._on( this.document, {\n\t\t\tmousedown: \"_closeOnClickOutside\"\n\t\t} );\n\t},\n\n\t_resizeMenu: function() {\n\t\tvar ul = this.menu.element;\n\t\tul.outerWidth( Math.max(\n\n\t\t\t// Firefox wraps long text (possibly a rounding bug)\n\t\t\t// so we add 1px to avoid the wrapping (#7513)\n\t\t\tul.width( \"\" ).outerWidth() + 1,\n\t\t\tthis.element.outerWidth()\n\t\t) );\n\t},\n\n\t_renderMenu: function( ul, items ) {\n\t\tvar that = this;\n\t\t$.each( items, function( index, item ) {\n\t\t\tthat._renderItemData( ul, item );\n\t\t} );\n\t},\n\n\t_renderItemData: function( ul, item ) {\n\t\treturn this._renderItem( ul, item ).data( \"ui-autocomplete-item\", item );\n\t},\n\n\t_renderItem: function( ul, item ) {\n\t\treturn $( \"<li>\" )\n\t\t\t.append( $( \"<div>\" ).text( item.label ) )\n\t\t\t.appendTo( ul );\n\t},\n\n\t_move: function( direction, event ) {\n\t\tif ( !this.menu.element.is( \":visible\" ) ) {\n\t\t\tthis.search( null, event );\n\t\t\treturn;\n\t\t}\n\t\tif ( this.menu.isFirstItem() && /^previous/.test( direction ) ||\n\t\t\t\tthis.menu.isLastItem() && /^next/.test( direction ) ) {\n\n\t\t\tif ( !this.isMultiLine ) {\n\t\t\t\tthis._value( this.term );\n\t\t\t}\n\n\t\t\tthis.menu.blur();\n\t\t\treturn;\n\t\t}\n\t\tthis.menu[ direction ]( event );\n\t},\n\n\twidget: function() {\n\t\treturn this.menu.element;\n\t},\n\n\t_value: function() {\n\t\treturn this.valueMethod.apply( this.element, arguments );\n\t},\n\n\t_keyEvent: function( keyEvent, event ) {\n\t\tif ( !this.isMultiLine || this.menu.element.is( \":visible\" ) ) {\n\t\t\tthis._move( keyEvent, event );\n\n\t\t\t// Prevents moving cursor to beginning/end of the text field in some browsers\n\t\t\tevent.preventDefault();\n\t\t}\n\t},\n\n\t// Support: Chrome <=50\n\t// We should be able to just use this.element.prop( \"isContentEditable\" )\n\t// but hidden elements always report false in Chrome.\n\t// https://code.google.com/p/chromium/issues/detail?id=313082\n\t_isContentEditable: function( element ) {\n\t\tif ( !element.length ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tvar editable = element.prop( \"contentEditable\" );\n\n\t\tif ( editable === \"inherit\" ) {\n\t\t  return this._isContentEditable( element.parent() );\n\t\t}\n\n\t\treturn editable === \"true\";\n\t}\n} );\n\n$.extend( $.ui.autocomplete, {\n\tescapeRegex: function( value ) {\n\t\treturn value.replace( /[\\-\\[\\]{}()*+?.,\\\\\\^$|#\\s]/g, \"\\\\$&\" );\n\t},\n\tfilter: function( array, term ) {\n\t\tvar matcher = new RegExp( $.ui.autocomplete.escapeRegex( term ), \"i\" );\n\t\treturn $.grep( array, function( value ) {\n\t\t\treturn matcher.test( value.label || value.value || value );\n\t\t} );\n\t}\n} );\n\n// Live region extension, adding a `messages` option\n// NOTE: This is an experimental API. We are still investigating\n// a full solution for string manipulation and internationalization.\n$.widget( \"ui.autocomplete\", $.ui.autocomplete, {\n\toptions: {\n\t\tmessages: {\n\t\t\tnoResults: \"No search results.\",\n\t\t\tresults: function( amount ) {\n\t\t\t\treturn amount + ( amount > 1 ? \" results are\" : \" result is\" ) +\n\t\t\t\t\t\" available, use up and down arrow keys to navigate.\";\n\t\t\t}\n\t\t}\n\t},\n\n\t__response: function( content ) {\n\t\tvar message;\n\t\tthis._superApply( arguments );\n\t\tif ( this.options.disabled || this.cancelSearch ) {\n\t\t\treturn;\n\t\t}\n\t\tif ( content && content.length ) {\n\t\t\tmessage = this.options.messages.results( content.length );\n\t\t} else {\n\t\t\tmessage = this.options.messages.noResults;\n\t\t}\n\t\tthis.liveRegion.children().hide();\n\t\t$( \"<div>\" ).text( message ).appendTo( this.liveRegion );\n\t}\n} );\n\nvar widgetsAutocomplete = $.ui.autocomplete;\n\n\n// jscs:disable maximumLineLength\n/* jscs:disable requireCamelCaseOrUpperCaseIdentifiers */\n/*!\n * jQuery UI Datepicker 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Datepicker\n//>>group: Widgets\n//>>description: Displays a calendar from an input or inline for selecting dates.\n//>>docs: http://api.jqueryui.com/datepicker/\n//>>demos: http://jqueryui.com/datepicker/\n//>>css.structure: ../../themes/base/core.css\n//>>css.structure: ../../themes/base/datepicker.css\n//>>css.theme: ../../themes/base/theme.css\n\n\n\n$.extend( $.ui, { datepicker: { version: \"1.12.1\" } } );\n\nvar datepicker_instActive;\n\nfunction datepicker_getZindex( elem ) {\n\tvar position, value;\n\twhile ( elem.length && elem[ 0 ] !== document ) {\n\n\t\t// Ignore z-index if position is set to a value where z-index is ignored by the browser\n\t\t// This makes behavior of this function consistent across browsers\n\t\t// WebKit always returns auto if the element is positioned\n\t\tposition = elem.css( \"position\" );\n\t\tif ( position === \"absolute\" || position === \"relative\" || position === \"fixed\" ) {\n\n\t\t\t// IE returns 0 when zIndex is not specified\n\t\t\t// other browsers return a string\n\t\t\t// we ignore the case of nested elements with an explicit value of 0\n\t\t\t// <div style=\"z-index: -10;\"><div style=\"z-index: 0;\"></div></div>\n\t\t\tvalue = parseInt( elem.css( \"zIndex\" ), 10 );\n\t\t\tif ( !isNaN( value ) && value !== 0 ) {\n\t\t\t\treturn value;\n\t\t\t}\n\t\t}\n\t\telem = elem.parent();\n\t}\n\n\treturn 0;\n}\n/* Date picker manager.\n   Use the singleton instance of this class, $.datepicker, to interact with the date picker.\n   Settings for (groups of) date pickers are maintained in an instance object,\n   allowing multiple different settings on the same page. */\n\nfunction Datepicker() {\n\tthis._curInst = null; // The current instance in use\n\tthis._keyEvent = false; // If the last event was a key event\n\tthis._disabledInputs = []; // List of date picker inputs that have been disabled\n\tthis._datepickerShowing = false; // True if the popup picker is showing , false if not\n\tthis._inDialog = false; // True if showing within a \"dialog\", false if not\n\tthis._mainDivId = \"ui-datepicker-div\"; // The ID of the main datepicker division\n\tthis._inlineClass = \"ui-datepicker-inline\"; // The name of the inline marker class\n\tthis._appendClass = \"ui-datepicker-append\"; // The name of the append marker class\n\tthis._triggerClass = \"ui-datepicker-trigger\"; // The name of the trigger marker class\n\tthis._dialogClass = \"ui-datepicker-dialog\"; // The name of the dialog marker class\n\tthis._disableClass = \"ui-datepicker-disabled\"; // The name of the disabled covering marker class\n\tthis._unselectableClass = \"ui-datepicker-unselectable\"; // The name of the unselectable cell marker class\n\tthis._currentClass = \"ui-datepicker-current-day\"; // The name of the current day marker class\n\tthis._dayOverClass = \"ui-datepicker-days-cell-over\"; // The name of the day hover marker class\n\tthis.regional = []; // Available regional settings, indexed by language code\n\tthis.regional[ \"\" ] = { // Default regional settings\n\t\tcloseText: \"Done\", // Display text for close link\n\t\tprevText: \"Prev\", // Display text for previous month link\n\t\tnextText: \"Next\", // Display text for next month link\n\t\tcurrentText: \"Today\", // Display text for current month link\n\t\tmonthNames: [ \"January\",\"February\",\"March\",\"April\",\"May\",\"June\",\n\t\t\t\"July\",\"August\",\"September\",\"October\",\"November\",\"December\" ], // Names of months for drop-down and formatting\n\t\tmonthNamesShort: [ \"Jan\", \"Feb\", \"Mar\", \"Apr\", \"May\", \"Jun\", \"Jul\", \"Aug\", \"Sep\", \"Oct\", \"Nov\", \"Dec\" ], // For formatting\n\t\tdayNames: [ \"Sunday\", \"Monday\", \"Tuesday\", \"Wednesday\", \"Thursday\", \"Friday\", \"Saturday\" ], // For formatting\n\t\tdayNamesShort: [ \"Sun\", \"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\", \"Sat\" ], // For formatting\n\t\tdayNamesMin: [ \"Su\",\"Mo\",\"Tu\",\"We\",\"Th\",\"Fr\",\"Sa\" ], // Column headings for days starting at Sunday\n\t\tweekHeader: \"Wk\", // Column header for week of the year\n\t\tdateFormat: \"mm/dd/yy\", // See format options on parseDate\n\t\tfirstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...\n\t\tisRTL: false, // True if right-to-left language, false if left-to-right\n\t\tshowMonthAfterYear: false, // True if the year select precedes month, false for month then year\n\t\tyearSuffix: \"\" // Additional text to append to the year in the month headers\n\t};\n\tthis._defaults = { // Global defaults for all the date picker instances\n\t\tshowOn: \"focus\", // \"focus\" for popup on focus,\n\t\t\t// \"button\" for trigger button, or \"both\" for either\n\t\tshowAnim: \"fadeIn\", // Name of jQuery animation for popup\n\t\tshowOptions: {}, // Options for enhanced animations\n\t\tdefaultDate: null, // Used when field is blank: actual date,\n\t\t\t// +/-number for offset from today, null for today\n\t\tappendText: \"\", // Display text following the input box, e.g. showing the format\n\t\tbuttonText: \"...\", // Text for trigger button\n\t\tbuttonImage: \"\", // URL for trigger button image\n\t\tbuttonImageOnly: false, // True if the image appears alone, false if it appears on a button\n\t\thideIfNoPrevNext: false, // True to hide next/previous month links\n\t\t\t// if not applicable, false to just disable them\n\t\tnavigationAsDateFormat: false, // True if date formatting applied to prev/today/next links\n\t\tgotoCurrent: false, // True if today link goes back to current selection instead\n\t\tchangeMonth: false, // True if month can be selected directly, false if only prev/next\n\t\tchangeYear: false, // True if year can be selected directly, false if only prev/next\n\t\tyearRange: \"c-10:c+10\", // Range of years to display in drop-down,\n\t\t\t// either relative to today's year (-nn:+nn), relative to currently displayed year\n\t\t\t// (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)\n\t\tshowOtherMonths: false, // True to show dates in other months, false to leave blank\n\t\tselectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable\n\t\tshowWeek: false, // True to show week of the year, false to not show it\n\t\tcalculateWeek: this.iso8601Week, // How to calculate the week of the year,\n\t\t\t// takes a Date and returns the number of the week for it\n\t\tshortYearCutoff: \"+10\", // Short year values < this are in the current century,\n\t\t\t// > this are in the previous century,\n\t\t\t// string value starting with \"+\" for current year + value\n\t\tminDate: null, // The earliest selectable date, or null for no limit\n\t\tmaxDate: null, // The latest selectable date, or null for no limit\n\t\tduration: \"fast\", // Duration of display/closure\n\t\tbeforeShowDay: null, // Function that takes a date and returns an array with\n\t\t\t// [0] = true if selectable, false if not, [1] = custom CSS class name(s) or \"\",\n\t\t\t// [2] = cell title (optional), e.g. $.datepicker.noWeekends\n\t\tbeforeShow: null, // Function that takes an input field and\n\t\t\t// returns a set of custom settings for the date picker\n\t\tonSelect: null, // Define a callback function when a date is selected\n\t\tonChangeMonthYear: null, // Define a callback function when the month or year is changed\n\t\tonClose: null, // Define a callback function when the datepicker is closed\n\t\tnumberOfMonths: 1, // Number of months to show at a time\n\t\tshowCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)\n\t\tstepMonths: 1, // Number of months to step back/forward\n\t\tstepBigMonths: 12, // Number of months to step back/forward for the big links\n\t\taltField: \"\", // Selector for an alternate field to store selected dates into\n\t\taltFormat: \"\", // The date format to use for the alternate field\n\t\tconstrainInput: true, // The input is constrained by the current date format\n\t\tshowButtonPanel: false, // True to show button panel, false to not show it\n\t\tautoSize: false, // True to size the input for the date format, false to leave as is\n\t\tdisabled: false // The initial disabled state\n\t};\n\t$.extend( this._defaults, this.regional[ \"\" ] );\n\tthis.regional.en = $.extend( true, {}, this.regional[ \"\" ] );\n\tthis.regional[ \"en-US\" ] = $.extend( true, {}, this.regional.en );\n\tthis.dpDiv = datepicker_bindHover( $( \"<div id='\" + this._mainDivId + \"' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>\" ) );\n}\n\n$.extend( Datepicker.prototype, {\n\t/* Class name added to elements to indicate already configured with a date picker. */\n\tmarkerClassName: \"hasDatepicker\",\n\n\t//Keep track of the maximum number of rows displayed (see #7043)\n\tmaxRows: 4,\n\n\t// TODO rename to \"widget\" when switching to widget factory\n\t_widgetDatepicker: function() {\n\t\treturn this.dpDiv;\n\t},\n\n\t/* Override the default settings for all instances of the date picker.\n\t * @param  settings  object - the new settings to use as defaults (anonymous object)\n\t * @return the manager object\n\t */\n\tsetDefaults: function( settings ) {\n\t\tdatepicker_extendRemove( this._defaults, settings || {} );\n\t\treturn this;\n\t},\n\n\t/* Attach the date picker to a jQuery selection.\n\t * @param  target\telement - the target input field or division or span\n\t * @param  settings  object - the new settings to use for this date picker instance (anonymous)\n\t */\n\t_attachDatepicker: function( target, settings ) {\n\t\tvar nodeName, inline, inst;\n\t\tnodeName = target.nodeName.toLowerCase();\n\t\tinline = ( nodeName === \"div\" || nodeName === \"span\" );\n\t\tif ( !target.id ) {\n\t\t\tthis.uuid += 1;\n\t\t\ttarget.id = \"dp\" + this.uuid;\n\t\t}\n\t\tinst = this._newInst( $( target ), inline );\n\t\tinst.settings = $.extend( {}, settings || {} );\n\t\tif ( nodeName === \"input\" ) {\n\t\t\tthis._connectDatepicker( target, inst );\n\t\t} else if ( inline ) {\n\t\t\tthis._inlineDatepicker( target, inst );\n\t\t}\n\t},\n\n\t/* Create a new instance object. */\n\t_newInst: function( target, inline ) {\n\t\tvar id = target[ 0 ].id.replace( /([^A-Za-z0-9_\\-])/g, \"\\\\\\\\$1\" ); // escape jQuery meta chars\n\t\treturn { id: id, input: target, // associated target\n\t\t\tselectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection\n\t\t\tdrawMonth: 0, drawYear: 0, // month being drawn\n\t\t\tinline: inline, // is datepicker inline or not\n\t\t\tdpDiv: ( !inline ? this.dpDiv : // presentation div\n\t\t\tdatepicker_bindHover( $( \"<div class='\" + this._inlineClass + \" ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>\" ) ) ) };\n\t},\n\n\t/* Attach the date picker to an input field. */\n\t_connectDatepicker: function( target, inst ) {\n\t\tvar input = $( target );\n\t\tinst.append = $( [] );\n\t\tinst.trigger = $( [] );\n\t\tif ( input.hasClass( this.markerClassName ) ) {\n\t\t\treturn;\n\t\t}\n\t\tthis._attachments( input, inst );\n\t\tinput.addClass( this.markerClassName ).on( \"keydown\", this._doKeyDown ).\n\t\t\ton( \"keypress\", this._doKeyPress ).on( \"keyup\", this._doKeyUp );\n\t\tthis._autoSize( inst );\n\t\t$.data( target, \"datepicker\", inst );\n\n\t\t//If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665)\n\t\tif ( inst.settings.disabled ) {\n\t\t\tthis._disableDatepicker( target );\n\t\t}\n\t},\n\n\t/* Make attachments based on settings. */\n\t_attachments: function( input, inst ) {\n\t\tvar showOn, buttonText, buttonImage,\n\t\t\tappendText = this._get( inst, \"appendText\" ),\n\t\t\tisRTL = this._get( inst, \"isRTL\" );\n\n\t\tif ( inst.append ) {\n\t\t\tinst.append.remove();\n\t\t}\n\t\tif ( appendText ) {\n\t\t\tinst.append = $( \"<span class='\" + this._appendClass + \"'>\" + appendText + \"</span>\" );\n\t\t\tinput[ isRTL ? \"before\" : \"after\" ]( inst.append );\n\t\t}\n\n\t\tinput.off( \"focus\", this._showDatepicker );\n\n\t\tif ( inst.trigger ) {\n\t\t\tinst.trigger.remove();\n\t\t}\n\n\t\tshowOn = this._get( inst, \"showOn\" );\n\t\tif ( showOn === \"focus\" || showOn === \"both\" ) { // pop-up date picker when in the marked field\n\t\t\tinput.on( \"focus\", this._showDatepicker );\n\t\t}\n\t\tif ( showOn === \"button\" || showOn === \"both\" ) { // pop-up date picker when button clicked\n\t\t\tbuttonText = this._get( inst, \"buttonText\" );\n\t\t\tbuttonImage = this._get( inst, \"buttonImage\" );\n\t\t\tinst.trigger = $( this._get( inst, \"buttonImageOnly\" ) ?\n\t\t\t\t$( \"<img/>\" ).addClass( this._triggerClass ).\n\t\t\t\t\tattr( { src: buttonImage, alt: buttonText, title: buttonText } ) :\n\t\t\t\t$( \"<button type='button'></button>\" ).addClass( this._triggerClass ).\n\t\t\t\t\thtml( !buttonImage ? buttonText : $( \"<img/>\" ).attr(\n\t\t\t\t\t{ src:buttonImage, alt:buttonText, title:buttonText } ) ) );\n\t\t\tinput[ isRTL ? \"before\" : \"after\" ]( inst.trigger );\n\t\t\tinst.trigger.on( \"click\", function() {\n\t\t\t\tif ( $.datepicker._datepickerShowing && $.datepicker._lastInput === input[ 0 ] ) {\n\t\t\t\t\t$.datepicker._hideDatepicker();\n\t\t\t\t} else if ( $.datepicker._datepickerShowing && $.datepicker._lastInput !== input[ 0 ] ) {\n\t\t\t\t\t$.datepicker._hideDatepicker();\n\t\t\t\t\t$.datepicker._showDatepicker( input[ 0 ] );\n\t\t\t\t} else {\n\t\t\t\t\t$.datepicker._showDatepicker( input[ 0 ] );\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t} );\n\t\t}\n\t},\n\n\t/* Apply the maximum length for the date format. */\n\t_autoSize: function( inst ) {\n\t\tif ( this._get( inst, \"autoSize\" ) && !inst.inline ) {\n\t\t\tvar findMax, max, maxI, i,\n\t\t\t\tdate = new Date( 2009, 12 - 1, 20 ), // Ensure double digits\n\t\t\t\tdateFormat = this._get( inst, \"dateFormat\" );\n\n\t\t\tif ( dateFormat.match( /[DM]/ ) ) {\n\t\t\t\tfindMax = function( names ) {\n\t\t\t\t\tmax = 0;\n\t\t\t\t\tmaxI = 0;\n\t\t\t\t\tfor ( i = 0; i < names.length; i++ ) {\n\t\t\t\t\t\tif ( names[ i ].length > max ) {\n\t\t\t\t\t\t\tmax = names[ i ].length;\n\t\t\t\t\t\t\tmaxI = i;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn maxI;\n\t\t\t\t};\n\t\t\t\tdate.setMonth( findMax( this._get( inst, ( dateFormat.match( /MM/ ) ?\n\t\t\t\t\t\"monthNames\" : \"monthNamesShort\" ) ) ) );\n\t\t\t\tdate.setDate( findMax( this._get( inst, ( dateFormat.match( /DD/ ) ?\n\t\t\t\t\t\"dayNames\" : \"dayNamesShort\" ) ) ) + 20 - date.getDay() );\n\t\t\t}\n\t\t\tinst.input.attr( \"size\", this._formatDate( inst, date ).length );\n\t\t}\n\t},\n\n\t/* Attach an inline date picker to a div. */\n\t_inlineDatepicker: function( target, inst ) {\n\t\tvar divSpan = $( target );\n\t\tif ( divSpan.hasClass( this.markerClassName ) ) {\n\t\t\treturn;\n\t\t}\n\t\tdivSpan.addClass( this.markerClassName ).append( inst.dpDiv );\n\t\t$.data( target, \"datepicker\", inst );\n\t\tthis._setDate( inst, this._getDefaultDate( inst ), true );\n\t\tthis._updateDatepicker( inst );\n\t\tthis._updateAlternate( inst );\n\n\t\t//If disabled option is true, disable the datepicker before showing it (see ticket #5665)\n\t\tif ( inst.settings.disabled ) {\n\t\t\tthis._disableDatepicker( target );\n\t\t}\n\n\t\t// Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements\n\t\t// http://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height\n\t\tinst.dpDiv.css( \"display\", \"block\" );\n\t},\n\n\t/* Pop-up the date picker in a \"dialog\" box.\n\t * @param  input element - ignored\n\t * @param  date\tstring or Date - the initial date to display\n\t * @param  onSelect  function - the function to call when a date is selected\n\t * @param  settings  object - update the dialog date picker instance's settings (anonymous object)\n\t * @param  pos int[2] - coordinates for the dialog's position within the screen or\n\t *\t\t\t\t\tevent - with x/y coordinates or\n\t *\t\t\t\t\tleave empty for default (screen centre)\n\t * @return the manager object\n\t */\n\t_dialogDatepicker: function( input, date, onSelect, settings, pos ) {\n\t\tvar id, browserWidth, browserHeight, scrollX, scrollY,\n\t\t\tinst = this._dialogInst; // internal instance\n\n\t\tif ( !inst ) {\n\t\t\tthis.uuid += 1;\n\t\t\tid = \"dp\" + this.uuid;\n\t\t\tthis._dialogInput = $( \"<input type='text' id='\" + id +\n\t\t\t\t\"' style='position: absolute; top: -100px; width: 0px;'/>\" );\n\t\t\tthis._dialogInput.on( \"keydown\", this._doKeyDown );\n\t\t\t$( \"body\" ).append( this._dialogInput );\n\t\t\tinst = this._dialogInst = this._newInst( this._dialogInput, false );\n\t\t\tinst.settings = {};\n\t\t\t$.data( this._dialogInput[ 0 ], \"datepicker\", inst );\n\t\t}\n\t\tdatepicker_extendRemove( inst.settings, settings || {} );\n\t\tdate = ( date && date.constructor === Date ? this._formatDate( inst, date ) : date );\n\t\tthis._dialogInput.val( date );\n\n\t\tthis._pos = ( pos ? ( pos.length ? pos : [ pos.pageX, pos.pageY ] ) : null );\n\t\tif ( !this._pos ) {\n\t\t\tbrowserWidth = document.documentElement.clientWidth;\n\t\t\tbrowserHeight = document.documentElement.clientHeight;\n\t\t\tscrollX = document.documentElement.scrollLeft || document.body.scrollLeft;\n\t\t\tscrollY = document.documentElement.scrollTop || document.body.scrollTop;\n\t\t\tthis._pos = // should use actual width/height below\n\t\t\t\t[ ( browserWidth / 2 ) - 100 + scrollX, ( browserHeight / 2 ) - 150 + scrollY ];\n\t\t}\n\n\t\t// Move input on screen for focus, but hidden behind dialog\n\t\tthis._dialogInput.css( \"left\", ( this._pos[ 0 ] + 20 ) + \"px\" ).css( \"top\", this._pos[ 1 ] + \"px\" );\n\t\tinst.settings.onSelect = onSelect;\n\t\tthis._inDialog = true;\n\t\tthis.dpDiv.addClass( this._dialogClass );\n\t\tthis._showDatepicker( this._dialogInput[ 0 ] );\n\t\tif ( $.blockUI ) {\n\t\t\t$.blockUI( this.dpDiv );\n\t\t}\n\t\t$.data( this._dialogInput[ 0 ], \"datepicker\", inst );\n\t\treturn this;\n\t},\n\n\t/* Detach a datepicker from its control.\n\t * @param  target\telement - the target input field or division or span\n\t */\n\t_destroyDatepicker: function( target ) {\n\t\tvar nodeName,\n\t\t\t$target = $( target ),\n\t\t\tinst = $.data( target, \"datepicker\" );\n\n\t\tif ( !$target.hasClass( this.markerClassName ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tnodeName = target.nodeName.toLowerCase();\n\t\t$.removeData( target, \"datepicker\" );\n\t\tif ( nodeName === \"input\" ) {\n\t\t\tinst.append.remove();\n\t\t\tinst.trigger.remove();\n\t\t\t$target.removeClass( this.markerClassName ).\n\t\t\t\toff( \"focus\", this._showDatepicker ).\n\t\t\t\toff( \"keydown\", this._doKeyDown ).\n\t\t\t\toff( \"keypress\", this._doKeyPress ).\n\t\t\t\toff( \"keyup\", this._doKeyUp );\n\t\t} else if ( nodeName === \"div\" || nodeName === \"span\" ) {\n\t\t\t$target.removeClass( this.markerClassName ).empty();\n\t\t}\n\n\t\tif ( datepicker_instActive === inst ) {\n\t\t\tdatepicker_instActive = null;\n\t\t}\n\t},\n\n\t/* Enable the date picker to a jQuery selection.\n\t * @param  target\telement - the target input field or division or span\n\t */\n\t_enableDatepicker: function( target ) {\n\t\tvar nodeName, inline,\n\t\t\t$target = $( target ),\n\t\t\tinst = $.data( target, \"datepicker\" );\n\n\t\tif ( !$target.hasClass( this.markerClassName ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tnodeName = target.nodeName.toLowerCase();\n\t\tif ( nodeName === \"input\" ) {\n\t\t\ttarget.disabled = false;\n\t\t\tinst.trigger.filter( \"button\" ).\n\t\t\t\teach( function() { this.disabled = false; } ).end().\n\t\t\t\tfilter( \"img\" ).css( { opacity: \"1.0\", cursor: \"\" } );\n\t\t} else if ( nodeName === \"div\" || nodeName === \"span\" ) {\n\t\t\tinline = $target.children( \".\" + this._inlineClass );\n\t\t\tinline.children().removeClass( \"ui-state-disabled\" );\n\t\t\tinline.find( \"select.ui-datepicker-month, select.ui-datepicker-year\" ).\n\t\t\t\tprop( \"disabled\", false );\n\t\t}\n\t\tthis._disabledInputs = $.map( this._disabledInputs,\n\t\t\tfunction( value ) { return ( value === target ? null : value ); } ); // delete entry\n\t},\n\n\t/* Disable the date picker to a jQuery selection.\n\t * @param  target\telement - the target input field or division or span\n\t */\n\t_disableDatepicker: function( target ) {\n\t\tvar nodeName, inline,\n\t\t\t$target = $( target ),\n\t\t\tinst = $.data( target, \"datepicker\" );\n\n\t\tif ( !$target.hasClass( this.markerClassName ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tnodeName = target.nodeName.toLowerCase();\n\t\tif ( nodeName === \"input\" ) {\n\t\t\ttarget.disabled = true;\n\t\t\tinst.trigger.filter( \"button\" ).\n\t\t\t\teach( function() { this.disabled = true; } ).end().\n\t\t\t\tfilter( \"img\" ).css( { opacity: \"0.5\", cursor: \"default\" } );\n\t\t} else if ( nodeName === \"div\" || nodeName === \"span\" ) {\n\t\t\tinline = $target.children( \".\" + this._inlineClass );\n\t\t\tinline.children().addClass( \"ui-state-disabled\" );\n\t\t\tinline.find( \"select.ui-datepicker-month, select.ui-datepicker-year\" ).\n\t\t\t\tprop( \"disabled\", true );\n\t\t}\n\t\tthis._disabledInputs = $.map( this._disabledInputs,\n\t\t\tfunction( value ) { return ( value === target ? null : value ); } ); // delete entry\n\t\tthis._disabledInputs[ this._disabledInputs.length ] = target;\n\t},\n\n\t/* Is the first field in a jQuery collection disabled as a datepicker?\n\t * @param  target\telement - the target input field or division or span\n\t * @return boolean - true if disabled, false if enabled\n\t */\n\t_isDisabledDatepicker: function( target ) {\n\t\tif ( !target ) {\n\t\t\treturn false;\n\t\t}\n\t\tfor ( var i = 0; i < this._disabledInputs.length; i++ ) {\n\t\t\tif ( this._disabledInputs[ i ] === target ) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t},\n\n\t/* Retrieve the instance data for the target control.\n\t * @param  target  element - the target input field or division or span\n\t * @return  object - the associated instance data\n\t * @throws  error if a jQuery problem getting data\n\t */\n\t_getInst: function( target ) {\n\t\ttry {\n\t\t\treturn $.data( target, \"datepicker\" );\n\t\t}\n\t\tcatch ( err ) {\n\t\t\tthrow \"Missing instance data for this datepicker\";\n\t\t}\n\t},\n\n\t/* Update or retrieve the settings for a date picker attached to an input field or division.\n\t * @param  target  element - the target input field or division or span\n\t * @param  name\tobject - the new settings to update or\n\t *\t\t\t\tstring - the name of the setting to change or retrieve,\n\t *\t\t\t\twhen retrieving also \"all\" for all instance settings or\n\t *\t\t\t\t\"defaults\" for all global defaults\n\t * @param  value   any - the new value for the setting\n\t *\t\t\t\t(omit if above is an object or to retrieve a value)\n\t */\n\t_optionDatepicker: function( target, name, value ) {\n\t\tvar settings, date, minDate, maxDate,\n\t\t\tinst = this._getInst( target );\n\n\t\tif ( arguments.length === 2 && typeof name === \"string\" ) {\n\t\t\treturn ( name === \"defaults\" ? $.extend( {}, $.datepicker._defaults ) :\n\t\t\t\t( inst ? ( name === \"all\" ? $.extend( {}, inst.settings ) :\n\t\t\t\tthis._get( inst, name ) ) : null ) );\n\t\t}\n\n\t\tsettings = name || {};\n\t\tif ( typeof name === \"string\" ) {\n\t\t\tsettings = {};\n\t\t\tsettings[ name ] = value;\n\t\t}\n\n\t\tif ( inst ) {\n\t\t\tif ( this._curInst === inst ) {\n\t\t\t\tthis._hideDatepicker();\n\t\t\t}\n\n\t\t\tdate = this._getDateDatepicker( target, true );\n\t\t\tminDate = this._getMinMaxDate( inst, \"min\" );\n\t\t\tmaxDate = this._getMinMaxDate( inst, \"max\" );\n\t\t\tdatepicker_extendRemove( inst.settings, settings );\n\n\t\t\t// reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided\n\t\t\tif ( minDate !== null && settings.dateFormat !== undefined && settings.minDate === undefined ) {\n\t\t\t\tinst.settings.minDate = this._formatDate( inst, minDate );\n\t\t\t}\n\t\t\tif ( maxDate !== null && settings.dateFormat !== undefined && settings.maxDate === undefined ) {\n\t\t\t\tinst.settings.maxDate = this._formatDate( inst, maxDate );\n\t\t\t}\n\t\t\tif ( \"disabled\" in settings ) {\n\t\t\t\tif ( settings.disabled ) {\n\t\t\t\t\tthis._disableDatepicker( target );\n\t\t\t\t} else {\n\t\t\t\t\tthis._enableDatepicker( target );\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis._attachments( $( target ), inst );\n\t\t\tthis._autoSize( inst );\n\t\t\tthis._setDate( inst, date );\n\t\t\tthis._updateAlternate( inst );\n\t\t\tthis._updateDatepicker( inst );\n\t\t}\n\t},\n\n\t// Change method deprecated\n\t_changeDatepicker: function( target, name, value ) {\n\t\tthis._optionDatepicker( target, name, value );\n\t},\n\n\t/* Redraw the date picker attached to an input field or division.\n\t * @param  target  element - the target input field or division or span\n\t */\n\t_refreshDatepicker: function( target ) {\n\t\tvar inst = this._getInst( target );\n\t\tif ( inst ) {\n\t\t\tthis._updateDatepicker( inst );\n\t\t}\n\t},\n\n\t/* Set the dates for a jQuery selection.\n\t * @param  target element - the target input field or division or span\n\t * @param  date\tDate - the new date\n\t */\n\t_setDateDatepicker: function( target, date ) {\n\t\tvar inst = this._getInst( target );\n\t\tif ( inst ) {\n\t\t\tthis._setDate( inst, date );\n\t\t\tthis._updateDatepicker( inst );\n\t\t\tthis._updateAlternate( inst );\n\t\t}\n\t},\n\n\t/* Get the date(s) for the first entry in a jQuery selection.\n\t * @param  target element - the target input field or division or span\n\t * @param  noDefault boolean - true if no default date is to be used\n\t * @return Date - the current date\n\t */\n\t_getDateDatepicker: function( target, noDefault ) {\n\t\tvar inst = this._getInst( target );\n\t\tif ( inst && !inst.inline ) {\n\t\t\tthis._setDateFromField( inst, noDefault );\n\t\t}\n\t\treturn ( inst ? this._getDate( inst ) : null );\n\t},\n\n\t/* Handle keystrokes. */\n\t_doKeyDown: function( event ) {\n\t\tvar onSelect, dateStr, sel,\n\t\t\tinst = $.datepicker._getInst( event.target ),\n\t\t\thandled = true,\n\t\t\tisRTL = inst.dpDiv.is( \".ui-datepicker-rtl\" );\n\n\t\tinst._keyEvent = true;\n\t\tif ( $.datepicker._datepickerShowing ) {\n\t\t\tswitch ( event.keyCode ) {\n\t\t\t\tcase 9: $.datepicker._hideDatepicker();\n\t\t\t\t\t\thandled = false;\n\t\t\t\t\t\tbreak; // hide on tab out\n\t\t\t\tcase 13: sel = $( \"td.\" + $.datepicker._dayOverClass + \":not(.\" +\n\t\t\t\t\t\t\t\t\t$.datepicker._currentClass + \")\", inst.dpDiv );\n\t\t\t\t\t\tif ( sel[ 0 ] ) {\n\t\t\t\t\t\t\t$.datepicker._selectDay( event.target, inst.selectedMonth, inst.selectedYear, sel[ 0 ] );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tonSelect = $.datepicker._get( inst, \"onSelect\" );\n\t\t\t\t\t\tif ( onSelect ) {\n\t\t\t\t\t\t\tdateStr = $.datepicker._formatDate( inst );\n\n\t\t\t\t\t\t\t// Trigger custom callback\n\t\t\t\t\t\t\tonSelect.apply( ( inst.input ? inst.input[ 0 ] : null ), [ dateStr, inst ] );\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t$.datepicker._hideDatepicker();\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn false; // don't submit the form\n\t\t\t\tcase 27: $.datepicker._hideDatepicker();\n\t\t\t\t\t\tbreak; // hide on escape\n\t\t\t\tcase 33: $.datepicker._adjustDate( event.target, ( event.ctrlKey ?\n\t\t\t\t\t\t\t-$.datepicker._get( inst, \"stepBigMonths\" ) :\n\t\t\t\t\t\t\t-$.datepicker._get( inst, \"stepMonths\" ) ), \"M\" );\n\t\t\t\t\t\tbreak; // previous month/year on page up/+ ctrl\n\t\t\t\tcase 34: $.datepicker._adjustDate( event.target, ( event.ctrlKey ?\n\t\t\t\t\t\t\t+$.datepicker._get( inst, \"stepBigMonths\" ) :\n\t\t\t\t\t\t\t+$.datepicker._get( inst, \"stepMonths\" ) ), \"M\" );\n\t\t\t\t\t\tbreak; // next month/year on page down/+ ctrl\n\t\t\t\tcase 35: if ( event.ctrlKey || event.metaKey ) {\n\t\t\t\t\t\t\t$.datepicker._clearDate( event.target );\n\t\t\t\t\t\t}\n\t\t\t\t\t\thandled = event.ctrlKey || event.metaKey;\n\t\t\t\t\t\tbreak; // clear on ctrl or command +end\n\t\t\t\tcase 36: if ( event.ctrlKey || event.metaKey ) {\n\t\t\t\t\t\t\t$.datepicker._gotoToday( event.target );\n\t\t\t\t\t\t}\n\t\t\t\t\t\thandled = event.ctrlKey || event.metaKey;\n\t\t\t\t\t\tbreak; // current on ctrl or command +home\n\t\t\t\tcase 37: if ( event.ctrlKey || event.metaKey ) {\n\t\t\t\t\t\t\t$.datepicker._adjustDate( event.target, ( isRTL ? +1 : -1 ), \"D\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t\thandled = event.ctrlKey || event.metaKey;\n\n\t\t\t\t\t\t// -1 day on ctrl or command +left\n\t\t\t\t\t\tif ( event.originalEvent.altKey ) {\n\t\t\t\t\t\t\t$.datepicker._adjustDate( event.target, ( event.ctrlKey ?\n\t\t\t\t\t\t\t\t-$.datepicker._get( inst, \"stepBigMonths\" ) :\n\t\t\t\t\t\t\t\t-$.datepicker._get( inst, \"stepMonths\" ) ), \"M\" );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// next month/year on alt +left on Mac\n\t\t\t\t\t\tbreak;\n\t\t\t\tcase 38: if ( event.ctrlKey || event.metaKey ) {\n\t\t\t\t\t\t\t$.datepicker._adjustDate( event.target, -7, \"D\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t\thandled = event.ctrlKey || event.metaKey;\n\t\t\t\t\t\tbreak; // -1 week on ctrl or command +up\n\t\t\t\tcase 39: if ( event.ctrlKey || event.metaKey ) {\n\t\t\t\t\t\t\t$.datepicker._adjustDate( event.target, ( isRTL ? -1 : +1 ), \"D\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t\thandled = event.ctrlKey || event.metaKey;\n\n\t\t\t\t\t\t// +1 day on ctrl or command +right\n\t\t\t\t\t\tif ( event.originalEvent.altKey ) {\n\t\t\t\t\t\t\t$.datepicker._adjustDate( event.target, ( event.ctrlKey ?\n\t\t\t\t\t\t\t\t+$.datepicker._get( inst, \"stepBigMonths\" ) :\n\t\t\t\t\t\t\t\t+$.datepicker._get( inst, \"stepMonths\" ) ), \"M\" );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// next month/year on alt +right\n\t\t\t\t\t\tbreak;\n\t\t\t\tcase 40: if ( event.ctrlKey || event.metaKey ) {\n\t\t\t\t\t\t\t$.datepicker._adjustDate( event.target, +7, \"D\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t\thandled = event.ctrlKey || event.metaKey;\n\t\t\t\t\t\tbreak; // +1 week on ctrl or command +down\n\t\t\t\tdefault: handled = false;\n\t\t\t}\n\t\t} else if ( event.keyCode === 36 && event.ctrlKey ) { // display the date picker on ctrl+home\n\t\t\t$.datepicker._showDatepicker( this );\n\t\t} else {\n\t\t\thandled = false;\n\t\t}\n\n\t\tif ( handled ) {\n\t\t\tevent.preventDefault();\n\t\t\tevent.stopPropagation();\n\t\t}\n\t},\n\n\t/* Filter entered characters - based on date format. */\n\t_doKeyPress: function( event ) {\n\t\tvar chars, chr,\n\t\t\tinst = $.datepicker._getInst( event.target );\n\n\t\tif ( $.datepicker._get( inst, \"constrainInput\" ) ) {\n\t\t\tchars = $.datepicker._possibleChars( $.datepicker._get( inst, \"dateFormat\" ) );\n\t\t\tchr = String.fromCharCode( event.charCode == null ? event.keyCode : event.charCode );\n\t\t\treturn event.ctrlKey || event.metaKey || ( chr < \" \" || !chars || chars.indexOf( chr ) > -1 );\n\t\t}\n\t},\n\n\t/* Synchronise manual entry and field/alternate field. */\n\t_doKeyUp: function( event ) {\n\t\tvar date,\n\t\t\tinst = $.datepicker._getInst( event.target );\n\n\t\tif ( inst.input.val() !== inst.lastVal ) {\n\t\t\ttry {\n\t\t\t\tdate = $.datepicker.parseDate( $.datepicker._get( inst, \"dateFormat\" ),\n\t\t\t\t\t( inst.input ? inst.input.val() : null ),\n\t\t\t\t\t$.datepicker._getFormatConfig( inst ) );\n\n\t\t\t\tif ( date ) { // only if valid\n\t\t\t\t\t$.datepicker._setDateFromField( inst );\n\t\t\t\t\t$.datepicker._updateAlternate( inst );\n\t\t\t\t\t$.datepicker._updateDatepicker( inst );\n\t\t\t\t}\n\t\t\t}\n\t\t\tcatch ( err ) {\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t},\n\n\t/* Pop-up the date picker for a given input field.\n\t * If false returned from beforeShow event handler do not show.\n\t * @param  input  element - the input field attached to the date picker or\n\t *\t\t\t\t\tevent - if triggered by focus\n\t */\n\t_showDatepicker: function( input ) {\n\t\tinput = input.target || input;\n\t\tif ( input.nodeName.toLowerCase() !== \"input\" ) { // find from button/image trigger\n\t\t\tinput = $( \"input\", input.parentNode )[ 0 ];\n\t\t}\n\n\t\tif ( $.datepicker._isDisabledDatepicker( input ) || $.datepicker._lastInput === input ) { // already here\n\t\t\treturn;\n\t\t}\n\n\t\tvar inst, beforeShow, beforeShowSettings, isFixed,\n\t\t\toffset, showAnim, duration;\n\n\t\tinst = $.datepicker._getInst( input );\n\t\tif ( $.datepicker._curInst && $.datepicker._curInst !== inst ) {\n\t\t\t$.datepicker._curInst.dpDiv.stop( true, true );\n\t\t\tif ( inst && $.datepicker._datepickerShowing ) {\n\t\t\t\t$.datepicker._hideDatepicker( $.datepicker._curInst.input[ 0 ] );\n\t\t\t}\n\t\t}\n\n\t\tbeforeShow = $.datepicker._get( inst, \"beforeShow\" );\n\t\tbeforeShowSettings = beforeShow ? beforeShow.apply( input, [ input, inst ] ) : {};\n\t\tif ( beforeShowSettings === false ) {\n\t\t\treturn;\n\t\t}\n\t\tdatepicker_extendRemove( inst.settings, beforeShowSettings );\n\n\t\tinst.lastVal = null;\n\t\t$.datepicker._lastInput = input;\n\t\t$.datepicker._setDateFromField( inst );\n\n\t\tif ( $.datepicker._inDialog ) { // hide cursor\n\t\t\tinput.value = \"\";\n\t\t}\n\t\tif ( !$.datepicker._pos ) { // position below input\n\t\t\t$.datepicker._pos = $.datepicker._findPos( input );\n\t\t\t$.datepicker._pos[ 1 ] += input.offsetHeight; // add the height\n\t\t}\n\n\t\tisFixed = false;\n\t\t$( input ).parents().each( function() {\n\t\t\tisFixed |= $( this ).css( \"position\" ) === \"fixed\";\n\t\t\treturn !isFixed;\n\t\t} );\n\n\t\toffset = { left: $.datepicker._pos[ 0 ], top: $.datepicker._pos[ 1 ] };\n\t\t$.datepicker._pos = null;\n\n\t\t//to avoid flashes on Firefox\n\t\tinst.dpDiv.empty();\n\n\t\t// determine sizing offscreen\n\t\tinst.dpDiv.css( { position: \"absolute\", display: \"block\", top: \"-1000px\" } );\n\t\t$.datepicker._updateDatepicker( inst );\n\n\t\t// fix width for dynamic number of date pickers\n\t\t// and adjust position before showing\n\t\toffset = $.datepicker._checkOffset( inst, offset, isFixed );\n\t\tinst.dpDiv.css( { position: ( $.datepicker._inDialog && $.blockUI ?\n\t\t\t\"static\" : ( isFixed ? \"fixed\" : \"absolute\" ) ), display: \"none\",\n\t\t\tleft: offset.left + \"px\", top: offset.top + \"px\" } );\n\n\t\tif ( !inst.inline ) {\n\t\t\tshowAnim = $.datepicker._get( inst, \"showAnim\" );\n\t\t\tduration = $.datepicker._get( inst, \"duration\" );\n\t\t\tinst.dpDiv.css( \"z-index\", datepicker_getZindex( $( input ) ) + 1 );\n\t\t\t$.datepicker._datepickerShowing = true;\n\n\t\t\tif ( $.effects && $.effects.effect[ showAnim ] ) {\n\t\t\t\tinst.dpDiv.show( showAnim, $.datepicker._get( inst, \"showOptions\" ), duration );\n\t\t\t} else {\n\t\t\t\tinst.dpDiv[ showAnim || \"show\" ]( showAnim ? duration : null );\n\t\t\t}\n\n\t\t\tif ( $.datepicker._shouldFocusInput( inst ) ) {\n\t\t\t\tinst.input.trigger( \"focus\" );\n\t\t\t}\n\n\t\t\t$.datepicker._curInst = inst;\n\t\t}\n\t},\n\n\t/* Generate the date picker content. */\n\t_updateDatepicker: function( inst ) {\n\t\tthis.maxRows = 4; //Reset the max number of rows being displayed (see #7043)\n\t\tdatepicker_instActive = inst; // for delegate hover events\n\t\tinst.dpDiv.empty().append( this._generateHTML( inst ) );\n\t\tthis._attachHandlers( inst );\n\n\t\tvar origyearshtml,\n\t\t\tnumMonths = this._getNumberOfMonths( inst ),\n\t\t\tcols = numMonths[ 1 ],\n\t\t\twidth = 17,\n\t\t\tactiveCell = inst.dpDiv.find( \".\" + this._dayOverClass + \" a\" );\n\n\t\tif ( activeCell.length > 0 ) {\n\t\t\tdatepicker_handleMouseover.apply( activeCell.get( 0 ) );\n\t\t}\n\n\t\tinst.dpDiv.removeClass( \"ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4\" ).width( \"\" );\n\t\tif ( cols > 1 ) {\n\t\t\tinst.dpDiv.addClass( \"ui-datepicker-multi-\" + cols ).css( \"width\", ( width * cols ) + \"em\" );\n\t\t}\n\t\tinst.dpDiv[ ( numMonths[ 0 ] !== 1 || numMonths[ 1 ] !== 1 ? \"add\" : \"remove\" ) +\n\t\t\t\"Class\" ]( \"ui-datepicker-multi\" );\n\t\tinst.dpDiv[ ( this._get( inst, \"isRTL\" ) ? \"add\" : \"remove\" ) +\n\t\t\t\"Class\" ]( \"ui-datepicker-rtl\" );\n\n\t\tif ( inst === $.datepicker._curInst && $.datepicker._datepickerShowing && $.datepicker._shouldFocusInput( inst ) ) {\n\t\t\tinst.input.trigger( \"focus\" );\n\t\t}\n\n\t\t// Deffered render of the years select (to avoid flashes on Firefox)\n\t\tif ( inst.yearshtml ) {\n\t\t\torigyearshtml = inst.yearshtml;\n\t\t\tsetTimeout( function() {\n\n\t\t\t\t//assure that inst.yearshtml didn't change.\n\t\t\t\tif ( origyearshtml === inst.yearshtml && inst.yearshtml ) {\n\t\t\t\t\tinst.dpDiv.find( \"select.ui-datepicker-year:first\" ).replaceWith( inst.yearshtml );\n\t\t\t\t}\n\t\t\t\torigyearshtml = inst.yearshtml = null;\n\t\t\t}, 0 );\n\t\t}\n\t},\n\n\t// #6694 - don't focus the input if it's already focused\n\t// this breaks the change event in IE\n\t// Support: IE and jQuery <1.9\n\t_shouldFocusInput: function( inst ) {\n\t\treturn inst.input && inst.input.is( \":visible\" ) && !inst.input.is( \":disabled\" ) && !inst.input.is( \":focus\" );\n\t},\n\n\t/* Check positioning to remain on screen. */\n\t_checkOffset: function( inst, offset, isFixed ) {\n\t\tvar dpWidth = inst.dpDiv.outerWidth(),\n\t\t\tdpHeight = inst.dpDiv.outerHeight(),\n\t\t\tinputWidth = inst.input ? inst.input.outerWidth() : 0,\n\t\t\tinputHeight = inst.input ? inst.input.outerHeight() : 0,\n\t\t\tviewWidth = document.documentElement.clientWidth + ( isFixed ? 0 : $( document ).scrollLeft() ),\n\t\t\tviewHeight = document.documentElement.clientHeight + ( isFixed ? 0 : $( document ).scrollTop() );\n\n\t\toffset.left -= ( this._get( inst, \"isRTL\" ) ? ( dpWidth - inputWidth ) : 0 );\n\t\toffset.left -= ( isFixed && offset.left === inst.input.offset().left ) ? $( document ).scrollLeft() : 0;\n\t\toffset.top -= ( isFixed && offset.top === ( inst.input.offset().top + inputHeight ) ) ? $( document ).scrollTop() : 0;\n\n\t\t// Now check if datepicker is showing outside window viewport - move to a better place if so.\n\t\toffset.left -= Math.min( offset.left, ( offset.left + dpWidth > viewWidth && viewWidth > dpWidth ) ?\n\t\t\tMath.abs( offset.left + dpWidth - viewWidth ) : 0 );\n\t\toffset.top -= Math.min( offset.top, ( offset.top + dpHeight > viewHeight && viewHeight > dpHeight ) ?\n\t\t\tMath.abs( dpHeight + inputHeight ) : 0 );\n\n\t\treturn offset;\n\t},\n\n\t/* Find an object's position on the screen. */\n\t_findPos: function( obj ) {\n\t\tvar position,\n\t\t\tinst = this._getInst( obj ),\n\t\t\tisRTL = this._get( inst, \"isRTL\" );\n\n\t\twhile ( obj && ( obj.type === \"hidden\" || obj.nodeType !== 1 || $.expr.filters.hidden( obj ) ) ) {\n\t\t\tobj = obj[ isRTL ? \"previousSibling\" : \"nextSibling\" ];\n\t\t}\n\n\t\tposition = $( obj ).offset();\n\t\treturn [ position.left, position.top ];\n\t},\n\n\t/* Hide the date picker from view.\n\t * @param  input  element - the input field attached to the date picker\n\t */\n\t_hideDatepicker: function( input ) {\n\t\tvar showAnim, duration, postProcess, onClose,\n\t\t\tinst = this._curInst;\n\n\t\tif ( !inst || ( input && inst !== $.data( input, \"datepicker\" ) ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( this._datepickerShowing ) {\n\t\t\tshowAnim = this._get( inst, \"showAnim\" );\n\t\t\tduration = this._get( inst, \"duration\" );\n\t\t\tpostProcess = function() {\n\t\t\t\t$.datepicker._tidyDialog( inst );\n\t\t\t};\n\n\t\t\t// DEPRECATED: after BC for 1.8.x $.effects[ showAnim ] is not needed\n\t\t\tif ( $.effects && ( $.effects.effect[ showAnim ] || $.effects[ showAnim ] ) ) {\n\t\t\t\tinst.dpDiv.hide( showAnim, $.datepicker._get( inst, \"showOptions\" ), duration, postProcess );\n\t\t\t} else {\n\t\t\t\tinst.dpDiv[ ( showAnim === \"slideDown\" ? \"slideUp\" :\n\t\t\t\t\t( showAnim === \"fadeIn\" ? \"fadeOut\" : \"hide\" ) ) ]( ( showAnim ? duration : null ), postProcess );\n\t\t\t}\n\n\t\t\tif ( !showAnim ) {\n\t\t\t\tpostProcess();\n\t\t\t}\n\t\t\tthis._datepickerShowing = false;\n\n\t\t\tonClose = this._get( inst, \"onClose\" );\n\t\t\tif ( onClose ) {\n\t\t\t\tonClose.apply( ( inst.input ? inst.input[ 0 ] : null ), [ ( inst.input ? inst.input.val() : \"\" ), inst ] );\n\t\t\t}\n\n\t\t\tthis._lastInput = null;\n\t\t\tif ( this._inDialog ) {\n\t\t\t\tthis._dialogInput.css( { position: \"absolute\", left: \"0\", top: \"-100px\" } );\n\t\t\t\tif ( $.blockUI ) {\n\t\t\t\t\t$.unblockUI();\n\t\t\t\t\t$( \"body\" ).append( this.dpDiv );\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis._inDialog = false;\n\t\t}\n\t},\n\n\t/* Tidy up after a dialog display. */\n\t_tidyDialog: function( inst ) {\n\t\tinst.dpDiv.removeClass( this._dialogClass ).off( \".ui-datepicker-calendar\" );\n\t},\n\n\t/* Close date picker if clicked elsewhere. */\n\t_checkExternalClick: function( event ) {\n\t\tif ( !$.datepicker._curInst ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar $target = $( event.target ),\n\t\t\tinst = $.datepicker._getInst( $target[ 0 ] );\n\n\t\tif ( ( ( $target[ 0 ].id !== $.datepicker._mainDivId &&\n\t\t\t\t$target.parents( \"#\" + $.datepicker._mainDivId ).length === 0 &&\n\t\t\t\t!$target.hasClass( $.datepicker.markerClassName ) &&\n\t\t\t\t!$target.closest( \".\" + $.datepicker._triggerClass ).length &&\n\t\t\t\t$.datepicker._datepickerShowing && !( $.datepicker._inDialog && $.blockUI ) ) ) ||\n\t\t\t( $target.hasClass( $.datepicker.markerClassName ) && $.datepicker._curInst !== inst ) ) {\n\t\t\t\t$.datepicker._hideDatepicker();\n\t\t}\n\t},\n\n\t/* Adjust one of the date sub-fields. */\n\t_adjustDate: function( id, offset, period ) {\n\t\tvar target = $( id ),\n\t\t\tinst = this._getInst( target[ 0 ] );\n\n\t\tif ( this._isDisabledDatepicker( target[ 0 ] ) ) {\n\t\t\treturn;\n\t\t}\n\t\tthis._adjustInstDate( inst, offset +\n\t\t\t( period === \"M\" ? this._get( inst, \"showCurrentAtPos\" ) : 0 ), // undo positioning\n\t\t\tperiod );\n\t\tthis._updateDatepicker( inst );\n\t},\n\n\t/* Action for current link. */\n\t_gotoToday: function( id ) {\n\t\tvar date,\n\t\t\ttarget = $( id ),\n\t\t\tinst = this._getInst( target[ 0 ] );\n\n\t\tif ( this._get( inst, \"gotoCurrent\" ) && inst.currentDay ) {\n\t\t\tinst.selectedDay = inst.currentDay;\n\t\t\tinst.drawMonth = inst.selectedMonth = inst.currentMonth;\n\t\t\tinst.drawYear = inst.selectedYear = inst.currentYear;\n\t\t} else {\n\t\t\tdate = new Date();\n\t\t\tinst.selectedDay = date.getDate();\n\t\t\tinst.drawMonth = inst.selectedMonth = date.getMonth();\n\t\t\tinst.drawYear = inst.selectedYear = date.getFullYear();\n\t\t}\n\t\tthis._notifyChange( inst );\n\t\tthis._adjustDate( target );\n\t},\n\n\t/* Action for selecting a new month/year. */\n\t_selectMonthYear: function( id, select, period ) {\n\t\tvar target = $( id ),\n\t\t\tinst = this._getInst( target[ 0 ] );\n\n\t\tinst[ \"selected\" + ( period === \"M\" ? \"Month\" : \"Year\" ) ] =\n\t\tinst[ \"draw\" + ( period === \"M\" ? \"Month\" : \"Year\" ) ] =\n\t\t\tparseInt( select.options[ select.selectedIndex ].value, 10 );\n\n\t\tthis._notifyChange( inst );\n\t\tthis._adjustDate( target );\n\t},\n\n\t/* Action for selecting a day. */\n\t_selectDay: function( id, month, year, td ) {\n\t\tvar inst,\n\t\t\ttarget = $( id );\n\n\t\tif ( $( td ).hasClass( this._unselectableClass ) || this._isDisabledDatepicker( target[ 0 ] ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tinst = this._getInst( target[ 0 ] );\n\t\tinst.selectedDay = inst.currentDay = $( \"a\", td ).html();\n\t\tinst.selectedMonth = inst.currentMonth = month;\n\t\tinst.selectedYear = inst.currentYear = year;\n\t\tthis._selectDate( id, this._formatDate( inst,\n\t\t\tinst.currentDay, inst.currentMonth, inst.currentYear ) );\n\t},\n\n\t/* Erase the input field and hide the date picker. */\n\t_clearDate: function( id ) {\n\t\tvar target = $( id );\n\t\tthis._selectDate( target, \"\" );\n\t},\n\n\t/* Update the input field with the selected date. */\n\t_selectDate: function( id, dateStr ) {\n\t\tvar onSelect,\n\t\t\ttarget = $( id ),\n\t\t\tinst = this._getInst( target[ 0 ] );\n\n\t\tdateStr = ( dateStr != null ? dateStr : this._formatDate( inst ) );\n\t\tif ( inst.input ) {\n\t\t\tinst.input.val( dateStr );\n\t\t}\n\t\tthis._updateAlternate( inst );\n\n\t\tonSelect = this._get( inst, \"onSelect\" );\n\t\tif ( onSelect ) {\n\t\t\tonSelect.apply( ( inst.input ? inst.input[ 0 ] : null ), [ dateStr, inst ] );  // trigger custom callback\n\t\t} else if ( inst.input ) {\n\t\t\tinst.input.trigger( \"change\" ); // fire the change event\n\t\t}\n\n\t\tif ( inst.inline ) {\n\t\t\tthis._updateDatepicker( inst );\n\t\t} else {\n\t\t\tthis._hideDatepicker();\n\t\t\tthis._lastInput = inst.input[ 0 ];\n\t\t\tif ( typeof( inst.input[ 0 ] ) !== \"object\" ) {\n\t\t\t\tinst.input.trigger( \"focus\" ); // restore focus\n\t\t\t}\n\t\t\tthis._lastInput = null;\n\t\t}\n\t},\n\n\t/* Update any alternate field to synchronise with the main field. */\n\t_updateAlternate: function( inst ) {\n\t\tvar altFormat, date, dateStr,\n\t\t\taltField = this._get( inst, \"altField\" );\n\n\t\tif ( altField ) { // update alternate field too\n\t\t\taltFormat = this._get( inst, \"altFormat\" ) || this._get( inst, \"dateFormat\" );\n\t\t\tdate = this._getDate( inst );\n\t\t\tdateStr = this.formatDate( altFormat, date, this._getFormatConfig( inst ) );\n\t\t\t$( altField ).val( dateStr );\n\t\t}\n\t},\n\n\t/* Set as beforeShowDay function to prevent selection of weekends.\n\t * @param  date  Date - the date to customise\n\t * @return [boolean, string] - is this date selectable?, what is its CSS class?\n\t */\n\tnoWeekends: function( date ) {\n\t\tvar day = date.getDay();\n\t\treturn [ ( day > 0 && day < 6 ), \"\" ];\n\t},\n\n\t/* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.\n\t * @param  date  Date - the date to get the week for\n\t * @return  number - the number of the week within the year that contains this date\n\t */\n\tiso8601Week: function( date ) {\n\t\tvar time,\n\t\t\tcheckDate = new Date( date.getTime() );\n\n\t\t// Find Thursday of this week starting on Monday\n\t\tcheckDate.setDate( checkDate.getDate() + 4 - ( checkDate.getDay() || 7 ) );\n\n\t\ttime = checkDate.getTime();\n\t\tcheckDate.setMonth( 0 ); // Compare with Jan 1\n\t\tcheckDate.setDate( 1 );\n\t\treturn Math.floor( Math.round( ( time - checkDate ) / 86400000 ) / 7 ) + 1;\n\t},\n\n\t/* Parse a string value into a date object.\n\t * See formatDate below for the possible formats.\n\t *\n\t * @param  format string - the expected format of the date\n\t * @param  value string - the date in the above format\n\t * @param  settings Object - attributes include:\n\t *\t\t\t\t\tshortYearCutoff  number - the cutoff year for determining the century (optional)\n\t *\t\t\t\t\tdayNamesShort\tstring[7] - abbreviated names of the days from Sunday (optional)\n\t *\t\t\t\t\tdayNames\t\tstring[7] - names of the days from Sunday (optional)\n\t *\t\t\t\t\tmonthNamesShort string[12] - abbreviated names of the months (optional)\n\t *\t\t\t\t\tmonthNames\t\tstring[12] - names of the months (optional)\n\t * @return  Date - the extracted date value or null if value is blank\n\t */\n\tparseDate: function( format, value, settings ) {\n\t\tif ( format == null || value == null ) {\n\t\t\tthrow \"Invalid arguments\";\n\t\t}\n\n\t\tvalue = ( typeof value === \"object\" ? value.toString() : value + \"\" );\n\t\tif ( value === \"\" ) {\n\t\t\treturn null;\n\t\t}\n\n\t\tvar iFormat, dim, extra,\n\t\t\tiValue = 0,\n\t\t\tshortYearCutoffTemp = ( settings ? settings.shortYearCutoff : null ) || this._defaults.shortYearCutoff,\n\t\t\tshortYearCutoff = ( typeof shortYearCutoffTemp !== \"string\" ? shortYearCutoffTemp :\n\t\t\t\tnew Date().getFullYear() % 100 + parseInt( shortYearCutoffTemp, 10 ) ),\n\t\t\tdayNamesShort = ( settings ? settings.dayNamesShort : null ) || this._defaults.dayNamesShort,\n\t\t\tdayNames = ( settings ? settings.dayNames : null ) || this._defaults.dayNames,\n\t\t\tmonthNamesShort = ( settings ? settings.monthNamesShort : null ) || this._defaults.monthNamesShort,\n\t\t\tmonthNames = ( settings ? settings.monthNames : null ) || this._defaults.monthNames,\n\t\t\tyear = -1,\n\t\t\tmonth = -1,\n\t\t\tday = -1,\n\t\t\tdoy = -1,\n\t\t\tliteral = false,\n\t\t\tdate,\n\n\t\t\t// Check whether a format character is doubled\n\t\t\tlookAhead = function( match ) {\n\t\t\t\tvar matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match );\n\t\t\t\tif ( matches ) {\n\t\t\t\t\tiFormat++;\n\t\t\t\t}\n\t\t\t\treturn matches;\n\t\t\t},\n\n\t\t\t// Extract a number from the string value\n\t\t\tgetNumber = function( match ) {\n\t\t\t\tvar isDoubled = lookAhead( match ),\n\t\t\t\t\tsize = ( match === \"@\" ? 14 : ( match === \"!\" ? 20 :\n\t\t\t\t\t( match === \"y\" && isDoubled ? 4 : ( match === \"o\" ? 3 : 2 ) ) ) ),\n\t\t\t\t\tminSize = ( match === \"y\" ? size : 1 ),\n\t\t\t\t\tdigits = new RegExp( \"^\\\\d{\" + minSize + \",\" + size + \"}\" ),\n\t\t\t\t\tnum = value.substring( iValue ).match( digits );\n\t\t\t\tif ( !num ) {\n\t\t\t\t\tthrow \"Missing number at position \" + iValue;\n\t\t\t\t}\n\t\t\t\tiValue += num[ 0 ].length;\n\t\t\t\treturn parseInt( num[ 0 ], 10 );\n\t\t\t},\n\n\t\t\t// Extract a name from the string value and convert to an index\n\t\t\tgetName = function( match, shortNames, longNames ) {\n\t\t\t\tvar index = -1,\n\t\t\t\t\tnames = $.map( lookAhead( match ) ? longNames : shortNames, function( v, k ) {\n\t\t\t\t\t\treturn [ [ k, v ] ];\n\t\t\t\t\t} ).sort( function( a, b ) {\n\t\t\t\t\t\treturn -( a[ 1 ].length - b[ 1 ].length );\n\t\t\t\t\t} );\n\n\t\t\t\t$.each( names, function( i, pair ) {\n\t\t\t\t\tvar name = pair[ 1 ];\n\t\t\t\t\tif ( value.substr( iValue, name.length ).toLowerCase() === name.toLowerCase() ) {\n\t\t\t\t\t\tindex = pair[ 0 ];\n\t\t\t\t\t\tiValue += name.length;\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t\tif ( index !== -1 ) {\n\t\t\t\t\treturn index + 1;\n\t\t\t\t} else {\n\t\t\t\t\tthrow \"Unknown name at position \" + iValue;\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t// Confirm that a literal character matches the string value\n\t\t\tcheckLiteral = function() {\n\t\t\t\tif ( value.charAt( iValue ) !== format.charAt( iFormat ) ) {\n\t\t\t\t\tthrow \"Unexpected literal at position \" + iValue;\n\t\t\t\t}\n\t\t\t\tiValue++;\n\t\t\t};\n\n\t\tfor ( iFormat = 0; iFormat < format.length; iFormat++ ) {\n\t\t\tif ( literal ) {\n\t\t\t\tif ( format.charAt( iFormat ) === \"'\" && !lookAhead( \"'\" ) ) {\n\t\t\t\t\tliteral = false;\n\t\t\t\t} else {\n\t\t\t\t\tcheckLiteral();\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tswitch ( format.charAt( iFormat ) ) {\n\t\t\t\t\tcase \"d\":\n\t\t\t\t\t\tday = getNumber( \"d\" );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"D\":\n\t\t\t\t\t\tgetName( \"D\", dayNamesShort, dayNames );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"o\":\n\t\t\t\t\t\tdoy = getNumber( \"o\" );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"m\":\n\t\t\t\t\t\tmonth = getNumber( \"m\" );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"M\":\n\t\t\t\t\t\tmonth = getName( \"M\", monthNamesShort, monthNames );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"y\":\n\t\t\t\t\t\tyear = getNumber( \"y\" );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"@\":\n\t\t\t\t\t\tdate = new Date( getNumber( \"@\" ) );\n\t\t\t\t\t\tyear = date.getFullYear();\n\t\t\t\t\t\tmonth = date.getMonth() + 1;\n\t\t\t\t\t\tday = date.getDate();\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"!\":\n\t\t\t\t\t\tdate = new Date( ( getNumber( \"!\" ) - this._ticksTo1970 ) / 10000 );\n\t\t\t\t\t\tyear = date.getFullYear();\n\t\t\t\t\t\tmonth = date.getMonth() + 1;\n\t\t\t\t\t\tday = date.getDate();\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"'\":\n\t\t\t\t\t\tif ( lookAhead( \"'\" ) ) {\n\t\t\t\t\t\t\tcheckLiteral();\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tliteral = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tcheckLiteral();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif ( iValue < value.length ) {\n\t\t\textra = value.substr( iValue );\n\t\t\tif ( !/^\\s+/.test( extra ) ) {\n\t\t\t\tthrow \"Extra/unparsed characters found in date: \" + extra;\n\t\t\t}\n\t\t}\n\n\t\tif ( year === -1 ) {\n\t\t\tyear = new Date().getFullYear();\n\t\t} else if ( year < 100 ) {\n\t\t\tyear += new Date().getFullYear() - new Date().getFullYear() % 100 +\n\t\t\t\t( year <= shortYearCutoff ? 0 : -100 );\n\t\t}\n\n\t\tif ( doy > -1 ) {\n\t\t\tmonth = 1;\n\t\t\tday = doy;\n\t\t\tdo {\n\t\t\t\tdim = this._getDaysInMonth( year, month - 1 );\n\t\t\t\tif ( day <= dim ) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tmonth++;\n\t\t\t\tday -= dim;\n\t\t\t} while ( true );\n\t\t}\n\n\t\tdate = this._daylightSavingAdjust( new Date( year, month - 1, day ) );\n\t\tif ( date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day ) {\n\t\t\tthrow \"Invalid date\"; // E.g. 31/02/00\n\t\t}\n\t\treturn date;\n\t},\n\n\t/* Standard date formats. */\n\tATOM: \"yy-mm-dd\", // RFC 3339 (ISO 8601)\n\tCOOKIE: \"D, dd M yy\",\n\tISO_8601: \"yy-mm-dd\",\n\tRFC_822: \"D, d M y\",\n\tRFC_850: \"DD, dd-M-y\",\n\tRFC_1036: \"D, d M y\",\n\tRFC_1123: \"D, d M yy\",\n\tRFC_2822: \"D, d M yy\",\n\tRSS: \"D, d M y\", // RFC 822\n\tTICKS: \"!\",\n\tTIMESTAMP: \"@\",\n\tW3C: \"yy-mm-dd\", // ISO 8601\n\n\t_ticksTo1970: ( ( ( 1970 - 1 ) * 365 + Math.floor( 1970 / 4 ) - Math.floor( 1970 / 100 ) +\n\t\tMath.floor( 1970 / 400 ) ) * 24 * 60 * 60 * 10000000 ),\n\n\t/* Format a date object into a string value.\n\t * The format can be combinations of the following:\n\t * d  - day of month (no leading zero)\n\t * dd - day of month (two digit)\n\t * o  - day of year (no leading zeros)\n\t * oo - day of year (three digit)\n\t * D  - day name short\n\t * DD - day name long\n\t * m  - month of year (no leading zero)\n\t * mm - month of year (two digit)\n\t * M  - month name short\n\t * MM - month name long\n\t * y  - year (two digit)\n\t * yy - year (four digit)\n\t * @ - Unix timestamp (ms since 01/01/1970)\n\t * ! - Windows ticks (100ns since 01/01/0001)\n\t * \"...\" - literal text\n\t * '' - single quote\n\t *\n\t * @param  format string - the desired format of the date\n\t * @param  date Date - the date value to format\n\t * @param  settings Object - attributes include:\n\t *\t\t\t\t\tdayNamesShort\tstring[7] - abbreviated names of the days from Sunday (optional)\n\t *\t\t\t\t\tdayNames\t\tstring[7] - names of the days from Sunday (optional)\n\t *\t\t\t\t\tmonthNamesShort string[12] - abbreviated names of the months (optional)\n\t *\t\t\t\t\tmonthNames\t\tstring[12] - names of the months (optional)\n\t * @return  string - the date in the above format\n\t */\n\tformatDate: function( format, date, settings ) {\n\t\tif ( !date ) {\n\t\t\treturn \"\";\n\t\t}\n\n\t\tvar iFormat,\n\t\t\tdayNamesShort = ( settings ? settings.dayNamesShort : null ) || this._defaults.dayNamesShort,\n\t\t\tdayNames = ( settings ? settings.dayNames : null ) || this._defaults.dayNames,\n\t\t\tmonthNamesShort = ( settings ? settings.monthNamesShort : null ) || this._defaults.monthNamesShort,\n\t\t\tmonthNames = ( settings ? settings.monthNames : null ) || this._defaults.monthNames,\n\n\t\t\t// Check whether a format character is doubled\n\t\t\tlookAhead = function( match ) {\n\t\t\t\tvar matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match );\n\t\t\t\tif ( matches ) {\n\t\t\t\t\tiFormat++;\n\t\t\t\t}\n\t\t\t\treturn matches;\n\t\t\t},\n\n\t\t\t// Format a number, with leading zero if necessary\n\t\t\tformatNumber = function( match, value, len ) {\n\t\t\t\tvar num = \"\" + value;\n\t\t\t\tif ( lookAhead( match ) ) {\n\t\t\t\t\twhile ( num.length < len ) {\n\t\t\t\t\t\tnum = \"0\" + num;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn num;\n\t\t\t},\n\n\t\t\t// Format a name, short or long as requested\n\t\t\tformatName = function( match, value, shortNames, longNames ) {\n\t\t\t\treturn ( lookAhead( match ) ? longNames[ value ] : shortNames[ value ] );\n\t\t\t},\n\t\t\toutput = \"\",\n\t\t\tliteral = false;\n\n\t\tif ( date ) {\n\t\t\tfor ( iFormat = 0; iFormat < format.length; iFormat++ ) {\n\t\t\t\tif ( literal ) {\n\t\t\t\t\tif ( format.charAt( iFormat ) === \"'\" && !lookAhead( \"'\" ) ) {\n\t\t\t\t\t\tliteral = false;\n\t\t\t\t\t} else {\n\t\t\t\t\t\toutput += format.charAt( iFormat );\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tswitch ( format.charAt( iFormat ) ) {\n\t\t\t\t\t\tcase \"d\":\n\t\t\t\t\t\t\toutput += formatNumber( \"d\", date.getDate(), 2 );\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"D\":\n\t\t\t\t\t\t\toutput += formatName( \"D\", date.getDay(), dayNamesShort, dayNames );\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"o\":\n\t\t\t\t\t\t\toutput += formatNumber( \"o\",\n\t\t\t\t\t\t\t\tMath.round( ( new Date( date.getFullYear(), date.getMonth(), date.getDate() ).getTime() - new Date( date.getFullYear(), 0, 0 ).getTime() ) / 86400000 ), 3 );\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"m\":\n\t\t\t\t\t\t\toutput += formatNumber( \"m\", date.getMonth() + 1, 2 );\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"M\":\n\t\t\t\t\t\t\toutput += formatName( \"M\", date.getMonth(), monthNamesShort, monthNames );\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"y\":\n\t\t\t\t\t\t\toutput += ( lookAhead( \"y\" ) ? date.getFullYear() :\n\t\t\t\t\t\t\t\t( date.getFullYear() % 100 < 10 ? \"0\" : \"\" ) + date.getFullYear() % 100 );\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"@\":\n\t\t\t\t\t\t\toutput += date.getTime();\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"!\":\n\t\t\t\t\t\t\toutput += date.getTime() * 10000 + this._ticksTo1970;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"'\":\n\t\t\t\t\t\t\tif ( lookAhead( \"'\" ) ) {\n\t\t\t\t\t\t\t\toutput += \"'\";\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tliteral = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\toutput += format.charAt( iFormat );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn output;\n\t},\n\n\t/* Extract all possible characters from the date format. */\n\t_possibleChars: function( format ) {\n\t\tvar iFormat,\n\t\t\tchars = \"\",\n\t\t\tliteral = false,\n\n\t\t\t// Check whether a format character is doubled\n\t\t\tlookAhead = function( match ) {\n\t\t\t\tvar matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match );\n\t\t\t\tif ( matches ) {\n\t\t\t\t\tiFormat++;\n\t\t\t\t}\n\t\t\t\treturn matches;\n\t\t\t};\n\n\t\tfor ( iFormat = 0; iFormat < format.length; iFormat++ ) {\n\t\t\tif ( literal ) {\n\t\t\t\tif ( format.charAt( iFormat ) === \"'\" && !lookAhead( \"'\" ) ) {\n\t\t\t\t\tliteral = false;\n\t\t\t\t} else {\n\t\t\t\t\tchars += format.charAt( iFormat );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tswitch ( format.charAt( iFormat ) ) {\n\t\t\t\t\tcase \"d\": case \"m\": case \"y\": case \"@\":\n\t\t\t\t\t\tchars += \"0123456789\";\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"D\": case \"M\":\n\t\t\t\t\t\treturn null; // Accept anything\n\t\t\t\t\tcase \"'\":\n\t\t\t\t\t\tif ( lookAhead( \"'\" ) ) {\n\t\t\t\t\t\t\tchars += \"'\";\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tliteral = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tchars += format.charAt( iFormat );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn chars;\n\t},\n\n\t/* Get a setting value, defaulting if necessary. */\n\t_get: function( inst, name ) {\n\t\treturn inst.settings[ name ] !== undefined ?\n\t\t\tinst.settings[ name ] : this._defaults[ name ];\n\t},\n\n\t/* Parse existing date and initialise date picker. */\n\t_setDateFromField: function( inst, noDefault ) {\n\t\tif ( inst.input.val() === inst.lastVal ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar dateFormat = this._get( inst, \"dateFormat\" ),\n\t\t\tdates = inst.lastVal = inst.input ? inst.input.val() : null,\n\t\t\tdefaultDate = this._getDefaultDate( inst ),\n\t\t\tdate = defaultDate,\n\t\t\tsettings = this._getFormatConfig( inst );\n\n\t\ttry {\n\t\t\tdate = this.parseDate( dateFormat, dates, settings ) || defaultDate;\n\t\t} catch ( event ) {\n\t\t\tdates = ( noDefault ? \"\" : dates );\n\t\t}\n\t\tinst.selectedDay = date.getDate();\n\t\tinst.drawMonth = inst.selectedMonth = date.getMonth();\n\t\tinst.drawYear = inst.selectedYear = date.getFullYear();\n\t\tinst.currentDay = ( dates ? date.getDate() : 0 );\n\t\tinst.currentMonth = ( dates ? date.getMonth() : 0 );\n\t\tinst.currentYear = ( dates ? date.getFullYear() : 0 );\n\t\tthis._adjustInstDate( inst );\n\t},\n\n\t/* Retrieve the default date shown on opening. */\n\t_getDefaultDate: function( inst ) {\n\t\treturn this._restrictMinMax( inst,\n\t\t\tthis._determineDate( inst, this._get( inst, \"defaultDate\" ), new Date() ) );\n\t},\n\n\t/* A date may be specified as an exact value or a relative one. */\n\t_determineDate: function( inst, date, defaultDate ) {\n\t\tvar offsetNumeric = function( offset ) {\n\t\t\t\tvar date = new Date();\n\t\t\t\tdate.setDate( date.getDate() + offset );\n\t\t\t\treturn date;\n\t\t\t},\n\t\t\toffsetString = function( offset ) {\n\t\t\t\ttry {\n\t\t\t\t\treturn $.datepicker.parseDate( $.datepicker._get( inst, \"dateFormat\" ),\n\t\t\t\t\t\toffset, $.datepicker._getFormatConfig( inst ) );\n\t\t\t\t}\n\t\t\t\tcatch ( e ) {\n\n\t\t\t\t\t// Ignore\n\t\t\t\t}\n\n\t\t\t\tvar date = ( offset.toLowerCase().match( /^c/ ) ?\n\t\t\t\t\t$.datepicker._getDate( inst ) : null ) || new Date(),\n\t\t\t\t\tyear = date.getFullYear(),\n\t\t\t\t\tmonth = date.getMonth(),\n\t\t\t\t\tday = date.getDate(),\n\t\t\t\t\tpattern = /([+\\-]?[0-9]+)\\s*(d|D|w|W|m|M|y|Y)?/g,\n\t\t\t\t\tmatches = pattern.exec( offset );\n\n\t\t\t\twhile ( matches ) {\n\t\t\t\t\tswitch ( matches[ 2 ] || \"d\" ) {\n\t\t\t\t\t\tcase \"d\" : case \"D\" :\n\t\t\t\t\t\t\tday += parseInt( matches[ 1 ], 10 ); break;\n\t\t\t\t\t\tcase \"w\" : case \"W\" :\n\t\t\t\t\t\t\tday += parseInt( matches[ 1 ], 10 ) * 7; break;\n\t\t\t\t\t\tcase \"m\" : case \"M\" :\n\t\t\t\t\t\t\tmonth += parseInt( matches[ 1 ], 10 );\n\t\t\t\t\t\t\tday = Math.min( day, $.datepicker._getDaysInMonth( year, month ) );\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"y\": case \"Y\" :\n\t\t\t\t\t\t\tyear += parseInt( matches[ 1 ], 10 );\n\t\t\t\t\t\t\tday = Math.min( day, $.datepicker._getDaysInMonth( year, month ) );\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tmatches = pattern.exec( offset );\n\t\t\t\t}\n\t\t\t\treturn new Date( year, month, day );\n\t\t\t},\n\t\t\tnewDate = ( date == null || date === \"\" ? defaultDate : ( typeof date === \"string\" ? offsetString( date ) :\n\t\t\t\t( typeof date === \"number\" ? ( isNaN( date ) ? defaultDate : offsetNumeric( date ) ) : new Date( date.getTime() ) ) ) );\n\n\t\tnewDate = ( newDate && newDate.toString() === \"Invalid Date\" ? defaultDate : newDate );\n\t\tif ( newDate ) {\n\t\t\tnewDate.setHours( 0 );\n\t\t\tnewDate.setMinutes( 0 );\n\t\t\tnewDate.setSeconds( 0 );\n\t\t\tnewDate.setMilliseconds( 0 );\n\t\t}\n\t\treturn this._daylightSavingAdjust( newDate );\n\t},\n\n\t/* Handle switch to/from daylight saving.\n\t * Hours may be non-zero on daylight saving cut-over:\n\t * > 12 when midnight changeover, but then cannot generate\n\t * midnight datetime, so jump to 1AM, otherwise reset.\n\t * @param  date  (Date) the date to check\n\t * @return  (Date) the corrected date\n\t */\n\t_daylightSavingAdjust: function( date ) {\n\t\tif ( !date ) {\n\t\t\treturn null;\n\t\t}\n\t\tdate.setHours( date.getHours() > 12 ? date.getHours() + 2 : 0 );\n\t\treturn date;\n\t},\n\n\t/* Set the date(s) directly. */\n\t_setDate: function( inst, date, noChange ) {\n\t\tvar clear = !date,\n\t\t\torigMonth = inst.selectedMonth,\n\t\t\torigYear = inst.selectedYear,\n\t\t\tnewDate = this._restrictMinMax( inst, this._determineDate( inst, date, new Date() ) );\n\n\t\tinst.selectedDay = inst.currentDay = newDate.getDate();\n\t\tinst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth();\n\t\tinst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear();\n\t\tif ( ( origMonth !== inst.selectedMonth || origYear !== inst.selectedYear ) && !noChange ) {\n\t\t\tthis._notifyChange( inst );\n\t\t}\n\t\tthis._adjustInstDate( inst );\n\t\tif ( inst.input ) {\n\t\t\tinst.input.val( clear ? \"\" : this._formatDate( inst ) );\n\t\t}\n\t},\n\n\t/* Retrieve the date(s) directly. */\n\t_getDate: function( inst ) {\n\t\tvar startDate = ( !inst.currentYear || ( inst.input && inst.input.val() === \"\" ) ? null :\n\t\t\tthis._daylightSavingAdjust( new Date(\n\t\t\tinst.currentYear, inst.currentMonth, inst.currentDay ) ) );\n\t\t\treturn startDate;\n\t},\n\n\t/* Attach the onxxx handlers.  These are declared statically so\n\t * they work with static code transformers like Caja.\n\t */\n\t_attachHandlers: function( inst ) {\n\t\tvar stepMonths = this._get( inst, \"stepMonths\" ),\n\t\t\tid = \"#\" + inst.id.replace( /\\\\\\\\/g, \"\\\\\" );\n\t\tinst.dpDiv.find( \"[data-handler]\" ).map( function() {\n\t\t\tvar handler = {\n\t\t\t\tprev: function() {\n\t\t\t\t\t$.datepicker._adjustDate( id, -stepMonths, \"M\" );\n\t\t\t\t},\n\t\t\t\tnext: function() {\n\t\t\t\t\t$.datepicker._adjustDate( id, +stepMonths, \"M\" );\n\t\t\t\t},\n\t\t\t\thide: function() {\n\t\t\t\t\t$.datepicker._hideDatepicker();\n\t\t\t\t},\n\t\t\t\ttoday: function() {\n\t\t\t\t\t$.datepicker._gotoToday( id );\n\t\t\t\t},\n\t\t\t\tselectDay: function() {\n\t\t\t\t\t$.datepicker._selectDay( id, +this.getAttribute( \"data-month\" ), +this.getAttribute( \"data-year\" ), this );\n\t\t\t\t\treturn false;\n\t\t\t\t},\n\t\t\t\tselectMonth: function() {\n\t\t\t\t\t$.datepicker._selectMonthYear( id, this, \"M\" );\n\t\t\t\t\treturn false;\n\t\t\t\t},\n\t\t\t\tselectYear: function() {\n\t\t\t\t\t$.datepicker._selectMonthYear( id, this, \"Y\" );\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t};\n\t\t\t$( this ).on( this.getAttribute( \"data-event\" ), handler[ this.getAttribute( \"data-handler\" ) ] );\n\t\t} );\n\t},\n\n\t/* Generate the HTML for the current state of the date picker. */\n\t_generateHTML: function( inst ) {\n\t\tvar maxDraw, prevText, prev, nextText, next, currentText, gotoDate,\n\t\t\tcontrols, buttonPanel, firstDay, showWeek, dayNames, dayNamesMin,\n\t\t\tmonthNames, monthNamesShort, beforeShowDay, showOtherMonths,\n\t\t\tselectOtherMonths, defaultDate, html, dow, row, group, col, selectedDate,\n\t\t\tcornerClass, calender, thead, day, daysInMonth, leadDays, curRows, numRows,\n\t\t\tprintDate, dRow, tbody, daySettings, otherMonth, unselectable,\n\t\t\ttempDate = new Date(),\n\t\t\ttoday = this._daylightSavingAdjust(\n\t\t\t\tnew Date( tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate() ) ), // clear time\n\t\t\tisRTL = this._get( inst, \"isRTL\" ),\n\t\t\tshowButtonPanel = this._get( inst, \"showButtonPanel\" ),\n\t\t\thideIfNoPrevNext = this._get( inst, \"hideIfNoPrevNext\" ),\n\t\t\tnavigationAsDateFormat = this._get( inst, \"navigationAsDateFormat\" ),\n\t\t\tnumMonths = this._getNumberOfMonths( inst ),\n\t\t\tshowCurrentAtPos = this._get( inst, \"showCurrentAtPos\" ),\n\t\t\tstepMonths = this._get( inst, \"stepMonths\" ),\n\t\t\tisMultiMonth = ( numMonths[ 0 ] !== 1 || numMonths[ 1 ] !== 1 ),\n\t\t\tcurrentDate = this._daylightSavingAdjust( ( !inst.currentDay ? new Date( 9999, 9, 9 ) :\n\t\t\t\tnew Date( inst.currentYear, inst.currentMonth, inst.currentDay ) ) ),\n\t\t\tminDate = this._getMinMaxDate( inst, \"min\" ),\n\t\t\tmaxDate = this._getMinMaxDate( inst, \"max\" ),\n\t\t\tdrawMonth = inst.drawMonth - showCurrentAtPos,\n\t\t\tdrawYear = inst.drawYear;\n\n\t\tif ( drawMonth < 0 ) {\n\t\t\tdrawMonth += 12;\n\t\t\tdrawYear--;\n\t\t}\n\t\tif ( maxDate ) {\n\t\t\tmaxDraw = this._daylightSavingAdjust( new Date( maxDate.getFullYear(),\n\t\t\t\tmaxDate.getMonth() - ( numMonths[ 0 ] * numMonths[ 1 ] ) + 1, maxDate.getDate() ) );\n\t\t\tmaxDraw = ( minDate && maxDraw < minDate ? minDate : maxDraw );\n\t\t\twhile ( this._daylightSavingAdjust( new Date( drawYear, drawMonth, 1 ) ) > maxDraw ) {\n\t\t\t\tdrawMonth--;\n\t\t\t\tif ( drawMonth < 0 ) {\n\t\t\t\t\tdrawMonth = 11;\n\t\t\t\t\tdrawYear--;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tinst.drawMonth = drawMonth;\n\t\tinst.drawYear = drawYear;\n\n\t\tprevText = this._get( inst, \"prevText\" );\n\t\tprevText = ( !navigationAsDateFormat ? prevText : this.formatDate( prevText,\n\t\t\tthis._daylightSavingAdjust( new Date( drawYear, drawMonth - stepMonths, 1 ) ),\n\t\t\tthis._getFormatConfig( inst ) ) );\n\n\t\tprev = ( this._canAdjustMonth( inst, -1, drawYear, drawMonth ) ?\n\t\t\t\"<a class='ui-datepicker-prev ui-corner-all' data-handler='prev' data-event='click'\" +\n\t\t\t\" title='\" + prevText + \"'><span class='ui-icon ui-icon-circle-triangle-\" + ( isRTL ? \"e\" : \"w\" ) + \"'>\" + prevText + \"</span></a>\" :\n\t\t\t( hideIfNoPrevNext ? \"\" : \"<a class='ui-datepicker-prev ui-corner-all ui-state-disabled' title='\" + prevText + \"'><span class='ui-icon ui-icon-circle-triangle-\" + ( isRTL ? \"e\" : \"w\" ) + \"'>\" + prevText + \"</span></a>\" ) );\n\n\t\tnextText = this._get( inst, \"nextText\" );\n\t\tnextText = ( !navigationAsDateFormat ? nextText : this.formatDate( nextText,\n\t\t\tthis._daylightSavingAdjust( new Date( drawYear, drawMonth + stepMonths, 1 ) ),\n\t\t\tthis._getFormatConfig( inst ) ) );\n\n\t\tnext = ( this._canAdjustMonth( inst, +1, drawYear, drawMonth ) ?\n\t\t\t\"<a class='ui-datepicker-next ui-corner-all' data-handler='next' data-event='click'\" +\n\t\t\t\" title='\" + nextText + \"'><span class='ui-icon ui-icon-circle-triangle-\" + ( isRTL ? \"w\" : \"e\" ) + \"'>\" + nextText + \"</span></a>\" :\n\t\t\t( hideIfNoPrevNext ? \"\" : \"<a class='ui-datepicker-next ui-corner-all ui-state-disabled' title='\" + nextText + \"'><span class='ui-icon ui-icon-circle-triangle-\" + ( isRTL ? \"w\" : \"e\" ) + \"'>\" + nextText + \"</span></a>\" ) );\n\n\t\tcurrentText = this._get( inst, \"currentText\" );\n\t\tgotoDate = ( this._get( inst, \"gotoCurrent\" ) && inst.currentDay ? currentDate : today );\n\t\tcurrentText = ( !navigationAsDateFormat ? currentText :\n\t\t\tthis.formatDate( currentText, gotoDate, this._getFormatConfig( inst ) ) );\n\n\t\tcontrols = ( !inst.inline ? \"<button type='button' class='ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all' data-handler='hide' data-event='click'>\" +\n\t\t\tthis._get( inst, \"closeText\" ) + \"</button>\" : \"\" );\n\n\t\tbuttonPanel = ( showButtonPanel ) ? \"<div class='ui-datepicker-buttonpane ui-widget-content'>\" + ( isRTL ? controls : \"\" ) +\n\t\t\t( this._isInRange( inst, gotoDate ) ? \"<button type='button' class='ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all' data-handler='today' data-event='click'\" +\n\t\t\t\">\" + currentText + \"</button>\" : \"\" ) + ( isRTL ? \"\" : controls ) + \"</div>\" : \"\";\n\n\t\tfirstDay = parseInt( this._get( inst, \"firstDay\" ), 10 );\n\t\tfirstDay = ( isNaN( firstDay ) ? 0 : firstDay );\n\n\t\tshowWeek = this._get( inst, \"showWeek\" );\n\t\tdayNames = this._get( inst, \"dayNames\" );\n\t\tdayNamesMin = this._get( inst, \"dayNamesMin\" );\n\t\tmonthNames = this._get( inst, \"monthNames\" );\n\t\tmonthNamesShort = this._get( inst, \"monthNamesShort\" );\n\t\tbeforeShowDay = this._get( inst, \"beforeShowDay\" );\n\t\tshowOtherMonths = this._get( inst, \"showOtherMonths\" );\n\t\tselectOtherMonths = this._get( inst, \"selectOtherMonths\" );\n\t\tdefaultDate = this._getDefaultDate( inst );\n\t\thtml = \"\";\n\n\t\tfor ( row = 0; row < numMonths[ 0 ]; row++ ) {\n\t\t\tgroup = \"\";\n\t\t\tthis.maxRows = 4;\n\t\t\tfor ( col = 0; col < numMonths[ 1 ]; col++ ) {\n\t\t\t\tselectedDate = this._daylightSavingAdjust( new Date( drawYear, drawMonth, inst.selectedDay ) );\n\t\t\t\tcornerClass = \" ui-corner-all\";\n\t\t\t\tcalender = \"\";\n\t\t\t\tif ( isMultiMonth ) {\n\t\t\t\t\tcalender += \"<div class='ui-datepicker-group\";\n\t\t\t\t\tif ( numMonths[ 1 ] > 1 ) {\n\t\t\t\t\t\tswitch ( col ) {\n\t\t\t\t\t\t\tcase 0: calender += \" ui-datepicker-group-first\";\n\t\t\t\t\t\t\t\tcornerClass = \" ui-corner-\" + ( isRTL ? \"right\" : \"left\" ); break;\n\t\t\t\t\t\t\tcase numMonths[ 1 ] - 1: calender += \" ui-datepicker-group-last\";\n\t\t\t\t\t\t\t\tcornerClass = \" ui-corner-\" + ( isRTL ? \"left\" : \"right\" ); break;\n\t\t\t\t\t\t\tdefault: calender += \" ui-datepicker-group-middle\"; cornerClass = \"\"; break;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tcalender += \"'>\";\n\t\t\t\t}\n\t\t\t\tcalender += \"<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix\" + cornerClass + \"'>\" +\n\t\t\t\t\t( /all|left/.test( cornerClass ) && row === 0 ? ( isRTL ? next : prev ) : \"\" ) +\n\t\t\t\t\t( /all|right/.test( cornerClass ) && row === 0 ? ( isRTL ? prev : next ) : \"\" ) +\n\t\t\t\t\tthis._generateMonthYearHeader( inst, drawMonth, drawYear, minDate, maxDate,\n\t\t\t\t\trow > 0 || col > 0, monthNames, monthNamesShort ) + // draw month headers\n\t\t\t\t\t\"</div><table class='ui-datepicker-calendar'><thead>\" +\n\t\t\t\t\t\"<tr>\";\n\t\t\t\tthead = ( showWeek ? \"<th class='ui-datepicker-week-col'>\" + this._get( inst, \"weekHeader\" ) + \"</th>\" : \"\" );\n\t\t\t\tfor ( dow = 0; dow < 7; dow++ ) { // days of the week\n\t\t\t\t\tday = ( dow + firstDay ) % 7;\n\t\t\t\t\tthead += \"<th scope='col'\" + ( ( dow + firstDay + 6 ) % 7 >= 5 ? \" class='ui-datepicker-week-end'\" : \"\" ) + \">\" +\n\t\t\t\t\t\t\"<span title='\" + dayNames[ day ] + \"'>\" + dayNamesMin[ day ] + \"</span></th>\";\n\t\t\t\t}\n\t\t\t\tcalender += thead + \"</tr></thead><tbody>\";\n\t\t\t\tdaysInMonth = this._getDaysInMonth( drawYear, drawMonth );\n\t\t\t\tif ( drawYear === inst.selectedYear && drawMonth === inst.selectedMonth ) {\n\t\t\t\t\tinst.selectedDay = Math.min( inst.selectedDay, daysInMonth );\n\t\t\t\t}\n\t\t\t\tleadDays = ( this._getFirstDayOfMonth( drawYear, drawMonth ) - firstDay + 7 ) % 7;\n\t\t\t\tcurRows = Math.ceil( ( leadDays + daysInMonth ) / 7 ); // calculate the number of rows to generate\n\t\t\t\tnumRows = ( isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows ); //If multiple months, use the higher number of rows (see #7043)\n\t\t\t\tthis.maxRows = numRows;\n\t\t\t\tprintDate = this._daylightSavingAdjust( new Date( drawYear, drawMonth, 1 - leadDays ) );\n\t\t\t\tfor ( dRow = 0; dRow < numRows; dRow++ ) { // create date picker rows\n\t\t\t\t\tcalender += \"<tr>\";\n\t\t\t\t\ttbody = ( !showWeek ? \"\" : \"<td class='ui-datepicker-week-col'>\" +\n\t\t\t\t\t\tthis._get( inst, \"calculateWeek\" )( printDate ) + \"</td>\" );\n\t\t\t\t\tfor ( dow = 0; dow < 7; dow++ ) { // create date picker days\n\t\t\t\t\t\tdaySettings = ( beforeShowDay ?\n\t\t\t\t\t\t\tbeforeShowDay.apply( ( inst.input ? inst.input[ 0 ] : null ), [ printDate ] ) : [ true, \"\" ] );\n\t\t\t\t\t\totherMonth = ( printDate.getMonth() !== drawMonth );\n\t\t\t\t\t\tunselectable = ( otherMonth && !selectOtherMonths ) || !daySettings[ 0 ] ||\n\t\t\t\t\t\t\t( minDate && printDate < minDate ) || ( maxDate && printDate > maxDate );\n\t\t\t\t\t\ttbody += \"<td class='\" +\n\t\t\t\t\t\t\t( ( dow + firstDay + 6 ) % 7 >= 5 ? \" ui-datepicker-week-end\" : \"\" ) + // highlight weekends\n\t\t\t\t\t\t\t( otherMonth ? \" ui-datepicker-other-month\" : \"\" ) + // highlight days from other months\n\t\t\t\t\t\t\t( ( printDate.getTime() === selectedDate.getTime() && drawMonth === inst.selectedMonth && inst._keyEvent ) || // user pressed key\n\t\t\t\t\t\t\t( defaultDate.getTime() === printDate.getTime() && defaultDate.getTime() === selectedDate.getTime() ) ?\n\n\t\t\t\t\t\t\t// or defaultDate is current printedDate and defaultDate is selectedDate\n\t\t\t\t\t\t\t\" \" + this._dayOverClass : \"\" ) + // highlight selected day\n\t\t\t\t\t\t\t( unselectable ? \" \" + this._unselectableClass + \" ui-state-disabled\" : \"\" ) +  // highlight unselectable days\n\t\t\t\t\t\t\t( otherMonth && !showOtherMonths ? \"\" : \" \" + daySettings[ 1 ] + // highlight custom dates\n\t\t\t\t\t\t\t( printDate.getTime() === currentDate.getTime() ? \" \" + this._currentClass : \"\" ) + // highlight selected day\n\t\t\t\t\t\t\t( printDate.getTime() === today.getTime() ? \" ui-datepicker-today\" : \"\" ) ) + \"'\" + // highlight today (if different)\n\t\t\t\t\t\t\t( ( !otherMonth || showOtherMonths ) && daySettings[ 2 ] ? \" title='\" + daySettings[ 2 ].replace( /'/g, \"&#39;\" ) + \"'\" : \"\" ) + // cell title\n\t\t\t\t\t\t\t( unselectable ? \"\" : \" data-handler='selectDay' data-event='click' data-month='\" + printDate.getMonth() + \"' data-year='\" + printDate.getFullYear() + \"'\" ) + \">\" + // actions\n\t\t\t\t\t\t\t( otherMonth && !showOtherMonths ? \"&#xa0;\" : // display for other months\n\t\t\t\t\t\t\t( unselectable ? \"<span class='ui-state-default'>\" + printDate.getDate() + \"</span>\" : \"<a class='ui-state-default\" +\n\t\t\t\t\t\t\t( printDate.getTime() === today.getTime() ? \" ui-state-highlight\" : \"\" ) +\n\t\t\t\t\t\t\t( printDate.getTime() === currentDate.getTime() ? \" ui-state-active\" : \"\" ) + // highlight selected day\n\t\t\t\t\t\t\t( otherMonth ? \" ui-priority-secondary\" : \"\" ) + // distinguish dates from other months\n\t\t\t\t\t\t\t\"' href='#'>\" + printDate.getDate() + \"</a>\" ) ) + \"</td>\"; // display selectable date\n\t\t\t\t\t\tprintDate.setDate( printDate.getDate() + 1 );\n\t\t\t\t\t\tprintDate = this._daylightSavingAdjust( printDate );\n\t\t\t\t\t}\n\t\t\t\t\tcalender += tbody + \"</tr>\";\n\t\t\t\t}\n\t\t\t\tdrawMonth++;\n\t\t\t\tif ( drawMonth > 11 ) {\n\t\t\t\t\tdrawMonth = 0;\n\t\t\t\t\tdrawYear++;\n\t\t\t\t}\n\t\t\t\tcalender += \"</tbody></table>\" + ( isMultiMonth ? \"</div>\" +\n\t\t\t\t\t\t\t( ( numMonths[ 0 ] > 0 && col === numMonths[ 1 ] - 1 ) ? \"<div class='ui-datepicker-row-break'></div>\" : \"\" ) : \"\" );\n\t\t\t\tgroup += calender;\n\t\t\t}\n\t\t\thtml += group;\n\t\t}\n\t\thtml += buttonPanel;\n\t\tinst._keyEvent = false;\n\t\treturn html;\n\t},\n\n\t/* Generate the month and year header. */\n\t_generateMonthYearHeader: function( inst, drawMonth, drawYear, minDate, maxDate,\n\t\t\tsecondary, monthNames, monthNamesShort ) {\n\n\t\tvar inMinYear, inMaxYear, month, years, thisYear, determineYear, year, endYear,\n\t\t\tchangeMonth = this._get( inst, \"changeMonth\" ),\n\t\t\tchangeYear = this._get( inst, \"changeYear\" ),\n\t\t\tshowMonthAfterYear = this._get( inst, \"showMonthAfterYear\" ),\n\t\t\thtml = \"<div class='ui-datepicker-title'>\",\n\t\t\tmonthHtml = \"\";\n\n\t\t// Month selection\n\t\tif ( secondary || !changeMonth ) {\n\t\t\tmonthHtml += \"<span class='ui-datepicker-month'>\" + monthNames[ drawMonth ] + \"</span>\";\n\t\t} else {\n\t\t\tinMinYear = ( minDate && minDate.getFullYear() === drawYear );\n\t\t\tinMaxYear = ( maxDate && maxDate.getFullYear() === drawYear );\n\t\t\tmonthHtml += \"<select class='ui-datepicker-month' data-handler='selectMonth' data-event='change'>\";\n\t\t\tfor ( month = 0; month < 12; month++ ) {\n\t\t\t\tif ( ( !inMinYear || month >= minDate.getMonth() ) && ( !inMaxYear || month <= maxDate.getMonth() ) ) {\n\t\t\t\t\tmonthHtml += \"<option value='\" + month + \"'\" +\n\t\t\t\t\t\t( month === drawMonth ? \" selected='selected'\" : \"\" ) +\n\t\t\t\t\t\t\">\" + monthNamesShort[ month ] + \"</option>\";\n\t\t\t\t}\n\t\t\t}\n\t\t\tmonthHtml += \"</select>\";\n\t\t}\n\n\t\tif ( !showMonthAfterYear ) {\n\t\t\thtml += monthHtml + ( secondary || !( changeMonth && changeYear ) ? \"&#xa0;\" : \"\" );\n\t\t}\n\n\t\t// Year selection\n\t\tif ( !inst.yearshtml ) {\n\t\t\tinst.yearshtml = \"\";\n\t\t\tif ( secondary || !changeYear ) {\n\t\t\t\thtml += \"<span class='ui-datepicker-year'>\" + drawYear + \"</span>\";\n\t\t\t} else {\n\n\t\t\t\t// determine range of years to display\n\t\t\t\tyears = this._get( inst, \"yearRange\" ).split( \":\" );\n\t\t\t\tthisYear = new Date().getFullYear();\n\t\t\t\tdetermineYear = function( value ) {\n\t\t\t\t\tvar year = ( value.match( /c[+\\-].*/ ) ? drawYear + parseInt( value.substring( 1 ), 10 ) :\n\t\t\t\t\t\t( value.match( /[+\\-].*/ ) ? thisYear + parseInt( value, 10 ) :\n\t\t\t\t\t\tparseInt( value, 10 ) ) );\n\t\t\t\t\treturn ( isNaN( year ) ? thisYear : year );\n\t\t\t\t};\n\t\t\t\tyear = determineYear( years[ 0 ] );\n\t\t\t\tendYear = Math.max( year, determineYear( years[ 1 ] || \"\" ) );\n\t\t\t\tyear = ( minDate ? Math.max( year, minDate.getFullYear() ) : year );\n\t\t\t\tendYear = ( maxDate ? Math.min( endYear, maxDate.getFullYear() ) : endYear );\n\t\t\t\tinst.yearshtml += \"<select class='ui-datepicker-year' data-handler='selectYear' data-event='change'>\";\n\t\t\t\tfor ( ; year <= endYear; year++ ) {\n\t\t\t\t\tinst.yearshtml += \"<option value='\" + year + \"'\" +\n\t\t\t\t\t\t( year === drawYear ? \" selected='selected'\" : \"\" ) +\n\t\t\t\t\t\t\">\" + year + \"</option>\";\n\t\t\t\t}\n\t\t\t\tinst.yearshtml += \"</select>\";\n\n\t\t\t\thtml += inst.yearshtml;\n\t\t\t\tinst.yearshtml = null;\n\t\t\t}\n\t\t}\n\n\t\thtml += this._get( inst, \"yearSuffix\" );\n\t\tif ( showMonthAfterYear ) {\n\t\t\thtml += ( secondary || !( changeMonth && changeYear ) ? \"&#xa0;\" : \"\" ) + monthHtml;\n\t\t}\n\t\thtml += \"</div>\"; // Close datepicker_header\n\t\treturn html;\n\t},\n\n\t/* Adjust one of the date sub-fields. */\n\t_adjustInstDate: function( inst, offset, period ) {\n\t\tvar year = inst.selectedYear + ( period === \"Y\" ? offset : 0 ),\n\t\t\tmonth = inst.selectedMonth + ( period === \"M\" ? offset : 0 ),\n\t\t\tday = Math.min( inst.selectedDay, this._getDaysInMonth( year, month ) ) + ( period === \"D\" ? offset : 0 ),\n\t\t\tdate = this._restrictMinMax( inst, this._daylightSavingAdjust( new Date( year, month, day ) ) );\n\n\t\tinst.selectedDay = date.getDate();\n\t\tinst.drawMonth = inst.selectedMonth = date.getMonth();\n\t\tinst.drawYear = inst.selectedYear = date.getFullYear();\n\t\tif ( period === \"M\" || period === \"Y\" ) {\n\t\t\tthis._notifyChange( inst );\n\t\t}\n\t},\n\n\t/* Ensure a date is within any min/max bounds. */\n\t_restrictMinMax: function( inst, date ) {\n\t\tvar minDate = this._getMinMaxDate( inst, \"min\" ),\n\t\t\tmaxDate = this._getMinMaxDate( inst, \"max\" ),\n\t\t\tnewDate = ( minDate && date < minDate ? minDate : date );\n\t\treturn ( maxDate && newDate > maxDate ? maxDate : newDate );\n\t},\n\n\t/* Notify change of month/year. */\n\t_notifyChange: function( inst ) {\n\t\tvar onChange = this._get( inst, \"onChangeMonthYear\" );\n\t\tif ( onChange ) {\n\t\t\tonChange.apply( ( inst.input ? inst.input[ 0 ] : null ),\n\t\t\t\t[ inst.selectedYear, inst.selectedMonth + 1, inst ] );\n\t\t}\n\t},\n\n\t/* Determine the number of months to show. */\n\t_getNumberOfMonths: function( inst ) {\n\t\tvar numMonths = this._get( inst, \"numberOfMonths\" );\n\t\treturn ( numMonths == null ? [ 1, 1 ] : ( typeof numMonths === \"number\" ? [ 1, numMonths ] : numMonths ) );\n\t},\n\n\t/* Determine the current maximum date - ensure no time components are set. */\n\t_getMinMaxDate: function( inst, minMax ) {\n\t\treturn this._determineDate( inst, this._get( inst, minMax + \"Date\" ), null );\n\t},\n\n\t/* Find the number of days in a given month. */\n\t_getDaysInMonth: function( year, month ) {\n\t\treturn 32 - this._daylightSavingAdjust( new Date( year, month, 32 ) ).getDate();\n\t},\n\n\t/* Find the day of the week of the first of a month. */\n\t_getFirstDayOfMonth: function( year, month ) {\n\t\treturn new Date( year, month, 1 ).getDay();\n\t},\n\n\t/* Determines if we should allow a \"next/prev\" month display change. */\n\t_canAdjustMonth: function( inst, offset, curYear, curMonth ) {\n\t\tvar numMonths = this._getNumberOfMonths( inst ),\n\t\t\tdate = this._daylightSavingAdjust( new Date( curYear,\n\t\t\tcurMonth + ( offset < 0 ? offset : numMonths[ 0 ] * numMonths[ 1 ] ), 1 ) );\n\n\t\tif ( offset < 0 ) {\n\t\t\tdate.setDate( this._getDaysInMonth( date.getFullYear(), date.getMonth() ) );\n\t\t}\n\t\treturn this._isInRange( inst, date );\n\t},\n\n\t/* Is the given date in the accepted range? */\n\t_isInRange: function( inst, date ) {\n\t\tvar yearSplit, currentYear,\n\t\t\tminDate = this._getMinMaxDate( inst, \"min\" ),\n\t\t\tmaxDate = this._getMinMaxDate( inst, \"max\" ),\n\t\t\tminYear = null,\n\t\t\tmaxYear = null,\n\t\t\tyears = this._get( inst, \"yearRange\" );\n\t\t\tif ( years ) {\n\t\t\t\tyearSplit = years.split( \":\" );\n\t\t\t\tcurrentYear = new Date().getFullYear();\n\t\t\t\tminYear = parseInt( yearSplit[ 0 ], 10 );\n\t\t\t\tmaxYear = parseInt( yearSplit[ 1 ], 10 );\n\t\t\t\tif ( yearSplit[ 0 ].match( /[+\\-].*/ ) ) {\n\t\t\t\t\tminYear += currentYear;\n\t\t\t\t}\n\t\t\t\tif ( yearSplit[ 1 ].match( /[+\\-].*/ ) ) {\n\t\t\t\t\tmaxYear += currentYear;\n\t\t\t\t}\n\t\t\t}\n\n\t\treturn ( ( !minDate || date.getTime() >= minDate.getTime() ) &&\n\t\t\t( !maxDate || date.getTime() <= maxDate.getTime() ) &&\n\t\t\t( !minYear || date.getFullYear() >= minYear ) &&\n\t\t\t( !maxYear || date.getFullYear() <= maxYear ) );\n\t},\n\n\t/* Provide the configuration settings for formatting/parsing. */\n\t_getFormatConfig: function( inst ) {\n\t\tvar shortYearCutoff = this._get( inst, \"shortYearCutoff\" );\n\t\tshortYearCutoff = ( typeof shortYearCutoff !== \"string\" ? shortYearCutoff :\n\t\t\tnew Date().getFullYear() % 100 + parseInt( shortYearCutoff, 10 ) );\n\t\treturn { shortYearCutoff: shortYearCutoff,\n\t\t\tdayNamesShort: this._get( inst, \"dayNamesShort\" ), dayNames: this._get( inst, \"dayNames\" ),\n\t\t\tmonthNamesShort: this._get( inst, \"monthNamesShort\" ), monthNames: this._get( inst, \"monthNames\" ) };\n\t},\n\n\t/* Format the given date for display. */\n\t_formatDate: function( inst, day, month, year ) {\n\t\tif ( !day ) {\n\t\t\tinst.currentDay = inst.selectedDay;\n\t\t\tinst.currentMonth = inst.selectedMonth;\n\t\t\tinst.currentYear = inst.selectedYear;\n\t\t}\n\t\tvar date = ( day ? ( typeof day === \"object\" ? day :\n\t\t\tthis._daylightSavingAdjust( new Date( year, month, day ) ) ) :\n\t\t\tthis._daylightSavingAdjust( new Date( inst.currentYear, inst.currentMonth, inst.currentDay ) ) );\n\t\treturn this.formatDate( this._get( inst, \"dateFormat\" ), date, this._getFormatConfig( inst ) );\n\t}\n} );\n\n/*\n * Bind hover events for datepicker elements.\n * Done via delegate so the binding only occurs once in the lifetime of the parent div.\n * Global datepicker_instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker.\n */\nfunction datepicker_bindHover( dpDiv ) {\n\tvar selector = \"button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a\";\n\treturn dpDiv.on( \"mouseout\", selector, function() {\n\t\t\t$( this ).removeClass( \"ui-state-hover\" );\n\t\t\tif ( this.className.indexOf( \"ui-datepicker-prev\" ) !== -1 ) {\n\t\t\t\t$( this ).removeClass( \"ui-datepicker-prev-hover\" );\n\t\t\t}\n\t\t\tif ( this.className.indexOf( \"ui-datepicker-next\" ) !== -1 ) {\n\t\t\t\t$( this ).removeClass( \"ui-datepicker-next-hover\" );\n\t\t\t}\n\t\t} )\n\t\t.on( \"mouseover\", selector, datepicker_handleMouseover );\n}\n\nfunction datepicker_handleMouseover() {\n\tif ( !$.datepicker._isDisabledDatepicker( datepicker_instActive.inline ? datepicker_instActive.dpDiv.parent()[ 0 ] : datepicker_instActive.input[ 0 ] ) ) {\n\t\t$( this ).parents( \".ui-datepicker-calendar\" ).find( \"a\" ).removeClass( \"ui-state-hover\" );\n\t\t$( this ).addClass( \"ui-state-hover\" );\n\t\tif ( this.className.indexOf( \"ui-datepicker-prev\" ) !== -1 ) {\n\t\t\t$( this ).addClass( \"ui-datepicker-prev-hover\" );\n\t\t}\n\t\tif ( this.className.indexOf( \"ui-datepicker-next\" ) !== -1 ) {\n\t\t\t$( this ).addClass( \"ui-datepicker-next-hover\" );\n\t\t}\n\t}\n}\n\n/* jQuery extend now ignores nulls! */\nfunction datepicker_extendRemove( target, props ) {\n\t$.extend( target, props );\n\tfor ( var name in props ) {\n\t\tif ( props[ name ] == null ) {\n\t\t\ttarget[ name ] = props[ name ];\n\t\t}\n\t}\n\treturn target;\n}\n\n/* Invoke the datepicker functionality.\n   @param  options  string - a command, optionally followed by additional parameters or\n\t\t\t\t\tObject - settings for attaching new datepicker functionality\n   @return  jQuery object */\n$.fn.datepicker = function( options ) {\n\n\t/* Verify an empty collection wasn't passed - Fixes #6976 */\n\tif ( !this.length ) {\n\t\treturn this;\n\t}\n\n\t/* Initialise the date picker. */\n\tif ( !$.datepicker.initialized ) {\n\t\t$( document ).on( \"mousedown\", $.datepicker._checkExternalClick );\n\t\t$.datepicker.initialized = true;\n\t}\n\n\t/* Append datepicker main container to body if not exist. */\n\tif ( $( \"#\" + $.datepicker._mainDivId ).length === 0 ) {\n\t\t$( \"body\" ).append( $.datepicker.dpDiv );\n\t}\n\n\tvar otherArgs = Array.prototype.slice.call( arguments, 1 );\n\tif ( typeof options === \"string\" && ( options === \"isDisabled\" || options === \"getDate\" || options === \"widget\" ) ) {\n\t\treturn $.datepicker[ \"_\" + options + \"Datepicker\" ].\n\t\t\tapply( $.datepicker, [ this[ 0 ] ].concat( otherArgs ) );\n\t}\n\tif ( options === \"option\" && arguments.length === 2 && typeof arguments[ 1 ] === \"string\" ) {\n\t\treturn $.datepicker[ \"_\" + options + \"Datepicker\" ].\n\t\t\tapply( $.datepicker, [ this[ 0 ] ].concat( otherArgs ) );\n\t}\n\treturn this.each( function() {\n\t\ttypeof options === \"string\" ?\n\t\t\t$.datepicker[ \"_\" + options + \"Datepicker\" ].\n\t\t\t\tapply( $.datepicker, [ this ].concat( otherArgs ) ) :\n\t\t\t$.datepicker._attachDatepicker( this, options );\n\t} );\n};\n\n$.datepicker = new Datepicker(); // singleton instance\n$.datepicker.initialized = false;\n$.datepicker.uuid = new Date().getTime();\n$.datepicker.version = \"1.12.1\";\n\nvar widgetsDatepicker = $.datepicker;\n\n\n/*!\n * jQuery UI Tooltip 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Tooltip\n//>>group: Widgets\n//>>description: Shows additional information for any element on hover or focus.\n//>>docs: http://api.jqueryui.com/tooltip/\n//>>demos: http://jqueryui.com/tooltip/\n//>>css.structure: ../../themes/base/core.css\n//>>css.structure: ../../themes/base/tooltip.css\n//>>css.theme: ../../themes/base/theme.css\n\n\n\n$.widget( \"ui.tooltip\", {\n\tversion: \"1.12.1\",\n\toptions: {\n\t\tclasses: {\n\t\t\t\"ui-tooltip\": \"ui-corner-all ui-widget-shadow\"\n\t\t},\n\t\tcontent: function() {\n\n\t\t\t// support: IE<9, Opera in jQuery <1.7\n\t\t\t// .text() can't accept undefined, so coerce to a string\n\t\t\tvar title = $( this ).attr( \"title\" ) || \"\";\n\n\t\t\t// Escape title, since we're going from an attribute to raw HTML\n\t\t\treturn $( \"<a>\" ).text( title ).html();\n\t\t},\n\t\thide: true,\n\n\t\t// Disabled elements have inconsistent behavior across browsers (#8661)\n\t\titems: \"[title]:not([disabled])\",\n\t\tposition: {\n\t\t\tmy: \"left top+15\",\n\t\t\tat: \"left bottom\",\n\t\t\tcollision: \"flipfit flip\"\n\t\t},\n\t\tshow: true,\n\t\ttrack: false,\n\n\t\t// Callbacks\n\t\tclose: null,\n\t\topen: null\n\t},\n\n\t_addDescribedBy: function( elem, id ) {\n\t\tvar describedby = ( elem.attr( \"aria-describedby\" ) || \"\" ).split( /\\s+/ );\n\t\tdescribedby.push( id );\n\t\telem\n\t\t\t.data( \"ui-tooltip-id\", id )\n\t\t\t.attr( \"aria-describedby\", $.trim( describedby.join( \" \" ) ) );\n\t},\n\n\t_removeDescribedBy: function( elem ) {\n\t\tvar id = elem.data( \"ui-tooltip-id\" ),\n\t\t\tdescribedby = ( elem.attr( \"aria-describedby\" ) || \"\" ).split( /\\s+/ ),\n\t\t\tindex = $.inArray( id, describedby );\n\n\t\tif ( index !== -1 ) {\n\t\t\tdescribedby.splice( index, 1 );\n\t\t}\n\n\t\telem.removeData( \"ui-tooltip-id\" );\n\t\tdescribedby = $.trim( describedby.join( \" \" ) );\n\t\tif ( describedby ) {\n\t\t\telem.attr( \"aria-describedby\", describedby );\n\t\t} else {\n\t\t\telem.removeAttr( \"aria-describedby\" );\n\t\t}\n\t},\n\n\t_create: function() {\n\t\tthis._on( {\n\t\t\tmouseover: \"open\",\n\t\t\tfocusin: \"open\"\n\t\t} );\n\n\t\t// IDs of generated tooltips, needed for destroy\n\t\tthis.tooltips = {};\n\n\t\t// IDs of parent tooltips where we removed the title attribute\n\t\tthis.parents = {};\n\n\t\t// Append the aria-live region so tooltips announce correctly\n\t\tthis.liveRegion = $( \"<div>\" )\n\t\t\t.attr( {\n\t\t\t\trole: \"log\",\n\t\t\t\t\"aria-live\": \"assertive\",\n\t\t\t\t\"aria-relevant\": \"additions\"\n\t\t\t} )\n\t\t\t.appendTo( this.document[ 0 ].body );\n\t\tthis._addClass( this.liveRegion, null, \"ui-helper-hidden-accessible\" );\n\n\t\tthis.disabledTitles = $( [] );\n\t},\n\n\t_setOption: function( key, value ) {\n\t\tvar that = this;\n\n\t\tthis._super( key, value );\n\n\t\tif ( key === \"content\" ) {\n\t\t\t$.each( this.tooltips, function( id, tooltipData ) {\n\t\t\t\tthat._updateContent( tooltipData.element );\n\t\t\t} );\n\t\t}\n\t},\n\n\t_setOptionDisabled: function( value ) {\n\t\tthis[ value ? \"_disable\" : \"_enable\" ]();\n\t},\n\n\t_disable: function() {\n\t\tvar that = this;\n\n\t\t// Close open tooltips\n\t\t$.each( this.tooltips, function( id, tooltipData ) {\n\t\t\tvar event = $.Event( \"blur\" );\n\t\t\tevent.target = event.currentTarget = tooltipData.element[ 0 ];\n\t\t\tthat.close( event, true );\n\t\t} );\n\n\t\t// Remove title attributes to prevent native tooltips\n\t\tthis.disabledTitles = this.disabledTitles.add(\n\t\t\tthis.element.find( this.options.items ).addBack()\n\t\t\t\t.filter( function() {\n\t\t\t\t\tvar element = $( this );\n\t\t\t\t\tif ( element.is( \"[title]\" ) ) {\n\t\t\t\t\t\treturn element\n\t\t\t\t\t\t\t.data( \"ui-tooltip-title\", element.attr( \"title\" ) )\n\t\t\t\t\t\t\t.removeAttr( \"title\" );\n\t\t\t\t\t}\n\t\t\t\t} )\n\t\t);\n\t},\n\n\t_enable: function() {\n\n\t\t// restore title attributes\n\t\tthis.disabledTitles.each( function() {\n\t\t\tvar element = $( this );\n\t\t\tif ( element.data( \"ui-tooltip-title\" ) ) {\n\t\t\t\telement.attr( \"title\", element.data( \"ui-tooltip-title\" ) );\n\t\t\t}\n\t\t} );\n\t\tthis.disabledTitles = $( [] );\n\t},\n\n\topen: function( event ) {\n\t\tvar that = this,\n\t\t\ttarget = $( event ? event.target : this.element )\n\n\t\t\t\t// we need closest here due to mouseover bubbling,\n\t\t\t\t// but always pointing at the same event target\n\t\t\t\t.closest( this.options.items );\n\n\t\t// No element to show a tooltip for or the tooltip is already open\n\t\tif ( !target.length || target.data( \"ui-tooltip-id\" ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( target.attr( \"title\" ) ) {\n\t\t\ttarget.data( \"ui-tooltip-title\", target.attr( \"title\" ) );\n\t\t}\n\n\t\ttarget.data( \"ui-tooltip-open\", true );\n\n\t\t// Kill parent tooltips, custom or native, for hover\n\t\tif ( event && event.type === \"mouseover\" ) {\n\t\t\ttarget.parents().each( function() {\n\t\t\t\tvar parent = $( this ),\n\t\t\t\t\tblurEvent;\n\t\t\t\tif ( parent.data( \"ui-tooltip-open\" ) ) {\n\t\t\t\t\tblurEvent = $.Event( \"blur\" );\n\t\t\t\t\tblurEvent.target = blurEvent.currentTarget = this;\n\t\t\t\t\tthat.close( blurEvent, true );\n\t\t\t\t}\n\t\t\t\tif ( parent.attr( \"title\" ) ) {\n\t\t\t\t\tparent.uniqueId();\n\t\t\t\t\tthat.parents[ this.id ] = {\n\t\t\t\t\t\telement: this,\n\t\t\t\t\t\ttitle: parent.attr( \"title\" )\n\t\t\t\t\t};\n\t\t\t\t\tparent.attr( \"title\", \"\" );\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\n\t\tthis._registerCloseHandlers( event, target );\n\t\tthis._updateContent( target, event );\n\t},\n\n\t_updateContent: function( target, event ) {\n\t\tvar content,\n\t\t\tcontentOption = this.options.content,\n\t\t\tthat = this,\n\t\t\teventType = event ? event.type : null;\n\n\t\tif ( typeof contentOption === \"string\" || contentOption.nodeType ||\n\t\t\t\tcontentOption.jquery ) {\n\t\t\treturn this._open( event, target, contentOption );\n\t\t}\n\n\t\tcontent = contentOption.call( target[ 0 ], function( response ) {\n\n\t\t\t// IE may instantly serve a cached response for ajax requests\n\t\t\t// delay this call to _open so the other call to _open runs first\n\t\t\tthat._delay( function() {\n\n\t\t\t\t// Ignore async response if tooltip was closed already\n\t\t\t\tif ( !target.data( \"ui-tooltip-open\" ) ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// JQuery creates a special event for focusin when it doesn't\n\t\t\t\t// exist natively. To improve performance, the native event\n\t\t\t\t// object is reused and the type is changed. Therefore, we can't\n\t\t\t\t// rely on the type being correct after the event finished\n\t\t\t\t// bubbling, so we set it back to the previous value. (#8740)\n\t\t\t\tif ( event ) {\n\t\t\t\t\tevent.type = eventType;\n\t\t\t\t}\n\t\t\t\tthis._open( event, target, response );\n\t\t\t} );\n\t\t} );\n\t\tif ( content ) {\n\t\t\tthis._open( event, target, content );\n\t\t}\n\t},\n\n\t_open: function( event, target, content ) {\n\t\tvar tooltipData, tooltip, delayedShow, a11yContent,\n\t\t\tpositionOption = $.extend( {}, this.options.position );\n\n\t\tif ( !content ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Content can be updated multiple times. If the tooltip already\n\t\t// exists, then just update the content and bail.\n\t\ttooltipData = this._find( target );\n\t\tif ( tooltipData ) {\n\t\t\ttooltipData.tooltip.find( \".ui-tooltip-content\" ).html( content );\n\t\t\treturn;\n\t\t}\n\n\t\t// If we have a title, clear it to prevent the native tooltip\n\t\t// we have to check first to avoid defining a title if none exists\n\t\t// (we don't want to cause an element to start matching [title])\n\t\t//\n\t\t// We use removeAttr only for key events, to allow IE to export the correct\n\t\t// accessible attributes. For mouse events, set to empty string to avoid\n\t\t// native tooltip showing up (happens only when removing inside mouseover).\n\t\tif ( target.is( \"[title]\" ) ) {\n\t\t\tif ( event && event.type === \"mouseover\" ) {\n\t\t\t\ttarget.attr( \"title\", \"\" );\n\t\t\t} else {\n\t\t\t\ttarget.removeAttr( \"title\" );\n\t\t\t}\n\t\t}\n\n\t\ttooltipData = this._tooltip( target );\n\t\ttooltip = tooltipData.tooltip;\n\t\tthis._addDescribedBy( target, tooltip.attr( \"id\" ) );\n\t\ttooltip.find( \".ui-tooltip-content\" ).html( content );\n\n\t\t// Support: Voiceover on OS X, JAWS on IE <= 9\n\t\t// JAWS announces deletions even when aria-relevant=\"additions\"\n\t\t// Voiceover will sometimes re-read the entire log region's contents from the beginning\n\t\tthis.liveRegion.children().hide();\n\t\ta11yContent = $( \"<div>\" ).html( tooltip.find( \".ui-tooltip-content\" ).html() );\n\t\ta11yContent.removeAttr( \"name\" ).find( \"[name]\" ).removeAttr( \"name\" );\n\t\ta11yContent.removeAttr( \"id\" ).find( \"[id]\" ).removeAttr( \"id\" );\n\t\ta11yContent.appendTo( this.liveRegion );\n\n\t\tfunction position( event ) {\n\t\t\tpositionOption.of = event;\n\t\t\tif ( tooltip.is( \":hidden\" ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\ttooltip.position( positionOption );\n\t\t}\n\t\tif ( this.options.track && event && /^mouse/.test( event.type ) ) {\n\t\t\tthis._on( this.document, {\n\t\t\t\tmousemove: position\n\t\t\t} );\n\n\t\t\t// trigger once to override element-relative positioning\n\t\t\tposition( event );\n\t\t} else {\n\t\t\ttooltip.position( $.extend( {\n\t\t\t\tof: target\n\t\t\t}, this.options.position ) );\n\t\t}\n\n\t\ttooltip.hide();\n\n\t\tthis._show( tooltip, this.options.show );\n\n\t\t// Handle tracking tooltips that are shown with a delay (#8644). As soon\n\t\t// as the tooltip is visible, position the tooltip using the most recent\n\t\t// event.\n\t\t// Adds the check to add the timers only when both delay and track options are set (#14682)\n\t\tif ( this.options.track && this.options.show && this.options.show.delay ) {\n\t\t\tdelayedShow = this.delayedShow = setInterval( function() {\n\t\t\t\tif ( tooltip.is( \":visible\" ) ) {\n\t\t\t\t\tposition( positionOption.of );\n\t\t\t\t\tclearInterval( delayedShow );\n\t\t\t\t}\n\t\t\t}, $.fx.interval );\n\t\t}\n\n\t\tthis._trigger( \"open\", event, { tooltip: tooltip } );\n\t},\n\n\t_registerCloseHandlers: function( event, target ) {\n\t\tvar events = {\n\t\t\tkeyup: function( event ) {\n\t\t\t\tif ( event.keyCode === $.ui.keyCode.ESCAPE ) {\n\t\t\t\t\tvar fakeEvent = $.Event( event );\n\t\t\t\t\tfakeEvent.currentTarget = target[ 0 ];\n\t\t\t\t\tthis.close( fakeEvent, true );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\t// Only bind remove handler for delegated targets. Non-delegated\n\t\t// tooltips will handle this in destroy.\n\t\tif ( target[ 0 ] !== this.element[ 0 ] ) {\n\t\t\tevents.remove = function() {\n\t\t\t\tthis._removeTooltip( this._find( target ).tooltip );\n\t\t\t};\n\t\t}\n\n\t\tif ( !event || event.type === \"mouseover\" ) {\n\t\t\tevents.mouseleave = \"close\";\n\t\t}\n\t\tif ( !event || event.type === \"focusin\" ) {\n\t\t\tevents.focusout = \"close\";\n\t\t}\n\t\tthis._on( true, target, events );\n\t},\n\n\tclose: function( event ) {\n\t\tvar tooltip,\n\t\t\tthat = this,\n\t\t\ttarget = $( event ? event.currentTarget : this.element ),\n\t\t\ttooltipData = this._find( target );\n\n\t\t// The tooltip may already be closed\n\t\tif ( !tooltipData ) {\n\n\t\t\t// We set ui-tooltip-open immediately upon open (in open()), but only set the\n\t\t\t// additional data once there's actually content to show (in _open()). So even if the\n\t\t\t// tooltip doesn't have full data, we always remove ui-tooltip-open in case we're in\n\t\t\t// the period between open() and _open().\n\t\t\ttarget.removeData( \"ui-tooltip-open\" );\n\t\t\treturn;\n\t\t}\n\n\t\ttooltip = tooltipData.tooltip;\n\n\t\t// Disabling closes the tooltip, so we need to track when we're closing\n\t\t// to avoid an infinite loop in case the tooltip becomes disabled on close\n\t\tif ( tooltipData.closing ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Clear the interval for delayed tracking tooltips\n\t\tclearInterval( this.delayedShow );\n\n\t\t// Only set title if we had one before (see comment in _open())\n\t\t// If the title attribute has changed since open(), don't restore\n\t\tif ( target.data( \"ui-tooltip-title\" ) && !target.attr( \"title\" ) ) {\n\t\t\ttarget.attr( \"title\", target.data( \"ui-tooltip-title\" ) );\n\t\t}\n\n\t\tthis._removeDescribedBy( target );\n\n\t\ttooltipData.hiding = true;\n\t\ttooltip.stop( true );\n\t\tthis._hide( tooltip, this.options.hide, function() {\n\t\t\tthat._removeTooltip( $( this ) );\n\t\t} );\n\n\t\ttarget.removeData( \"ui-tooltip-open\" );\n\t\tthis._off( target, \"mouseleave focusout keyup\" );\n\n\t\t// Remove 'remove' binding only on delegated targets\n\t\tif ( target[ 0 ] !== this.element[ 0 ] ) {\n\t\t\tthis._off( target, \"remove\" );\n\t\t}\n\t\tthis._off( this.document, \"mousemove\" );\n\n\t\tif ( event && event.type === \"mouseleave\" ) {\n\t\t\t$.each( this.parents, function( id, parent ) {\n\t\t\t\t$( parent.element ).attr( \"title\", parent.title );\n\t\t\t\tdelete that.parents[ id ];\n\t\t\t} );\n\t\t}\n\n\t\ttooltipData.closing = true;\n\t\tthis._trigger( \"close\", event, { tooltip: tooltip } );\n\t\tif ( !tooltipData.hiding ) {\n\t\t\ttooltipData.closing = false;\n\t\t}\n\t},\n\n\t_tooltip: function( element ) {\n\t\tvar tooltip = $( \"<div>\" ).attr( \"role\", \"tooltip\" ),\n\t\t\tcontent = $( \"<div>\" ).appendTo( tooltip ),\n\t\t\tid = tooltip.uniqueId().attr( \"id\" );\n\n\t\tthis._addClass( content, \"ui-tooltip-content\" );\n\t\tthis._addClass( tooltip, \"ui-tooltip\", \"ui-widget ui-widget-content\" );\n\n\t\ttooltip.appendTo( this._appendTo( element ) );\n\n\t\treturn this.tooltips[ id ] = {\n\t\t\telement: element,\n\t\t\ttooltip: tooltip\n\t\t};\n\t},\n\n\t_find: function( target ) {\n\t\tvar id = target.data( \"ui-tooltip-id\" );\n\t\treturn id ? this.tooltips[ id ] : null;\n\t},\n\n\t_removeTooltip: function( tooltip ) {\n\t\ttooltip.remove();\n\t\tdelete this.tooltips[ tooltip.attr( \"id\" ) ];\n\t},\n\n\t_appendTo: function( target ) {\n\t\tvar element = target.closest( \".ui-front, dialog\" );\n\n\t\tif ( !element.length ) {\n\t\t\telement = this.document[ 0 ].body;\n\t\t}\n\n\t\treturn element;\n\t},\n\n\t_destroy: function() {\n\t\tvar that = this;\n\n\t\t// Close open tooltips\n\t\t$.each( this.tooltips, function( id, tooltipData ) {\n\n\t\t\t// Delegate to close method to handle common cleanup\n\t\t\tvar event = $.Event( \"blur\" ),\n\t\t\t\telement = tooltipData.element;\n\t\t\tevent.target = event.currentTarget = element[ 0 ];\n\t\t\tthat.close( event, true );\n\n\t\t\t// Remove immediately; destroying an open tooltip doesn't use the\n\t\t\t// hide animation\n\t\t\t$( \"#\" + id ).remove();\n\n\t\t\t// Restore the title\n\t\t\tif ( element.data( \"ui-tooltip-title\" ) ) {\n\n\t\t\t\t// If the title attribute has changed since open(), don't restore\n\t\t\t\tif ( !element.attr( \"title\" ) ) {\n\t\t\t\t\telement.attr( \"title\", element.data( \"ui-tooltip-title\" ) );\n\t\t\t\t}\n\t\t\t\telement.removeData( \"ui-tooltip-title\" );\n\t\t\t}\n\t\t} );\n\t\tthis.liveRegion.remove();\n\t}\n} );\n\n// DEPRECATED\n// TODO: Switch return back to widget declaration at top of file when this is removed\nif ( $.uiBackCompat !== false ) {\n\n\t// Backcompat for tooltipClass option\n\t$.widget( \"ui.tooltip\", $.ui.tooltip, {\n\t\toptions: {\n\t\t\ttooltipClass: null\n\t\t},\n\t\t_tooltip: function() {\n\t\t\tvar tooltipData = this._superApply( arguments );\n\t\t\tif ( this.options.tooltipClass ) {\n\t\t\t\ttooltipData.tooltip.addClass( this.options.tooltipClass );\n\t\t\t}\n\t\t\treturn tooltipData;\n\t\t}\n\t} );\n}\n\nvar widgetsTooltip = $.ui.tooltip;\n\n\n/*!\n * jQuery UI Effects 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Effects Core\n//>>group: Effects\n// jscs:disable maximumLineLength\n//>>description: Extends the internal jQuery effects. Includes morphing and easing. Required by all other effects.\n// jscs:enable maximumLineLength\n//>>docs: http://api.jqueryui.com/category/effects-core/\n//>>demos: http://jqueryui.com/effect/\n\n\n\nvar dataSpace = \"ui-effects-\",\n\tdataSpaceStyle = \"ui-effects-style\",\n\tdataSpaceAnimated = \"ui-effects-animated\",\n\n\t// Create a local jQuery because jQuery Color relies on it and the\n\t// global may not exist with AMD and a custom build (#10199)\n\tjQuery = $;\n\n$.effects = {\n\teffect: {}\n};\n\n/*!\n * jQuery Color Animations v2.1.2\n * https://github.com/jquery/jquery-color\n *\n * Copyright 2014 jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n *\n * Date: Wed Jan 16 08:47:09 2013 -0600\n */\n( function( jQuery, undefined ) {\n\n\tvar stepHooks = \"backgroundColor borderBottomColor borderLeftColor borderRightColor \" +\n\t\t\"borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor\",\n\n\t// Plusequals test for += 100 -= 100\n\trplusequals = /^([\\-+])=\\s*(\\d+\\.?\\d*)/,\n\n\t// A set of RE's that can match strings and generate color tuples.\n\tstringParsers = [ {\n\t\t\tre: /rgba?\\(\\s*(\\d{1,3})\\s*,\\s*(\\d{1,3})\\s*,\\s*(\\d{1,3})\\s*(?:,\\s*(\\d?(?:\\.\\d+)?)\\s*)?\\)/,\n\t\t\tparse: function( execResult ) {\n\t\t\t\treturn [\n\t\t\t\t\texecResult[ 1 ],\n\t\t\t\t\texecResult[ 2 ],\n\t\t\t\t\texecResult[ 3 ],\n\t\t\t\t\texecResult[ 4 ]\n\t\t\t\t];\n\t\t\t}\n\t\t}, {\n\t\t\tre: /rgba?\\(\\s*(\\d+(?:\\.\\d+)?)\\%\\s*,\\s*(\\d+(?:\\.\\d+)?)\\%\\s*,\\s*(\\d+(?:\\.\\d+)?)\\%\\s*(?:,\\s*(\\d?(?:\\.\\d+)?)\\s*)?\\)/,\n\t\t\tparse: function( execResult ) {\n\t\t\t\treturn [\n\t\t\t\t\texecResult[ 1 ] * 2.55,\n\t\t\t\t\texecResult[ 2 ] * 2.55,\n\t\t\t\t\texecResult[ 3 ] * 2.55,\n\t\t\t\t\texecResult[ 4 ]\n\t\t\t\t];\n\t\t\t}\n\t\t}, {\n\n\t\t\t// This regex ignores A-F because it's compared against an already lowercased string\n\t\t\tre: /#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/,\n\t\t\tparse: function( execResult ) {\n\t\t\t\treturn [\n\t\t\t\t\tparseInt( execResult[ 1 ], 16 ),\n\t\t\t\t\tparseInt( execResult[ 2 ], 16 ),\n\t\t\t\t\tparseInt( execResult[ 3 ], 16 )\n\t\t\t\t];\n\t\t\t}\n\t\t}, {\n\n\t\t\t// This regex ignores A-F because it's compared against an already lowercased string\n\t\t\tre: /#([a-f0-9])([a-f0-9])([a-f0-9])/,\n\t\t\tparse: function( execResult ) {\n\t\t\t\treturn [\n\t\t\t\t\tparseInt( execResult[ 1 ] + execResult[ 1 ], 16 ),\n\t\t\t\t\tparseInt( execResult[ 2 ] + execResult[ 2 ], 16 ),\n\t\t\t\t\tparseInt( execResult[ 3 ] + execResult[ 3 ], 16 )\n\t\t\t\t];\n\t\t\t}\n\t\t}, {\n\t\t\tre: /hsla?\\(\\s*(\\d+(?:\\.\\d+)?)\\s*,\\s*(\\d+(?:\\.\\d+)?)\\%\\s*,\\s*(\\d+(?:\\.\\d+)?)\\%\\s*(?:,\\s*(\\d?(?:\\.\\d+)?)\\s*)?\\)/,\n\t\t\tspace: \"hsla\",\n\t\t\tparse: function( execResult ) {\n\t\t\t\treturn [\n\t\t\t\t\texecResult[ 1 ],\n\t\t\t\t\texecResult[ 2 ] / 100,\n\t\t\t\t\texecResult[ 3 ] / 100,\n\t\t\t\t\texecResult[ 4 ]\n\t\t\t\t];\n\t\t\t}\n\t\t} ],\n\n\t// JQuery.Color( )\n\tcolor = jQuery.Color = function( color, green, blue, alpha ) {\n\t\treturn new jQuery.Color.fn.parse( color, green, blue, alpha );\n\t},\n\tspaces = {\n\t\trgba: {\n\t\t\tprops: {\n\t\t\t\tred: {\n\t\t\t\t\tidx: 0,\n\t\t\t\t\ttype: \"byte\"\n\t\t\t\t},\n\t\t\t\tgreen: {\n\t\t\t\t\tidx: 1,\n\t\t\t\t\ttype: \"byte\"\n\t\t\t\t},\n\t\t\t\tblue: {\n\t\t\t\t\tidx: 2,\n\t\t\t\t\ttype: \"byte\"\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\thsla: {\n\t\t\tprops: {\n\t\t\t\thue: {\n\t\t\t\t\tidx: 0,\n\t\t\t\t\ttype: \"degrees\"\n\t\t\t\t},\n\t\t\t\tsaturation: {\n\t\t\t\t\tidx: 1,\n\t\t\t\t\ttype: \"percent\"\n\t\t\t\t},\n\t\t\t\tlightness: {\n\t\t\t\t\tidx: 2,\n\t\t\t\t\ttype: \"percent\"\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\tpropTypes = {\n\t\t\"byte\": {\n\t\t\tfloor: true,\n\t\t\tmax: 255\n\t\t},\n\t\t\"percent\": {\n\t\t\tmax: 1\n\t\t},\n\t\t\"degrees\": {\n\t\t\tmod: 360,\n\t\t\tfloor: true\n\t\t}\n\t},\n\tsupport = color.support = {},\n\n\t// Element for support tests\n\tsupportElem = jQuery( \"<p>\" )[ 0 ],\n\n\t// Colors = jQuery.Color.names\n\tcolors,\n\n\t// Local aliases of functions called often\n\teach = jQuery.each;\n\n// Determine rgba support immediately\nsupportElem.style.cssText = \"background-color:rgba(1,1,1,.5)\";\nsupport.rgba = supportElem.style.backgroundColor.indexOf( \"rgba\" ) > -1;\n\n// Define cache name and alpha properties\n// for rgba and hsla spaces\neach( spaces, function( spaceName, space ) {\n\tspace.cache = \"_\" + spaceName;\n\tspace.props.alpha = {\n\t\tidx: 3,\n\t\ttype: \"percent\",\n\t\tdef: 1\n\t};\n} );\n\nfunction clamp( value, prop, allowEmpty ) {\n\tvar type = propTypes[ prop.type ] || {};\n\n\tif ( value == null ) {\n\t\treturn ( allowEmpty || !prop.def ) ? null : prop.def;\n\t}\n\n\t// ~~ is an short way of doing floor for positive numbers\n\tvalue = type.floor ? ~~value : parseFloat( value );\n\n\t// IE will pass in empty strings as value for alpha,\n\t// which will hit this case\n\tif ( isNaN( value ) ) {\n\t\treturn prop.def;\n\t}\n\n\tif ( type.mod ) {\n\n\t\t// We add mod before modding to make sure that negatives values\n\t\t// get converted properly: -10 -> 350\n\t\treturn ( value + type.mod ) % type.mod;\n\t}\n\n\t// For now all property types without mod have min and max\n\treturn 0 > value ? 0 : type.max < value ? type.max : value;\n}\n\nfunction stringParse( string ) {\n\tvar inst = color(),\n\t\trgba = inst._rgba = [];\n\n\tstring = string.toLowerCase();\n\n\teach( stringParsers, function( i, parser ) {\n\t\tvar parsed,\n\t\t\tmatch = parser.re.exec( string ),\n\t\t\tvalues = match && parser.parse( match ),\n\t\t\tspaceName = parser.space || \"rgba\";\n\n\t\tif ( values ) {\n\t\t\tparsed = inst[ spaceName ]( values );\n\n\t\t\t// If this was an rgba parse the assignment might happen twice\n\t\t\t// oh well....\n\t\t\tinst[ spaces[ spaceName ].cache ] = parsed[ spaces[ spaceName ].cache ];\n\t\t\trgba = inst._rgba = parsed._rgba;\n\n\t\t\t// Exit each( stringParsers ) here because we matched\n\t\t\treturn false;\n\t\t}\n\t} );\n\n\t// Found a stringParser that handled it\n\tif ( rgba.length ) {\n\n\t\t// If this came from a parsed string, force \"transparent\" when alpha is 0\n\t\t// chrome, (and maybe others) return \"transparent\" as rgba(0,0,0,0)\n\t\tif ( rgba.join() === \"0,0,0,0\" ) {\n\t\t\tjQuery.extend( rgba, colors.transparent );\n\t\t}\n\t\treturn inst;\n\t}\n\n\t// Named colors\n\treturn colors[ string ];\n}\n\ncolor.fn = jQuery.extend( color.prototype, {\n\tparse: function( red, green, blue, alpha ) {\n\t\tif ( red === undefined ) {\n\t\t\tthis._rgba = [ null, null, null, null ];\n\t\t\treturn this;\n\t\t}\n\t\tif ( red.jquery || red.nodeType ) {\n\t\t\tred = jQuery( red ).css( green );\n\t\t\tgreen = undefined;\n\t\t}\n\n\t\tvar inst = this,\n\t\t\ttype = jQuery.type( red ),\n\t\t\trgba = this._rgba = [];\n\n\t\t// More than 1 argument specified - assume ( red, green, blue, alpha )\n\t\tif ( green !== undefined ) {\n\t\t\tred = [ red, green, blue, alpha ];\n\t\t\ttype = \"array\";\n\t\t}\n\n\t\tif ( type === \"string\" ) {\n\t\t\treturn this.parse( stringParse( red ) || colors._default );\n\t\t}\n\n\t\tif ( type === \"array\" ) {\n\t\t\teach( spaces.rgba.props, function( key, prop ) {\n\t\t\t\trgba[ prop.idx ] = clamp( red[ prop.idx ], prop );\n\t\t\t} );\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( type === \"object\" ) {\n\t\t\tif ( red instanceof color ) {\n\t\t\t\teach( spaces, function( spaceName, space ) {\n\t\t\t\t\tif ( red[ space.cache ] ) {\n\t\t\t\t\t\tinst[ space.cache ] = red[ space.cache ].slice();\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t} else {\n\t\t\t\teach( spaces, function( spaceName, space ) {\n\t\t\t\t\tvar cache = space.cache;\n\t\t\t\t\teach( space.props, function( key, prop ) {\n\n\t\t\t\t\t\t// If the cache doesn't exist, and we know how to convert\n\t\t\t\t\t\tif ( !inst[ cache ] && space.to ) {\n\n\t\t\t\t\t\t\t// If the value was null, we don't need to copy it\n\t\t\t\t\t\t\t// if the key was alpha, we don't need to copy it either\n\t\t\t\t\t\t\tif ( key === \"alpha\" || red[ key ] == null ) {\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tinst[ cache ] = space.to( inst._rgba );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// This is the only case where we allow nulls for ALL properties.\n\t\t\t\t\t\t// call clamp with alwaysAllowEmpty\n\t\t\t\t\t\tinst[ cache ][ prop.idx ] = clamp( red[ key ], prop, true );\n\t\t\t\t\t} );\n\n\t\t\t\t\t// Everything defined but alpha?\n\t\t\t\t\tif ( inst[ cache ] &&\n\t\t\t\t\t\t\tjQuery.inArray( null, inst[ cache ].slice( 0, 3 ) ) < 0 ) {\n\n\t\t\t\t\t\t// Use the default of 1\n\t\t\t\t\t\tinst[ cache ][ 3 ] = 1;\n\t\t\t\t\t\tif ( space.from ) {\n\t\t\t\t\t\t\tinst._rgba = space.from( inst[ cache ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\t},\n\tis: function( compare ) {\n\t\tvar is = color( compare ),\n\t\t\tsame = true,\n\t\t\tinst = this;\n\n\t\teach( spaces, function( _, space ) {\n\t\t\tvar localCache,\n\t\t\t\tisCache = is[ space.cache ];\n\t\t\tif ( isCache ) {\n\t\t\t\tlocalCache = inst[ space.cache ] || space.to && space.to( inst._rgba ) || [];\n\t\t\t\teach( space.props, function( _, prop ) {\n\t\t\t\t\tif ( isCache[ prop.idx ] != null ) {\n\t\t\t\t\t\tsame = ( isCache[ prop.idx ] === localCache[ prop.idx ] );\n\t\t\t\t\t\treturn same;\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t}\n\t\t\treturn same;\n\t\t} );\n\t\treturn same;\n\t},\n\t_space: function() {\n\t\tvar used = [],\n\t\t\tinst = this;\n\t\teach( spaces, function( spaceName, space ) {\n\t\t\tif ( inst[ space.cache ] ) {\n\t\t\t\tused.push( spaceName );\n\t\t\t}\n\t\t} );\n\t\treturn used.pop();\n\t},\n\ttransition: function( other, distance ) {\n\t\tvar end = color( other ),\n\t\t\tspaceName = end._space(),\n\t\t\tspace = spaces[ spaceName ],\n\t\t\tstartColor = this.alpha() === 0 ? color( \"transparent\" ) : this,\n\t\t\tstart = startColor[ space.cache ] || space.to( startColor._rgba ),\n\t\t\tresult = start.slice();\n\n\t\tend = end[ space.cache ];\n\t\teach( space.props, function( key, prop ) {\n\t\t\tvar index = prop.idx,\n\t\t\t\tstartValue = start[ index ],\n\t\t\t\tendValue = end[ index ],\n\t\t\t\ttype = propTypes[ prop.type ] || {};\n\n\t\t\t// If null, don't override start value\n\t\t\tif ( endValue === null ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// If null - use end\n\t\t\tif ( startValue === null ) {\n\t\t\t\tresult[ index ] = endValue;\n\t\t\t} else {\n\t\t\t\tif ( type.mod ) {\n\t\t\t\t\tif ( endValue - startValue > type.mod / 2 ) {\n\t\t\t\t\t\tstartValue += type.mod;\n\t\t\t\t\t} else if ( startValue - endValue > type.mod / 2 ) {\n\t\t\t\t\t\tstartValue -= type.mod;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tresult[ index ] = clamp( ( endValue - startValue ) * distance + startValue, prop );\n\t\t\t}\n\t\t} );\n\t\treturn this[ spaceName ]( result );\n\t},\n\tblend: function( opaque ) {\n\n\t\t// If we are already opaque - return ourself\n\t\tif ( this._rgba[ 3 ] === 1 ) {\n\t\t\treturn this;\n\t\t}\n\n\t\tvar rgb = this._rgba.slice(),\n\t\t\ta = rgb.pop(),\n\t\t\tblend = color( opaque )._rgba;\n\n\t\treturn color( jQuery.map( rgb, function( v, i ) {\n\t\t\treturn ( 1 - a ) * blend[ i ] + a * v;\n\t\t} ) );\n\t},\n\ttoRgbaString: function() {\n\t\tvar prefix = \"rgba(\",\n\t\t\trgba = jQuery.map( this._rgba, function( v, i ) {\n\t\t\t\treturn v == null ? ( i > 2 ? 1 : 0 ) : v;\n\t\t\t} );\n\n\t\tif ( rgba[ 3 ] === 1 ) {\n\t\t\trgba.pop();\n\t\t\tprefix = \"rgb(\";\n\t\t}\n\n\t\treturn prefix + rgba.join() + \")\";\n\t},\n\ttoHslaString: function() {\n\t\tvar prefix = \"hsla(\",\n\t\t\thsla = jQuery.map( this.hsla(), function( v, i ) {\n\t\t\t\tif ( v == null ) {\n\t\t\t\t\tv = i > 2 ? 1 : 0;\n\t\t\t\t}\n\n\t\t\t\t// Catch 1 and 2\n\t\t\t\tif ( i && i < 3 ) {\n\t\t\t\t\tv = Math.round( v * 100 ) + \"%\";\n\t\t\t\t}\n\t\t\t\treturn v;\n\t\t\t} );\n\n\t\tif ( hsla[ 3 ] === 1 ) {\n\t\t\thsla.pop();\n\t\t\tprefix = \"hsl(\";\n\t\t}\n\t\treturn prefix + hsla.join() + \")\";\n\t},\n\ttoHexString: function( includeAlpha ) {\n\t\tvar rgba = this._rgba.slice(),\n\t\t\talpha = rgba.pop();\n\n\t\tif ( includeAlpha ) {\n\t\t\trgba.push( ~~( alpha * 255 ) );\n\t\t}\n\n\t\treturn \"#\" + jQuery.map( rgba, function( v ) {\n\n\t\t\t// Default to 0 when nulls exist\n\t\t\tv = ( v || 0 ).toString( 16 );\n\t\t\treturn v.length === 1 ? \"0\" + v : v;\n\t\t} ).join( \"\" );\n\t},\n\ttoString: function() {\n\t\treturn this._rgba[ 3 ] === 0 ? \"transparent\" : this.toRgbaString();\n\t}\n} );\ncolor.fn.parse.prototype = color.fn;\n\n// Hsla conversions adapted from:\n// https://code.google.com/p/maashaack/source/browse/packages/graphics/trunk/src/graphics/colors/HUE2RGB.as?r=5021\n\nfunction hue2rgb( p, q, h ) {\n\th = ( h + 1 ) % 1;\n\tif ( h * 6 < 1 ) {\n\t\treturn p + ( q - p ) * h * 6;\n\t}\n\tif ( h * 2 < 1 ) {\n\t\treturn q;\n\t}\n\tif ( h * 3 < 2 ) {\n\t\treturn p + ( q - p ) * ( ( 2 / 3 ) - h ) * 6;\n\t}\n\treturn p;\n}\n\nspaces.hsla.to = function( rgba ) {\n\tif ( rgba[ 0 ] == null || rgba[ 1 ] == null || rgba[ 2 ] == null ) {\n\t\treturn [ null, null, null, rgba[ 3 ] ];\n\t}\n\tvar r = rgba[ 0 ] / 255,\n\t\tg = rgba[ 1 ] / 255,\n\t\tb = rgba[ 2 ] / 255,\n\t\ta = rgba[ 3 ],\n\t\tmax = Math.max( r, g, b ),\n\t\tmin = Math.min( r, g, b ),\n\t\tdiff = max - min,\n\t\tadd = max + min,\n\t\tl = add * 0.5,\n\t\th, s;\n\n\tif ( min === max ) {\n\t\th = 0;\n\t} else if ( r === max ) {\n\t\th = ( 60 * ( g - b ) / diff ) + 360;\n\t} else if ( g === max ) {\n\t\th = ( 60 * ( b - r ) / diff ) + 120;\n\t} else {\n\t\th = ( 60 * ( r - g ) / diff ) + 240;\n\t}\n\n\t// Chroma (diff) == 0 means greyscale which, by definition, saturation = 0%\n\t// otherwise, saturation is based on the ratio of chroma (diff) to lightness (add)\n\tif ( diff === 0 ) {\n\t\ts = 0;\n\t} else if ( l <= 0.5 ) {\n\t\ts = diff / add;\n\t} else {\n\t\ts = diff / ( 2 - add );\n\t}\n\treturn [ Math.round( h ) % 360, s, l, a == null ? 1 : a ];\n};\n\nspaces.hsla.from = function( hsla ) {\n\tif ( hsla[ 0 ] == null || hsla[ 1 ] == null || hsla[ 2 ] == null ) {\n\t\treturn [ null, null, null, hsla[ 3 ] ];\n\t}\n\tvar h = hsla[ 0 ] / 360,\n\t\ts = hsla[ 1 ],\n\t\tl = hsla[ 2 ],\n\t\ta = hsla[ 3 ],\n\t\tq = l <= 0.5 ? l * ( 1 + s ) : l + s - l * s,\n\t\tp = 2 * l - q;\n\n\treturn [\n\t\tMath.round( hue2rgb( p, q, h + ( 1 / 3 ) ) * 255 ),\n\t\tMath.round( hue2rgb( p, q, h ) * 255 ),\n\t\tMath.round( hue2rgb( p, q, h - ( 1 / 3 ) ) * 255 ),\n\t\ta\n\t];\n};\n\neach( spaces, function( spaceName, space ) {\n\tvar props = space.props,\n\t\tcache = space.cache,\n\t\tto = space.to,\n\t\tfrom = space.from;\n\n\t// Makes rgba() and hsla()\n\tcolor.fn[ spaceName ] = function( value ) {\n\n\t\t// Generate a cache for this space if it doesn't exist\n\t\tif ( to && !this[ cache ] ) {\n\t\t\tthis[ cache ] = to( this._rgba );\n\t\t}\n\t\tif ( value === undefined ) {\n\t\t\treturn this[ cache ].slice();\n\t\t}\n\n\t\tvar ret,\n\t\t\ttype = jQuery.type( value ),\n\t\t\tarr = ( type === \"array\" || type === \"object\" ) ? value : arguments,\n\t\t\tlocal = this[ cache ].slice();\n\n\t\teach( props, function( key, prop ) {\n\t\t\tvar val = arr[ type === \"object\" ? key : prop.idx ];\n\t\t\tif ( val == null ) {\n\t\t\t\tval = local[ prop.idx ];\n\t\t\t}\n\t\t\tlocal[ prop.idx ] = clamp( val, prop );\n\t\t} );\n\n\t\tif ( from ) {\n\t\t\tret = color( from( local ) );\n\t\t\tret[ cache ] = local;\n\t\t\treturn ret;\n\t\t} else {\n\t\t\treturn color( local );\n\t\t}\n\t};\n\n\t// Makes red() green() blue() alpha() hue() saturation() lightness()\n\teach( props, function( key, prop ) {\n\n\t\t// Alpha is included in more than one space\n\t\tif ( color.fn[ key ] ) {\n\t\t\treturn;\n\t\t}\n\t\tcolor.fn[ key ] = function( value ) {\n\t\t\tvar vtype = jQuery.type( value ),\n\t\t\t\tfn = ( key === \"alpha\" ? ( this._hsla ? \"hsla\" : \"rgba\" ) : spaceName ),\n\t\t\t\tlocal = this[ fn ](),\n\t\t\t\tcur = local[ prop.idx ],\n\t\t\t\tmatch;\n\n\t\t\tif ( vtype === \"undefined\" ) {\n\t\t\t\treturn cur;\n\t\t\t}\n\n\t\t\tif ( vtype === \"function\" ) {\n\t\t\t\tvalue = value.call( this, cur );\n\t\t\t\tvtype = jQuery.type( value );\n\t\t\t}\n\t\t\tif ( value == null && prop.empty ) {\n\t\t\t\treturn this;\n\t\t\t}\n\t\t\tif ( vtype === \"string\" ) {\n\t\t\t\tmatch = rplusequals.exec( value );\n\t\t\t\tif ( match ) {\n\t\t\t\t\tvalue = cur + parseFloat( match[ 2 ] ) * ( match[ 1 ] === \"+\" ? 1 : -1 );\n\t\t\t\t}\n\t\t\t}\n\t\t\tlocal[ prop.idx ] = value;\n\t\t\treturn this[ fn ]( local );\n\t\t};\n\t} );\n} );\n\n// Add cssHook and .fx.step function for each named hook.\n// accept a space separated string of properties\ncolor.hook = function( hook ) {\n\tvar hooks = hook.split( \" \" );\n\teach( hooks, function( i, hook ) {\n\t\tjQuery.cssHooks[ hook ] = {\n\t\t\tset: function( elem, value ) {\n\t\t\t\tvar parsed, curElem,\n\t\t\t\t\tbackgroundColor = \"\";\n\n\t\t\t\tif ( value !== \"transparent\" && ( jQuery.type( value ) !== \"string\" ||\n\t\t\t\t\t\t( parsed = stringParse( value ) ) ) ) {\n\t\t\t\t\tvalue = color( parsed || value );\n\t\t\t\t\tif ( !support.rgba && value._rgba[ 3 ] !== 1 ) {\n\t\t\t\t\t\tcurElem = hook === \"backgroundColor\" ? elem.parentNode : elem;\n\t\t\t\t\t\twhile (\n\t\t\t\t\t\t\t( backgroundColor === \"\" || backgroundColor === \"transparent\" ) &&\n\t\t\t\t\t\t\tcurElem && curElem.style\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tbackgroundColor = jQuery.css( curElem, \"backgroundColor\" );\n\t\t\t\t\t\t\t\tcurElem = curElem.parentNode;\n\t\t\t\t\t\t\t} catch ( e ) {\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tvalue = value.blend( backgroundColor && backgroundColor !== \"transparent\" ?\n\t\t\t\t\t\t\tbackgroundColor :\n\t\t\t\t\t\t\t\"_default\" );\n\t\t\t\t\t}\n\n\t\t\t\t\tvalue = value.toRgbaString();\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\telem.style[ hook ] = value;\n\t\t\t\t} catch ( e ) {\n\n\t\t\t\t\t// Wrapped to prevent IE from throwing errors on \"invalid\" values like\n\t\t\t\t\t// 'auto' or 'inherit'\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t\tjQuery.fx.step[ hook ] = function( fx ) {\n\t\t\tif ( !fx.colorInit ) {\n\t\t\t\tfx.start = color( fx.elem, hook );\n\t\t\t\tfx.end = color( fx.end );\n\t\t\t\tfx.colorInit = true;\n\t\t\t}\n\t\t\tjQuery.cssHooks[ hook ].set( fx.elem, fx.start.transition( fx.end, fx.pos ) );\n\t\t};\n\t} );\n\n};\n\ncolor.hook( stepHooks );\n\njQuery.cssHooks.borderColor = {\n\texpand: function( value ) {\n\t\tvar expanded = {};\n\n\t\teach( [ \"Top\", \"Right\", \"Bottom\", \"Left\" ], function( i, part ) {\n\t\t\texpanded[ \"border\" + part + \"Color\" ] = value;\n\t\t} );\n\t\treturn expanded;\n\t}\n};\n\n// Basic color names only.\n// Usage of any of the other color names requires adding yourself or including\n// jquery.color.svg-names.js.\ncolors = jQuery.Color.names = {\n\n\t// 4.1. Basic color keywords\n\taqua: \"#00ffff\",\n\tblack: \"#000000\",\n\tblue: \"#0000ff\",\n\tfuchsia: \"#ff00ff\",\n\tgray: \"#808080\",\n\tgreen: \"#008000\",\n\tlime: \"#00ff00\",\n\tmaroon: \"#800000\",\n\tnavy: \"#000080\",\n\tolive: \"#808000\",\n\tpurple: \"#800080\",\n\tred: \"#ff0000\",\n\tsilver: \"#c0c0c0\",\n\tteal: \"#008080\",\n\twhite: \"#ffffff\",\n\tyellow: \"#ffff00\",\n\n\t// 4.2.3. \"transparent\" color keyword\n\ttransparent: [ null, null, null, 0 ],\n\n\t_default: \"#ffffff\"\n};\n\n} )( jQuery );\n\n/******************************************************************************/\n/****************************** CLASS ANIMATIONS ******************************/\n/******************************************************************************/\n( function() {\n\nvar classAnimationActions = [ \"add\", \"remove\", \"toggle\" ],\n\tshorthandStyles = {\n\t\tborder: 1,\n\t\tborderBottom: 1,\n\t\tborderColor: 1,\n\t\tborderLeft: 1,\n\t\tborderRight: 1,\n\t\tborderTop: 1,\n\t\tborderWidth: 1,\n\t\tmargin: 1,\n\t\tpadding: 1\n\t};\n\n$.each(\n\t[ \"borderLeftStyle\", \"borderRightStyle\", \"borderBottomStyle\", \"borderTopStyle\" ],\n\tfunction( _, prop ) {\n\t\t$.fx.step[ prop ] = function( fx ) {\n\t\t\tif ( fx.end !== \"none\" && !fx.setAttr || fx.pos === 1 && !fx.setAttr ) {\n\t\t\t\tjQuery.style( fx.elem, prop, fx.end );\n\t\t\t\tfx.setAttr = true;\n\t\t\t}\n\t\t};\n\t}\n);\n\nfunction getElementStyles( elem ) {\n\tvar key, len,\n\t\tstyle = elem.ownerDocument.defaultView ?\n\t\t\telem.ownerDocument.defaultView.getComputedStyle( elem, null ) :\n\t\t\telem.currentStyle,\n\t\tstyles = {};\n\n\tif ( style && style.length && style[ 0 ] && style[ style[ 0 ] ] ) {\n\t\tlen = style.length;\n\t\twhile ( len-- ) {\n\t\t\tkey = style[ len ];\n\t\t\tif ( typeof style[ key ] === \"string\" ) {\n\t\t\t\tstyles[ $.camelCase( key ) ] = style[ key ];\n\t\t\t}\n\t\t}\n\n\t// Support: Opera, IE <9\n\t} else {\n\t\tfor ( key in style ) {\n\t\t\tif ( typeof style[ key ] === \"string\" ) {\n\t\t\t\tstyles[ key ] = style[ key ];\n\t\t\t}\n\t\t}\n\t}\n\n\treturn styles;\n}\n\nfunction styleDifference( oldStyle, newStyle ) {\n\tvar diff = {},\n\t\tname, value;\n\n\tfor ( name in newStyle ) {\n\t\tvalue = newStyle[ name ];\n\t\tif ( oldStyle[ name ] !== value ) {\n\t\t\tif ( !shorthandStyles[ name ] ) {\n\t\t\t\tif ( $.fx.step[ name ] || !isNaN( parseFloat( value ) ) ) {\n\t\t\t\t\tdiff[ name ] = value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn diff;\n}\n\n// Support: jQuery <1.8\nif ( !$.fn.addBack ) {\n\t$.fn.addBack = function( selector ) {\n\t\treturn this.add( selector == null ?\n\t\t\tthis.prevObject : this.prevObject.filter( selector )\n\t\t);\n\t};\n}\n\n$.effects.animateClass = function( value, duration, easing, callback ) {\n\tvar o = $.speed( duration, easing, callback );\n\n\treturn this.queue( function() {\n\t\tvar animated = $( this ),\n\t\t\tbaseClass = animated.attr( \"class\" ) || \"\",\n\t\t\tapplyClassChange,\n\t\t\tallAnimations = o.children ? animated.find( \"*\" ).addBack() : animated;\n\n\t\t// Map the animated objects to store the original styles.\n\t\tallAnimations = allAnimations.map( function() {\n\t\t\tvar el = $( this );\n\t\t\treturn {\n\t\t\t\tel: el,\n\t\t\t\tstart: getElementStyles( this )\n\t\t\t};\n\t\t} );\n\n\t\t// Apply class change\n\t\tapplyClassChange = function() {\n\t\t\t$.each( classAnimationActions, function( i, action ) {\n\t\t\t\tif ( value[ action ] ) {\n\t\t\t\t\tanimated[ action + \"Class\" ]( value[ action ] );\n\t\t\t\t}\n\t\t\t} );\n\t\t};\n\t\tapplyClassChange();\n\n\t\t// Map all animated objects again - calculate new styles and diff\n\t\tallAnimations = allAnimations.map( function() {\n\t\t\tthis.end = getElementStyles( this.el[ 0 ] );\n\t\t\tthis.diff = styleDifference( this.start, this.end );\n\t\t\treturn this;\n\t\t} );\n\n\t\t// Apply original class\n\t\tanimated.attr( \"class\", baseClass );\n\n\t\t// Map all animated objects again - this time collecting a promise\n\t\tallAnimations = allAnimations.map( function() {\n\t\t\tvar styleInfo = this,\n\t\t\t\tdfd = $.Deferred(),\n\t\t\t\topts = $.extend( {}, o, {\n\t\t\t\t\tqueue: false,\n\t\t\t\t\tcomplete: function() {\n\t\t\t\t\t\tdfd.resolve( styleInfo );\n\t\t\t\t\t}\n\t\t\t\t} );\n\n\t\t\tthis.el.animate( this.diff, opts );\n\t\t\treturn dfd.promise();\n\t\t} );\n\n\t\t// Once all animations have completed:\n\t\t$.when.apply( $, allAnimations.get() ).done( function() {\n\n\t\t\t// Set the final class\n\t\t\tapplyClassChange();\n\n\t\t\t// For each animated element,\n\t\t\t// clear all css properties that were animated\n\t\t\t$.each( arguments, function() {\n\t\t\t\tvar el = this.el;\n\t\t\t\t$.each( this.diff, function( key ) {\n\t\t\t\t\tel.css( key, \"\" );\n\t\t\t\t} );\n\t\t\t} );\n\n\t\t\t// This is guarnteed to be there if you use jQuery.speed()\n\t\t\t// it also handles dequeuing the next anim...\n\t\t\to.complete.call( animated[ 0 ] );\n\t\t} );\n\t} );\n};\n\n$.fn.extend( {\n\taddClass: ( function( orig ) {\n\t\treturn function( classNames, speed, easing, callback ) {\n\t\t\treturn speed ?\n\t\t\t\t$.effects.animateClass.call( this,\n\t\t\t\t\t{ add: classNames }, speed, easing, callback ) :\n\t\t\t\torig.apply( this, arguments );\n\t\t};\n\t} )( $.fn.addClass ),\n\n\tremoveClass: ( function( orig ) {\n\t\treturn function( classNames, speed, easing, callback ) {\n\t\t\treturn arguments.length > 1 ?\n\t\t\t\t$.effects.animateClass.call( this,\n\t\t\t\t\t{ remove: classNames }, speed, easing, callback ) :\n\t\t\t\torig.apply( this, arguments );\n\t\t};\n\t} )( $.fn.removeClass ),\n\n\ttoggleClass: ( function( orig ) {\n\t\treturn function( classNames, force, speed, easing, callback ) {\n\t\t\tif ( typeof force === \"boolean\" || force === undefined ) {\n\t\t\t\tif ( !speed ) {\n\n\t\t\t\t\t// Without speed parameter\n\t\t\t\t\treturn orig.apply( this, arguments );\n\t\t\t\t} else {\n\t\t\t\t\treturn $.effects.animateClass.call( this,\n\t\t\t\t\t\t( force ? { add: classNames } : { remove: classNames } ),\n\t\t\t\t\t\tspeed, easing, callback );\n\t\t\t\t}\n\t\t\t} else {\n\n\t\t\t\t// Without force parameter\n\t\t\t\treturn $.effects.animateClass.call( this,\n\t\t\t\t\t{ toggle: classNames }, force, speed, easing );\n\t\t\t}\n\t\t};\n\t} )( $.fn.toggleClass ),\n\n\tswitchClass: function( remove, add, speed, easing, callback ) {\n\t\treturn $.effects.animateClass.call( this, {\n\t\t\tadd: add,\n\t\t\tremove: remove\n\t\t}, speed, easing, callback );\n\t}\n} );\n\n} )();\n\n/******************************************************************************/\n/*********************************** EFFECTS **********************************/\n/******************************************************************************/\n\n( function() {\n\nif ( $.expr && $.expr.filters && $.expr.filters.animated ) {\n\t$.expr.filters.animated = ( function( orig ) {\n\t\treturn function( elem ) {\n\t\t\treturn !!$( elem ).data( dataSpaceAnimated ) || orig( elem );\n\t\t};\n\t} )( $.expr.filters.animated );\n}\n\nif ( $.uiBackCompat !== false ) {\n\t$.extend( $.effects, {\n\n\t\t// Saves a set of properties in a data storage\n\t\tsave: function( element, set ) {\n\t\t\tvar i = 0, length = set.length;\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tif ( set[ i ] !== null ) {\n\t\t\t\t\telement.data( dataSpace + set[ i ], element[ 0 ].style[ set[ i ] ] );\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t// Restores a set of previously saved properties from a data storage\n\t\trestore: function( element, set ) {\n\t\t\tvar val, i = 0, length = set.length;\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tif ( set[ i ] !== null ) {\n\t\t\t\t\tval = element.data( dataSpace + set[ i ] );\n\t\t\t\t\telement.css( set[ i ], val );\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tsetMode: function( el, mode ) {\n\t\t\tif ( mode === \"toggle\" ) {\n\t\t\t\tmode = el.is( \":hidden\" ) ? \"show\" : \"hide\";\n\t\t\t}\n\t\t\treturn mode;\n\t\t},\n\n\t\t// Wraps the element around a wrapper that copies position properties\n\t\tcreateWrapper: function( element ) {\n\n\t\t\t// If the element is already wrapped, return it\n\t\t\tif ( element.parent().is( \".ui-effects-wrapper\" ) ) {\n\t\t\t\treturn element.parent();\n\t\t\t}\n\n\t\t\t// Wrap the element\n\t\t\tvar props = {\n\t\t\t\t\twidth: element.outerWidth( true ),\n\t\t\t\t\theight: element.outerHeight( true ),\n\t\t\t\t\t\"float\": element.css( \"float\" )\n\t\t\t\t},\n\t\t\t\twrapper = $( \"<div></div>\" )\n\t\t\t\t\t.addClass( \"ui-effects-wrapper\" )\n\t\t\t\t\t.css( {\n\t\t\t\t\t\tfontSize: \"100%\",\n\t\t\t\t\t\tbackground: \"transparent\",\n\t\t\t\t\t\tborder: \"none\",\n\t\t\t\t\t\tmargin: 0,\n\t\t\t\t\t\tpadding: 0\n\t\t\t\t\t} ),\n\n\t\t\t\t// Store the size in case width/height are defined in % - Fixes #5245\n\t\t\t\tsize = {\n\t\t\t\t\twidth: element.width(),\n\t\t\t\t\theight: element.height()\n\t\t\t\t},\n\t\t\t\tactive = document.activeElement;\n\n\t\t\t// Support: Firefox\n\t\t\t// Firefox incorrectly exposes anonymous content\n\t\t\t// https://bugzilla.mozilla.org/show_bug.cgi?id=561664\n\t\t\ttry {\n\t\t\t\tactive.id;\n\t\t\t} catch ( e ) {\n\t\t\t\tactive = document.body;\n\t\t\t}\n\n\t\t\telement.wrap( wrapper );\n\n\t\t\t// Fixes #7595 - Elements lose focus when wrapped.\n\t\t\tif ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {\n\t\t\t\t$( active ).trigger( \"focus\" );\n\t\t\t}\n\n\t\t\t// Hotfix for jQuery 1.4 since some change in wrap() seems to actually\n\t\t\t// lose the reference to the wrapped element\n\t\t\twrapper = element.parent();\n\n\t\t\t// Transfer positioning properties to the wrapper\n\t\t\tif ( element.css( \"position\" ) === \"static\" ) {\n\t\t\t\twrapper.css( { position: \"relative\" } );\n\t\t\t\telement.css( { position: \"relative\" } );\n\t\t\t} else {\n\t\t\t\t$.extend( props, {\n\t\t\t\t\tposition: element.css( \"position\" ),\n\t\t\t\t\tzIndex: element.css( \"z-index\" )\n\t\t\t\t} );\n\t\t\t\t$.each( [ \"top\", \"left\", \"bottom\", \"right\" ], function( i, pos ) {\n\t\t\t\t\tprops[ pos ] = element.css( pos );\n\t\t\t\t\tif ( isNaN( parseInt( props[ pos ], 10 ) ) ) {\n\t\t\t\t\t\tprops[ pos ] = \"auto\";\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t\telement.css( {\n\t\t\t\t\tposition: \"relative\",\n\t\t\t\t\ttop: 0,\n\t\t\t\t\tleft: 0,\n\t\t\t\t\tright: \"auto\",\n\t\t\t\t\tbottom: \"auto\"\n\t\t\t\t} );\n\t\t\t}\n\t\t\telement.css( size );\n\n\t\t\treturn wrapper.css( props ).show();\n\t\t},\n\n\t\tremoveWrapper: function( element ) {\n\t\t\tvar active = document.activeElement;\n\n\t\t\tif ( element.parent().is( \".ui-effects-wrapper\" ) ) {\n\t\t\t\telement.parent().replaceWith( element );\n\n\t\t\t\t// Fixes #7595 - Elements lose focus when wrapped.\n\t\t\t\tif ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {\n\t\t\t\t\t$( active ).trigger( \"focus\" );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn element;\n\t\t}\n\t} );\n}\n\n$.extend( $.effects, {\n\tversion: \"1.12.1\",\n\n\tdefine: function( name, mode, effect ) {\n\t\tif ( !effect ) {\n\t\t\teffect = mode;\n\t\t\tmode = \"effect\";\n\t\t}\n\n\t\t$.effects.effect[ name ] = effect;\n\t\t$.effects.effect[ name ].mode = mode;\n\n\t\treturn effect;\n\t},\n\n\tscaledDimensions: function( element, percent, direction ) {\n\t\tif ( percent === 0 ) {\n\t\t\treturn {\n\t\t\t\theight: 0,\n\t\t\t\twidth: 0,\n\t\t\t\touterHeight: 0,\n\t\t\t\touterWidth: 0\n\t\t\t};\n\t\t}\n\n\t\tvar x = direction !== \"horizontal\" ? ( ( percent || 100 ) / 100 ) : 1,\n\t\t\ty = direction !== \"vertical\" ? ( ( percent || 100 ) / 100 ) : 1;\n\n\t\treturn {\n\t\t\theight: element.height() * y,\n\t\t\twidth: element.width() * x,\n\t\t\touterHeight: element.outerHeight() * y,\n\t\t\touterWidth: element.outerWidth() * x\n\t\t};\n\n\t},\n\n\tclipToBox: function( animation ) {\n\t\treturn {\n\t\t\twidth: animation.clip.right - animation.clip.left,\n\t\t\theight: animation.clip.bottom - animation.clip.top,\n\t\t\tleft: animation.clip.left,\n\t\t\ttop: animation.clip.top\n\t\t};\n\t},\n\n\t// Injects recently queued functions to be first in line (after \"inprogress\")\n\tunshift: function( element, queueLength, count ) {\n\t\tvar queue = element.queue();\n\n\t\tif ( queueLength > 1 ) {\n\t\t\tqueue.splice.apply( queue,\n\t\t\t\t[ 1, 0 ].concat( queue.splice( queueLength, count ) ) );\n\t\t}\n\t\telement.dequeue();\n\t},\n\n\tsaveStyle: function( element ) {\n\t\telement.data( dataSpaceStyle, element[ 0 ].style.cssText );\n\t},\n\n\trestoreStyle: function( element ) {\n\t\telement[ 0 ].style.cssText = element.data( dataSpaceStyle ) || \"\";\n\t\telement.removeData( dataSpaceStyle );\n\t},\n\n\tmode: function( element, mode ) {\n\t\tvar hidden = element.is( \":hidden\" );\n\n\t\tif ( mode === \"toggle\" ) {\n\t\t\tmode = hidden ? \"show\" : \"hide\";\n\t\t}\n\t\tif ( hidden ? mode === \"hide\" : mode === \"show\" ) {\n\t\t\tmode = \"none\";\n\t\t}\n\t\treturn mode;\n\t},\n\n\t// Translates a [top,left] array into a baseline value\n\tgetBaseline: function( origin, original ) {\n\t\tvar y, x;\n\n\t\tswitch ( origin[ 0 ] ) {\n\t\tcase \"top\":\n\t\t\ty = 0;\n\t\t\tbreak;\n\t\tcase \"middle\":\n\t\t\ty = 0.5;\n\t\t\tbreak;\n\t\tcase \"bottom\":\n\t\t\ty = 1;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\ty = origin[ 0 ] / original.height;\n\t\t}\n\n\t\tswitch ( origin[ 1 ] ) {\n\t\tcase \"left\":\n\t\t\tx = 0;\n\t\t\tbreak;\n\t\tcase \"center\":\n\t\t\tx = 0.5;\n\t\t\tbreak;\n\t\tcase \"right\":\n\t\t\tx = 1;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tx = origin[ 1 ] / original.width;\n\t\t}\n\n\t\treturn {\n\t\t\tx: x,\n\t\t\ty: y\n\t\t};\n\t},\n\n\t// Creates a placeholder element so that the original element can be made absolute\n\tcreatePlaceholder: function( element ) {\n\t\tvar placeholder,\n\t\t\tcssPosition = element.css( \"position\" ),\n\t\t\tposition = element.position();\n\n\t\t// Lock in margins first to account for form elements, which\n\t\t// will change margin if you explicitly set height\n\t\t// see: http://jsfiddle.net/JZSMt/3/ https://bugs.webkit.org/show_bug.cgi?id=107380\n\t\t// Support: Safari\n\t\telement.css( {\n\t\t\tmarginTop: element.css( \"marginTop\" ),\n\t\t\tmarginBottom: element.css( \"marginBottom\" ),\n\t\t\tmarginLeft: element.css( \"marginLeft\" ),\n\t\t\tmarginRight: element.css( \"marginRight\" )\n\t\t} )\n\t\t.outerWidth( element.outerWidth() )\n\t\t.outerHeight( element.outerHeight() );\n\n\t\tif ( /^(static|relative)/.test( cssPosition ) ) {\n\t\t\tcssPosition = \"absolute\";\n\n\t\t\tplaceholder = $( \"<\" + element[ 0 ].nodeName + \">\" ).insertAfter( element ).css( {\n\n\t\t\t\t// Convert inline to inline block to account for inline elements\n\t\t\t\t// that turn to inline block based on content (like img)\n\t\t\t\tdisplay: /^(inline|ruby)/.test( element.css( \"display\" ) ) ?\n\t\t\t\t\t\"inline-block\" :\n\t\t\t\t\t\"block\",\n\t\t\t\tvisibility: \"hidden\",\n\n\t\t\t\t// Margins need to be set to account for margin collapse\n\t\t\t\tmarginTop: element.css( \"marginTop\" ),\n\t\t\t\tmarginBottom: element.css( \"marginBottom\" ),\n\t\t\t\tmarginLeft: element.css( \"marginLeft\" ),\n\t\t\t\tmarginRight: element.css( \"marginRight\" ),\n\t\t\t\t\"float\": element.css( \"float\" )\n\t\t\t} )\n\t\t\t.outerWidth( element.outerWidth() )\n\t\t\t.outerHeight( element.outerHeight() )\n\t\t\t.addClass( \"ui-effects-placeholder\" );\n\n\t\t\telement.data( dataSpace + \"placeholder\", placeholder );\n\t\t}\n\n\t\telement.css( {\n\t\t\tposition: cssPosition,\n\t\t\tleft: position.left,\n\t\t\ttop: position.top\n\t\t} );\n\n\t\treturn placeholder;\n\t},\n\n\tremovePlaceholder: function( element ) {\n\t\tvar dataKey = dataSpace + \"placeholder\",\n\t\t\t\tplaceholder = element.data( dataKey );\n\n\t\tif ( placeholder ) {\n\t\t\tplaceholder.remove();\n\t\t\telement.removeData( dataKey );\n\t\t}\n\t},\n\n\t// Removes a placeholder if it exists and restores\n\t// properties that were modified during placeholder creation\n\tcleanUp: function( element ) {\n\t\t$.effects.restoreStyle( element );\n\t\t$.effects.removePlaceholder( element );\n\t},\n\n\tsetTransition: function( element, list, factor, value ) {\n\t\tvalue = value || {};\n\t\t$.each( list, function( i, x ) {\n\t\t\tvar unit = element.cssUnit( x );\n\t\t\tif ( unit[ 0 ] > 0 ) {\n\t\t\t\tvalue[ x ] = unit[ 0 ] * factor + unit[ 1 ];\n\t\t\t}\n\t\t} );\n\t\treturn value;\n\t}\n} );\n\n// Return an effect options object for the given parameters:\nfunction _normalizeArguments( effect, options, speed, callback ) {\n\n\t// Allow passing all options as the first parameter\n\tif ( $.isPlainObject( effect ) ) {\n\t\toptions = effect;\n\t\teffect = effect.effect;\n\t}\n\n\t// Convert to an object\n\teffect = { effect: effect };\n\n\t// Catch (effect, null, ...)\n\tif ( options == null ) {\n\t\toptions = {};\n\t}\n\n\t// Catch (effect, callback)\n\tif ( $.isFunction( options ) ) {\n\t\tcallback = options;\n\t\tspeed = null;\n\t\toptions = {};\n\t}\n\n\t// Catch (effect, speed, ?)\n\tif ( typeof options === \"number\" || $.fx.speeds[ options ] ) {\n\t\tcallback = speed;\n\t\tspeed = options;\n\t\toptions = {};\n\t}\n\n\t// Catch (effect, options, callback)\n\tif ( $.isFunction( speed ) ) {\n\t\tcallback = speed;\n\t\tspeed = null;\n\t}\n\n\t// Add options to effect\n\tif ( options ) {\n\t\t$.extend( effect, options );\n\t}\n\n\tspeed = speed || options.duration;\n\teffect.duration = $.fx.off ? 0 :\n\t\ttypeof speed === \"number\" ? speed :\n\t\tspeed in $.fx.speeds ? $.fx.speeds[ speed ] :\n\t\t$.fx.speeds._default;\n\n\teffect.complete = callback || options.complete;\n\n\treturn effect;\n}\n\nfunction standardAnimationOption( option ) {\n\n\t// Valid standard speeds (nothing, number, named speed)\n\tif ( !option || typeof option === \"number\" || $.fx.speeds[ option ] ) {\n\t\treturn true;\n\t}\n\n\t// Invalid strings - treat as \"normal\" speed\n\tif ( typeof option === \"string\" && !$.effects.effect[ option ] ) {\n\t\treturn true;\n\t}\n\n\t// Complete callback\n\tif ( $.isFunction( option ) ) {\n\t\treturn true;\n\t}\n\n\t// Options hash (but not naming an effect)\n\tif ( typeof option === \"object\" && !option.effect ) {\n\t\treturn true;\n\t}\n\n\t// Didn't match any standard API\n\treturn false;\n}\n\n$.fn.extend( {\n\teffect: function( /* effect, options, speed, callback */ ) {\n\t\tvar args = _normalizeArguments.apply( this, arguments ),\n\t\t\teffectMethod = $.effects.effect[ args.effect ],\n\t\t\tdefaultMode = effectMethod.mode,\n\t\t\tqueue = args.queue,\n\t\t\tqueueName = queue || \"fx\",\n\t\t\tcomplete = args.complete,\n\t\t\tmode = args.mode,\n\t\t\tmodes = [],\n\t\t\tprefilter = function( next ) {\n\t\t\t\tvar el = $( this ),\n\t\t\t\t\tnormalizedMode = $.effects.mode( el, mode ) || defaultMode;\n\n\t\t\t\t// Sentinel for duck-punching the :animated psuedo-selector\n\t\t\t\tel.data( dataSpaceAnimated, true );\n\n\t\t\t\t// Save effect mode for later use,\n\t\t\t\t// we can't just call $.effects.mode again later,\n\t\t\t\t// as the .show() below destroys the initial state\n\t\t\t\tmodes.push( normalizedMode );\n\n\t\t\t\t// See $.uiBackCompat inside of run() for removal of defaultMode in 1.13\n\t\t\t\tif ( defaultMode && ( normalizedMode === \"show\" ||\n\t\t\t\t\t\t( normalizedMode === defaultMode && normalizedMode === \"hide\" ) ) ) {\n\t\t\t\t\tel.show();\n\t\t\t\t}\n\n\t\t\t\tif ( !defaultMode || normalizedMode !== \"none\" ) {\n\t\t\t\t\t$.effects.saveStyle( el );\n\t\t\t\t}\n\n\t\t\t\tif ( $.isFunction( next ) ) {\n\t\t\t\t\tnext();\n\t\t\t\t}\n\t\t\t};\n\n\t\tif ( $.fx.off || !effectMethod ) {\n\n\t\t\t// Delegate to the original method (e.g., .show()) if possible\n\t\t\tif ( mode ) {\n\t\t\t\treturn this[ mode ]( args.duration, complete );\n\t\t\t} else {\n\t\t\t\treturn this.each( function() {\n\t\t\t\t\tif ( complete ) {\n\t\t\t\t\t\tcomplete.call( this );\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t}\n\t\t}\n\n\t\tfunction run( next ) {\n\t\t\tvar elem = $( this );\n\n\t\t\tfunction cleanup() {\n\t\t\t\telem.removeData( dataSpaceAnimated );\n\n\t\t\t\t$.effects.cleanUp( elem );\n\n\t\t\t\tif ( args.mode === \"hide\" ) {\n\t\t\t\t\telem.hide();\n\t\t\t\t}\n\n\t\t\t\tdone();\n\t\t\t}\n\n\t\t\tfunction done() {\n\t\t\t\tif ( $.isFunction( complete ) ) {\n\t\t\t\t\tcomplete.call( elem[ 0 ] );\n\t\t\t\t}\n\n\t\t\t\tif ( $.isFunction( next ) ) {\n\t\t\t\t\tnext();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Override mode option on a per element basis,\n\t\t\t// as toggle can be either show or hide depending on element state\n\t\t\targs.mode = modes.shift();\n\n\t\t\tif ( $.uiBackCompat !== false && !defaultMode ) {\n\t\t\t\tif ( elem.is( \":hidden\" ) ? mode === \"hide\" : mode === \"show\" ) {\n\n\t\t\t\t\t// Call the core method to track \"olddisplay\" properly\n\t\t\t\t\telem[ mode ]();\n\t\t\t\t\tdone();\n\t\t\t\t} else {\n\t\t\t\t\teffectMethod.call( elem[ 0 ], args, done );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif ( args.mode === \"none\" ) {\n\n\t\t\t\t\t// Call the core method to track \"olddisplay\" properly\n\t\t\t\t\telem[ mode ]();\n\t\t\t\t\tdone();\n\t\t\t\t} else {\n\t\t\t\t\teffectMethod.call( elem[ 0 ], args, cleanup );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Run prefilter on all elements first to ensure that\n\t\t// any showing or hiding happens before placeholder creation,\n\t\t// which ensures that any layout changes are correctly captured.\n\t\treturn queue === false ?\n\t\t\tthis.each( prefilter ).each( run ) :\n\t\t\tthis.queue( queueName, prefilter ).queue( queueName, run );\n\t},\n\n\tshow: ( function( orig ) {\n\t\treturn function( option ) {\n\t\t\tif ( standardAnimationOption( option ) ) {\n\t\t\t\treturn orig.apply( this, arguments );\n\t\t\t} else {\n\t\t\t\tvar args = _normalizeArguments.apply( this, arguments );\n\t\t\t\targs.mode = \"show\";\n\t\t\t\treturn this.effect.call( this, args );\n\t\t\t}\n\t\t};\n\t} )( $.fn.show ),\n\n\thide: ( function( orig ) {\n\t\treturn function( option ) {\n\t\t\tif ( standardAnimationOption( option ) ) {\n\t\t\t\treturn orig.apply( this, arguments );\n\t\t\t} else {\n\t\t\t\tvar args = _normalizeArguments.apply( this, arguments );\n\t\t\t\targs.mode = \"hide\";\n\t\t\t\treturn this.effect.call( this, args );\n\t\t\t}\n\t\t};\n\t} )( $.fn.hide ),\n\n\ttoggle: ( function( orig ) {\n\t\treturn function( option ) {\n\t\t\tif ( standardAnimationOption( option ) || typeof option === \"boolean\" ) {\n\t\t\t\treturn orig.apply( this, arguments );\n\t\t\t} else {\n\t\t\t\tvar args = _normalizeArguments.apply( this, arguments );\n\t\t\t\targs.mode = \"toggle\";\n\t\t\t\treturn this.effect.call( this, args );\n\t\t\t}\n\t\t};\n\t} )( $.fn.toggle ),\n\n\tcssUnit: function( key ) {\n\t\tvar style = this.css( key ),\n\t\t\tval = [];\n\n\t\t$.each( [ \"em\", \"px\", \"%\", \"pt\" ], function( i, unit ) {\n\t\t\tif ( style.indexOf( unit ) > 0 ) {\n\t\t\t\tval = [ parseFloat( style ), unit ];\n\t\t\t}\n\t\t} );\n\t\treturn val;\n\t},\n\n\tcssClip: function( clipObj ) {\n\t\tif ( clipObj ) {\n\t\t\treturn this.css( \"clip\", \"rect(\" + clipObj.top + \"px \" + clipObj.right + \"px \" +\n\t\t\t\tclipObj.bottom + \"px \" + clipObj.left + \"px)\" );\n\t\t}\n\t\treturn parseClip( this.css( \"clip\" ), this );\n\t},\n\n\ttransfer: function( options, done ) {\n\t\tvar element = $( this ),\n\t\t\ttarget = $( options.to ),\n\t\t\ttargetFixed = target.css( \"position\" ) === \"fixed\",\n\t\t\tbody = $( \"body\" ),\n\t\t\tfixTop = targetFixed ? body.scrollTop() : 0,\n\t\t\tfixLeft = targetFixed ? body.scrollLeft() : 0,\n\t\t\tendPosition = target.offset(),\n\t\t\tanimation = {\n\t\t\t\ttop: endPosition.top - fixTop,\n\t\t\t\tleft: endPosition.left - fixLeft,\n\t\t\t\theight: target.innerHeight(),\n\t\t\t\twidth: target.innerWidth()\n\t\t\t},\n\t\t\tstartPosition = element.offset(),\n\t\t\ttransfer = $( \"<div class='ui-effects-transfer'></div>\" )\n\t\t\t\t.appendTo( \"body\" )\n\t\t\t\t.addClass( options.className )\n\t\t\t\t.css( {\n\t\t\t\t\ttop: startPosition.top - fixTop,\n\t\t\t\t\tleft: startPosition.left - fixLeft,\n\t\t\t\t\theight: element.innerHeight(),\n\t\t\t\t\twidth: element.innerWidth(),\n\t\t\t\t\tposition: targetFixed ? \"fixed\" : \"absolute\"\n\t\t\t\t} )\n\t\t\t\t.animate( animation, options.duration, options.easing, function() {\n\t\t\t\t\ttransfer.remove();\n\t\t\t\t\tif ( $.isFunction( done ) ) {\n\t\t\t\t\t\tdone();\n\t\t\t\t\t}\n\t\t\t\t} );\n\t}\n} );\n\nfunction parseClip( str, element ) {\n\t\tvar outerWidth = element.outerWidth(),\n\t\t\touterHeight = element.outerHeight(),\n\t\t\tclipRegex = /^rect\\((-?\\d*\\.?\\d*px|-?\\d+%|auto),?\\s*(-?\\d*\\.?\\d*px|-?\\d+%|auto),?\\s*(-?\\d*\\.?\\d*px|-?\\d+%|auto),?\\s*(-?\\d*\\.?\\d*px|-?\\d+%|auto)\\)$/,\n\t\t\tvalues = clipRegex.exec( str ) || [ \"\", 0, outerWidth, outerHeight, 0 ];\n\n\t\treturn {\n\t\t\ttop: parseFloat( values[ 1 ] ) || 0,\n\t\t\tright: values[ 2 ] === \"auto\" ? outerWidth : parseFloat( values[ 2 ] ),\n\t\t\tbottom: values[ 3 ] === \"auto\" ? outerHeight : parseFloat( values[ 3 ] ),\n\t\t\tleft: parseFloat( values[ 4 ] ) || 0\n\t\t};\n}\n\n$.fx.step.clip = function( fx ) {\n\tif ( !fx.clipInit ) {\n\t\tfx.start = $( fx.elem ).cssClip();\n\t\tif ( typeof fx.end === \"string\" ) {\n\t\t\tfx.end = parseClip( fx.end, fx.elem );\n\t\t}\n\t\tfx.clipInit = true;\n\t}\n\n\t$( fx.elem ).cssClip( {\n\t\ttop: fx.pos * ( fx.end.top - fx.start.top ) + fx.start.top,\n\t\tright: fx.pos * ( fx.end.right - fx.start.right ) + fx.start.right,\n\t\tbottom: fx.pos * ( fx.end.bottom - fx.start.bottom ) + fx.start.bottom,\n\t\tleft: fx.pos * ( fx.end.left - fx.start.left ) + fx.start.left\n\t} );\n};\n\n} )();\n\n/******************************************************************************/\n/*********************************** EASING ***********************************/\n/******************************************************************************/\n\n( function() {\n\n// Based on easing equations from Robert Penner (http://www.robertpenner.com/easing)\n\nvar baseEasings = {};\n\n$.each( [ \"Quad\", \"Cubic\", \"Quart\", \"Quint\", \"Expo\" ], function( i, name ) {\n\tbaseEasings[ name ] = function( p ) {\n\t\treturn Math.pow( p, i + 2 );\n\t};\n} );\n\n$.extend( baseEasings, {\n\tSine: function( p ) {\n\t\treturn 1 - Math.cos( p * Math.PI / 2 );\n\t},\n\tCirc: function( p ) {\n\t\treturn 1 - Math.sqrt( 1 - p * p );\n\t},\n\tElastic: function( p ) {\n\t\treturn p === 0 || p === 1 ? p :\n\t\t\t-Math.pow( 2, 8 * ( p - 1 ) ) * Math.sin( ( ( p - 1 ) * 80 - 7.5 ) * Math.PI / 15 );\n\t},\n\tBack: function( p ) {\n\t\treturn p * p * ( 3 * p - 2 );\n\t},\n\tBounce: function( p ) {\n\t\tvar pow2,\n\t\t\tbounce = 4;\n\n\t\twhile ( p < ( ( pow2 = Math.pow( 2, --bounce ) ) - 1 ) / 11 ) {}\n\t\treturn 1 / Math.pow( 4, 3 - bounce ) - 7.5625 * Math.pow( ( pow2 * 3 - 2 ) / 22 - p, 2 );\n\t}\n} );\n\n$.each( baseEasings, function( name, easeIn ) {\n\t$.easing[ \"easeIn\" + name ] = easeIn;\n\t$.easing[ \"easeOut\" + name ] = function( p ) {\n\t\treturn 1 - easeIn( 1 - p );\n\t};\n\t$.easing[ \"easeInOut\" + name ] = function( p ) {\n\t\treturn p < 0.5 ?\n\t\t\teaseIn( p * 2 ) / 2 :\n\t\t\t1 - easeIn( p * -2 + 2 ) / 2;\n\t};\n} );\n\n} )();\n\nvar effect = $.effects;\n\n\n/*!\n * jQuery UI Effects Bounce 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Bounce Effect\n//>>group: Effects\n//>>description: Bounces an element horizontally or vertically n times.\n//>>docs: http://api.jqueryui.com/bounce-effect/\n//>>demos: http://jqueryui.com/effect/\n\n\n\nvar effectsEffectBounce = $.effects.define( \"bounce\", function( options, done ) {\n\tvar upAnim, downAnim, refValue,\n\t\telement = $( this ),\n\n\t\t// Defaults:\n\t\tmode = options.mode,\n\t\thide = mode === \"hide\",\n\t\tshow = mode === \"show\",\n\t\tdirection = options.direction || \"up\",\n\t\tdistance = options.distance,\n\t\ttimes = options.times || 5,\n\n\t\t// Number of internal animations\n\t\tanims = times * 2 + ( show || hide ? 1 : 0 ),\n\t\tspeed = options.duration / anims,\n\t\teasing = options.easing,\n\n\t\t// Utility:\n\t\tref = ( direction === \"up\" || direction === \"down\" ) ? \"top\" : \"left\",\n\t\tmotion = ( direction === \"up\" || direction === \"left\" ),\n\t\ti = 0,\n\n\t\tqueuelen = element.queue().length;\n\n\t$.effects.createPlaceholder( element );\n\n\trefValue = element.css( ref );\n\n\t// Default distance for the BIGGEST bounce is the outer Distance / 3\n\tif ( !distance ) {\n\t\tdistance = element[ ref === \"top\" ? \"outerHeight\" : \"outerWidth\" ]() / 3;\n\t}\n\n\tif ( show ) {\n\t\tdownAnim = { opacity: 1 };\n\t\tdownAnim[ ref ] = refValue;\n\n\t\t// If we are showing, force opacity 0 and set the initial position\n\t\t// then do the \"first\" animation\n\t\telement\n\t\t\t.css( \"opacity\", 0 )\n\t\t\t.css( ref, motion ? -distance * 2 : distance * 2 )\n\t\t\t.animate( downAnim, speed, easing );\n\t}\n\n\t// Start at the smallest distance if we are hiding\n\tif ( hide ) {\n\t\tdistance = distance / Math.pow( 2, times - 1 );\n\t}\n\n\tdownAnim = {};\n\tdownAnim[ ref ] = refValue;\n\n\t// Bounces up/down/left/right then back to 0 -- times * 2 animations happen here\n\tfor ( ; i < times; i++ ) {\n\t\tupAnim = {};\n\t\tupAnim[ ref ] = ( motion ? \"-=\" : \"+=\" ) + distance;\n\n\t\telement\n\t\t\t.animate( upAnim, speed, easing )\n\t\t\t.animate( downAnim, speed, easing );\n\n\t\tdistance = hide ? distance * 2 : distance / 2;\n\t}\n\n\t// Last Bounce when Hiding\n\tif ( hide ) {\n\t\tupAnim = { opacity: 0 };\n\t\tupAnim[ ref ] = ( motion ? \"-=\" : \"+=\" ) + distance;\n\n\t\telement.animate( upAnim, speed, easing );\n\t}\n\n\telement.queue( done );\n\n\t$.effects.unshift( element, queuelen, anims + 1 );\n} );\n\n\n\n\n}));", "(function() {\n    /** reimport deprecated $.browser, remove me when jquery.ba-bqq is dropped */\n    $.uaMatch = function( ua ) {\n        var ua = ua.toLowerCase();\n\n        var match = /(chrome)[ \\/]([\\w.]+)/.exec( ua ) ||\n            /(webkit)[ \\/]([\\w.]+)/.exec( ua ) ||\n            /(opera)(?:.*version|)[ \\/]([\\w.]+)/.exec( ua ) ||\n            /(msie) ([\\w.]+)/.exec( ua ) ||\n            ua.indexOf(\"compatible\") < 0 && /(mozilla)(?:.*? rv:([\\w.]+)|)/.exec( ua ) ||\n            [];\n\n        return {\n            browser: match[ 1 ] || \"\",\n            version: match[ 2 ] || \"0\"\n        };\n    };\n    // Don't clobber any existing jQuery.browser in case it's different\n    if ( !$.browser ) {\n        var matched = $.uaMatch( navigator.userAgent );\n        var browser = {};\n\n        if ( matched.browser ) {\n            browser[ matched.browser ] = true;\n            browser.version = matched.version;\n        }\n\n        // Chrome is Webkit, but Webkit is also Safari.\n        if ( browser.chrome ) {\n            browser.webkit = true;\n        } else if ( browser.webkit ) {\n            browser.safari = true;\n        }\n\n        $.browser = browser;\n    }\n})();\n", "/*!\n * jQuery blockUI plugin\n * Version 2.70.0-2014.11.23\n * Requires jQuery v1.7 or later\n *\n * Examples at: http://malsup.com/jquery/block/\n * Copyright (c) 2007-2013 M. Alsup\n * Dual licensed under the MIT and GPL licenses:\n * http://www.opensource.org/licenses/mit-license.php\n * http://www.gnu.org/licenses/gpl.html\n *\n * Thanks to Amir-Hossein Sobhi for some excellent contributions!\n */\n\n;(function() {\n/*jshint eqeqeq:false curly:false latedef:false */\n\"use strict\";\n\n\tfunction setup($) {\n\t\t$.fn._fadeIn = $.fn.fadeIn;\n\n\t\tvar noOp = $.noop || function() {};\n\n\t\t// this bit is to ensure we don't call setExpression when we shouldn't (with extra muscle to handle\n\t\t// confusing userAgent strings on Vista)\n\t\tvar msie = /MSIE/.test(navigator.userAgent);\n\t\tvar ie6  = /MSIE 6.0/.test(navigator.userAgent) && ! /MSIE 8.0/.test(navigator.userAgent);\n\t\tvar mode = document.documentMode || 0;\n\t\tvar setExpr = $.isFunction( document.createElement('div').style.setExpression );\n\n\t\t// global $ methods for blocking/unblocking the entire page\n\t\t$.blockUI   = function(opts) { install(window, opts); };\n\t\t$.unblockUI = function(opts) { remove(window, opts); };\n\n\t\t// convenience method for quick growl-like notifications  (http://www.google.com/search?q=growl)\n\t\t$.growlUI = function(title, message, timeout, onClose) {\n\t\t\tvar $m = $('<div class=\"growlUI\"></div>');\n\t\t\tif (title) $m.append('<h1>'+title+'</h1>');\n\t\t\tif (message) $m.append('<h2>'+message+'</h2>');\n\t\t\tif (timeout === undefined) timeout = 3000;\n\n\t\t\t// Added by konapun: Set timeout to 30 seconds if this growl is moused over, like normal toast notifications\n\t\t\tvar callBlock = function(opts) {\n\t\t\t\topts = opts || {};\n\n\t\t\t\t$.blockUI({\n\t\t\t\t\tmessage: $m,\n\t\t\t\t\tfadeIn : typeof opts.fadeIn  !== 'undefined' ? opts.fadeIn  : 700,\n\t\t\t\t\tfadeOut: typeof opts.fadeOut !== 'undefined' ? opts.fadeOut : 1000,\n\t\t\t\t\ttimeout: typeof opts.timeout !== 'undefined' ? opts.timeout : timeout,\n\t\t\t\t\tcenterY: false,\n\t\t\t\t\tshowOverlay: false,\n\t\t\t\t\tonUnblock: onClose,\n\t\t\t\t\tcss: $.blockUI.defaults.growlCSS\n\t\t\t\t});\n\t\t\t};\n\n\t\t\tcallBlock();\n\t\t\tvar nonmousedOpacity = $m.css('opacity');\n\t\t\t$m.mouseover(function() {\n\t\t\t\tcallBlock({\n\t\t\t\t\tfadeIn: 0,\n\t\t\t\t\ttimeout: 30000\n\t\t\t\t});\n\n\t\t\t\tvar displayBlock = $('.blockMsg');\n\t\t\t\tdisplayBlock.stop(); // cancel fadeout if it has started\n\t\t\t\tdisplayBlock.fadeTo(300, 1); // make it easier to read the message by removing transparency\n\t\t\t}).mouseout(function() {\n\t\t\t\t$('.blockMsg').fadeOut(1000);\n\t\t\t});\n\t\t\t// End konapun additions\n\t\t};\n\n\t\t// plugin method for blocking element content\n\t\t$.fn.block = function(opts) {\n\t\t\tif ( this[0] === window ) {\n\t\t\t\t$.blockUI( opts );\n\t\t\t\treturn this;\n\t\t\t}\n\t\t\tvar fullOpts = $.extend({}, $.blockUI.defaults, opts || {});\n\t\t\tthis.each(function() {\n\t\t\t\tvar $el = $(this);\n\t\t\t\tif (fullOpts.ignoreIfBlocked && $el.data('blockUI.isBlocked'))\n\t\t\t\t\treturn;\n\t\t\t\t$el.unblock({ fadeOut: 0 });\n\t\t\t});\n\n\t\t\treturn this.each(function() {\n\t\t\t\tif ($.css(this,'position') == 'static') {\n\t\t\t\t\tthis.style.position = 'relative';\n\t\t\t\t\t$(this).data('blockUI.static', true);\n\t\t\t\t}\n\t\t\t\tthis.style.zoom = 1; // force 'hasLayout' in ie\n\t\t\t\tinstall(this, opts);\n\t\t\t});\n\t\t};\n\n\t\t// plugin method for unblocking element content\n\t\t$.fn.unblock = function(opts) {\n\t\t\tif ( this[0] === window ) {\n\t\t\t\t$.unblockUI( opts );\n\t\t\t\treturn this;\n\t\t\t}\n\t\t\treturn this.each(function() {\n\t\t\t\tremove(this, opts);\n\t\t\t});\n\t\t};\n\n\t\t$.blockUI.version = 2.70; // 2nd generation blocking at no extra cost!\n\n\t\t// override these in your code to change the default behavior and style\n\t\t$.blockUI.defaults = {\n\t\t\t// message displayed when blocking (use null for no message)\n\t\t\tmessage:  '<h1>Please wait...</h1>',\n\n\t\t\ttitle: null,\t\t// title string; only used when theme == true\n\t\t\tdraggable: true,\t// only used when theme == true (requires jquery-ui.js to be loaded)\n\n\t\t\ttheme: false, // set to true to use with jQuery UI themes\n\n\t\t\t// styles for the message when blocking; if you wish to disable\n\t\t\t// these and use an external stylesheet then do this in your code:\n\t\t\t// $.blockUI.defaults.css = {};\n\t\t\tcss: {\n\t\t\t\tpadding:\t0,\n\t\t\t\tmargin:\t\t0,\n\t\t\t\twidth:\t\t'30%',\n\t\t\t\ttop:\t\t'40%',\n\t\t\t\tleft:\t\t'35%',\n\t\t\t\ttextAlign:\t'center',\n\t\t\t\tcolor:\t\t'#000',\n\t\t\t\tborder:\t\t'3px solid #aaa',\n\t\t\t\tbackgroundColor:'#fff',\n\t\t\t\tcursor:\t\t'wait'\n\t\t\t},\n\n\t\t\t// minimal style set used when themes are used\n\t\t\tthemedCSS: {\n\t\t\t\twidth:\t'30%',\n\t\t\t\ttop:\t'40%',\n\t\t\t\tleft:\t'35%'\n\t\t\t},\n\n\t\t\t// styles for the overlay\n\t\t\toverlayCSS:  {\n\t\t\t\tbackgroundColor:\t'#000',\n\t\t\t\topacity:\t\t\t0.6,\n\t\t\t\tcursor:\t\t\t\t'wait'\n\t\t\t},\n\n\t\t\t// style to replace wait cursor before unblocking to correct issue\n\t\t\t// of lingering wait cursor\n\t\t\tcursorReset: 'default',\n\n\t\t\t// styles applied when using $.growlUI\n\t\t\tgrowlCSS: {\n\t\t\t\twidth:\t\t'350px',\n\t\t\t\ttop:\t\t'10px',\n\t\t\t\tleft:\t\t'',\n\t\t\t\tright:\t\t'10px',\n\t\t\t\tborder:\t\t'none',\n\t\t\t\tpadding:\t'5px',\n\t\t\t\topacity:\t0.6,\n\t\t\t\tcursor:\t\t'default',\n\t\t\t\tcolor:\t\t'#fff',\n\t\t\t\tbackgroundColor: '#000',\n\t\t\t\t'-webkit-border-radius':'10px',\n\t\t\t\t'-moz-border-radius':\t'10px',\n\t\t\t\t'border-radius':\t\t'10px'\n\t\t\t},\n\n\t\t\t// IE issues: 'about:blank' fails on HTTPS and javascript:false is s-l-o-w\n\t\t\t// (hat tip to Jorge H. N. de Vasconcelos)\n\t\t\t/*jshint scripturl:true */\n\t\t\tiframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank',\n\n\t\t\t// force usage of iframe in non-IE browsers (handy for blocking applets)\n\t\t\tforceIframe: false,\n\n\t\t\t// z-index for the blocking overlay\n\t\t\tbaseZ: 1000,\n\n\t\t\t// set these to true to have the message automatically centered\n\t\t\tcenterX: true, // <-- only effects element blocking (page block controlled via css above)\n\t\t\tcenterY: true,\n\n\t\t\t// allow body element to be stetched in ie6; this makes blocking look better\n\t\t\t// on \"short\" pages.  disable if you wish to prevent changes to the body height\n\t\t\tallowBodyStretch: true,\n\n\t\t\t// enable if you want key and mouse events to be disabled for content that is blocked\n\t\t\tbindEvents: true,\n\n\t\t\t// be default blockUI will supress tab navigation from leaving blocking content\n\t\t\t// (if bindEvents is true)\n\t\t\tconstrainTabKey: true,\n\n\t\t\t// fadeIn time in millis; set to 0 to disable fadeIn on block\n\t\t\tfadeIn:  200,\n\n\t\t\t// fadeOut time in millis; set to 0 to disable fadeOut on unblock\n\t\t\tfadeOut:  400,\n\n\t\t\t// time in millis to wait before auto-unblocking; set to 0 to disable auto-unblock\n\t\t\ttimeout: 0,\n\n\t\t\t// disable if you don't want to show the overlay\n\t\t\tshowOverlay: true,\n\n\t\t\t// if true, focus will be placed in the first available input field when\n\t\t\t// page blocking\n\t\t\tfocusInput: true,\n\n            // elements that can receive focus\n            focusableElements: ':input:enabled:visible',\n\n\t\t\t// suppresses the use of overlay styles on FF/Linux (due to performance issues with opacity)\n\t\t\t// no longer needed in 2012\n\t\t\t// applyPlatformOpacityRules: true,\n\n\t\t\t// callback method invoked when fadeIn has completed and blocking message is visible\n\t\t\tonBlock: null,\n\n\t\t\t// callback method invoked when unblocking has completed; the callback is\n\t\t\t// passed the element that has been unblocked (which is the window object for page\n\t\t\t// blocks) and the options that were passed to the unblock call:\n\t\t\t//\tonUnblock(element, options)\n\t\t\tonUnblock: null,\n\n\t\t\t// callback method invoked when the overlay area is clicked.\n\t\t\t// setting this will turn the cursor to a pointer, otherwise cursor defined in overlayCss will be used.\n\t\t\tonOverlayClick: null,\n\n\t\t\t// don't ask; if you really must know: http://groups.google.com/group/jquery-en/browse_thread/thread/36640a8730503595/2f6a79a77a78e493#2f6a79a77a78e493\n\t\t\tquirksmodeOffsetHack: 4,\n\n\t\t\t// class name of the message block\n\t\t\tblockMsgClass: 'blockMsg',\n\n\t\t\t// if it is already blocked, then ignore it (don't unblock and reblock)\n\t\t\tignoreIfBlocked: false\n\t\t};\n\n\t\t// private data and functions follow...\n\n\t\tvar pageBlock = null;\n\t\tvar pageBlockEls = [];\n\n\t\tfunction install(el, opts) {\n\t\t\tvar css, themedCSS;\n\t\t\tvar full = (el == window);\n\t\t\tvar msg = (opts && opts.message !== undefined ? opts.message : undefined);\n\t\t\topts = $.extend({}, $.blockUI.defaults, opts || {});\n\n\t\t\tif (opts.ignoreIfBlocked && $(el).data('blockUI.isBlocked'))\n\t\t\t\treturn;\n\n\t\t\topts.overlayCSS = $.extend({}, $.blockUI.defaults.overlayCSS, opts.overlayCSS || {});\n\t\t\tcss = $.extend({}, $.blockUI.defaults.css, opts.css || {});\n\t\t\tif (opts.onOverlayClick)\n\t\t\t\topts.overlayCSS.cursor = 'pointer';\n\n\t\t\tthemedCSS = $.extend({}, $.blockUI.defaults.themedCSS, opts.themedCSS || {});\n\t\t\tmsg = msg === undefined ? opts.message : msg;\n\n\t\t\t// remove the current block (if there is one)\n\t\t\tif (full && pageBlock)\n\t\t\t\tremove(window, {fadeOut:0});\n\n\t\t\t// if an existing element is being used as the blocking content then we capture\n\t\t\t// its current place in the DOM (and current display style) so we can restore\n\t\t\t// it when we unblock\n\t\t\tif (msg && typeof msg != 'string' && (msg.parentNode || msg.jquery)) {\n\t\t\t\tvar node = msg.jquery ? msg[0] : msg;\n\t\t\t\tvar data = {};\n\t\t\t\t$(el).data('blockUI.history', data);\n\t\t\t\tdata.el = node;\n\t\t\t\tdata.parent = node.parentNode;\n\t\t\t\tdata.display = node.style.display;\n\t\t\t\tdata.position = node.style.position;\n\t\t\t\tif (data.parent)\n\t\t\t\t\tdata.parent.removeChild(node);\n\t\t\t}\n\n\t\t\t$(el).data('blockUI.onUnblock', opts.onUnblock);\n\t\t\tvar z = opts.baseZ;\n\n\t\t\t// blockUI uses 3 layers for blocking, for simplicity they are all used on every platform;\n\t\t\t// layer1 is the iframe layer which is used to supress bleed through of underlying content\n\t\t\t// layer2 is the overlay layer which has opacity and a wait cursor (by default)\n\t\t\t// layer3 is the message content that is displayed while blocking\n\t\t\tvar lyr1, lyr2, lyr3, s;\n\t\t\tif (msie || opts.forceIframe)\n\t\t\t\tlyr1 = $('<iframe class=\"blockUI\" style=\"z-index:'+ (z++) +';display:none;border:none;margin:0;padding:0;position:absolute;width:100%;height:100%;top:0;left:0\" src=\"'+opts.iframeSrc+'\"></iframe>');\n\t\t\telse\n\t\t\t\tlyr1 = $('<div class=\"blockUI\" style=\"display:none\"></div>');\n\n\t\t\tif (opts.theme)\n\t\t\t\tlyr2 = $('<div class=\"blockUI blockOverlay ui-widget-overlay\" style=\"z-index:'+ (z++) +';display:none\"></div>');\n\t\t\telse\n\t\t\t\tlyr2 = $('<div class=\"blockUI blockOverlay\" style=\"z-index:'+ (z++) +';display:none;border:none;margin:0;padding:0;width:100%;height:100%;top:0;left:0\"></div>');\n\n\t\t\tif (opts.theme && full) {\n\t\t\t\ts = '<div class=\"blockUI ' + opts.blockMsgClass + ' blockPage ui-dialog ui-widget ui-corner-all\" style=\"z-index:'+(z+10)+';display:none;position:fixed\">';\n\t\t\t\tif ( opts.title ) {\n\t\t\t\t\ts += '<div class=\"ui-widget-header ui-dialog-titlebar ui-corner-all blockTitle\">'+(opts.title || '&nbsp;')+'</div>';\n\t\t\t\t}\n\t\t\t\ts += '<div class=\"ui-widget-content ui-dialog-content\"></div>';\n\t\t\t\ts += '</div>';\n\t\t\t}\n\t\t\telse if (opts.theme) {\n\t\t\t\ts = '<div class=\"blockUI ' + opts.blockMsgClass + ' blockElement ui-dialog ui-widget ui-corner-all\" style=\"z-index:'+(z+10)+';display:none;position:absolute\">';\n\t\t\t\tif ( opts.title ) {\n\t\t\t\t\ts += '<div class=\"ui-widget-header ui-dialog-titlebar ui-corner-all blockTitle\">'+(opts.title || '&nbsp;')+'</div>';\n\t\t\t\t}\n\t\t\t\ts += '<div class=\"ui-widget-content ui-dialog-content\"></div>';\n\t\t\t\ts += '</div>';\n\t\t\t}\n\t\t\telse if (full) {\n\t\t\t\ts = '<div class=\"blockUI ' + opts.blockMsgClass + ' blockPage\" style=\"z-index:'+(z+10)+';display:none;position:fixed\"></div>';\n\t\t\t}\n\t\t\telse {\n\t\t\t\ts = '<div class=\"blockUI ' + opts.blockMsgClass + ' blockElement\" style=\"z-index:'+(z+10)+';display:none;position:absolute\"></div>';\n\t\t\t}\n\t\t\tlyr3 = $(s);\n\n\t\t\t// if we have a message, style it\n\t\t\tif (msg) {\n\t\t\t\tif (opts.theme) {\n\t\t\t\t\tlyr3.css(themedCSS);\n\t\t\t\t\tlyr3.addClass('ui-widget-content');\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\tlyr3.css(css);\n\t\t\t}\n\n\t\t\t// style the overlay\n\t\t\tif (!opts.theme /*&& (!opts.applyPlatformOpacityRules)*/)\n\t\t\t\tlyr2.css(opts.overlayCSS);\n\t\t\tlyr2.css('position', full ? 'fixed' : 'absolute');\n\n\t\t\t// make iframe layer transparent in IE\n\t\t\tif (msie || opts.forceIframe)\n\t\t\t\tlyr1.css('opacity',0.0);\n\n\t\t\t//$([lyr1[0],lyr2[0],lyr3[0]]).appendTo(full ? 'body' : el);\n\t\t\tvar layers = [lyr1,lyr2,lyr3], $par = full ? $('body') : $(el);\n\t\t\t$.each(layers, function() {\n\t\t\t\tthis.appendTo($par);\n\t\t\t});\n\n\t\t\tif (opts.theme && opts.draggable && $.fn.draggable) {\n\t\t\t\tlyr3.draggable({\n\t\t\t\t\thandle: '.ui-dialog-titlebar',\n\t\t\t\t\tcancel: 'li'\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// ie7 must use absolute positioning in quirks mode and to account for activex issues (when scrolling)\n\t\t\tvar expr = setExpr && (!$.support.boxModel || $('object,embed', full ? null : el).length > 0);\n\t\t\tif (ie6 || expr) {\n\t\t\t\t// give body 100% height\n\t\t\t\tif (full && opts.allowBodyStretch && $.support.boxModel)\n\t\t\t\t\t$('html,body').css('height','100%');\n\n\t\t\t\t// fix ie6 issue when blocked element has a border width\n\t\t\t\tif ((ie6 || !$.support.boxModel) && !full) {\n\t\t\t\t\tvar t = sz(el,'borderTopWidth'), l = sz(el,'borderLeftWidth');\n\t\t\t\t\tvar fixT = t ? '(0 - '+t+')' : 0;\n\t\t\t\t\tvar fixL = l ? '(0 - '+l+')' : 0;\n\t\t\t\t}\n\n\t\t\t\t// simulate fixed position\n\t\t\t\t$.each(layers, function(i,o) {\n\t\t\t\t\tvar s = o[0].style;\n\t\t\t\t\ts.position = 'absolute';\n\t\t\t\t\tif (i < 2) {\n\t\t\t\t\t\tif (full)\n\t\t\t\t\t\t\ts.setExpression('height','Math.max(document.body.scrollHeight, document.body.offsetHeight) - (jQuery.support.boxModel?0:'+opts.quirksmodeOffsetHack+') + \"px\"');\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\ts.setExpression('height','this.parentNode.offsetHeight + \"px\"');\n\t\t\t\t\t\tif (full)\n\t\t\t\t\t\t\ts.setExpression('width','jQuery.support.boxModel && document.documentElement.clientWidth || document.body.clientWidth + \"px\"');\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\ts.setExpression('width','this.parentNode.offsetWidth + \"px\"');\n\t\t\t\t\t\tif (fixL) s.setExpression('left', fixL);\n\t\t\t\t\t\tif (fixT) s.setExpression('top', fixT);\n\t\t\t\t\t}\n\t\t\t\t\telse if (opts.centerY) {\n\t\t\t\t\t\tif (full) s.setExpression('top','(document.documentElement.clientHeight || document.body.clientHeight) / 2 - (this.offsetHeight / 2) + (blah = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + \"px\"');\n\t\t\t\t\t\ts.marginTop = 0;\n\t\t\t\t\t}\n\t\t\t\t\telse if (!opts.centerY && full) {\n\t\t\t\t\t\tvar top = (opts.css && opts.css.top) ? parseInt(opts.css.top, 10) : 0;\n\t\t\t\t\t\tvar expression = '((document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + '+top+') + \"px\"';\n\t\t\t\t\t\ts.setExpression('top',expression);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// show the message\n\t\t\tif (msg) {\n\t\t\t\tif (opts.theme)\n\t\t\t\t\tlyr3.find('.ui-widget-content').append(msg);\n\t\t\t\telse\n\t\t\t\t\tlyr3.append(msg);\n\t\t\t\tif (msg.jquery || msg.nodeType)\n\t\t\t\t\t$(msg).show();\n\t\t\t}\n\n\t\t\tif ((msie || opts.forceIframe) && opts.showOverlay)\n\t\t\t\tlyr1.show(); // opacity is zero\n\t\t\tif (opts.fadeIn) {\n\t\t\t\tvar cb = opts.onBlock ? opts.onBlock : noOp;\n\t\t\t\tvar cb1 = (opts.showOverlay && !msg) ? cb : noOp;\n\t\t\t\tvar cb2 = msg ? cb : noOp;\n\t\t\t\tif (opts.showOverlay)\n\t\t\t\t\tlyr2._fadeIn(opts.fadeIn, cb1);\n\t\t\t\tif (msg)\n\t\t\t\t\tlyr3._fadeIn(opts.fadeIn, cb2);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tif (opts.showOverlay)\n\t\t\t\t\tlyr2.show();\n\t\t\t\tif (msg)\n\t\t\t\t\tlyr3.show();\n\t\t\t\tif (opts.onBlock)\n\t\t\t\t\topts.onBlock.bind(lyr3)();\n\t\t\t}\n\n\t\t\t// bind key and mouse events\n\t\t\tbind(1, el, opts);\n\n\t\t\tif (full) {\n\t\t\t\tpageBlock = lyr3[0];\n\t\t\t\tpageBlockEls = $(opts.focusableElements,pageBlock);\n\t\t\t\tif (opts.focusInput)\n\t\t\t\t\tsetTimeout(focus, 20);\n\t\t\t}\n\t\t\telse\n\t\t\t\tcenter(lyr3[0], opts.centerX, opts.centerY);\n\n\t\t\tif (opts.timeout) {\n\t\t\t\t// auto-unblock\n\t\t\t\tvar to = setTimeout(function() {\n\t\t\t\t\tif (full)\n\t\t\t\t\t\t$.unblockUI(opts);\n\t\t\t\t\telse\n\t\t\t\t\t\t$(el).unblock(opts);\n\t\t\t\t}, opts.timeout);\n\t\t\t\t$(el).data('blockUI.timeout', to);\n\t\t\t}\n\t\t}\n\n\t\t// remove the block\n\t\tfunction remove(el, opts) {\n\t\t\tvar count;\n\t\t\tvar full = (el == window);\n\t\t\tvar $el = $(el);\n\t\t\tvar data = $el.data('blockUI.history');\n\t\t\tvar to = $el.data('blockUI.timeout');\n\t\t\tif (to) {\n\t\t\t\tclearTimeout(to);\n\t\t\t\t$el.removeData('blockUI.timeout');\n\t\t\t}\n\t\t\topts = $.extend({}, $.blockUI.defaults, opts || {});\n\t\t\tbind(0, el, opts); // unbind events\n\n\t\t\tif (opts.onUnblock === null) {\n\t\t\t\topts.onUnblock = $el.data('blockUI.onUnblock');\n\t\t\t\t$el.removeData('blockUI.onUnblock');\n\t\t\t}\n\n\t\t\tvar els;\n\t\t\tif (full) // crazy selector to handle odd field errors in ie6/7\n\t\t\t\tels = $('body').children().filter('.blockUI').add('body > .blockUI');\n\t\t\telse\n\t\t\t\tels = $el.find('>.blockUI');\n\n\t\t\t// fix cursor issue\n\t\t\tif ( opts.cursorReset ) {\n\t\t\t\tif ( els.length > 1 )\n\t\t\t\t\tels[1].style.cursor = opts.cursorReset;\n\t\t\t\tif ( els.length > 2 )\n\t\t\t\t\tels[2].style.cursor = opts.cursorReset;\n\t\t\t}\n\n\t\t\tif (full)\n\t\t\t\tpageBlock = pageBlockEls = null;\n\n\t\t\tif (opts.fadeOut) {\n\t\t\t\tcount = els.length;\n\t\t\t\tels.stop().fadeOut(opts.fadeOut, function() {\n\t\t\t\t\tif ( --count === 0)\n\t\t\t\t\t\treset(els,data,opts,el);\n\t\t\t\t});\n\t\t\t}\n\t\t\telse\n\t\t\t\treset(els, data, opts, el);\n\t\t}\n\n\t\t// move blocking element back into the DOM where it started\n\t\tfunction reset(els,data,opts,el) {\n\t\t\tvar $el = $(el);\n\t\t\tif ( $el.data('blockUI.isBlocked') )\n\t\t\t\treturn;\n\n\t\t\tels.each(function(i,o) {\n\t\t\t\t// remove via DOM calls so we don't lose event handlers\n\t\t\t\tif (this.parentNode)\n\t\t\t\t\tthis.parentNode.removeChild(this);\n\t\t\t});\n\n\t\t\tif (data && data.el) {\n\t\t\t\tdata.el.style.display = data.display;\n\t\t\t\tdata.el.style.position = data.position;\n\t\t\t\tdata.el.style.cursor = 'default'; // #59\n\t\t\t\tif (data.parent)\n\t\t\t\t\tdata.parent.appendChild(data.el);\n\t\t\t\t$el.removeData('blockUI.history');\n\t\t\t}\n\n\t\t\tif ($el.data('blockUI.static')) {\n\t\t\t\t$el.css('position', 'static'); // #22\n\t\t\t}\n\n\t\t\tif (typeof opts.onUnblock == 'function')\n\t\t\t\topts.onUnblock(el,opts);\n\n\t\t\t// fix issue in Safari 6 where block artifacts remain until reflow\n\t\t\tvar body = $(document.body), w = body.width(), cssW = body[0].style.width;\n\t\t\tbody.width(w-1).width(w);\n\t\t\tbody[0].style.width = cssW;\n\t\t}\n\n\t\t// bind/unbind the handler\n\t\tfunction bind(b, el, opts) {\n\t\t\tvar full = el == window, $el = $(el);\n\n\t\t\t// don't bother unbinding if there is nothing to unbind\n\t\t\tif (!b && (full && !pageBlock || !full && !$el.data('blockUI.isBlocked')))\n\t\t\t\treturn;\n\n\t\t\t$el.data('blockUI.isBlocked', b);\n\n\t\t\t// don't bind events when overlay is not in use or if bindEvents is false\n\t\t\tif (!full || !opts.bindEvents || (b && !opts.showOverlay))\n\t\t\t\treturn;\n\n\t\t\t// bind anchors and inputs for mouse and key events\n\t\t\tvar events = 'mousedown mouseup keydown keypress keyup touchstart touchend touchmove';\n\t\t\tif (b)\n\t\t\t\t$(document).bind(events, opts, handler);\n\t\t\telse\n\t\t\t\t$(document).unbind(events, handler);\n\n\t\t// former impl...\n\t\t//\t\tvar $e = $('a,:input');\n\t\t//\t\tb ? $e.bind(events, opts, handler) : $e.unbind(events, handler);\n\t\t}\n\n\t\t// event handler to suppress keyboard/mouse events when blocking\n\t\tfunction handler(e) {\n\t\t\t// allow tab navigation (conditionally)\n\t\t\tif (e.type === 'keydown' && e.keyCode && e.keyCode == 9) {\n\t\t\t\tif (pageBlock && e.data.constrainTabKey) {\n\t\t\t\t\tvar els = pageBlockEls;\n\t\t\t\t\tvar fwd = !e.shiftKey && e.target === els[els.length-1];\n\t\t\t\t\tvar back = e.shiftKey && e.target === els[0];\n\t\t\t\t\tif (fwd || back) {\n\t\t\t\t\t\tsetTimeout(function(){focus(back);},10);\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tvar opts = e.data;\n\t\t\tvar target = $(e.target);\n\t\t\tif (target.hasClass('blockOverlay') && opts.onOverlayClick)\n\t\t\t\topts.onOverlayClick(e);\n\n\t\t\t// allow events within the message content\n\t\t\tif (target.parents('div.' + opts.blockMsgClass).length > 0)\n\t\t\t\treturn true;\n\n\t\t\t// allow events for content that is not being blocked\n\t\t\treturn target.parents().children().filter('div.blockUI').length === 0;\n\t\t}\n\n\t\tfunction focus(back) {\n\t\t\tif (!pageBlockEls)\n\t\t\t\treturn;\n\t\t\tvar e = pageBlockEls[back===true ? pageBlockEls.length-1 : 0];\n\t\t\tif (e)\n\t\t\t\te.focus();\n\t\t}\n\n\t\tfunction center(el, x, y) {\n\t\t\tvar p = el.parentNode, s = el.style;\n\t\t\tvar l = ((p.offsetWidth - el.offsetWidth)/2) - sz(p,'borderLeftWidth');\n\t\t\tvar t = ((p.offsetHeight - el.offsetHeight)/2) - sz(p,'borderTopWidth');\n\t\t\tif (x) s.left = l > 0 ? (l+'px') : '0';\n\t\t\tif (y) s.top  = t > 0 ? (t+'px') : '0';\n\t\t}\n\n\t\tfunction sz(el, p) {\n\t\t\treturn parseInt($.css(el,p),10)||0;\n\t\t}\n\n\t}\n\n\n\t/*global define:true */\n\tif (typeof define === 'function' && define.amd && define.amd.jQuery) {\n\t\tdefine(['jquery'], setup);\n\t} else {\n\t\tsetup(jQuery);\n\t}\n\n})();\n", "/*\n * jQuery Hotkeys Plugin\n * Copyright 2010, John Resig\n * Dual licensed under the MIT or GPL Version 2 licenses.\n *\n * Based upon the plugin by Tzury Bar Yochay:\n * http://github.com/tzuryby/hotkeys\n *\n * Original idea by:\n * Binny V A, http://www.openjs.com/scripts/events/keyboard_shortcuts/\n*/\n\n(function(jQuery){\n\t\n\tjQuery.hotkeys = {\n\t\tversion: \"0.8\",\n\n\t\tspecialKeys: {\n\t\t\t8: \"backspace\", 9: \"tab\", 13: \"return\", 16: \"shift\", 17: \"ctrl\", 18: \"alt\", 19: \"pause\",\n\t\t\t20: \"capslock\", 27: \"esc\", 32: \"space\", 33: \"pageup\", 34: \"pagedown\", 35: \"end\", 36: \"home\",\n\t\t\t37: \"left\", 38: \"up\", 39: \"right\", 40: \"down\", 45: \"insert\", 46: \"del\", \n\t\t\t96: \"0\", 97: \"1\", 98: \"2\", 99: \"3\", 100: \"4\", 101: \"5\", 102: \"6\", 103: \"7\",\n\t\t\t104: \"8\", 105: \"9\", 106: \"*\", 107: \"+\", 109: \"-\", 110: \".\", 111 : \"/\", \n\t\t\t112: \"f1\", 113: \"f2\", 114: \"f3\", 115: \"f4\", 116: \"f5\", 117: \"f6\", 118: \"f7\", 119: \"f8\", \n\t\t\t120: \"f9\", 121: \"f10\", 122: \"f11\", 123: \"f12\", 144: \"numlock\", 145: \"scroll\", 191: \"/\", 224: \"meta\"\n\t\t},\n\t\n\t\tshiftNums: {\n\t\t\t\"`\": \"~\", \"1\": \"!\", \"2\": \"@\", \"3\": \"#\", \"4\": \"$\", \"5\": \"%\", \"6\": \"^\", \"7\": \"&\", \n\t\t\t\"8\": \"*\", \"9\": \"(\", \"0\": \")\", \"-\": \"_\", \"=\": \"+\", \";\": \": \", \"'\": \"\\\"\", \",\": \"<\", \n\t\t\t\".\": \">\",  \"/\": \"?\",  \"\\\\\": \"|\"\n\t\t}\n\t};\n\n\tfunction keyHandler( handleObj ) {\n\t\t// Only care when a possible input has been specified\n\t\tif ( typeof handleObj.data !== \"string\" ) {\n\t\t\treturn;\n\t\t}\n\t\t\n\t\tvar origHandler = handleObj.handler,\n\t\t\tkeys = handleObj.data.toLowerCase().split(\" \");\n\t\n\t\thandleObj.handler = function( event ) {\n\t\t\t// Don't fire in text-accepting inputs that we didn't directly bind to\n\t\t\tif ( this !== event.target && (/textarea|select/i.test( event.target.nodeName ) ||\n\t\t\t\t event.target.type === \"text\") ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t\n\t\t\t// Keypress represents characters, not special keys\n\t\t\tvar special = event.type !== \"keypress\" && jQuery.hotkeys.specialKeys[ event.which ],\n\t\t\t\tcharacter = String.fromCharCode( event.which ).toLowerCase(),\n\t\t\t\tkey, modif = \"\", possible = {};\n\n\t\t\t// check combinations (alt|ctrl|shift+anything)\n\t\t\tif ( event.altKey && special !== \"alt\" ) {\n\t\t\t\tmodif += \"alt+\";\n\t\t\t}\n\n\t\t\tif ( event.ctrlKey && special !== \"ctrl\" ) {\n\t\t\t\tmodif += \"ctrl+\";\n\t\t\t}\n\t\t\t\n\t\t\t// TODO: Need to make sure this works consistently across platforms\n\t\t\tif ( event.metaKey && !event.ctrlKey && special !== \"meta\" ) {\n\t\t\t\tmodif += \"meta+\";\n\t\t\t}\n\n\t\t\tif ( event.shiftKey && special !== \"shift\" ) {\n\t\t\t\tmodif += \"shift+\";\n\t\t\t}\n\n\t\t\tif ( special ) {\n\t\t\t\tpossible[ modif + special ] = true;\n\n\t\t\t} else {\n\t\t\t\tpossible[ modif + character ] = true;\n\t\t\t\tpossible[ modif + jQuery.hotkeys.shiftNums[ character ] ] = true;\n\n\t\t\t\t// \"$\" can be triggered as \"Shift+4\" or \"Shift+$\" or just \"$\"\n\t\t\t\tif ( modif === \"shift+\" ) {\n\t\t\t\t\tpossible[ jQuery.hotkeys.shiftNums[ character ] ] = true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor ( var i = 0, l = keys.length; i < l; i++ ) {\n\t\t\t\tif ( possible[ keys[i] ] ) {\n\t\t\t\t\treturn origHandler.apply( this, arguments );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n\n\tjQuery.each([ \"keydown\", \"keyup\", \"keypress\" ], function() {\n\t\tjQuery.event.special[ this ] = { add: keyHandler };\n\t});\n\n})( jQuery );", "/*! http://mths.be/placeholder v2.0.7 by @mathias */\r\n;(function(window, document, $) {\r\n\r\n    var isInputSupported = 'placeholder' in document.createElement('input'),\r\n        isTextareaSupported = 'placeholder' in document.createElement('textarea'),\r\n        prototype = $.fn,\r\n        valHooks = $.valHooks,\r\n        hooks,\r\n        placeholder;\r\n\r\n    if (isInputSupported && isTextareaSupported) {\r\n\r\n        placeholder = prototype.placeholder = function() {\r\n            return this;\r\n        };\r\n\r\n        placeholder.input = placeholder.textarea = true;\r\n\r\n    } else {\r\n\r\n        placeholder = prototype.placeholder = function() {\r\n            var $this = this;\r\n            $this\r\n                .filter((isInputSupported ? 'textarea' : ':input') + '[placeholder]')\r\n                .not('.placeholder')\r\n                .bind({\r\n                    'focus.placeholder': clearPlaceholder,\r\n                    'blur.placeholder': setPlaceholder\r\n                })\r\n                .data('placeholder-enabled', true)\r\n                .trigger('blur.placeholder');\r\n            return $this;\r\n        };\r\n\r\n        placeholder.input = isInputSupported;\r\n        placeholder.textarea = isTextareaSupported;\r\n\r\n        hooks = {\r\n            'get': function(element) {\r\n                var $element = $(element);\r\n                return $element.data('placeholder-enabled') && $element.hasClass('placeholder') ? '' : element.value;\r\n            },\r\n            'set': function(element, value) {\r\n                var $element = $(element);\r\n                if (!$element.data('placeholder-enabled')) {\r\n                    return element.value = value;\r\n                }\r\n                if (value == '') {\r\n                    element.value = value;\r\n                    // Issue #56: Setting the placeholder causes problems if the element continues to have focus.\r\n                    if (element != document.activeElement) {\r\n                        // We can't use `triggerHandler` here because of dummy text/password inputs :(\r\n                        setPlaceholder.call(element);\r\n                    }\r\n                } else if ($element.hasClass('placeholder')) {\r\n                    clearPlaceholder.call(element, true, value) || (element.value = value);\r\n                } else {\r\n                    element.value = value;\r\n                }\r\n                // `set` can not return `undefined`; see http://jsapi.info/jquery/1.7.1/val#L2363\r\n                return $element;\r\n            }\r\n        };\r\n\r\n        isInputSupported || (valHooks.input = hooks);\r\n        isTextareaSupported || (valHooks.textarea = hooks);\r\n\r\n        $(function() {\r\n            // Look for forms\r\n            $(document).delegate('form', 'submit.placeholder', function() {\r\n                // Clear the placeholder values so they don't get submitted\r\n                var $inputs = $('.placeholder', this).each(clearPlaceholder);\r\n                setTimeout(function() {\r\n                    $inputs.each(setPlaceholder);\r\n                }, 10);\r\n            });\r\n        });\r\n\r\n        // Clear placeholder values upon page reload\r\n        $(window).bind('beforeunload.placeholder', function() {\r\n            $('.placeholder').each(function() {\r\n                this.value = '';\r\n            });\r\n        });\r\n\r\n    }\r\n\r\n    function args(elem) {\r\n        // Return an object of element attributes\r\n        var newAttrs = {},\r\n            rinlinejQuery = /^jQuery\\d+$/;\r\n        $.each(elem.attributes, function(i, attr) {\r\n            if (attr.specified && !rinlinejQuery.test(attr.name)) {\r\n                newAttrs[attr.name] = attr.value;\r\n            }\r\n        });\r\n        return newAttrs;\r\n    }\r\n\r\n    function clearPlaceholder(event, value) {\r\n        var input = this,\r\n            $input = $(input);\r\n        if (input.value == $input.attr('placeholder') && $input.hasClass('placeholder')) {\r\n            if ($input.data('placeholder-password')) {\r\n                $input = $input.hide().next().show().attr('id', $input.removeAttr('id').data('placeholder-id'));\r\n                // If `clearPlaceholder` was called from `$.valHooks.input.set`\r\n                if (event === true) {\r\n                    return $input[0].value = value;\r\n                }\r\n                $input.focus();\r\n            } else {\r\n                input.value = '';\r\n                $input.removeClass('placeholder');\r\n                input == document.activeElement && input.select();\r\n            }\r\n        }\r\n    }\r\n\r\n    function setPlaceholder() {\r\n        var $replacement,\r\n            input = this,\r\n            $input = $(input),\r\n            $origInput = $input,\r\n            id = this.id;\r\n        if (input.value == '') {\r\n            if (input.type == 'password') {\r\n                if (!$input.data('placeholder-textinput')) {\r\n                    try {\r\n                        $replacement = $input.clone().attr({ 'type': 'text' });\r\n                    } catch(e) {\r\n                        $replacement = $('<input>').attr($.extend(args(this), { 'type': 'text' }));\r\n                    }\r\n                    $replacement\r\n                        .removeAttr('name')\r\n                        .data({\r\n                            'placeholder-password': true,\r\n                            'placeholder-id': id\r\n                        })\r\n                        .bind('focus.placeholder', clearPlaceholder);\r\n                    $input\r\n                        .data({\r\n                            'placeholder-textinput': $replacement,\r\n                            'placeholder-id': id\r\n                        })\r\n                        .before($replacement);\r\n                }\r\n                $input = $input.removeAttr('id').hide().prev().attr('id', id).show();\r\n                // Note: `$input[0] != input` now!\r\n            }\r\n            $input.addClass('placeholder');\r\n            $input[0].value = $input.attr('placeholder');\r\n        } else {\r\n            $input.removeClass('placeholder');\r\n        }\r\n    }\r\n\r\n}(this, document, jQuery));", "/*!\n * jQuery Form Plugin\n * version: 3.51.0-2014.06.20\n * Requires jQuery v1.5 or later\n * Copyright (c) 2014 M. Alsup\n * Examples and documentation at: http://malsup.com/jquery/form/\n * Project repository: https://github.com/malsup/form\n * Dual licensed under the MIT and GPL licenses.\n * https://github.com/malsup/form#copyright-and-license\n */\n/*global ActiveXObject */\n\n// AMD support\n(function (factory) {\n    \"use strict\";\n    if (typeof define === 'function' && define.amd) {\n        // using AMD; register as anon module\n        define(['jquery'], factory);\n    } else {\n        // no AMD; invoke directly\n        factory( (typeof(jQuery) != 'undefined') ? jQuery : window.Zepto );\n    }\n}\n\n(function($) {\n\"use strict\";\n\n/*\n    Usage Note:\n    -----------\n    Do not use both ajaxSubmit and ajaxForm on the same form.  These\n    functions are mutually exclusive.  Use ajaxSubmit if you want\n    to bind your own submit handler to the form.  For example,\n\n    $(document).ready(function() {\n        $('#myForm').on('submit', function(e) {\n            e.preventDefault(); // <-- important\n            $(this).ajaxSubmit({\n                target: '#output'\n            });\n        });\n    });\n\n    Use ajaxForm when you want the plugin to manage all the event binding\n    for you.  For example,\n\n    $(document).ready(function() {\n        $('#myForm').ajaxForm({\n            target: '#output'\n        });\n    });\n\n    You can also use ajaxForm with delegation (requires jQuery v1.7+), so the\n    form does not have to exist when you invoke ajaxForm:\n\n    $('#myForm').ajaxForm({\n        delegation: true,\n        target: '#output'\n    });\n\n    When using ajaxForm, the ajaxSubmit function will be invoked for you\n    at the appropriate time.\n*/\n\n/**\n * Feature detection\n */\nvar feature = {};\nfeature.fileapi = $(\"<input type='file'/>\").get(0).files !== undefined;\nfeature.formdata = window.FormData !== undefined;\n\nvar hasProp = !!$.fn.prop;\n\n// attr2 uses prop when it can but checks the return type for\n// an expected string.  this accounts for the case where a form \n// contains inputs with names like \"action\" or \"method\"; in those\n// cases \"prop\" returns the element\n$.fn.attr2 = function() {\n    if ( ! hasProp ) {\n        return this.attr.apply(this, arguments);\n    }\n    var val = this.prop.apply(this, arguments);\n    if ( ( val && val.jquery ) || typeof val === 'string' ) {\n        return val;\n    }\n    return this.attr.apply(this, arguments);\n};\n\n/**\n * ajaxSubmit() provides a mechanism for immediately submitting\n * an HTML form using AJAX.\n */\n$.fn.ajaxSubmit = function(options) {\n    /*jshint scripturl:true */\n\n    // fast fail if nothing selected (http://dev.jquery.com/ticket/2752)\n    if (!this.length) {\n        log('ajaxSubmit: skipping submit process - no element selected');\n        return this;\n    }\n\n    var method, action, url, $form = this;\n\n    if (typeof options == 'function') {\n        options = { success: options };\n    }\n    else if ( options === undefined ) {\n        options = {};\n    }\n\n    method = options.type || this.attr2('method');\n    action = options.url  || this.attr2('action');\n\n    url = (typeof action === 'string') ? $.trim(action) : '';\n    url = url || window.location.href || '';\n    if (url) {\n        // clean url (don't include hash vaue)\n        url = (url.match(/^([^#]+)/)||[])[1];\n    }\n\n    options = $.extend(true, {\n        url:  url,\n        success: $.ajaxSettings.success,\n        type: method || $.ajaxSettings.type,\n        iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank'\n    }, options);\n\n    // hook for manipulating the form data before it is extracted;\n    // convenient for use with rich editors like tinyMCE or FCKEditor\n    var veto = {};\n    this.trigger('form-pre-serialize', [this, options, veto]);\n    if (veto.veto) {\n        log('ajaxSubmit: submit vetoed via form-pre-serialize trigger');\n        return this;\n    }\n\n    // provide opportunity to alter form data before it is serialized\n    if (options.beforeSerialize && options.beforeSerialize(this, options) === false) {\n        log('ajaxSubmit: submit aborted via beforeSerialize callback');\n        return this;\n    }\n\n    var traditional = options.traditional;\n    if ( traditional === undefined ) {\n        traditional = $.ajaxSettings.traditional;\n    }\n\n    var elements = [];\n    var qx, a = this.formToArray(options.semantic, elements);\n    if (options.data) {\n        options.extraData = options.data;\n        qx = $.param(options.data, traditional);\n    }\n\n    // give pre-submit callback an opportunity to abort the submit\n    if (options.beforeSubmit && options.beforeSubmit(a, this, options) === false) {\n        log('ajaxSubmit: submit aborted via beforeSubmit callback');\n        return this;\n    }\n\n    // fire vetoable 'validate' event\n    this.trigger('form-submit-validate', [a, this, options, veto]);\n    if (veto.veto) {\n        log('ajaxSubmit: submit vetoed via form-submit-validate trigger');\n        return this;\n    }\n\n    var q = $.param(a, traditional);\n    if (qx) {\n        q = ( q ? (q + '&' + qx) : qx );\n    }\n    if (options.type.toUpperCase() == 'GET') {\n        options.url += (options.url.indexOf('?') >= 0 ? '&' : '?') + q;\n        options.data = null;  // data is null for 'get'\n    }\n    else {\n        options.data = q; // data is the query string for 'post'\n    }\n\n    var callbacks = [];\n    if (options.resetForm) {\n        callbacks.push(function() { $form.resetForm(); });\n    }\n    if (options.clearForm) {\n        callbacks.push(function() { $form.clearForm(options.includeHidden); });\n    }\n\n    // perform a load on the target only if dataType is not provided\n    if (!options.dataType && options.target) {\n        var oldSuccess = options.success || function(){};\n        callbacks.push(function(data) {\n            var fn = options.replaceTarget ? 'replaceWith' : 'html';\n            $(options.target)[fn](data).each(oldSuccess, arguments);\n        });\n    }\n    else if (options.success) {\n        callbacks.push(options.success);\n    }\n\n    options.success = function(data, status, xhr) { // jQuery 1.4+ passes xhr as 3rd arg\n        var context = options.context || this ;    // jQuery 1.4+ supports scope context\n        for (var i=0, max=callbacks.length; i < max; i++) {\n            callbacks[i].apply(context, [data, status, xhr || $form, $form]);\n        }\n    };\n\n    if (options.error) {\n        var oldError = options.error;\n        options.error = function(xhr, status, error) {\n            var context = options.context || this;\n            oldError.apply(context, [xhr, status, error, $form]);\n        };\n    }\n\n     if (options.complete) {\n        var oldComplete = options.complete;\n        options.complete = function(xhr, status) {\n            var context = options.context || this;\n            oldComplete.apply(context, [xhr, status, $form]);\n        };\n    }\n\n    // are there files to upload?\n\n    // [value] (issue #113), also see comment:\n    // https://github.com/malsup/form/commit/588306aedba1de01388032d5f42a60159eea9228#commitcomment-2180219\n    var fileInputs = $('input[type=file]:enabled', this).filter(function() { return $(this).val() !== ''; });\n\n    var hasFileInputs = fileInputs.length > 0;\n    var mp = 'multipart/form-data';\n    var multipart = ($form.attr('enctype') == mp || $form.attr('encoding') == mp);\n\n    var fileAPI = feature.fileapi && feature.formdata;\n    log(\"fileAPI :\" + fileAPI);\n    var shouldUseFrame = (hasFileInputs || multipart) && !fileAPI;\n\n    var jqxhr;\n\n    // options.iframe allows user to force iframe mode\n    // 06-NOV-09: now defaulting to iframe mode if file input is detected\n    if (options.iframe !== false && (options.iframe || shouldUseFrame)) {\n        // hack to fix Safari hang (thanks to Tim Molendijk for this)\n        // see:  http://groups.google.com/group/jquery-dev/browse_thread/thread/36395b7ab510dd5d\n        if (options.closeKeepAlive) {\n            $.get(options.closeKeepAlive, function() {\n                jqxhr = fileUploadIframe(a);\n            });\n        }\n        else {\n            jqxhr = fileUploadIframe(a);\n        }\n    }\n    else if ((hasFileInputs || multipart) && fileAPI) {\n        jqxhr = fileUploadXhr(a);\n    }\n    else {\n        jqxhr = $.ajax(options);\n    }\n\n    $form.removeData('jqxhr').data('jqxhr', jqxhr);\n\n    // clear element array\n    for (var k=0; k < elements.length; k++) {\n        elements[k] = null;\n    }\n\n    // fire 'notify' event\n    this.trigger('form-submit-notify', [this, options]);\n    return this;\n\n    // utility fn for deep serialization\n    function deepSerialize(extraData){\n        var serialized = $.param(extraData, options.traditional).split('&');\n        var len = serialized.length;\n        var result = [];\n        var i, part;\n        for (i=0; i < len; i++) {\n            // #252; undo param space replacement\n            serialized[i] = serialized[i].replace(/\\+/g,' ');\n            part = serialized[i].split('=');\n            // #278; use array instead of object storage, favoring array serializations\n            result.push([decodeURIComponent(part[0]), decodeURIComponent(part[1])]);\n        }\n        return result;\n    }\n\n     // XMLHttpRequest Level 2 file uploads (big hat tip to francois2metz)\n    function fileUploadXhr(a) {\n        var formdata = new FormData();\n\n        for (var i=0; i < a.length; i++) {\n            formdata.append(a[i].name, a[i].value);\n        }\n\n        if (options.extraData) {\n            var serializedData = deepSerialize(options.extraData);\n            for (i=0; i < serializedData.length; i++) {\n                if (serializedData[i]) {\n                    formdata.append(serializedData[i][0], serializedData[i][1]);\n                }\n            }\n        }\n\n        options.data = null;\n\n        var s = $.extend(true, {}, $.ajaxSettings, options, {\n            contentType: false,\n            processData: false,\n            cache: false,\n            type: method || 'POST'\n        });\n\n        if (options.uploadProgress) {\n            // workaround because jqXHR does not expose upload property\n            s.xhr = function() {\n                var xhr = $.ajaxSettings.xhr();\n                if (xhr.upload) {\n                    xhr.upload.addEventListener('progress', function(event) {\n                        var percent = 0;\n                        var position = event.loaded || event.position; /*event.position is deprecated*/\n                        var total = event.total;\n                        if (event.lengthComputable) {\n                            percent = Math.ceil(position / total * 100);\n                        }\n                        options.uploadProgress(event, position, total, percent);\n                    }, false);\n                }\n                return xhr;\n            };\n        }\n\n        s.data = null;\n        var beforeSend = s.beforeSend;\n        s.beforeSend = function(xhr, o) {\n            //Send FormData() provided by user\n            if (options.formData) {\n                o.data = options.formData;\n            }\n            else {\n                o.data = formdata;\n            }\n            if(beforeSend) {\n                beforeSend.call(this, xhr, o);\n            }\n        };\n        return $.ajax(s);\n    }\n\n    // private function for handling file uploads (hat tip to YAHOO!)\n    function fileUploadIframe(a) {\n        var form = $form[0], el, i, s, g, id, $io, io, xhr, sub, n, timedOut, timeoutHandle;\n        var deferred = $.Deferred();\n\n        // #341\n        deferred.abort = function(status) {\n            xhr.abort(status);\n        };\n\n        if (a) {\n            // ensure that every serialized input is still enabled\n            for (i=0; i < elements.length; i++) {\n                el = $(elements[i]);\n                if ( hasProp ) {\n                    el.prop('disabled', false);\n                }\n                else {\n                    el.removeAttr('disabled');\n                }\n            }\n        }\n\n        s = $.extend(true, {}, $.ajaxSettings, options);\n        s.context = s.context || s;\n        id = 'jqFormIO' + (new Date().getTime());\n        if (s.iframeTarget) {\n            $io = $(s.iframeTarget);\n            n = $io.attr2('name');\n            if (!n) {\n                $io.attr2('name', id);\n            }\n            else {\n                id = n;\n            }\n        }\n        else {\n            $io = $('<iframe name=\"' + id + '\" src=\"'+ s.iframeSrc +'\" />');\n            $io.css({ position: 'absolute', top: '-1000px', left: '-1000px' });\n        }\n        io = $io[0];\n\n\n        xhr = { // mock object\n            aborted: 0,\n            responseText: null,\n            responseXML: null,\n            status: 0,\n            statusText: 'n/a',\n            getAllResponseHeaders: function() {},\n            getResponseHeader: function() {},\n            setRequestHeader: function() {},\n            abort: function(status) {\n                var e = (status === 'timeout' ? 'timeout' : 'aborted');\n                log('aborting upload... ' + e);\n                this.aborted = 1;\n\n                try { // #214, #257\n                    if (io.contentWindow.document.execCommand) {\n                        io.contentWindow.document.execCommand('Stop');\n                    }\n                }\n                catch(ignore) {}\n\n                $io.attr('src', s.iframeSrc); // abort op in progress\n                xhr.error = e;\n                if (s.error) {\n                    s.error.call(s.context, xhr, e, status);\n                }\n                if (g) {\n                    $.event.trigger(\"ajaxError\", [xhr, s, e]);\n                }\n                if (s.complete) {\n                    s.complete.call(s.context, xhr, e);\n                }\n            }\n        };\n\n        g = s.global;\n        // trigger ajax global events so that activity/block indicators work like normal\n        if (g && 0 === $.active++) {\n            $.event.trigger(\"ajaxStart\");\n        }\n        if (g) {\n            $.event.trigger(\"ajaxSend\", [xhr, s]);\n        }\n\n        if (s.beforeSend && s.beforeSend.call(s.context, xhr, s) === false) {\n            if (s.global) {\n                $.active--;\n            }\n            deferred.reject();\n            return deferred;\n        }\n        if (xhr.aborted) {\n            deferred.reject();\n            return deferred;\n        }\n\n        // add submitting element to data if we know it\n        sub = form.clk;\n        if (sub) {\n            n = sub.name;\n            if (n && !sub.disabled) {\n                s.extraData = s.extraData || {};\n                s.extraData[n] = sub.value;\n                if (sub.type == \"image\") {\n                    s.extraData[n+'.x'] = form.clk_x;\n                    s.extraData[n+'.y'] = form.clk_y;\n                }\n            }\n        }\n\n        var CLIENT_TIMEOUT_ABORT = 1;\n        var SERVER_ABORT = 2;\n                \n        function getDoc(frame) {\n            /* it looks like contentWindow or contentDocument do not\n             * carry the protocol property in ie8, when running under ssl\n             * frame.document is the only valid response document, since\n             * the protocol is know but not on the other two objects. strange?\n             * \"Same origin policy\" http://en.wikipedia.org/wiki/Same_origin_policy\n             */\n            \n            var doc = null;\n            \n            // IE8 cascading access check\n            try {\n                if (frame.contentWindow) {\n                    doc = frame.contentWindow.document;\n                }\n            } catch(err) {\n                // IE8 access denied under ssl & missing protocol\n                log('cannot get iframe.contentWindow document: ' + err);\n            }\n\n            if (doc) { // successful getting content\n                return doc;\n            }\n\n            try { // simply checking may throw in ie8 under ssl or mismatched protocol\n                doc = frame.contentDocument ? frame.contentDocument : frame.document;\n            } catch(err) {\n                // last attempt\n                log('cannot get iframe.contentDocument: ' + err);\n                doc = frame.document;\n            }\n            return doc;\n        }\n\n        // Rails CSRF hack (thanks to Yvan Barthelemy)\n        var csrf_token = $('meta[name=csrf-token]').attr('content');\n        var csrf_param = $('meta[name=csrf-param]').attr('content');\n        if (csrf_param && csrf_token) {\n            s.extraData = s.extraData || {};\n            s.extraData[csrf_param] = csrf_token;\n        }\n\n        // take a breath so that pending repaints get some cpu time before the upload starts\n        function doSubmit() {\n            // make sure form attrs are set\n            var t = $form.attr2('target'), \n                a = $form.attr2('action'), \n                mp = 'multipart/form-data',\n                et = $form.attr('enctype') || $form.attr('encoding') || mp;\n\n            // update form attrs in IE friendly way\n            form.setAttribute('target',id);\n            if (!method || /post/i.test(method) ) {\n                form.setAttribute('method', 'POST');\n            }\n            if (a != s.url) {\n                form.setAttribute('action', s.url);\n            }\n\n            // ie borks in some cases when setting encoding\n            if (! s.skipEncodingOverride && (!method || /post/i.test(method))) {\n                $form.attr({\n                    encoding: 'multipart/form-data',\n                    enctype:  'multipart/form-data'\n                });\n            }\n\n            // support timout\n            if (s.timeout) {\n                timeoutHandle = setTimeout(function() { timedOut = true; cb(CLIENT_TIMEOUT_ABORT); }, s.timeout);\n            }\n\n            // look for server aborts\n            function checkState() {\n                try {\n                    var state = getDoc(io).readyState;\n                    log('state = ' + state);\n                    if (state && state.toLowerCase() == 'uninitialized') {\n                        setTimeout(checkState,50);\n                    }\n                }\n                catch(e) {\n                    log('Server abort: ' , e, ' (', e.name, ')');\n                    cb(SERVER_ABORT);\n                    if (timeoutHandle) {\n                        clearTimeout(timeoutHandle);\n                    }\n                    timeoutHandle = undefined;\n                }\n            }\n\n            // add \"extra\" data to form if provided in options\n            var extraInputs = [];\n            try {\n                if (s.extraData) {\n                    for (var n in s.extraData) {\n                        if (s.extraData.hasOwnProperty(n)) {\n                           // if using the $.param format that allows for multiple values with the same name\n                           if($.isPlainObject(s.extraData[n]) && s.extraData[n].hasOwnProperty('name') && s.extraData[n].hasOwnProperty('value')) {\n                               extraInputs.push(\n                               $('<input type=\"hidden\" name=\"'+s.extraData[n].name+'\">').val(s.extraData[n].value)\n                                   .appendTo(form)[0]);\n                           } else {\n                               extraInputs.push(\n                               $('<input type=\"hidden\" name=\"'+n+'\">').val(s.extraData[n])\n                                   .appendTo(form)[0]);\n                           }\n                        }\n                    }\n                }\n\n                if (!s.iframeTarget) {\n                    // add iframe to doc and submit the form\n                    $io.appendTo('body');\n                }\n                if (io.attachEvent) {\n                    io.attachEvent('onload', cb);\n                }\n                else {\n                    io.addEventListener('load', cb, false);\n                }\n                setTimeout(checkState,15);\n\n                try {\n                    form.submit();\n                } catch(err) {\n                    // just in case form has element with name/id of 'submit'\n                    var submitFn = document.createElement('form').submit;\n                    submitFn.apply(form);\n                }\n            }\n            finally {\n                // reset attrs and remove \"extra\" input elements\n                form.setAttribute('action',a);\n                form.setAttribute('enctype', et); // #380\n                if(t) {\n                    form.setAttribute('target', t);\n                } else {\n                    $form.removeAttr('target');\n                }\n                $(extraInputs).remove();\n            }\n        }\n\n        if (s.forceSync) {\n            doSubmit();\n        }\n        else {\n            setTimeout(doSubmit, 10); // this lets dom updates render\n        }\n\n        var data, doc, domCheckCount = 50, callbackProcessed;\n\n        function cb(e) {\n            if (xhr.aborted || callbackProcessed) {\n                return;\n            }\n            \n            doc = getDoc(io);\n            if(!doc) {\n                log('cannot access response document');\n                e = SERVER_ABORT;\n            }\n            if (e === CLIENT_TIMEOUT_ABORT && xhr) {\n                xhr.abort('timeout');\n                deferred.reject(xhr, 'timeout');\n                return;\n            }\n            else if (e == SERVER_ABORT && xhr) {\n                xhr.abort('server abort');\n                deferred.reject(xhr, 'error', 'server abort');\n                return;\n            }\n\n            if (!doc || doc.location.href == s.iframeSrc) {\n                // response not received yet\n                if (!timedOut) {\n                    return;\n                }\n            }\n            if (io.detachEvent) {\n                io.detachEvent('onload', cb);\n            }\n            else {\n                io.removeEventListener('load', cb, false);\n            }\n\n            var status = 'success', errMsg;\n            try {\n                if (timedOut) {\n                    throw 'timeout';\n                }\n\n                var isXml = s.dataType == 'xml' || doc.XMLDocument || $.isXMLDoc(doc);\n                log('isXml='+isXml);\n                if (!isXml && window.opera && (doc.body === null || !doc.body.innerHTML)) {\n                    if (--domCheckCount) {\n                        // in some browsers (Opera) the iframe DOM is not always traversable when\n                        // the onload callback fires, so we loop a bit to accommodate\n                        log('requeing onLoad callback, DOM not available');\n                        setTimeout(cb, 250);\n                        return;\n                    }\n                    // let this fall through because server response could be an empty document\n                    //log('Could not access iframe DOM after mutiple tries.');\n                    //throw 'DOMException: not available';\n                }\n\n                //log('response detected');\n                var docRoot = doc.body ? doc.body : doc.documentElement;\n                xhr.responseText = docRoot ? docRoot.innerHTML : null;\n                xhr.responseXML = doc.XMLDocument ? doc.XMLDocument : doc;\n                if (isXml) {\n                    s.dataType = 'xml';\n                }\n                xhr.getResponseHeader = function(header){\n                    var headers = {'content-type': s.dataType};\n                    return headers[header.toLowerCase()];\n                };\n                // support for XHR 'status' & 'statusText' emulation :\n                if (docRoot) {\n                    xhr.status = Number( docRoot.getAttribute('status') ) || xhr.status;\n                    xhr.statusText = docRoot.getAttribute('statusText') || xhr.statusText;\n                }\n\n                var dt = (s.dataType || '').toLowerCase();\n                var scr = /(json|script|text)/.test(dt);\n                if (scr || s.textarea) {\n                    // see if user embedded response in textarea\n                    var ta = doc.getElementsByTagName('textarea')[0];\n                    if (ta) {\n                        xhr.responseText = ta.value;\n                        // support for XHR 'status' & 'statusText' emulation :\n                        xhr.status = Number( ta.getAttribute('status') ) || xhr.status;\n                        xhr.statusText = ta.getAttribute('statusText') || xhr.statusText;\n                    }\n                    else if (scr) {\n                        // account for browsers injecting pre around json response\n                        var pre = doc.getElementsByTagName('pre')[0];\n                        var b = doc.getElementsByTagName('body')[0];\n                        if (pre) {\n                            xhr.responseText = pre.textContent ? pre.textContent : pre.innerText;\n                        }\n                        else if (b) {\n                            xhr.responseText = b.textContent ? b.textContent : b.innerText;\n                        }\n                    }\n                }\n                else if (dt == 'xml' && !xhr.responseXML && xhr.responseText) {\n                    xhr.responseXML = toXml(xhr.responseText);\n                }\n\n                try {\n                    data = httpData(xhr, dt, s);\n                }\n                catch (err) {\n                    status = 'parsererror';\n                    xhr.error = errMsg = (err || status);\n                }\n            }\n            catch (err) {\n                log('error caught: ',err);\n                status = 'error';\n                xhr.error = errMsg = (err || status);\n            }\n\n            if (xhr.aborted) {\n                log('upload aborted');\n                status = null;\n            }\n\n            if (xhr.status) { // we've set xhr.status\n                status = (xhr.status >= 200 && xhr.status < 300 || xhr.status === 304) ? 'success' : 'error';\n            }\n\n            // ordering of these callbacks/triggers is odd, but that's how $.ajax does it\n            if (status === 'success') {\n                if (s.success) {\n                    s.success.call(s.context, data, 'success', xhr);\n                }\n                deferred.resolve(xhr.responseText, 'success', xhr);\n                if (g) {\n                    $.event.trigger(\"ajaxSuccess\", [xhr, s]);\n                }\n            }\n            else if (status) {\n                if (errMsg === undefined) {\n                    errMsg = xhr.statusText;\n                }\n                if (s.error) {\n                    s.error.call(s.context, xhr, status, errMsg);\n                }\n                deferred.reject(xhr, 'error', errMsg);\n                if (g) {\n                    $.event.trigger(\"ajaxError\", [xhr, s, errMsg]);\n                }\n            }\n\n            if (g) {\n                $.event.trigger(\"ajaxComplete\", [xhr, s]);\n            }\n\n            if (g && ! --$.active) {\n                $.event.trigger(\"ajaxStop\");\n            }\n\n            if (s.complete) {\n                s.complete.call(s.context, xhr, status);\n            }\n\n            callbackProcessed = true;\n            if (s.timeout) {\n                clearTimeout(timeoutHandle);\n            }\n\n            // clean up\n            setTimeout(function() {\n                if (!s.iframeTarget) {\n                    $io.remove();\n                }\n                else { //adding else to clean up existing iframe response.\n                    $io.attr('src', s.iframeSrc);\n                }\n                xhr.responseXML = null;\n            }, 100);\n        }\n\n        var toXml = $.parseXML || function(s, doc) { // use parseXML if available (jQuery 1.5+)\n            if (window.ActiveXObject) {\n                doc = new ActiveXObject('Microsoft.XMLDOM');\n                doc.async = 'false';\n                doc.loadXML(s);\n            }\n            else {\n                doc = (new DOMParser()).parseFromString(s, 'text/xml');\n            }\n            return (doc && doc.documentElement && doc.documentElement.nodeName != 'parsererror') ? doc : null;\n        };\n        var parseJSON = $.parseJSON || function(s) {\n            /*jslint evil:true */\n            return window['eval']('(' + s + ')');\n        };\n\n        var httpData = function( xhr, type, s ) { // mostly lifted from jq1.4.4\n\n            var ct = xhr.getResponseHeader('content-type') || '',\n                xml = type === 'xml' || !type && ct.indexOf('xml') >= 0,\n                data = xml ? xhr.responseXML : xhr.responseText;\n\n            if (xml && data.documentElement.nodeName === 'parsererror') {\n                if ($.error) {\n                    $.error('parsererror');\n                }\n            }\n            if (s && s.dataFilter) {\n                data = s.dataFilter(data, type);\n            }\n            if (typeof data === 'string') {\n                if (type === 'json' || !type && ct.indexOf('json') >= 0) {\n                    data = parseJSON(data);\n                } else if (type === \"script\" || !type && ct.indexOf(\"javascript\") >= 0) {\n                    $.globalEval(data);\n                }\n            }\n            return data;\n        };\n\n        return deferred;\n    }\n};\n\n/**\n * ajaxForm() provides a mechanism for fully automating form submission.\n *\n * The advantages of using this method instead of ajaxSubmit() are:\n *\n * 1: This method will include coordinates for <input type=\"image\" /> elements (if the element\n *    is used to submit the form).\n * 2. This method will include the submit element's name/value data (for the element that was\n *    used to submit the form).\n * 3. This method binds the submit() method to the form for you.\n *\n * The options argument for ajaxForm works exactly as it does for ajaxSubmit.  ajaxForm merely\n * passes the options argument along after properly binding events for submit elements and\n * the form itself.\n */\n$.fn.ajaxForm = function(options) {\n    options = options || {};\n    options.delegation = options.delegation && $.isFunction($.fn.on);\n\n    // in jQuery 1.3+ we can fix mistakes with the ready state\n    if (!options.delegation && this.length === 0) {\n        var o = { s: this.selector, c: this.context };\n        if (!$.isReady && o.s) {\n            log('DOM not ready, queuing ajaxForm');\n            $(function() {\n                $(o.s,o.c).ajaxForm(options);\n            });\n            return this;\n        }\n        // is your DOM ready?  http://docs.jquery.com/Tutorials:Introducing_$(document).ready()\n        log('terminating; zero elements found by selector' + ($.isReady ? '' : ' (DOM not ready)'));\n        return this;\n    }\n\n    if ( options.delegation ) {\n        $(document)\n            .off('submit.form-plugin', this.selector, doAjaxSubmit)\n            .off('click.form-plugin', this.selector, captureSubmittingElement)\n            .on('submit.form-plugin', this.selector, options, doAjaxSubmit)\n            .on('click.form-plugin', this.selector, options, captureSubmittingElement);\n        return this;\n    }\n\n    return this.ajaxFormUnbind()\n        .bind('submit.form-plugin', options, doAjaxSubmit)\n        .bind('click.form-plugin', options, captureSubmittingElement);\n};\n\n// private event handlers\nfunction doAjaxSubmit(e) {\n    /*jshint validthis:true */\n    var options = e.data;\n    if (!e.isDefaultPrevented()) { // if event has been canceled, don't proceed\n        e.preventDefault();\n        $(e.target).ajaxSubmit(options); // #365\n    }\n}\n\nfunction captureSubmittingElement(e) {\n    /*jshint validthis:true */\n    var target = e.target;\n    var $el = $(target);\n    if (!($el.is(\"[type=submit],[type=image]\"))) {\n        // is this a child element of the submit el?  (ex: a span within a button)\n        var t = $el.closest('[type=submit]');\n        if (t.length === 0) {\n            return;\n        }\n        target = t[0];\n    }\n    var form = this;\n    form.clk = target;\n    if (target.type == 'image') {\n        if (e.offsetX !== undefined) {\n            form.clk_x = e.offsetX;\n            form.clk_y = e.offsetY;\n        } else if (typeof $.fn.offset == 'function') {\n            var offset = $el.offset();\n            form.clk_x = e.pageX - offset.left;\n            form.clk_y = e.pageY - offset.top;\n        } else {\n            form.clk_x = e.pageX - target.offsetLeft;\n            form.clk_y = e.pageY - target.offsetTop;\n        }\n    }\n    // clear form vars\n    setTimeout(function() { form.clk = form.clk_x = form.clk_y = null; }, 100);\n}\n\n\n// ajaxFormUnbind unbinds the event handlers that were bound by ajaxForm\n$.fn.ajaxFormUnbind = function() {\n    return this.unbind('submit.form-plugin click.form-plugin');\n};\n\n/**\n * formToArray() gathers form element data into an array of objects that can\n * be passed to any of the following ajax functions: $.get, $.post, or load.\n * Each object in the array has both a 'name' and 'value' property.  An example of\n * an array for a simple login form might be:\n *\n * [ { name: 'username', value: 'jresig' }, { name: 'password', value: 'secret' } ]\n *\n * It is this array that is passed to pre-submit callback functions provided to the\n * ajaxSubmit() and ajaxForm() methods.\n */\n$.fn.formToArray = function(semantic, elements) {\n    var a = [];\n    if (this.length === 0) {\n        return a;\n    }\n\n    var form = this[0];\n    var formId = this.attr('id');\n    var els = semantic ? form.getElementsByTagName('*') : form.elements;\n    var els2;\n\n    if (els && !/MSIE [678]/.test(navigator.userAgent)) { // #390\n        els = $(els).get();  // convert to standard array\n    }\n\n    // #386; account for inputs outside the form which use the 'form' attribute\n    if ( formId ) {\n        els2 = $(':input[form=\"' + formId + '\"]').get(); // hat tip @thet\n        if ( els2.length ) {\n            els = (els || []).concat(els2);\n        }\n    }\n\n    if (!els || !els.length) {\n        return a;\n    }\n\n    var i,j,n,v,el,max,jmax;\n    for(i=0, max=els.length; i < max; i++) {\n        el = els[i];\n        n = el.name;\n        if (!n || el.disabled) {\n            continue;\n        }\n\n        if (semantic && form.clk && el.type == \"image\") {\n            // handle image inputs on the fly when semantic == true\n            if(form.clk == el) {\n                a.push({name: n, value: $(el).val(), type: el.type });\n                a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});\n            }\n            continue;\n        }\n\n        v = $.fieldValue(el, true);\n        if (v && v.constructor == Array) {\n            if (elements) {\n                elements.push(el);\n            }\n            for(j=0, jmax=v.length; j < jmax; j++) {\n                a.push({name: n, value: v[j]});\n            }\n        }\n        else if (feature.fileapi && el.type == 'file') {\n            if (elements) {\n                elements.push(el);\n            }\n            var files = el.files;\n            if (files.length) {\n                for (j=0; j < files.length; j++) {\n                    a.push({name: n, value: files[j], type: el.type});\n                }\n            }\n            else {\n                // #180\n                a.push({ name: n, value: '', type: el.type });\n            }\n        }\n        else if (v !== null && typeof v != 'undefined') {\n            if (elements) {\n                elements.push(el);\n            }\n            a.push({name: n, value: v, type: el.type, required: el.required});\n        }\n    }\n\n    if (!semantic && form.clk) {\n        // input type=='image' are not found in elements array! handle it here\n        var $input = $(form.clk), input = $input[0];\n        n = input.name;\n        if (n && !input.disabled && input.type == 'image') {\n            a.push({name: n, value: $input.val()});\n            a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});\n        }\n    }\n    return a;\n};\n\n/**\n * Serializes form data into a 'submittable' string. This method will return a string\n * in the format: name1=value1&amp;name2=value2\n */\n$.fn.formSerialize = function(semantic) {\n    //hand off to jQuery.param for proper encoding\n    return $.param(this.formToArray(semantic));\n};\n\n/**\n * Serializes all field elements in the jQuery object into a query string.\n * This method will return a string in the format: name1=value1&amp;name2=value2\n */\n$.fn.fieldSerialize = function(successful) {\n    var a = [];\n    this.each(function() {\n        var n = this.name;\n        if (!n) {\n            return;\n        }\n        var v = $.fieldValue(this, successful);\n        if (v && v.constructor == Array) {\n            for (var i=0,max=v.length; i < max; i++) {\n                a.push({name: n, value: v[i]});\n            }\n        }\n        else if (v !== null && typeof v != 'undefined') {\n            a.push({name: this.name, value: v});\n        }\n    });\n    //hand off to jQuery.param for proper encoding\n    return $.param(a);\n};\n\n/**\n * Returns the value(s) of the element in the matched set.  For example, consider the following form:\n *\n *  <form><fieldset>\n *      <input name=\"A\" type=\"text\" />\n *      <input name=\"A\" type=\"text\" />\n *      <input name=\"B\" type=\"checkbox\" value=\"B1\" />\n *      <input name=\"B\" type=\"checkbox\" value=\"B2\"/>\n *      <input name=\"C\" type=\"radio\" value=\"C1\" />\n *      <input name=\"C\" type=\"radio\" value=\"C2\" />\n *  </fieldset></form>\n *\n *  var v = $('input[type=text]').fieldValue();\n *  // if no values are entered into the text inputs\n *  v == ['','']\n *  // if values entered into the text inputs are 'foo' and 'bar'\n *  v == ['foo','bar']\n *\n *  var v = $('input[type=checkbox]').fieldValue();\n *  // if neither checkbox is checked\n *  v === undefined\n *  // if both checkboxes are checked\n *  v == ['B1', 'B2']\n *\n *  var v = $('input[type=radio]').fieldValue();\n *  // if neither radio is checked\n *  v === undefined\n *  // if first radio is checked\n *  v == ['C1']\n *\n * The successful argument controls whether or not the field element must be 'successful'\n * (per http://www.w3.org/TR/html4/interact/forms.html#successful-controls).\n * The default value of the successful argument is true.  If this value is false the value(s)\n * for each element is returned.\n *\n * Note: This method *always* returns an array.  If no valid value can be determined the\n *    array will be empty, otherwise it will contain one or more values.\n */\n$.fn.fieldValue = function(successful) {\n    for (var val=[], i=0, max=this.length; i < max; i++) {\n        var el = this[i];\n        var v = $.fieldValue(el, successful);\n        if (v === null || typeof v == 'undefined' || (v.constructor == Array && !v.length)) {\n            continue;\n        }\n        if (v.constructor == Array) {\n            $.merge(val, v);\n        }\n        else {\n            val.push(v);\n        }\n    }\n    return val;\n};\n\n/**\n * Returns the value of the field element.\n */\n$.fieldValue = function(el, successful) {\n    var n = el.name, t = el.type, tag = el.tagName.toLowerCase();\n    if (successful === undefined) {\n        successful = true;\n    }\n\n    if (successful && (!n || el.disabled || t == 'reset' || t == 'button' ||\n        (t == 'checkbox' || t == 'radio') && !el.checked ||\n        (t == 'submit' || t == 'image') && el.form && el.form.clk != el ||\n        tag == 'select' && el.selectedIndex == -1)) {\n            return null;\n    }\n\n    if (tag == 'select') {\n        var index = el.selectedIndex;\n        if (index < 0) {\n            return null;\n        }\n        var a = [], ops = el.options;\n        var one = (t == 'select-one');\n        var max = (one ? index+1 : ops.length);\n        for(var i=(one ? index : 0); i < max; i++) {\n            var op = ops[i];\n            if (op.selected) {\n                var v = op.value;\n                if (!v) { // extra pain for IE...\n                    v = (op.attributes && op.attributes.value && !(op.attributes.value.specified)) ? op.text : op.value;\n                }\n                if (one) {\n                    return v;\n                }\n                a.push(v);\n            }\n        }\n        return a;\n    }\n    return $(el).val();\n};\n\n/**\n * Clears the form data.  Takes the following actions on the form's input fields:\n *  - input text fields will have their 'value' property set to the empty string\n *  - select elements will have their 'selectedIndex' property set to -1\n *  - checkbox and radio inputs will have their 'checked' property set to false\n *  - inputs of type submit, button, reset, and hidden will *not* be effected\n *  - button elements will *not* be effected\n */\n$.fn.clearForm = function(includeHidden) {\n    return this.each(function() {\n        $('input,select,textarea', this).clearFields(includeHidden);\n    });\n};\n\n/**\n * Clears the selected form elements.\n */\n$.fn.clearFields = $.fn.clearInputs = function(includeHidden) {\n    var re = /^(?:color|date|datetime|email|month|number|password|range|search|tel|text|time|url|week)$/i; // 'hidden' is not in this list\n    return this.each(function() {\n        var t = this.type, tag = this.tagName.toLowerCase();\n        if (re.test(t) || tag == 'textarea') {\n            this.value = '';\n        }\n        else if (t == 'checkbox' || t == 'radio') {\n            this.checked = false;\n        }\n        else if (tag == 'select') {\n            this.selectedIndex = -1;\n        }\n        else if (t == \"file\") {\n            if (/MSIE/.test(navigator.userAgent)) {\n                $(this).replaceWith($(this).clone(true));\n            } else {\n                $(this).val('');\n            }\n        }\n        else if (includeHidden) {\n            // includeHidden can be the value true, or it can be a selector string\n            // indicating a special test; for example:\n            //  $('#myForm').clearForm('.special:hidden')\n            // the above would clean hidden inputs that have the class of 'special'\n            if ( (includeHidden === true && /hidden/.test(t)) ||\n                 (typeof includeHidden == 'string' && $(this).is(includeHidden)) ) {\n                this.value = '';\n            }\n        }\n    });\n};\n\n/**\n * Resets the form data.  Causes all form elements to be reset to their original value.\n */\n$.fn.resetForm = function() {\n    return this.each(function() {\n        // guard against an input with the name of 'reset'\n        // note that IE reports the reset function as an 'object'\n        if (typeof this.reset == 'function' || (typeof this.reset == 'object' && !this.reset.nodeType)) {\n            this.reset();\n        }\n    });\n};\n\n/**\n * Enables or disables any matching elements.\n */\n$.fn.enable = function(b) {\n    if (b === undefined) {\n        b = true;\n    }\n    return this.each(function() {\n        this.disabled = !b;\n    });\n};\n\n/**\n * Checks/unchecks any matching checkboxes or radio buttons and\n * selects/deselects and matching option elements.\n */\n$.fn.selected = function(select) {\n    if (select === undefined) {\n        select = true;\n    }\n    return this.each(function() {\n        var t = this.type;\n        if (t == 'checkbox' || t == 'radio') {\n            this.checked = select;\n        }\n        else if (this.tagName.toLowerCase() == 'option') {\n            var $sel = $(this).parent('select');\n            if (select && $sel[0] && $sel[0].type == 'select-one') {\n                // deselect all other options\n                $sel.find('option').selected(false);\n            }\n            this.selected = select;\n        }\n    });\n};\n\n// expose debug var\n$.fn.ajaxSubmit.debug = false;\n\n// helper fn for console logging\nfunction log() {\n    if (!$.fn.ajaxSubmit.debug) {\n        return;\n    }\n    var msg = '[jquery.form] ' + Array.prototype.join.call(arguments,'');\n    if (window.console && window.console.log) {\n        window.console.log(msg);\n    }\n    else if (window.opera && window.opera.postError) {\n        window.opera.postError(msg);\n    }\n}\n\n}));\n", "/*!\n * jQuery BBQ: Back Button & Query Library - v1.3pre - 8/26/2010\n * http://benalman.com/projects/jquery-bbq-plugin/\n * \n * Copyright (c) 2010 \"Cowboy\" Ben Alman\n * Dual licensed under the MIT and GPL licenses.\n * http://benalman.com/about/license/\n */\n\n// Script: jQuery BBQ: Back Button & Query Library\n//\n// *Version: 1.3pre, Last updated: 8/26/2010*\n// \n// Project Home - http://benalman.com/projects/jquery-bbq-plugin/\n// GitHub       - http://github.com/cowboy/jquery-bbq/\n// Source       - http://github.com/cowboy/jquery-bbq/raw/master/jquery.ba-bbq.js\n// (Minified)   - http://github.com/cowboy/jquery-bbq/raw/master/jquery.ba-bbq.min.js (2.2kb gzipped)\n// \n// About: License\n// \n// Copyright (c) 2010 \"Cowboy\" Ben Alman,\n// Dual licensed under the MIT and GPL licenses.\n// http://benalman.com/about/license/\n// \n// About: Examples\n// \n// These working examples, complete with fully commented code, illustrate a few\n// ways in which this plugin can be used.\n// \n// Basic AJAX     - http://benalman.com/code/projects/jquery-bbq/examples/fragment-basic/\n// Advanced AJAX  - http://benalman.com/code/projects/jquery-bbq/examples/fragment-advanced/\n// jQuery UI Tabs - http://benalman.com/code/projects/jquery-bbq/examples/fragment-jquery-ui-tabs/\n// Deparam        - http://benalman.com/code/projects/jquery-bbq/examples/deparam/\n// \n// About: Support and Testing\n// \n// Information about what version or versions of jQuery this plugin has been\n// tested with, what browsers it has been tested in, and where the unit tests\n// reside (so you can test it yourself).\n// \n// jQuery Versions - 1.2.6, 1.3.2, 1.4.1, 1.4.2\n// Browsers Tested - Internet Explorer 6-8, Firefox 2-4, Chrome 5-6, Safari 3.2-5,\n//                   Opera 9.6-10.60, iPhone 3.1, Android 1.6-2.2, BlackBerry 4.6-5.\n// Unit Tests      - http://benalman.com/code/projects/jquery-bbq/unit/\n// \n// About: Release History\n// \n// 1.3pre - (8/26/2010) Integrated <jQuery hashchange event> v1.3, which adds\n//         document.title and document.domain support in IE6/7, BlackBerry\n//         support, better Iframe hiding for accessibility reasons, and the new\n//         <jQuery.fn.hashchange> \"shortcut\" method. Added the\n//         <jQuery.param.sorted> method which reduces the possibility of\n//         extraneous hashchange event triggering. Added the\n//         <jQuery.param.fragment.ajaxCrawlable> method which can be used to\n//         enable Google \"AJAX Crawlable mode.\"\n// 1.2.1 - (2/17/2010) Actually fixed the stale window.location Safari bug from\n//         <jQuery hashchange event> in BBQ, which was the main reason for the\n//         previous release!\n// 1.2   - (2/16/2010) Integrated <jQuery hashchange event> v1.2, which fixes a\n//         Safari bug, the event can now be bound before DOM ready, and IE6/7\n//         page should no longer scroll when the event is first bound. Also\n//         added the <jQuery.param.fragment.noEscape> method, and reworked the\n//         <hashchange event (BBQ)> internal \"add\" method to be compatible with\n//         changes made to the jQuery 1.4.2 special events API.\n// 1.1.1 - (1/22/2010) Integrated <jQuery hashchange event> v1.1, which fixes an\n//         obscure IE8 EmulateIE7 meta tag compatibility mode bug.\n// 1.1   - (1/9/2010) Broke out the jQuery BBQ event.special <hashchange event>\n//         functionality into a separate plugin for users who want just the\n//         basic event & back button support, without all the extra awesomeness\n//         that BBQ provides. This plugin will be included as part of jQuery BBQ,\n//         but also be available separately. See <jQuery hashchange event>\n//         plugin for more information. Also added the <jQuery.bbq.removeState>\n//         method and added additional <jQuery.deparam> examples.\n// 1.0.3 - (12/2/2009) Fixed an issue in IE 6 where location.search and\n//         location.hash would report incorrectly if the hash contained the ?\n//         character. Also <jQuery.param.querystring> and <jQuery.param.fragment>\n//         will no longer parse params out of a URL that doesn't contain ? or #,\n//         respectively.\n// 1.0.2 - (10/10/2009) Fixed an issue in IE 6/7 where the hidden IFRAME caused\n//         a \"This page contains both secure and nonsecure items.\" warning when\n//         used on an https:// page.\n// 1.0.1 - (10/7/2009) Fixed an issue in IE 8. Since both \"IE7\" and \"IE8\n//         Compatibility View\" modes erroneously report that the browser\n//         supports the native window.onhashchange event, a slightly more\n//         robust test needed to be added.\n// 1.0   - (10/2/2009) Initial release\n\n(function($,window){\n  '$:nomunge'; // Used by YUI compressor.\n  \n  // Some convenient shortcuts.\n  var undefined,\n    aps = Array.prototype.slice,\n    decode = decodeURIComponent,\n    \n    // Method / object references.\n    jq_param = $.param,\n    jq_param_sorted,\n    jq_param_fragment,\n    jq_deparam,\n    jq_deparam_fragment,\n    jq_bbq = $.bbq = $.bbq || {},\n    jq_bbq_pushState,\n    jq_bbq_getState,\n    jq_elemUrlAttr,\n    special = $.event.special,\n    \n    // Reused strings.\n    str_hashchange = 'hashchange',\n    str_querystring = 'querystring',\n    str_fragment = 'fragment',\n    str_elemUrlAttr = 'elemUrlAttr',\n    str_href = 'href',\n    str_src = 'src',\n    \n    // Reused RegExp.\n    re_params_querystring = /^.*\\?|#.*$/g,\n    re_params_fragment,\n    re_fragment,\n    re_no_escape,\n    \n    ajax_crawlable,\n    fragment_prefix,\n    \n    // Used by jQuery.elemUrlAttr.\n    elemUrlAttr_cache = {};\n  \n  // A few commonly used bits, broken out to help reduce minified file size.\n  \n  function is_string( arg ) {\n    return typeof arg === 'string';\n  };\n  \n  // Why write the same function twice? Let's curry! Mmmm, curry..\n  \n  function curry( func ) {\n    var args = aps.call( arguments, 1 );\n    \n    return function() {\n      return func.apply( this, args.concat( aps.call( arguments ) ) );\n    };\n  };\n  \n  // Get location.hash (or what you'd expect location.hash to be) sans any\n  // leading #. Thanks for making this necessary, Firefox!\n  function get_fragment( url ) {\n    return url.replace( re_fragment, '$2' );\n  };\n  \n  // Get location.search (or what you'd expect location.search to be) sans any\n  // leading #. Thanks for making this necessary, IE6!\n  function get_querystring( url ) {\n    return url.replace( /(?:^[^?#]*\\?([^#]*).*$)?.*/, '$1' );\n  };\n  \n  // Section: Param (to string)\n  // \n  // Method: jQuery.param.querystring\n  // \n  // Retrieve the query string from a URL or if no arguments are passed, the\n  // current window.location.href.\n  // \n  // Usage:\n  // \n  // > jQuery.param.querystring( [ url ] );\n  // \n  // Arguments:\n  // \n  //  url - (String) A URL containing query string params to be parsed. If url\n  //    is not passed, the current window.location.href is used.\n  // \n  // Returns:\n  // \n  //  (String) The parsed query string, with any leading \"?\" removed.\n  //\n  \n  // Method: jQuery.param.querystring (build url)\n  // \n  // Merge a URL, with or without pre-existing query string params, plus any\n  // object, params string or URL containing query string params into a new URL.\n  // \n  // Usage:\n  // \n  // > jQuery.param.querystring( url, params [, merge_mode ] );\n  // \n  // Arguments:\n  // \n  //  url - (String) A valid URL for params to be merged into. This URL may\n  //    contain a query string and/or fragment (hash).\n  //  params - (String) A params string or URL containing query string params to\n  //    be merged into url.\n  //  params - (Object) A params object to be merged into url.\n  //  merge_mode - (Number) Merge behavior defaults to 0 if merge_mode is not\n  //    specified, and is as-follows:\n  // \n  //    * 0: params in the params argument will override any query string\n  //         params in url.\n  //    * 1: any query string params in url will override params in the params\n  //         argument.\n  //    * 2: params argument will completely replace any query string in url.\n  // \n  // Returns:\n  // \n  //  (String) A URL with a urlencoded query string in the format '?a=b&c=d&e=f'.\n  \n  // Method: jQuery.param.fragment\n  // \n  // Retrieve the fragment (hash) from a URL or if no arguments are passed, the\n  // current window.location.href.\n  // \n  // Usage:\n  // \n  // > jQuery.param.fragment( [ url ] );\n  // \n  // Arguments:\n  // \n  //  url - (String) A URL containing fragment (hash) params to be parsed. If\n  //    url is not passed, the current window.location.href is used.\n  // \n  // Returns:\n  // \n  //  (String) The parsed fragment (hash) string, with any leading \"#\" removed.\n  \n  // Method: jQuery.param.fragment (build url)\n  // \n  // Merge a URL, with or without pre-existing fragment (hash) params, plus any\n  // object, params string or URL containing fragment (hash) params into a new\n  // URL.\n  // \n  // Usage:\n  // \n  // > jQuery.param.fragment( url, params [, merge_mode ] );\n  // \n  // Arguments:\n  // \n  //  url - (String) A valid URL for params to be merged into. This URL may\n  //    contain a query string and/or fragment (hash).\n  //  params - (String) A params string or URL containing fragment (hash) params\n  //    to be merged into url.\n  //  params - (Object) A params object to be merged into url.\n  //  merge_mode - (Number) Merge behavior defaults to 0 if merge_mode is not\n  //    specified, and is as-follows:\n  // \n  //    * 0: params in the params argument will override any fragment (hash)\n  //         params in url.\n  //    * 1: any fragment (hash) params in url will override params in the\n  //         params argument.\n  //    * 2: params argument will completely replace any query string in url.\n  // \n  // Returns:\n  // \n  //  (String) A URL with a urlencoded fragment (hash) in the format '#a=b&c=d&e=f'.\n  \n  function jq_param_sub( is_fragment, get_func, url, params, merge_mode ) {\n    var result,\n      qs,\n      matches,\n      url_params,\n      hash;\n    \n    if ( params !== undefined ) {\n      // Build URL by merging params into url string.\n      \n      // matches[1] = url part that precedes params, not including trailing ?/#\n      // matches[2] = params, not including leading ?/#\n      // matches[3] = if in 'querystring' mode, hash including leading #, otherwise ''\n      matches = url.match( is_fragment ? re_fragment : /^([^#?]*)\\??([^#]*)(#?.*)/ );\n      \n      // Get the hash if in 'querystring' mode, and it exists.\n      hash = matches[3] || '';\n      \n      if ( merge_mode === 2 && is_string( params ) ) {\n        // If merge_mode is 2 and params is a string, merge the fragment / query\n        // string into the URL wholesale, without converting it into an object.\n        qs = params.replace( is_fragment ? re_params_fragment : re_params_querystring, '' );\n        \n      } else {\n        // Convert relevant params in url to object.\n        url_params = jq_deparam( matches[2] );\n        \n        params = is_string( params )\n          \n          // Convert passed params string into object.\n          ? jq_deparam[ is_fragment ? str_fragment : str_querystring ]( params )\n          \n          // Passed params object.\n          : params;\n        \n        qs = merge_mode === 2 ? params                              // passed params replace url params\n          : merge_mode === 1  ? $.extend( {}, params, url_params )  // url params override passed params\n          : $.extend( {}, url_params, params );                     // passed params override url params\n        \n        // Convert params object into a sorted params string.\n        qs = jq_param_sorted( qs );\n        \n        // Unescape characters specified via $.param.noEscape. Since only hash-\n        // history users have requested this feature, it's only enabled for\n        // fragment-related params strings.\n        if ( is_fragment ) {\n          qs = qs.replace( re_no_escape, decode );\n        }\n      }\n      \n      // Build URL from the base url, querystring and hash. In 'querystring'\n      // mode, ? is only added if a query string exists. In 'fragment' mode, #\n      // is always added.\n      result = matches[1] + ( is_fragment ? fragment_prefix : qs || !matches[1] ? '?' : '' ) + qs + hash;\n      \n    } else {\n      // If URL was passed in, parse params from URL string, otherwise parse\n      // params from window.location.href.\n      result = get_func( url !== undefined ? url : location.href );\n    }\n    \n    return result;\n  };\n  \n  jq_param[ str_querystring ]                  = curry( jq_param_sub, 0, get_querystring );\n  jq_param[ str_fragment ] = jq_param_fragment = curry( jq_param_sub, 1, get_fragment );\n  \n  // Method: jQuery.param.sorted\n  // \n  // Returns a params string equivalent to that returned by the internal\n  // jQuery.param method, but sorted, which makes it suitable for use as a\n  // cache key.\n  // \n  // For example, in most browsers jQuery.param({z:1,a:2}) returns \"z=1&a=2\"\n  // and jQuery.param({a:2,z:1}) returns \"a=2&z=1\". Even though both the\n  // objects being serialized and the resulting params strings are equivalent,\n  // if these params strings were set into the location.hash fragment\n  // sequentially, the hashchange event would be triggered unnecessarily, since\n  // the strings are different (even though the data described by them is the\n  // same). By sorting the params string, unecessary hashchange event triggering\n  // can be avoided.\n  // \n  // Usage:\n  // \n  // > jQuery.param.sorted( obj [, traditional ] );\n  // \n  // Arguments:\n  // \n  //  obj - (Object) An object to be serialized.\n  //  traditional - (Boolean) Params deep/shallow serialization mode. See the\n  //    documentation at http://api.jquery.com/jQuery.param/ for more detail.\n  // \n  // Returns:\n  // \n  //  (String) A sorted params string.\n  \n  jq_param.sorted = jq_param_sorted = function( a, traditional ) {\n    var arr = [],\n      obj = {};\n    \n    $.each( jq_param( a, traditional ).split( '&' ), function(i,v){\n      var key = v.replace( /(?:%5B|=).*$/, '' ),\n        key_obj = obj[ key ];\n      \n      if ( !key_obj ) {\n        key_obj = obj[ key ] = [];\n        arr.push( key );\n      }\n      \n      key_obj.push( v );\n    });\n    \n    return $.map( arr.sort(), function(v){\n      return obj[ v ];\n    }).join( '&' );\n  };\n  \n  // Method: jQuery.param.fragment.noEscape\n  // \n  // Specify characters that will be left unescaped when fragments are created\n  // or merged using <jQuery.param.fragment>, or when the fragment is modified\n  // using <jQuery.bbq.pushState>. This option only applies to serialized data\n  // object fragments, and not set-as-string fragments. Does not affect the\n  // query string. Defaults to \",/\" (comma, forward slash).\n  // \n  // Note that this is considered a purely aesthetic option, and will help to\n  // create URLs that \"look pretty\" in the address bar or bookmarks, without\n  // affecting functionality in any way. That being said, be careful to not\n  // unescape characters that are used as delimiters or serve a special\n  // purpose, such as the \"#?&=+\" (octothorpe, question mark, ampersand,\n  // equals, plus) characters.\n  // \n  // Usage:\n  // \n  // > jQuery.param.fragment.noEscape( [ chars ] );\n  // \n  // Arguments:\n  // \n  //  chars - (String) The characters to not escape in the fragment. If\n  //    unspecified, defaults to empty string (escape all characters).\n  // \n  // Returns:\n  // \n  //  Nothing.\n  \n  jq_param_fragment.noEscape = function( chars ) {\n    chars = chars || '';\n    var arr = $.map( chars.split(''), encodeURIComponent );\n    re_no_escape = new RegExp( arr.join('|'), 'g' );\n  };\n  \n  // A sensible default. These are the characters people seem to complain about\n  // \"uglifying up the URL\" the most.\n  jq_param_fragment.noEscape( ',/' );\n  \n  // Method: jQuery.param.fragment.ajaxCrawlable\n  // \n  // TODO: DESCRIBE\n  // \n  // Usage:\n  // \n  // > jQuery.param.fragment.ajaxCrawlable( [ state ] );\n  // \n  // Arguments:\n  // \n  //  state - (Boolean) TODO: DESCRIBE\n  // \n  // Returns:\n  // \n  //  (Boolean) The current ajaxCrawlable state.\n  \n  jq_param_fragment.ajaxCrawlable = function( state ) {\n    if ( state !== undefined ) {\n      if ( state ) {\n        re_params_fragment = /^.*(?:#!|#)/;\n        re_fragment = /^([^#]*)(?:#!|#)?(.*)$/;\n        fragment_prefix = '#!';\n      } else {\n        re_params_fragment = /^.*#/;\n        re_fragment = /^([^#]*)#?(.*)$/;\n        fragment_prefix = '#';\n      }\n      ajax_crawlable = !!state;\n    }\n    \n    return ajax_crawlable;\n  };\n  \n  jq_param_fragment.ajaxCrawlable( 0 );\n  \n  // Section: Deparam (from string)\n  // \n  // Method: jQuery.deparam\n  // \n  // Deserialize a params string into an object, optionally coercing numbers,\n  // booleans, null and undefined values; this method is the counterpart to the\n  // internal jQuery.param method.\n  // \n  // Usage:\n  // \n  // > jQuery.deparam( params [, coerce ] );\n  // \n  // Arguments:\n  // \n  //  params - (String) A params string to be parsed.\n  //  coerce - (Boolean) If true, coerces any numbers or true, false, null, and\n  //    undefined to their actual value. Defaults to false if omitted.\n  // \n  // Returns:\n  // \n  //  (Object) An object representing the deserialized params string.\n  \n  $.deparam = jq_deparam = function( params, coerce ) {\n    var obj = {},\n      coerce_types = { 'true': !0, 'false': !1, 'null': null };\n    \n    // Iterate over all name=value pairs.\n    $.each( params.replace( /\\+/g, ' ' ).split( '&' ), function(j,v){\n      var param = v.split( '=' ),\n        key = decode( param[0] ),\n        val,\n        cur = obj,\n        i = 0,\n        \n        // If key is more complex than 'foo', like 'a[]' or 'a[b][c]', split it\n        // into its component parts.\n        keys = key.split( '][' ),\n        keys_last = keys.length - 1;\n      \n      // If the first keys part contains [ and the last ends with ], then []\n      // are correctly balanced.\n      if ( /\\[/.test( keys[0] ) && /\\]$/.test( keys[ keys_last ] ) ) {\n        // Remove the trailing ] from the last keys part.\n        keys[ keys_last ] = keys[ keys_last ].replace( /\\]$/, '' );\n        \n        // Split first keys part into two parts on the [ and add them back onto\n        // the beginning of the keys array.\n        keys = keys.shift().split('[').concat( keys );\n        \n        keys_last = keys.length - 1;\n      } else {\n        // Basic 'foo' style key.\n        keys_last = 0;\n      }\n      \n      // Are we dealing with a name=value pair, or just a name?\n      if ( param.length === 2 ) {\n        val = decode( param[1] );\n        \n        // Coerce values.\n        if ( coerce ) {\n          val = val && !isNaN(val)            ? +val              // number\n            : val === 'undefined'             ? undefined         // undefined\n            : coerce_types[val] !== undefined ? coerce_types[val] // true, false, null\n            : val;                                                // string\n        }\n        \n        if ( keys_last ) {\n          // Complex key, build deep object structure based on a few rules:\n          // * The 'cur' pointer starts at the object top-level.\n          // * [] = array push (n is set to array length), [n] = array if n is \n          //   numeric, otherwise object.\n          // * If at the last keys part, set the value.\n          // * For each keys part, if the current level is undefined create an\n          //   object or array based on the type of the next keys part.\n          // * Move the 'cur' pointer to the next level.\n          // * Rinse & repeat.\n          for ( ; i <= keys_last; i++ ) {\n            key = keys[i] === '' ? cur.length : keys[i];\n            if ( key === \"__proto__\" || key === \"prototype\" || key === \"constructor\" ) break;\n            cur = cur[key] = i < keys_last\n              ? cur[key] || ( keys[i+1] && isNaN( keys[i+1] ) ? {} : [] )\n              : val;\n          }\n          \n        } else {\n          // Simple key, even simpler rules, since only scalars and shallow\n          // arrays are allowed.\n          \n          if ( $.isArray( obj[key] ) ) {\n            // val is already an array, so push on the next value.\n            obj[key].push( val );\n            \n          } else if ( obj[key] !== undefined ) {\n            // val isn't an array, but since a second value has been specified,\n            // convert val into an array.\n            obj[key] = [ obj[key], val ];\n            \n          } else {\n            // val is a scalar.\n            obj[key] = val;\n          }\n        }\n        \n      } else if ( key ) {\n        // No value was defined, so set something meaningful.\n        obj[key] = coerce\n          ? undefined\n          : '';\n      }\n    });\n    \n    return obj;\n  };\n  \n  // Method: jQuery.deparam.querystring\n  // \n  // Parse the query string from a URL or the current window.location.href,\n  // deserializing it into an object, optionally coercing numbers, booleans,\n  // null and undefined values.\n  // \n  // Usage:\n  // \n  // > jQuery.deparam.querystring( [ url ] [, coerce ] );\n  // \n  // Arguments:\n  // \n  //  url - (String) An optional params string or URL containing query string\n  //    params to be parsed. If url is omitted, the current\n  //    window.location.href is used.\n  //  coerce - (Boolean) If true, coerces any numbers or true, false, null, and\n  //    undefined to their actual value. Defaults to false if omitted.\n  // \n  // Returns:\n  // \n  //  (Object) An object representing the deserialized params string.\n  \n  // Method: jQuery.deparam.fragment\n  // \n  // Parse the fragment (hash) from a URL or the current window.location.href,\n  // deserializing it into an object, optionally coercing numbers, booleans,\n  // null and undefined values.\n  // \n  // Usage:\n  // \n  // > jQuery.deparam.fragment( [ url ] [, coerce ] );\n  // \n  // Arguments:\n  // \n  //  url - (String) An optional params string or URL containing fragment (hash)\n  //    params to be parsed. If url is omitted, the current window.location.href\n  //    is used.\n  //  coerce - (Boolean) If true, coerces any numbers or true, false, null, and\n  //    undefined to their actual value. Defaults to false if omitted.\n  // \n  // Returns:\n  // \n  //  (Object) An object representing the deserialized params string.\n  \n  function jq_deparam_sub( is_fragment, url_or_params, coerce ) {\n    if ( url_or_params === undefined || typeof url_or_params === 'boolean' ) {\n      // url_or_params not specified.\n      coerce = url_or_params;\n      url_or_params = jq_param[ is_fragment ? str_fragment : str_querystring ]();\n    } else {\n      url_or_params = is_string( url_or_params )\n        ? url_or_params.replace( is_fragment ? re_params_fragment : re_params_querystring, '' )\n        : url_or_params;\n    }\n    \n    return jq_deparam( url_or_params, coerce );\n  };\n  \n  jq_deparam[ str_querystring ]                    = curry( jq_deparam_sub, 0 );\n  jq_deparam[ str_fragment ] = jq_deparam_fragment = curry( jq_deparam_sub, 1 );\n  \n  // Section: Element manipulation\n  // \n  // Method: jQuery.elemUrlAttr\n  // \n  // Get the internal \"Default URL attribute per tag\" list, or augment the list\n  // with additional tag-attribute pairs, in case the defaults are insufficient.\n  // \n  // In the <jQuery.fn.querystring> and <jQuery.fn.fragment> methods, this list\n  // is used to determine which attribute contains the URL to be modified, if\n  // an \"attr\" param is not specified.\n  // \n  // Default Tag-Attribute List:\n  // \n  //  a      - href\n  //  base   - href\n  //  iframe - src\n  //  img    - src\n  //  input  - src\n  //  form   - action\n  //  link   - href\n  //  script - src\n  // \n  // Usage:\n  // \n  // > jQuery.elemUrlAttr( [ tag_attr ] );\n  // \n  // Arguments:\n  // \n  //  tag_attr - (Object) An object containing a list of tag names and their\n  //    associated default attribute names in the format { tag: 'attr', ... } to\n  //    be merged into the internal tag-attribute list.\n  // \n  // Returns:\n  // \n  //  (Object) An object containing all stored tag-attribute values.\n  \n  // Only define function and set defaults if function doesn't already exist, as\n  // the urlInternal plugin will provide this method as well.\n  $[ str_elemUrlAttr ] || ($[ str_elemUrlAttr ] = function( obj ) {\n    return $.extend( elemUrlAttr_cache, obj );\n  })({\n    a: str_href,\n    base: str_href,\n    iframe: str_src,\n    img: str_src,\n    input: str_src,\n    form: 'action',\n    link: str_href,\n    script: str_src\n  });\n  \n  jq_elemUrlAttr = $[ str_elemUrlAttr ];\n  \n  // Method: jQuery.fn.querystring\n  // \n  // Update URL attribute in one or more elements, merging the current URL (with\n  // or without pre-existing query string params) plus any params object or\n  // string into a new URL, which is then set into that attribute. Like\n  // <jQuery.param.querystring (build url)>, but for all elements in a jQuery\n  // collection.\n  // \n  // Usage:\n  // \n  // > jQuery('selector').querystring( [ attr, ] params [, merge_mode ] );\n  // \n  // Arguments:\n  // \n  //  attr - (String) Optional name of an attribute that will contain a URL to\n  //    merge params or url into. See <jQuery.elemUrlAttr> for a list of default\n  //    attributes.\n  //  params - (Object) A params object to be merged into the URL attribute.\n  //  params - (String) A URL containing query string params, or params string\n  //    to be merged into the URL attribute.\n  //  merge_mode - (Number) Merge behavior defaults to 0 if merge_mode is not\n  //    specified, and is as-follows:\n  //    \n  //    * 0: params in the params argument will override any params in attr URL.\n  //    * 1: any params in attr URL will override params in the params argument.\n  //    * 2: params argument will completely replace any query string in attr\n  //         URL.\n  // \n  // Returns:\n  // \n  //  (jQuery) The initial jQuery collection of elements, but with modified URL\n  //  attribute values.\n  \n  // Method: jQuery.fn.fragment\n  // \n  // Update URL attribute in one or more elements, merging the current URL (with\n  // or without pre-existing fragment/hash params) plus any params object or\n  // string into a new URL, which is then set into that attribute. Like\n  // <jQuery.param.fragment (build url)>, but for all elements in a jQuery\n  // collection.\n  // \n  // Usage:\n  // \n  // > jQuery('selector').fragment( [ attr, ] params [, merge_mode ] );\n  // \n  // Arguments:\n  // \n  //  attr - (String) Optional name of an attribute that will contain a URL to\n  //    merge params into. See <jQuery.elemUrlAttr> for a list of default\n  //    attributes.\n  //  params - (Object) A params object to be merged into the URL attribute.\n  //  params - (String) A URL containing fragment (hash) params, or params\n  //    string to be merged into the URL attribute.\n  //  merge_mode - (Number) Merge behavior defaults to 0 if merge_mode is not\n  //    specified, and is as-follows:\n  //    \n  //    * 0: params in the params argument will override any params in attr URL.\n  //    * 1: any params in attr URL will override params in the params argument.\n  //    * 2: params argument will completely replace any fragment (hash) in attr\n  //         URL.\n  // \n  // Returns:\n  // \n  //  (jQuery) The initial jQuery collection of elements, but with modified URL\n  //  attribute values.\n  \n  function jq_fn_sub( mode, force_attr, params, merge_mode ) {\n    if ( !is_string( params ) && typeof params !== 'object' ) {\n      // force_attr not specified.\n      merge_mode = params;\n      params = force_attr;\n      force_attr = undefined;\n    }\n    \n    return this.each(function(){\n      var that = $(this),\n        \n        // Get attribute specified, or default specified via $.elemUrlAttr.\n        attr = force_attr || jq_elemUrlAttr()[ ( this.nodeName || '' ).toLowerCase() ] || '',\n        \n        // Get URL value.\n        url = attr && that.attr( attr ) || '';\n      \n      // Update attribute with new URL.\n      that.attr( attr, jq_param[ mode ]( url, params, merge_mode ) );\n    });\n    \n  };\n  \n  $.fn[ str_querystring ] = curry( jq_fn_sub, str_querystring );\n  $.fn[ str_fragment ]    = curry( jq_fn_sub, str_fragment );\n  \n  // Section: History, hashchange event\n  // \n  // Method: jQuery.bbq.pushState\n  // \n  // Adds a 'state' into the browser history at the current position, setting\n  // location.hash and triggering any bound <hashchange event> callbacks\n  // (provided the new state is different than the previous state).\n  // \n  // If no arguments are passed, an empty state is created, which is just a\n  // shortcut for jQuery.bbq.pushState( {}, 2 ).\n  // \n  // Usage:\n  // \n  // > jQuery.bbq.pushState( [ params [, merge_mode ] ] );\n  // \n  // Arguments:\n  // \n  //  params - (String) A serialized params string or a hash string beginning\n  //    with # to merge into location.hash.\n  //  params - (Object) A params object to merge into location.hash.\n  //  merge_mode - (Number) Merge behavior defaults to 0 if merge_mode is not\n  //    specified (unless a hash string beginning with # is specified, in which\n  //    case merge behavior defaults to 2), and is as-follows:\n  // \n  //    * 0: params in the params argument will override any params in the\n  //         current state.\n  //    * 1: any params in the current state will override params in the params\n  //         argument.\n  //    * 2: params argument will completely replace current state.\n  // \n  // Returns:\n  // \n  //  Nothing.\n  // \n  // Additional Notes:\n  // \n  //  * Setting an empty state may cause the browser to scroll.\n  //  * Unlike the fragment and querystring methods, if a hash string beginning\n  //    with # is specified as the params agrument, merge_mode defaults to 2.\n  \n  jq_bbq.pushState = jq_bbq_pushState = function( params, merge_mode ) {\n    if ( is_string( params ) && /^#/.test( params ) && merge_mode === undefined ) {\n      // Params string begins with # and merge_mode not specified, so completely\n      // overwrite window.location.hash.\n      merge_mode = 2;\n    }\n    \n    var has_args = params !== undefined,\n      // Merge params into window.location using $.param.fragment.\n      url = jq_param_fragment( location.href,\n        has_args ? params : {}, has_args ? merge_mode : 2 );\n    \n    // Set new window.location.href. Note that Safari 3 & Chrome barf on\n    // location.hash = '#' so the entire URL is set.\n    location.href = url;\n  };\n  \n  // Method: jQuery.bbq.getState\n  // \n  // Retrieves the current 'state' from the browser history, parsing\n  // location.hash for a specific key or returning an object containing the\n  // entire state, optionally coercing numbers, booleans, null and undefined\n  // values.\n  // \n  // Usage:\n  // \n  // > jQuery.bbq.getState( [ key ] [, coerce ] );\n  // \n  // Arguments:\n  // \n  //  key - (String) An optional state key for which to return a value.\n  //  coerce - (Boolean) If true, coerces any numbers or true, false, null, and\n  //    undefined to their actual value. Defaults to false.\n  // \n  // Returns:\n  // \n  //  (Anything) If key is passed, returns the value corresponding with that key\n  //    in the location.hash 'state', or undefined. If not, an object\n  //    representing the entire 'state' is returned.\n  \n  jq_bbq.getState = jq_bbq_getState = function( key, coerce ) {\n    return key === undefined || typeof key === 'boolean'\n      ? jq_deparam_fragment( key ) // 'key' really means 'coerce' here\n      : jq_deparam_fragment( coerce )[ key ];\n  };\n  \n  // Method: jQuery.bbq.removeState\n  // \n  // Remove one or more keys from the current browser history 'state', creating\n  // a new state, setting location.hash and triggering any bound\n  // <hashchange event> callbacks (provided the new state is different than\n  // the previous state).\n  // \n  // If no arguments are passed, an empty state is created, which is just a\n  // shortcut for jQuery.bbq.pushState( {}, 2 ).\n  // \n  // Usage:\n  // \n  // > jQuery.bbq.removeState( [ key [, key ... ] ] );\n  // \n  // Arguments:\n  // \n  //  key - (String) One or more key values to remove from the current state,\n  //    passed as individual arguments.\n  //  key - (Array) A single array argument that contains a list of key values\n  //    to remove from the current state.\n  // \n  // Returns:\n  // \n  //  Nothing.\n  // \n  // Additional Notes:\n  // \n  //  * Setting an empty state may cause the browser to scroll.\n  \n  jq_bbq.removeState = function( arr ) {\n    var state = {};\n    \n    // If one or more arguments is passed..\n    if ( arr !== undefined ) {\n      \n      // Get the current state.\n      state = jq_bbq_getState();\n      \n      // For each passed key, delete the corresponding property from the current\n      // state.\n      $.each( $.isArray( arr ) ? arr : arguments, function(i,v){\n        delete state[ v ];\n      });\n    }\n    \n    // Set the state, completely overriding any existing state.\n    jq_bbq_pushState( state, 2 );\n  };\n  \n  // Event: hashchange event (BBQ)\n  // \n  // Usage in jQuery 1.4 and newer:\n  // \n  // In jQuery 1.4 and newer, the event object passed into any hashchange event\n  // callback is augmented with a copy of the location.hash fragment at the time\n  // the event was triggered as its event.fragment property. In addition, the\n  // event.getState method operates on this property (instead of location.hash)\n  // which allows this fragment-as-a-state to be referenced later, even after\n  // window.location may have changed.\n  // \n  // Note that event.fragment and event.getState are not defined according to\n  // W3C (or any other) specification, but will still be available whether or\n  // not the hashchange event exists natively in the browser, because of the\n  // utility they provide.\n  // \n  // The event.fragment property contains the output of <jQuery.param.fragment>\n  // and the event.getState method is equivalent to the <jQuery.bbq.getState>\n  // method.\n  // \n  // > $(window).bind( 'hashchange', function( event ) {\n  // >   var hash_str = event.fragment,\n  // >     param_obj = event.getState(),\n  // >     param_val = event.getState( 'param_name' ),\n  // >     param_val_coerced = event.getState( 'param_name', true );\n  // >   ...\n  // > });\n  // \n  // Usage in jQuery 1.3.2:\n  // \n  // In jQuery 1.3.2, the event object cannot to be augmented as in jQuery 1.4+,\n  // so the fragment state isn't bound to the event object and must instead be\n  // parsed using the <jQuery.param.fragment> and <jQuery.bbq.getState> methods.\n  // \n  // > $(window).bind( 'hashchange', function( event ) {\n  // >   var hash_str = $.param.fragment(),\n  // >     param_obj = $.bbq.getState(),\n  // >     param_val = $.bbq.getState( 'param_name' ),\n  // >     param_val_coerced = $.bbq.getState( 'param_name', true );\n  // >   ...\n  // > });\n  // \n  // Additional Notes:\n  // \n  // * Due to changes in the special events API, jQuery BBQ v1.2 or newer is\n  //   required to enable the augmented event object in jQuery 1.4.2 and newer.\n  // * See <jQuery hashchange event> for more detailed information.\n  \n  special[ str_hashchange ] = $.extend( special[ str_hashchange ], {\n    \n    // Augmenting the event object with the .fragment property and .getState\n    // method requires jQuery 1.4 or newer. Note: with 1.3.2, everything will\n    // work, but the event won't be augmented)\n    add: function( handleObj ) {\n      var old_handler;\n      \n      function new_handler(e) {\n        // e.fragment is set to the value of location.hash (with any leading #\n        // removed) at the time the event is triggered.\n        var hash = e[ str_fragment ] = jq_param_fragment();\n        \n        // e.getState() works just like $.bbq.getState(), but uses the\n        // e.fragment property stored on the event object.\n        e.getState = function( key, coerce ) {\n          return key === undefined || typeof key === 'boolean'\n            ? jq_deparam( hash, key ) // 'key' really means 'coerce' here\n            : jq_deparam( hash, coerce )[ key ];\n        };\n        \n        old_handler.apply( this, arguments );\n      };\n      \n      // This may seem a little complicated, but it normalizes the special event\n      // .add method between jQuery 1.4/1.4.1 and 1.4.2+\n      if ( $.isFunction( handleObj ) ) {\n        // 1.4, 1.4.1\n        old_handler = handleObj;\n        return new_handler;\n      } else {\n        // 1.4.2+\n        old_handler = handleObj.handler;\n        handleObj.handler = new_handler;\n      }\n    }\n    \n  });\n  \n})(jQuery,this);\n\n/*!\n * jQuery hashchange event - v1.3 - 7/21/2010\n * http://benalman.com/projects/jquery-hashchange-plugin/\n * \n * Copyright (c) 2010 \"Cowboy\" Ben Alman\n * Dual licensed under the MIT and GPL licenses.\n * http://benalman.com/about/license/\n */\n\n// Script: jQuery hashchange event\n//\n// *Version: 1.3, Last updated: 7/21/2010*\n// \n// Project Home - http://benalman.com/projects/jquery-hashchange-plugin/\n// GitHub       - http://github.com/cowboy/jquery-hashchange/\n// Source       - http://github.com/cowboy/jquery-hashchange/raw/master/jquery.ba-hashchange.js\n// (Minified)   - http://github.com/cowboy/jquery-hashchange/raw/master/jquery.ba-hashchange.min.js (0.8kb gzipped)\n// \n// About: License\n// \n// Copyright (c) 2010 \"Cowboy\" Ben Alman,\n// Dual licensed under the MIT and GPL licenses.\n// http://benalman.com/about/license/\n// \n// About: Examples\n// \n// These working examples, complete with fully commented code, illustrate a few\n// ways in which this plugin can be used.\n// \n// hashchange event - http://benalman.com/code/projects/jquery-hashchange/examples/hashchange/\n// document.domain - http://benalman.com/code/projects/jquery-hashchange/examples/document_domain/\n// \n// About: Support and Testing\n// \n// Information about what version or versions of jQuery this plugin has been\n// tested with, what browsers it has been tested in, and where the unit tests\n// reside (so you can test it yourself).\n// \n// jQuery Versions - 1.2.6, 1.3.2, 1.4.1, 1.4.2\n// Browsers Tested - Internet Explorer 6-8, Firefox 2-4, Chrome 5-6, Safari 3.2-5,\n//                   Opera 9.6-10.60, iPhone 3.1, Android 1.6-2.2, BlackBerry 4.6-5.\n// Unit Tests      - http://benalman.com/code/projects/jquery-hashchange/unit/\n// \n// About: Known issues\n// \n// While this jQuery hashchange event implementation is quite stable and\n// robust, there are a few unfortunate browser bugs surrounding expected\n// hashchange event-based behaviors, independent of any JavaScript\n// window.onhashchange abstraction. See the following examples for more\n// information:\n// \n// Chrome: Back Button - http://benalman.com/code/projects/jquery-hashchange/examples/bug-chrome-back-button/\n// Firefox: Remote XMLHttpRequest - http://benalman.com/code/projects/jquery-hashchange/examples/bug-firefox-remote-xhr/\n// WebKit: Back Button in an Iframe - http://benalman.com/code/projects/jquery-hashchange/examples/bug-webkit-hash-iframe/\n// Safari: Back Button from a different domain - http://benalman.com/code/projects/jquery-hashchange/examples/bug-safari-back-from-diff-domain/\n// \n// Also note that should a browser natively support the window.onhashchange \n// event, but not report that it does, the fallback polling loop will be used.\n// \n// About: Release History\n// \n// 1.3   - (7/21/2010) Reorganized IE6/7 Iframe code to make it more\n//         \"removable\" for mobile-only development. Added IE6/7 document.title\n//         support. Attempted to make Iframe as hidden as possible by using\n//         techniques from http://www.paciellogroup.com/blog/?p=604. Added \n//         support for the \"shortcut\" format $(window).hashchange( fn ) and\n//         $(window).hashchange() like jQuery provides for built-in events.\n//         Renamed jQuery.hashchangeDelay to <jQuery.fn.hashchange.delay> and\n//         lowered its default value to 50. Added <jQuery.fn.hashchange.domain>\n//         and <jQuery.fn.hashchange.src> properties plus document-domain.html\n//         file to address access denied issues when setting document.domain in\n//         IE6/7.\n// 1.2   - (2/11/2010) Fixed a bug where coming back to a page using this plugin\n//         from a page on another domain would cause an error in Safari 4. Also,\n//         IE6/7 Iframe is now inserted after the body (this actually works),\n//         which prevents the page from scrolling when the event is first bound.\n//         Event can also now be bound before DOM ready, but it won't be usable\n//         before then in IE6/7.\n// 1.1   - (1/21/2010) Incorporated document.documentMode test to fix IE8 bug\n//         where browser version is incorrectly reported as 8.0, despite\n//         inclusion of the X-UA-Compatible IE=EmulateIE7 meta tag.\n// 1.0   - (1/9/2010) Initial Release. Broke out the jQuery BBQ event.special\n//         window.onhashchange functionality into a separate plugin for users\n//         who want just the basic event & back button support, without all the\n//         extra awesomeness that BBQ provides. This plugin will be included as\n//         part of jQuery BBQ, but also be available separately.\n\n(function($,window,undefined){\n  '$:nomunge'; // Used by YUI compressor.\n  \n  // Reused string.\n  var str_hashchange = 'hashchange',\n    \n    // Method / object references.\n    doc = document,\n    fake_onhashchange,\n    special = $.event.special,\n    \n    // Does the browser support window.onhashchange? Note that IE8 running in\n    // IE7 compatibility mode reports true for 'onhashchange' in window, even\n    // though the event isn't supported, so also test document.documentMode.\n    doc_mode = doc.documentMode,\n    supports_onhashchange = 'on' + str_hashchange in window && ( doc_mode === undefined || doc_mode > 7 );\n  \n  // Get location.hash (or what you'd expect location.hash to be) sans any\n  // leading #. Thanks for making this necessary, Firefox!\n  function get_fragment( url ) {\n    url = url || location.href;\n    return '#' + url.replace( /^[^#]*#?(.*)$/, '$1' );\n  };\n  \n  // Method: jQuery.fn.hashchange\n  // \n  // Bind a handler to the window.onhashchange event or trigger all bound\n  // window.onhashchange event handlers. This behavior is consistent with\n  // jQuery's built-in event handlers.\n  // \n  // Usage:\n  // \n  // > jQuery(window).hashchange( [ handler ] );\n  // \n  // Arguments:\n  // \n  //  handler - (Function) Optional handler to be bound to the hashchange\n  //    event. This is a \"shortcut\" for the more verbose form:\n  //    jQuery(window).bind( 'hashchange', handler ). If handler is omitted,\n  //    all bound window.onhashchange event handlers will be triggered. This\n  //    is a shortcut for the more verbose\n  //    jQuery(window).trigger( 'hashchange' ). These forms are described in\n  //    the <hashchange event> section.\n  // \n  // Returns:\n  // \n  //  (jQuery) The initial jQuery collection of elements.\n  \n  // Allow the \"shortcut\" format $(elem).hashchange( fn ) for binding and\n  // $(elem).hashchange() for triggering, like jQuery does for built-in events.\n  $.fn[ str_hashchange ] = function( fn ) {\n    return fn ? this.bind( str_hashchange, fn ) : this.trigger( str_hashchange );\n  };\n  \n  // Property: jQuery.fn.hashchange.delay\n  // \n  // The numeric interval (in milliseconds) at which the <hashchange event>\n  // polling loop executes. Defaults to 50.\n  \n  // Property: jQuery.fn.hashchange.domain\n  // \n  // If you're setting document.domain in your JavaScript, and you want hash\n  // history to work in IE6/7, not only must this property be set, but you must\n  // also set document.domain BEFORE jQuery is loaded into the page. This\n  // property is only applicable if you are supporting IE6/7 (or IE8 operating\n  // in \"IE7 compatibility\" mode).\n  // \n  // In addition, the <jQuery.fn.hashchange.src> property must be set to the\n  // path of the included \"document-domain.html\" file, which can be renamed or\n  // modified if necessary (note that the document.domain specified must be the\n  // same in both your main JavaScript as well as in this file).\n  // \n  // Usage:\n  // \n  // jQuery.fn.hashchange.domain = document.domain;\n  \n  // Property: jQuery.fn.hashchange.src\n  // \n  // If, for some reason, you need to specify an Iframe src file (for example,\n  // when setting document.domain as in <jQuery.fn.hashchange.domain>), you can\n  // do so using this property. Note that when using this property, history\n  // won't be recorded in IE6/7 until the Iframe src file loads. This property\n  // is only applicable if you are supporting IE6/7 (or IE8 operating in \"IE7\n  // compatibility\" mode).\n  // \n  // Usage:\n  // \n  // jQuery.fn.hashchange.src = 'path/to/file.html';\n  \n  $.fn[ str_hashchange ].delay = 50;\n  /*\n  $.fn[ str_hashchange ].domain = null;\n  $.fn[ str_hashchange ].src = null;\n  */\n  \n  // Event: hashchange event\n  // \n  // Fired when location.hash changes. In browsers that support it, the native\n  // HTML5 window.onhashchange event is used, otherwise a polling loop is\n  // initialized, running every <jQuery.fn.hashchange.delay> milliseconds to\n  // see if the hash has changed. In IE6/7 (and IE8 operating in \"IE7\n  // compatibility\" mode), a hidden Iframe is created to allow the back button\n  // and hash-based history to work.\n  // \n  // Usage as described in <jQuery.fn.hashchange>:\n  // \n  // > // Bind an event handler.\n  // > jQuery(window).hashchange( function(e) {\n  // >   var hash = location.hash;\n  // >   ...\n  // > });\n  // > \n  // > // Manually trigger the event handler.\n  // > jQuery(window).hashchange();\n  // \n  // A more verbose usage that allows for event namespacing:\n  // \n  // > // Bind an event handler.\n  // > jQuery(window).bind( 'hashchange', function(e) {\n  // >   var hash = location.hash;\n  // >   ...\n  // > });\n  // > \n  // > // Manually trigger the event handler.\n  // > jQuery(window).trigger( 'hashchange' );\n  // \n  // Additional Notes:\n  // \n  // * The polling loop and Iframe are not created until at least one handler\n  //   is actually bound to the 'hashchange' event.\n  // * If you need the bound handler(s) to execute immediately, in cases where\n  //   a location.hash exists on page load, via bookmark or page refresh for\n  //   example, use jQuery(window).hashchange() or the more verbose \n  //   jQuery(window).trigger( 'hashchange' ).\n  // * The event can be bound before DOM ready, but since it won't be usable\n  //   before then in IE6/7 (due to the necessary Iframe), recommended usage is\n  //   to bind it inside a DOM ready handler.\n  \n  // Override existing $.event.special.hashchange methods (allowing this plugin\n  // to be defined after jQuery BBQ in BBQ's source code).\n  special[ str_hashchange ] = $.extend( special[ str_hashchange ], {\n    \n    // Called only when the first 'hashchange' event is bound to window.\n    setup: function() {\n      // If window.onhashchange is supported natively, there's nothing to do..\n      if ( supports_onhashchange ) { return false; }\n      \n      // Otherwise, we need to create our own. And we don't want to call this\n      // until the user binds to the event, just in case they never do, since it\n      // will create a polling loop and possibly even a hidden Iframe.\n      $( fake_onhashchange.start );\n    },\n    \n    // Called only when the last 'hashchange' event is unbound from window.\n    teardown: function() {\n      // If window.onhashchange is supported natively, there's nothing to do..\n      if ( supports_onhashchange ) { return false; }\n      \n      // Otherwise, we need to stop ours (if possible).\n      $( fake_onhashchange.stop );\n    }\n    \n  });\n  \n  // fake_onhashchange does all the work of triggering the window.onhashchange\n  // event for browsers that don't natively support it, including creating a\n  // polling loop to watch for hash changes and in IE 6/7 creating a hidden\n  // Iframe to enable back and forward.\n  fake_onhashchange = (function(){\n    var self = {},\n      timeout_id,\n      \n      // Remember the initial hash so it doesn't get triggered immediately.\n      last_hash = get_fragment(),\n      \n      fn_retval = function(val){ return val; },\n      history_set = fn_retval,\n      history_get = fn_retval;\n    \n    // Start the polling loop.\n    self.start = function() {\n      timeout_id || poll();\n    };\n    \n    // Stop the polling loop.\n    self.stop = function() {\n      timeout_id && clearTimeout( timeout_id );\n      timeout_id = undefined;\n    };\n    \n    // This polling loop checks every $.fn.hashchange.delay milliseconds to see\n    // if location.hash has changed, and triggers the 'hashchange' event on\n    // window when necessary.\n    function poll() {\n      var hash = get_fragment(),\n        history_hash = history_get( last_hash );\n      \n      if ( hash !== last_hash ) {\n        history_set( last_hash = hash, history_hash );\n        \n        $(window).trigger( str_hashchange );\n        \n      } else if ( history_hash !== last_hash ) {\n        location.href = location.href.replace( /#.*/, '' ) + history_hash;\n      }\n      \n      timeout_id = setTimeout( poll, $.fn[ str_hashchange ].delay );\n    };\n    \n    // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\n    // vvvvvvvvvvvvvvvvvvv REMOVE IF NOT SUPPORTING IE6/7/8 vvvvvvvvvvvvvvvvvvv\n    // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\n    $.browser.msie && !supports_onhashchange && (function(){\n      // Not only do IE6/7 need the \"magical\" Iframe treatment, but so does IE8\n      // when running in \"IE7 compatibility\" mode.\n      \n      var iframe,\n        iframe_src;\n      \n      // When the event is bound and polling starts in IE 6/7, create a hidden\n      // Iframe for history handling.\n      self.start = function(){\n        if ( !iframe ) {\n          iframe_src = $.fn[ str_hashchange ].src;\n          iframe_src = iframe_src && iframe_src + get_fragment();\n          \n          // Create hidden Iframe. Attempt to make Iframe as hidden as possible\n          // by using techniques from http://www.paciellogroup.com/blog/?p=604.\n          iframe = $('<iframe tabindex=\"-1\" title=\"empty\"/>').hide()\n            \n            // When Iframe has completely loaded, initialize the history and\n            // start polling.\n            .one( 'load', function(){\n              iframe_src || history_set( get_fragment() );\n              poll();\n            })\n            \n            // Load Iframe src if specified, otherwise nothing.\n            .attr( 'src', iframe_src || 'javascript:0' )\n            \n            // Append Iframe after the end of the body to prevent unnecessary\n            // initial page scrolling (yes, this works).\n            .insertAfter( 'body' )[0].contentWindow;\n          \n          // Whenever `document.title` changes, update the Iframe's title to\n          // prettify the back/next history menu entries. Since IE sometimes\n          // errors with \"Unspecified error\" the very first time this is set\n          // (yes, very useful) wrap this with a try/catch block.\n          doc.onpropertychange = function(){\n            try {\n              if ( event.propertyName === 'title' ) {\n                iframe.document.title = doc.title;\n              }\n            } catch(e) {}\n          };\n          \n        }\n      };\n      \n      // Override the \"stop\" method since an IE6/7 Iframe was created. Even\n      // if there are no longer any bound event handlers, the polling loop\n      // is still necessary for back/next to work at all!\n      self.stop = fn_retval;\n      \n      // Get history by looking at the hidden Iframe's location.hash.\n      history_get = function() {\n        return get_fragment( iframe.location.href );\n      };\n      \n      // Set a new history item by opening and then closing the Iframe\n      // document, *then* setting its location.hash. If document.domain has\n      // been set, update that as well.\n      history_set = function( hash, history_hash ) {\n        var iframe_doc = iframe.document,\n          domain = $.fn[ str_hashchange ].domain;\n        \n        if ( hash !== history_hash ) {\n          // Update Iframe with any initial `document.title` that might be set.\n          iframe_doc.title = doc.title;\n          \n          // Opening the Iframe's document after it has been closed is what\n          // actually adds a history entry.\n          iframe_doc.open();\n          \n          // Set document.domain for the Iframe document as well, if necessary.\n          domain && iframe_doc.write( '<script>document.domain=\"' + domain + '\"</script>' );\n          \n          iframe_doc.close();\n          \n          // Update the Iframe's hash, for great justice.\n          iframe.location.hash = hash;\n        }\n      };\n      \n    })();\n    // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n    // ^^^^^^^^^^^^^^^^^^^ REMOVE IF NOT SUPPORTING IE6/7/8 ^^^^^^^^^^^^^^^^^^^\n    // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n    \n    return self;\n  })();\n  \n})(jQuery,this);\n", "/*\n * jQuery UI Nested Sortable\n * v 2.1a / 2016-02-04\n * https://github.com/ilikenwf/nestedSortable\n *\n * Depends on:\n *\t jquery.ui.sortable.js 1.10+\n *\n * Copyright (c) 2010-2016 Manuele J Sarfatti and contributors\n * Licensed under the MIT License\n * http://www.opensource.org/licenses/mit-license.php\n */\n(function( factory ) {\n\t\"use strict\";\n\n\tif ( typeof define === \"function\" && define.amd ) {\n\n\t\t// AMD. Register as an anonymous module.\n\t\tdefine([\n\t\t\t\"jquery\",\n\t\t\t\"jquery-ui/sortable\"\n\t\t], factory );\n\t} else {\n\n\t\t// Browser globals\n\t\tfactory( window.jQuery );\n\t}\n}(function($) {\n\t\"use strict\";\n\n\tfunction isOverAxis( x, reference, size ) {\n\t\treturn ( x > reference ) && ( x < ( reference + size ) );\n\t}\n\n\t$.widget(\"mjs.nestedSortable\", $.extend({}, $.ui.sortable.prototype, {\n\n\t\toptions: {\n\t\t\tdisableParentChange: false,\n\t\t\tdoNotClear: false,\n\t\t\texpandOnHover: 700,\n\t\t\tisAllowed: function() { return true; },\n\t\t\tisTree: false,\n\t\t\tlistType: \"ol\",\n\t\t\tmaxLevels: 0,\n\t\t\tprotectRoot: false,\n\t\t\trootID: null,\n\t\t\trtl: false,\n\t\t\tstartCollapsed: false,\n\t\t\ttabSize: 20,\n\n\t\t\tbranchClass: \"mjs-nestedSortable-branch\",\n\t\t\tcollapsedClass: \"mjs-nestedSortable-collapsed\",\n\t\t\tdisableNestingClass: \"mjs-nestedSortable-no-nesting\",\n\t\t\terrorClass: \"mjs-nestedSortable-error\",\n\t\t\texpandedClass: \"mjs-nestedSortable-expanded\",\n\t\t\thoveringClass: \"mjs-nestedSortable-hovering\",\n\t\t\tleafClass: \"mjs-nestedSortable-leaf\",\n\t\t\tdisabledClass: \"mjs-nestedSortable-disabled\"\n\t\t},\n\n\t\t_create: function() {\n\t\t\tvar self = this,\n\t\t\t\terr;\n\n\t\t\tthis.element.data(\"ui-sortable\", this.element.data(\"mjs-nestedSortable\"));\n\n\t\t\t// mjs - prevent browser from freezing if the HTML is not correct\n\t\t\tif (!this.element.is(this.options.listType)) {\n\t\t\t\terr = \"nestedSortable: \" +\n\t\t\t\t\t\"Please check that the listType option is set to your actual list type\";\n\n\t\t\t\tthrow new Error(err);\n\t\t\t}\n\n\t\t\t// if we have a tree with expanding/collapsing functionality,\n\t\t\t// force 'intersect' tolerance method\n\t\t\tif (this.options.isTree && this.options.expandOnHover) {\n\t\t\t\tthis.options.tolerance = \"intersect\";\n\t\t\t}\n\n\t\t\t$.ui.sortable.prototype._create.apply(this, arguments);\n\n\t\t\t// prepare the tree by applying the right classes\n\t\t\t// (the CSS is responsible for actual hide/show functionality)\n\t\t\tif (this.options.isTree) {\n\t\t\t\t$(this.items).each(function() {\n\t\t\t\t\tvar $li = this.item,\n\t\t\t\t\t\thasCollapsedClass = $li.hasClass(self.options.collapsedClass),\n\t\t\t\t\t\thasExpandedClass = $li.hasClass(self.options.expandedClass);\n\n\t\t\t\t\tif ($li.children(self.options.listType).length) {\n\t\t\t\t\t\t$li.addClass(self.options.branchClass);\n\t\t\t\t\t\t// expand/collapse class only if they have children\n\n\t\t\t\t\t\tif ( !hasCollapsedClass && !hasExpandedClass ) {\n\t\t\t\t\t\t\tif (self.options.startCollapsed) {\n\t\t\t\t\t\t\t\t$li.addClass(self.options.collapsedClass);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t$li.addClass(self.options.expandedClass);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\t$li.addClass(self.options.leafClass);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\n\t\t_destroy: function() {\n\t\t\tthis.element\n\t\t\t\t.removeData(\"mjs-nestedSortable\")\n\t\t\t\t.removeData(\"ui-sortable\");\n\t\t\treturn $.ui.sortable.prototype._destroy.apply(this, arguments);\n\t\t},\n\n\t\t_mouseDrag: function(event) {\n\t\t\tvar i,\n\t\t\t\titem,\n\t\t\t\titemElement,\n\t\t\t\tintersection,\n\t\t\t\tself = this,\n\t\t\t\to = this.options,\n\t\t\t\tscrolled = false,\n\t\t\t\t$document = $(document),\n\t\t\t\tpreviousTopOffset,\n\t\t\t\tparentItem,\n\t\t\t\tlevel,\n\t\t\t\tchildLevels,\n\t\t\t\titemAfter,\n\t\t\t\titemBefore,\n\t\t\t\tnewList,\n\t\t\t\tmethod,\n\t\t\t\ta,\n\t\t\t\tpreviousItem,\n\t\t\t\tnextItem,\n\t\t\t\thelperIsNotSibling;\n\n\t\t\t//Compute the helpers position\n\t\t\tthis.position = this._generatePosition(event);\n\t\t\tthis.positionAbs = this._convertPositionTo(\"absolute\");\n\n\t\t\tif (!this.lastPositionAbs) {\n\t\t\t\tthis.lastPositionAbs = this.positionAbs;\n\t\t\t}\n\n\t\t\t//Do scrolling\n\t\t\tif (this.options.scroll) {\n\t\t\t\tif (this.scrollParent[0] !== document && this.scrollParent[0].tagName !== \"HTML\") {\n\n\t\t\t\t\tif (\n\t\t\t\t\t\t(\n\t\t\t\t\t\t\tthis.overflowOffset.top +\n\t\t\t\t\t\t\tthis.scrollParent[0].offsetHeight\n\t\t\t\t\t\t) -\n\t\t\t\t\t\tevent.pageY <\n\t\t\t\t\t\to.scrollSensitivity\n\t\t\t\t\t) {\n\t\t\t\t\t\tscrolled = this.scrollParent.scrollTop() + o.scrollSpeed;\n\t\t\t\t\t\tthis.scrollParent.scrollTop(scrolled);\n\t\t\t\t\t} else if (\n\t\t\t\t\t\tevent.pageY -\n\t\t\t\t\t\tthis.overflowOffset.top <\n\t\t\t\t\t\to.scrollSensitivity\n\t\t\t\t\t) {\n\t\t\t\t\t\tscrolled = this.scrollParent.scrollTop() - o.scrollSpeed;\n\t\t\t\t\t\tthis.scrollParent.scrollTop(scrolled);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (\n\t\t\t\t\t\t(\n\t\t\t\t\t\t\tthis.overflowOffset.left +\n\t\t\t\t\t\t\tthis.scrollParent[0].offsetWidth\n\t\t\t\t\t\t) -\n\t\t\t\t\t\tevent.pageX <\n\t\t\t\t\t\to.scrollSensitivity\n\t\t\t\t\t) {\n\t\t\t\t\t\tscrolled = this.scrollParent.scrollLeft() + o.scrollSpeed;\n\t\t\t\t\t\tthis.scrollParent.scrollLeft(scrolled);\n\t\t\t\t\t} else if (\n\t\t\t\t\t\tevent.pageX -\n\t\t\t\t\t\tthis.overflowOffset.left <\n\t\t\t\t\t\to.scrollSensitivity\n\t\t\t\t\t) {\n\t\t\t\t\t\tscrolled = this.scrollParent.scrollLeft() - o.scrollSpeed;\n\t\t\t\t\t\tthis.scrollParent.scrollLeft(scrolled);\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\n\t\t\t\t\tif (\n\t\t\t\t\t\tevent.pageY -\n\t\t\t\t\t\t$document.scrollTop() <\n\t\t\t\t\t\to.scrollSensitivity\n\t\t\t\t\t) {\n\t\t\t\t\t\tscrolled = $document.scrollTop() - o.scrollSpeed;\n\t\t\t\t\t\t$document.scrollTop(scrolled);\n\t\t\t\t\t} else if (\n\t\t\t\t\t\t$(window).height() -\n\t\t\t\t\t\t(\n\t\t\t\t\t\t\tevent.pageY -\n\t\t\t\t\t\t\t$document.scrollTop()\n\t\t\t\t\t\t) <\n\t\t\t\t\t\to.scrollSensitivity\n\t\t\t\t\t) {\n\t\t\t\t\t\tscrolled = $document.scrollTop() + o.scrollSpeed;\n\t\t\t\t\t\t$document.scrollTop(scrolled);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (\n\t\t\t\t\t\tevent.pageX -\n\t\t\t\t\t\t$document.scrollLeft() <\n\t\t\t\t\t\to.scrollSensitivity\n\t\t\t\t\t) {\n\t\t\t\t\t\tscrolled = $document.scrollLeft() - o.scrollSpeed;\n\t\t\t\t\t\t$document.scrollLeft(scrolled);\n\t\t\t\t\t} else if (\n\t\t\t\t\t\t$(window).width() -\n\t\t\t\t\t\t(\n\t\t\t\t\t\t\tevent.pageX -\n\t\t\t\t\t\t\t$document.scrollLeft()\n\t\t\t\t\t\t) <\n\t\t\t\t\t\to.scrollSensitivity\n\t\t\t\t\t) {\n\t\t\t\t\t\tscrolled = $document.scrollLeft() + o.scrollSpeed;\n\t\t\t\t\t\t$document.scrollLeft(scrolled);\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t\tif (scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) {\n\t\t\t\t\t$.ui.ddmanager.prepareOffsets(this, event);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t//Regenerate the absolute position used for position checks\n\t\t\tthis.positionAbs = this._convertPositionTo(\"absolute\");\n\n\t\t\t// mjs - find the top offset before rearrangement,\n\t\t\tpreviousTopOffset = this.placeholder.offset().top;\n\n\t\t\t//Set the helper position\n\t\t\tif (!this.options.axis || this.options.axis !== \"y\") {\n\t\t\t\tthis.helper[0].style.left = this.position.left + \"px\";\n\t\t\t}\n\t\t\tif (!this.options.axis || this.options.axis !== \"x\") {\n\t\t\t\tthis.helper[0].style.top = (this.position.top) + \"px\";\n\t\t\t}\n\n\t\t\t// mjs - check and reset hovering state at each cycle\n\t\t\tthis.hovering = this.hovering ? this.hovering : null;\n\t\t\tthis.mouseentered = this.mouseentered ? this.mouseentered : false;\n\n\t\t\t// mjs - let's start caching some variables\n\t\t\t(function() {\n\t\t\t\tvar _parentItem = this.placeholder.parent().parent();\n\t\t\t\tif (_parentItem && _parentItem.closest(\".ui-sortable\").length) {\n\t\t\t\t\tparentItem = _parentItem;\n\t\t\t\t}\n\t\t\t}.call(this));\n\n\t\t\tlevel = this._getLevel(this.placeholder);\n\t\t\tchildLevels = this._getChildLevels(this.helper);\n\t\t\tnewList = document.createElement(o.listType);\n\n\t\t\t//Rearrange\n\t\t\tfor (i = this.items.length - 1; i >= 0; i--) {\n\n\t\t\t\t//Cache variables and intersection, continue if no intersection\n\t\t\t\titem = this.items[i];\n\t\t\t\titemElement = item.item[0];\n\t\t\t\tintersection = this._intersectsWithPointer(item);\n\t\t\t\tif (!intersection) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// Only put the placeholder inside the current Container, skip all\n\t\t\t\t// items form other containers. This works because when moving\n\t\t\t\t// an item from one container to another the\n\t\t\t\t// currentContainer is switched before the placeholder is moved.\n\t\t\t\t//\n\t\t\t\t// Without this moving items in \"sub-sortables\" can cause the placeholder to jitter\n\t\t\t\t// beetween the outer and inner container.\n\t\t\t\tif (item.instance !== this.currentContainer) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// No action if intersected item is disabled\n\t\t\t\t// and the element above or below in the direction we're going is also disabled\n\t\t\t\tif (itemElement.className.indexOf(o.disabledClass) !== -1) {\n\t\t\t\t\t// Note: intersection hardcoded direction values from\n\t\t\t\t\t// jquery.ui.sortable.js:_intersectsWithPointer\n\t\t\t\t\tif (intersection === 2) {\n\t\t\t\t\t\t// Going down\n\t\t\t\t\t\titemAfter = this.items[i + 1];\n\t\t\t\t\t\tif (itemAfter && itemAfter.item.hasClass(o.disabledClass)) {\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else if (intersection === 1) {\n\t\t\t\t\t\t// Going up\n\t\t\t\t\t\titemBefore = this.items[i - 1];\n\t\t\t\t\t\tif (itemBefore && itemBefore.item.hasClass(o.disabledClass)) {\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tmethod = intersection === 1 ? \"next\" : \"prev\";\n\n\t\t\t\t// cannot intersect with itself\n\t\t\t\t// no useless actions that have been done before\n\t\t\t\t// no action if the item moved is the parent of the item checked\n\t\t\t\tif (itemElement !== this.currentItem[0] &&\n\t\t\t\t\tthis.placeholder[method]()[0] !== itemElement &&\n\t\t\t\t\t!$.contains(this.placeholder[0], itemElement) &&\n\t\t\t\t\t(\n\t\t\t\t\t\tthis.options.type === \"semi-dynamic\" ?\n\t\t\t\t\t\t\t!$.contains(this.element[0], itemElement) :\n\t\t\t\t\t\t\ttrue\n\t\t\t\t\t)\n\t\t\t\t) {\n\n\t\t\t\t\t// mjs - we are intersecting an element:\n\t\t\t\t\t// trigger the mouseenter event and store this state\n\t\t\t\t\tif (!this.mouseentered) {\n\t\t\t\t\t\t$(itemElement).mouseenter();\n\t\t\t\t\t\tthis.mouseentered = true;\n\t\t\t\t\t}\n\n\t\t\t\t\t// mjs - if the element has children and they are hidden,\n\t\t\t\t\t// show them after a delay (CSS responsible)\n\t\t\t\t\tif (o.isTree && $(itemElement).hasClass(o.collapsedClass) && o.expandOnHover) {\n\t\t\t\t\t\tif (!this.hovering) {\n\t\t\t\t\t\t\t$(itemElement).addClass(o.hoveringClass);\n\t\t\t\t\t\t\tthis.hovering = window.setTimeout(function() {\n\t\t\t\t\t\t\t\t$(itemElement)\n\t\t\t\t\t\t\t\t\t.removeClass(o.collapsedClass)\n\t\t\t\t\t\t\t\t\t.addClass(o.expandedClass);\n\n\t\t\t\t\t\t\t\tself.refreshPositions();\n\t\t\t\t\t\t\t\tself._trigger(\"expand\", event, self._uiHash());\n\t\t\t\t\t\t\t}, o.expandOnHover);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.direction = intersection === 1 ? \"down\" : \"up\";\n\n\t\t\t\t\t// mjs - rearrange the elements and reset timeouts and hovering state\n\t\t\t\t\tif (this.options.tolerance === \"pointer\" || this._intersectsWithSides(item)) {\n\t\t\t\t\t\t$(itemElement).mouseleave();\n\t\t\t\t\t\tthis.mouseentered = false;\n\t\t\t\t\t\t$(itemElement).removeClass(o.hoveringClass);\n\t\t\t\t\t\tif (this.hovering) {\n\t\t\t\t\t\t\twindow.clearTimeout(this.hovering);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tthis.hovering = null;\n\n\t\t\t\t\t\t// mjs - do not switch container if\n\t\t\t\t\t\t// it's a root item and 'protectRoot' is true\n\t\t\t\t\t\t// or if it's not a root item but we are trying to make it root\n\t\t\t\t\t\tif (o.protectRoot &&\n\t\t\t\t\t\t\t!(\n\t\t\t\t\t\t\t\tthis.currentItem[0].parentNode === this.element[0] &&\n\t\t\t\t\t\t\t\t// it's a root item\n\t\t\t\t\t\t\t\titemElement.parentNode !== this.element[0]\n\t\t\t\t\t\t\t\t// it's intersecting a non-root item\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tif (this.currentItem[0].parentNode !== this.element[0] &&\n\t\t\t\t\t\t\t\titemElement.parentNode === this.element[0]\n\t\t\t\t\t\t\t) {\n\n\t\t\t\t\t\t\t\tif ( !$(itemElement).children(o.listType).length) {\n\t\t\t\t\t\t\t\t\titemElement.appendChild(newList);\n\t\t\t\t\t\t\t\t\tif (o.isTree) {\n\t\t\t\t\t\t\t\t\t\t$(itemElement)\n\t\t\t\t\t\t\t\t\t\t\t.removeClass(o.leafClass)\n\t\t\t\t\t\t\t\t\t\t\t.addClass(o.branchClass + \" \" + o.expandedClass);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tif (this.direction === \"down\") {\n\t\t\t\t\t\t\t\t\ta = $(itemElement).prev().children(o.listType);\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\ta = $(itemElement).children(o.listType);\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tif (a[0] !== undefined) {\n\t\t\t\t\t\t\t\t\tthis._rearrange(event, null, a);\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tthis._rearrange(event, item);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if (!o.protectRoot) {\n\t\t\t\t\t\t\tthis._rearrange(event, item);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Clear emtpy ul's/ol's\n\t\t\t\t\tthis._clearEmpty(itemElement);\n\n\t\t\t\t\tthis._trigger(\"change\", event, this._uiHash());\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// mjs - to find the previous sibling in the list,\n\t\t\t// keep backtracking until we hit a valid list item.\n\t\t\t(function() {\n\t\t\t\tvar _previousItem = this.placeholder.prev();\n\t\t\t\tif (_previousItem.length) {\n\t\t\t\t\tpreviousItem = _previousItem;\n\t\t\t\t} else {\n\t\t\t\t\tpreviousItem = null;\n\t\t\t\t}\n\t\t\t}.call(this));\n\n\t\t\tif (previousItem != null) {\n\t\t\t\twhile (\n\t\t\t\t\tpreviousItem[0].nodeName.toLowerCase() !== \"li\" ||\n\t\t\t\t\tpreviousItem[0].className.indexOf(o.disabledClass) !== -1 ||\n\t\t\t\t\tpreviousItem[0] === this.currentItem[0] ||\n\t\t\t\t\tpreviousItem[0] === this.helper[0]\n\t\t\t\t) {\n\t\t\t\t\tif (previousItem[0].previousSibling) {\n\t\t\t\t\t\tpreviousItem = $(previousItem[0].previousSibling);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tpreviousItem = null;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// mjs - to find the next sibling in the list,\n\t\t\t// keep stepping forward until we hit a valid list item.\n\t\t\t(function() {\n\t\t\t\tvar _nextItem = this.placeholder.next();\n\t\t\t\tif (_nextItem.length) {\n\t\t\t\t\tnextItem = _nextItem;\n\t\t\t\t} else {\n\t\t\t\t\tnextItem = null;\n\t\t\t\t}\n\t\t\t}.call(this));\n\n\t\t\tif (nextItem != null) {\n\t\t\t\twhile (\n\t\t\t\t\tnextItem[0].nodeName.toLowerCase() !== \"li\" ||\n\t\t\t\t\tnextItem[0].className.indexOf(o.disabledClass) !== -1 ||\n\t\t\t\t\tnextItem[0] === this.currentItem[0] ||\n\t\t\t\t\tnextItem[0] === this.helper[0]\n\t\t\t\t) {\n\t\t\t\t\tif (nextItem[0].nextSibling) {\n\t\t\t\t\t\tnextItem = $(nextItem[0].nextSibling);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tnextItem = null;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.beyondMaxLevels = 0;\n\n\t\t\t// mjs - if the item is moved to the left, send it one level up\n\t\t\t// but only if it's at the bottom of the list\n\t\t\tif (parentItem != null &&\n\t\t\t\tnextItem == null &&\n\t\t\t\t!(o.protectRoot && parentItem[0].parentNode == this.element[0]) &&\n\t\t\t\t(\n\t\t\t\t\to.rtl &&\n\t\t\t\t\t(\n\t\t\t\t\t\tthis.positionAbs.left +\n\t\t\t\t\t\tthis.helper.outerWidth() > parentItem.offset().left +\n\t\t\t\t\t\tparentItem.outerWidth()\n\t\t\t\t\t) ||\n\t\t\t\t\t!o.rtl && (this.positionAbs.left < parentItem.offset().left)\n\t\t\t\t)\n\t\t\t) {\n\n\t\t\t\tparentItem.after(this.placeholder[0]);\n\t\t\t\thelperIsNotSibling = !parentItem\n\t\t\t\t\t\t\t\t\t\t\t.children(o.listItem)\n\t\t\t\t\t\t\t\t\t\t\t.children(\"li:visible:not(.ui-sortable-helper)\")\n\t\t\t\t\t\t\t\t\t\t\t.length;\n\t\t\t\tif (o.isTree && helperIsNotSibling) {\n\t\t\t\t\tparentItem\n\t\t\t\t\t\t.removeClass(this.options.branchClass + \" \" + this.options.expandedClass)\n\t\t\t\t\t\t.addClass(this.options.leafClass);\n\t\t\t\t}\n                if(typeof parentItem !== 'undefined')\n\t\t\t\t    this._clearEmpty(parentItem[0]);\n\t\t\t\tthis._trigger(\"change\", event, this._uiHash());\n\t\t\t\t// mjs - if the item is below a sibling and is moved to the right,\n\t\t\t\t// make it a child of that sibling\n\t\t\t} else if (previousItem != null &&\n\t\t\t\t!previousItem.hasClass(o.disableNestingClass) &&\n\t\t\t\t(\n\t\t\t\t\tpreviousItem.children(o.listType).length &&\n\t\t\t\t\tpreviousItem.children(o.listType).is(\":visible\") ||\n\t\t\t\t\t!previousItem.children(o.listType).length\n\t\t\t\t) &&\n\t\t\t\t!(o.protectRoot && this.currentItem[0].parentNode === this.element[0]) &&\n\t\t\t\t(\n\t\t\t\t\to.rtl &&\n\t\t\t\t\t(\n\t\t\t\t\t\tthis.positionAbs.left +\n\t\t\t\t\t\tthis.helper.outerWidth() <\n\t\t\t\t\t\tpreviousItem.offset().left +\n\t\t\t\t\t\tpreviousItem.outerWidth() -\n\t\t\t\t\t\to.tabSize\n\t\t\t\t\t) ||\n\t\t\t\t\t!o.rtl &&\n\t\t\t\t\t(this.positionAbs.left > previousItem.offset().left + o.tabSize)\n\t\t\t\t)\n\t\t\t) {\n\n\t\t\t\tthis._isAllowed(previousItem, level, level + childLevels + 1);\n\n\t\t\t\tif (!previousItem.children(o.listType).length) {\n\t\t\t\t\tpreviousItem[0].appendChild(newList);\n\t\t\t\t\tif (o.isTree) {\n\t\t\t\t\t\tpreviousItem\n\t\t\t\t\t\t\t.removeClass(o.leafClass)\n\t\t\t\t\t\t\t.addClass(o.branchClass + \" \" + o.expandedClass);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// mjs - if this item is being moved from the top, add it to the top of the list.\n\t\t\t\tif (previousTopOffset && (previousTopOffset <= previousItem.offset().top)) {\n\t\t\t\t\tpreviousItem.children(o.listType).prepend(this.placeholder);\n\t\t\t\t} else {\n\t\t\t\t\t// mjs - otherwise, add it to the bottom of the list.\n\t\t\t\t\tpreviousItem.children(o.listType)[0].appendChild(this.placeholder[0]);\n\t\t\t\t}\n                if(typeof parentItem !== 'undefined')\n\t\t\t\t    this._clearEmpty(parentItem[0]);\n\t\t\t\tthis._trigger(\"change\", event, this._uiHash());\n\t\t\t} else {\n\t\t\t\tthis._isAllowed(parentItem, level, level + childLevels);\n\t\t\t}\n\n\t\t\t//Post events to containers\n\t\t\tthis._contactContainers(event);\n\n\t\t\t//Interconnect with droppables\n\t\t\tif ($.ui.ddmanager) {\n\t\t\t\t$.ui.ddmanager.drag(this, event);\n\t\t\t}\n\n\t\t\t//Call callbacks\n\t\t\tthis._trigger(\"sort\", event, this._uiHash());\n\n\t\t\tthis.lastPositionAbs = this.positionAbs;\n\t\t\treturn false;\n\n\t\t},\n\n\t\t_mouseStop: function(event) {\n\t\t\t// mjs - if the item is in a position not allowed, send it back\n\t\t\tif (this.beyondMaxLevels) {\n\n\t\t\t\tthis.placeholder.removeClass(this.options.errorClass);\n\n\t\t\t\tif (this.domPosition.prev) {\n\t\t\t\t\t$(this.domPosition.prev).after(this.placeholder);\n\t\t\t\t} else {\n\t\t\t\t\t$(this.domPosition.parent).prepend(this.placeholder);\n\t\t\t\t}\n\n\t\t\t\tthis._trigger(\"revert\", event, this._uiHash());\n\n\t\t\t}\n\n\t\t\t// mjs - clear the hovering timeout, just to be sure\n\t\t\t$(\".\" + this.options.hoveringClass)\n\t\t\t\t.mouseleave()\n\t\t\t\t.removeClass(this.options.hoveringClass);\n\n\t\t\tthis.mouseentered = false;\n\t\t\tif (this.hovering) {\n\t\t\t\twindow.clearTimeout(this.hovering);\n\t\t\t}\n\t\t\tthis.hovering = null;\n\n\t\t\tthis._relocate_event = event;\n\t\t\tthis._pid_current = $(this.domPosition.parent).parent().attr(\"id\");\n\t\t\tthis._sort_current = this.domPosition.prev ? $(this.domPosition.prev).next().index() : 0;\n\t\t\t$.ui.sortable.prototype._mouseStop.apply(this, arguments); //asybnchronous execution, @see _clear for the relocate event.\n\t\t},\n\n\t\t// mjs - this function is slightly modified\n\t\t// to make it easier to hover over a collapsed element and have it expand\n\t\t_intersectsWithSides: function(item) {\n\n\t\t\tvar half = this.options.isTree ? .8 : .5,\n\t\t\t\tisOverBottomHalf = isOverAxis(\n\t\t\t\t\tthis.positionAbs.top + this.offset.click.top,\n\t\t\t\t\titem.top + (item.height * half),\n\t\t\t\t\titem.height\n\t\t\t\t),\n\t\t\t\tisOverTopHalf = isOverAxis(\n\t\t\t\t\tthis.positionAbs.top + this.offset.click.top,\n\t\t\t\t\titem.top - (item.height * half),\n\t\t\t\t\titem.height\n\t\t\t\t),\n\t\t\t\tisOverRightHalf = isOverAxis(\n\t\t\t\t\tthis.positionAbs.left + this.offset.click.left,\n\t\t\t\t\titem.left + (item.width / 2),\n\t\t\t\t\titem.width\n\t\t\t\t),\n\t\t\t\tverticalDirection = this._getDragVerticalDirection(),\n\t\t\t\thorizontalDirection = this._getDragHorizontalDirection();\n\n\t\t\tif (this.floating && horizontalDirection) {\n\t\t\t\treturn (\n\t\t\t\t\t(horizontalDirection === \"right\" && isOverRightHalf) ||\n\t\t\t\t\t(horizontalDirection === \"left\" && !isOverRightHalf)\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\treturn verticalDirection && (\n\t\t\t\t\t(verticalDirection === \"down\" && isOverBottomHalf) ||\n\t\t\t\t\t(verticalDirection === \"up\" && isOverTopHalf)\n\t\t\t\t);\n\t\t\t}\n\n\t\t},\n\n\t\t_contactContainers: function() {\n\n\t\t\tif (this.options.protectRoot && this.currentItem[0].parentNode === this.element[0] ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t$.ui.sortable.prototype._contactContainers.apply(this, arguments);\n\n\t\t},\n\n\t\t_clear: function() {\n\t\t\tvar i,\n\t\t\t\titem;\n\n\t\t\t$.ui.sortable.prototype._clear.apply(this, arguments);\n\n\t\t\t//relocate event\n\t\t\tif (!(this._pid_current === this._uiHash().item.parent().parent().attr(\"id\") &&\n\t\t\t\tthis._sort_current === this._uiHash().item.index())) {\n\t\t\t\tthis._trigger(\"relocate\", this._relocate_event, this._uiHash());\n\t\t\t}\n\n\t\t\t// mjs - clean last empty ul/ol\n\t\t\tfor (i = this.items.length - 1; i >= 0; i--) {\n\t\t\t\titem = this.items[i].item[0];\n\t\t\t\tthis._clearEmpty(item);\n\t\t\t}\n\n\t\t},\n\n\t\tserialize: function(options) {\n\n\t\t\tvar o = $.extend({}, this.options, options),\n\t\t\t\titems = this._getItemsAsjQuery(o && o.connected),\n\t\t\t\tstr = [];\n\n\t\t\t$(items).each(function() {\n\t\t\t\tvar res = ($(o.item || this).attr(o.attribute || \"id\") || \"\")\n\t\t\t\t\t\t.match(o.expression || (/(.+)[-=_](.+)/)),\n\t\t\t\t\tpid = ($(o.item || this).parent(o.listType)\n\t\t\t\t\t\t.parent(o.items)\n\t\t\t\t\t\t.attr(o.attribute || \"id\") || \"\")\n\t\t\t\t\t\t.match(o.expression || (/(.+)[-=_](.+)/));\n\n\t\t\t\tif (res) {\n\t\t\t\t\tstr.push(\n\t\t\t\t\t\t(\n\t\t\t\t\t\t\t(o.key || res[1]) +\n\t\t\t\t\t\t\t\"[\" +\n\t\t\t\t\t\t\t(o.key && o.expression ? res[1] : res[2]) + \"]\"\n\t\t\t\t\t\t) +\n\t\t\t\t\t\t\"=\" +\n\t\t\t\t\t\t(pid ? (o.key && o.expression ? pid[1] : pid[2]) : o.rootID));\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tif (!str.length && o.key) {\n\t\t\t\tstr.push(o.key + \"=\");\n\t\t\t}\n\n\t\t\treturn str.join(\"&\");\n\n\t\t},\n\n\t\ttoHierarchy: function(options) {\n\n\t\t\tvar o = $.extend({}, this.options, options),\n\t\t\t\tret = [];\n\n\t\t\t$(this.element).children(o.items).each(function() {\n\t\t\t\tvar level = _recursiveItems(this);\n\t\t\t\tret.push(level);\n\t\t\t});\n\n\t\t\treturn ret;\n\n\t\t\tfunction _recursiveItems(item) {\n\t\t\t\tvar id = ($(item).attr(o.attribute || \"id\") || \"\").match(o.expression || (/(.+)[-=_](.+)/)),\n\t\t\t\t\tcurrentItem;\n\n\t\t\t\tvar data = $(item).data();\n\t\t\t\tif (data.nestedSortableItem) {\n\t\t\t\t\tdelete data.nestedSortableItem; // Remove the nestedSortableItem object from the data\n\t\t\t\t}\n\n\t\t\t\tif (id) {\n\t\t\t\t\tcurrentItem = {\n\t\t\t\t\t\t\"id\": id[2]\n\t\t\t\t\t};\n\n\t\t\t\t\tcurrentItem = $.extend({}, currentItem, data); // Combine the two objects\n\n\t\t\t\t\tif ($(item).children(o.listType).children(o.items).length > 0) {\n\t\t\t\t\t\tcurrentItem.children = [];\n\t\t\t\t\t\t$(item).children(o.listType).children(o.items).each(function() {\n\t\t\t\t\t\t\tvar level = _recursiveItems(this);\n\t\t\t\t\t\t\tcurrentItem.children.push(level);\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\treturn currentItem;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\ttoArray: function(options) {\n\n\t\t\tvar o = $.extend({}, this.options, options),\n\t\t\t\tsDepth = o.startDepthCount || 0,\n\t\t\t\tret = [],\n\t\t\t\tleft = 1;\n\n\t\t\tif (!o.excludeRoot) {\n\t\t\t\tret.push({\n\t\t\t\t\t\"item_id\": o.rootID,\n\t\t\t\t\t\"parent_id\": null,\n\t\t\t\t\t\"depth\": sDepth,\n\t\t\t\t\t\"left\": left,\n\t\t\t\t\t\"right\": ($(o.items, this.element).length + 1) * 2\n\t\t\t\t});\n\t\t\t\tleft++;\n\t\t\t}\n\n\t\t\t$(this.element).children(o.items).each(function() {\n\t\t\t\tleft = _recursiveArray(this, sDepth, left);\n\t\t\t});\n\n\t\t\tret = ret.sort(function(a, b) { return (a.left - b.left); });\n\n\t\t\treturn ret;\n\n\t\t\tfunction _recursiveArray(item, depth, _left) {\n\n\t\t\t\tvar right = _left + 1,\n\t\t\t\t\tid,\n\t\t\t\t\tpid,\n\t\t\t\t\tparentItem;\n\n\t\t\t\tif ($(item).children(o.listType).children(o.items).length > 0) {\n\t\t\t\t\tdepth++;\n\t\t\t\t\t$(item).children(o.listType).children(o.items).each(function() {\n\t\t\t\t\t\tright = _recursiveArray($(this), depth, right);\n\t\t\t\t\t});\n\t\t\t\t\tdepth--;\n\t\t\t\t}\n\n\t\t\t\tid = ($(item).attr(o.attribute || \"id\")).match(o.expression || (/(.+)[-=_](.+)/));\n\n\t\t\t\tif (depth === sDepth) {\n\t\t\t\t\tpid = o.rootID;\n\t\t\t\t} else {\n\t\t\t\t\tparentItem = ($(item).parent(o.listType)\n\t\t\t\t\t\t\t\t\t\t\t.parent(o.items)\n\t\t\t\t\t\t\t\t\t\t\t.attr(o.attribute || \"id\"))\n\t\t\t\t\t\t\t\t\t\t\t.match(o.expression || (/(.+)[-=_](.+)/));\n\t\t\t\t\tpid = parentItem[2];\n\t\t\t\t}\n\n\t\t\t\tif (id) {\n\t\t\t\t\tvar data = $(item).children('div').data();\n\t\t\t\t\tvar itemObj = $.extend( data, {\n\t\t\t\t\t\t\"id\":id[2],\n\t\t\t\t\t\t\"parent_id\":pid,\n\t\t\t\t\t\t\"depth\":depth,\n\t\t\t\t\t\t\"left\":_left,\n\t\t\t\t\t\t\"right\":right\n\t\t\t\t\t\t} );\n\t\t\t\t\tret.push( itemObj );\n\t\t\t\t}\n\n\t\t\t\t_left = right + 1;\n\t\t\t\treturn _left;\n\t\t\t}\n\n\t\t},\n\n\t\t_clearEmpty: function (item) {\n\t\t\tfunction replaceClass(elem, search, replace, swap) {\n\t\t\t\tif (swap) {\n\t\t\t\t\tsearch = [replace, replace = search][0];\n\t\t\t\t}\n\n\t\t\t\t$(elem).removeClass(search).addClass(replace);\n\t\t\t}\n\n\t\t\tvar o = this.options,\n\t\t\t\tchildrenList = $(item).children(o.listType),\n\t\t\t\thasChildren = childrenList.has('li').length;\n\n\t\t\tvar doNotClear =\n\t\t\t\to.doNotClear ||\n\t\t\t\thasChildren ||\n\t\t\t\to.protectRoot && $(item)[0] === this.element[0];\n\n\t\t\tif (o.isTree) {\n\t\t\t\treplaceClass(item, o.branchClass, o.leafClass, doNotClear);\n\t\t\t}\n\n\t\t\tif (!doNotClear) {\n\t\t\t\tchildrenList.parent().removeClass(o.expandedClass);\n\t\t\t\tchildrenList.remove();\n\t\t\t}\n\t\t},\n\n\t\t_getLevel: function(item) {\n\n\t\t\tvar level = 1,\n\t\t\t\tlist;\n\n\t\t\tif (this.options.listType) {\n\t\t\t\tlist = item.closest(this.options.listType);\n\t\t\t\twhile (list && list.length > 0 && !list.is(\".ui-sortable\")) {\n\t\t\t\t\tlevel++;\n\t\t\t\t\tlist = list.parent().closest(this.options.listType);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn level;\n\t\t},\n\n\t\t_getChildLevels: function(parent, depth) {\n\t\t\tvar self = this,\n\t\t\t\to = this.options,\n\t\t\t\tresult = 0;\n\t\t\tdepth = depth || 0;\n\n\t\t\t$(parent).children(o.listType).children(o.items).each(function(index, child) {\n\t\t\t\tresult = Math.max(self._getChildLevels(child, depth + 1), result);\n\t\t\t});\n\n\t\t\treturn depth ? result + 1 : result;\n\t\t},\n\n\t\t_isAllowed: function(parentItem, level, levels) {\n\t\t\tvar o = this.options,\n\t\t\t\t// this takes into account the maxLevels set to the recipient list\n\t\t\t\tmaxLevels = this\n\t\t\t\t\t.placeholder\n\t\t\t\t\t.closest(\".ui-sortable\")\n\t\t\t\t\t.nestedSortable(\"option\", \"maxLevels\"),\n\n\t\t\t\t// Check if the parent has changed to prevent it, when o.disableParentChange is true\n\t\t\t\toldParent = this.currentItem.parent().parent(),\n\t\t\t\tdisabledByParentchange = o.disableParentChange && (\n\t\t\t\t\t//From somewhere to somewhere else, except the root\n\t\t\t\t\ttypeof parentItem !== 'undefined' && !oldParent.is(parentItem) ||\n\t\t\t\t\ttypeof parentItem === 'undefined' && oldParent.is(\"li\")\t//From somewhere to the root\n\t\t\t\t);\n\t\t\t// mjs - is the root protected?\n\t\t\t// mjs - are we nesting too deep?\n\t\t\tif (\n\t\t\t\tdisabledByParentchange ||\n\t\t\t\t!o.isAllowed(this.placeholder, parentItem, this.currentItem)\n\t\t\t) {\n\t\t\t\tthis.placeholder.addClass(o.errorClass);\n\t\t\t\tif (maxLevels < levels && maxLevels !== 0) {\n\t\t\t\t\tthis.beyondMaxLevels = levels - maxLevels;\n\t\t\t\t} else {\n\t\t\t\t\tthis.beyondMaxLevels = 1;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (maxLevels < levels && maxLevels !== 0) {\n\t\t\t\t\tthis.placeholder.addClass(o.errorClass);\n\t\t\t\t\tthis.beyondMaxLevels = levels - maxLevels;\n\t\t\t\t} else {\n\t\t\t\t\tthis.placeholder.removeClass(o.errorClass);\n\t\t\t\t\tthis.beyondMaxLevels = 0;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t}));\n\n\t$.mjs.nestedSortable.prototype.options = $.extend(\n\t\t{},\n\t\t$.ui.sortable.prototype.options,\n\t\t$.mjs.nestedSortable.prototype.options\n\t);\n}));", "/**!\n * @fileOverview Kickass library to create and place poppers near their reference elements.\n * @version 1.14.3\n * @license\n * Copyright (c) 2016 Federico Zivolo and contributors\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n(function (global, factory) {\n    typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :\n    typeof define === 'function' && define.amd ? define(factory) :\n    (global.Popper = factory());\n}(this, (function () { 'use strict';\n\nvar isBrowser = typeof window !== 'undefined' && typeof document !== 'undefined';\n\nvar longerTimeoutBrowsers = ['Edge', 'Trident', 'Firefox'];\nvar timeoutDuration = 0;\nfor (var i = 0; i < longerTimeoutBrowsers.length; i += 1) {\n  if (isBrowser && navigator.userAgent.indexOf(longerTimeoutBrowsers[i]) >= 0) {\n    timeoutDuration = 1;\n    break;\n  }\n}\n\nfunction microtaskDebounce(fn) {\n  var called = false;\n  return function () {\n    if (called) {\n      return;\n    }\n    called = true;\n    window.Promise.resolve().then(function () {\n      called = false;\n      fn();\n    });\n  };\n}\n\nfunction taskDebounce(fn) {\n  var scheduled = false;\n  return function () {\n    if (!scheduled) {\n      scheduled = true;\n      setTimeout(function () {\n        scheduled = false;\n        fn();\n      }, timeoutDuration);\n    }\n  };\n}\n\nvar supportsMicroTasks = isBrowser && window.Promise;\n\n/**\n* Create a debounced version of a method, that's asynchronously deferred\n* but called in the minimum time possible.\n*\n* @method\n* @memberof Popper.Utils\n* @argument {Function} fn\n* @returns {Function}\n*/\nvar debounce = supportsMicroTasks ? microtaskDebounce : taskDebounce;\n\n/**\n * Check if the given variable is a function\n * @method\n * @memberof Popper.Utils\n * @argument {Any} functionToCheck - variable to check\n * @returns {Boolean} answer to: is a function?\n */\nfunction isFunction(functionToCheck) {\n  var getType = {};\n  return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]';\n}\n\n/**\n * Get CSS computed property of the given element\n * @method\n * @memberof Popper.Utils\n * @argument {Eement} element\n * @argument {String} property\n */\nfunction getStyleComputedProperty(element, property) {\n  if (element.nodeType !== 1) {\n    return [];\n  }\n  // NOTE: 1 DOM access here\n  var css = getComputedStyle(element, null);\n  return property ? css[property] : css;\n}\n\n/**\n * Returns the parentNode or the host of the element\n * @method\n * @memberof Popper.Utils\n * @argument {Element} element\n * @returns {Element} parent\n */\nfunction getParentNode(element) {\n  if (element.nodeName === 'HTML') {\n    return element;\n  }\n  return element.parentNode || element.host;\n}\n\n/**\n * Returns the scrolling parent of the given element\n * @method\n * @memberof Popper.Utils\n * @argument {Element} element\n * @returns {Element} scroll parent\n */\nfunction getScrollParent(element) {\n  // Return body, `getScroll` will take care to get the correct `scrollTop` from it\n  if (!element) {\n    return document.body;\n  }\n\n  switch (element.nodeName) {\n    case 'HTML':\n    case 'BODY':\n      return element.ownerDocument.body;\n    case '#document':\n      return element.body;\n  }\n\n  // Firefox want us to check `-x` and `-y` variations as well\n\n  var _getStyleComputedProp = getStyleComputedProperty(element),\n      overflow = _getStyleComputedProp.overflow,\n      overflowX = _getStyleComputedProp.overflowX,\n      overflowY = _getStyleComputedProp.overflowY;\n\n  if (/(auto|scroll|overlay)/.test(overflow + overflowY + overflowX)) {\n    return element;\n  }\n\n  return getScrollParent(getParentNode(element));\n}\n\nvar isIE11 = isBrowser && !!(window.MSInputMethodContext && document.documentMode);\nvar isIE10 = isBrowser && /MSIE 10/.test(navigator.userAgent);\n\n/**\n * Determines if the browser is Internet Explorer\n * @method\n * @memberof Popper.Utils\n * @param {Number} version to check\n * @returns {Boolean} isIE\n */\nfunction isIE(version) {\n  if (version === 11) {\n    return isIE11;\n  }\n  if (version === 10) {\n    return isIE10;\n  }\n  return isIE11 || isIE10;\n}\n\n/**\n * Returns the offset parent of the given element\n * @method\n * @memberof Popper.Utils\n * @argument {Element} element\n * @returns {Element} offset parent\n */\nfunction getOffsetParent(element) {\n  if (!element) {\n    return document.documentElement;\n  }\n\n  var noOffsetParent = isIE(10) ? document.body : null;\n\n  // NOTE: 1 DOM access here\n  var offsetParent = element.offsetParent;\n  // Skip hidden elements which don't have an offsetParent\n  while (offsetParent === noOffsetParent && element.nextElementSibling) {\n    offsetParent = (element = element.nextElementSibling).offsetParent;\n  }\n\n  var nodeName = offsetParent && offsetParent.nodeName;\n\n  if (!nodeName || nodeName === 'BODY' || nodeName === 'HTML') {\n    return element ? element.ownerDocument.documentElement : document.documentElement;\n  }\n\n  // .offsetParent will return the closest TD or TABLE in case\n  // no offsetParent is present, I hate this job...\n  if (['TD', 'TABLE'].indexOf(offsetParent.nodeName) !== -1 && getStyleComputedProperty(offsetParent, 'position') === 'static') {\n    return getOffsetParent(offsetParent);\n  }\n\n  return offsetParent;\n}\n\nfunction isOffsetContainer(element) {\n  var nodeName = element.nodeName;\n\n  if (nodeName === 'BODY') {\n    return false;\n  }\n  return nodeName === 'HTML' || getOffsetParent(element.firstElementChild) === element;\n}\n\n/**\n * Finds the root node (document, shadowDOM root) of the given element\n * @method\n * @memberof Popper.Utils\n * @argument {Element} node\n * @returns {Element} root node\n */\nfunction getRoot(node) {\n  if (node.parentNode !== null) {\n    return getRoot(node.parentNode);\n  }\n\n  return node;\n}\n\n/**\n * Finds the offset parent common to the two provided nodes\n * @method\n * @memberof Popper.Utils\n * @argument {Element} element1\n * @argument {Element} element2\n * @returns {Element} common offset parent\n */\nfunction findCommonOffsetParent(element1, element2) {\n  // This check is needed to avoid errors in case one of the elements isn't defined for any reason\n  if (!element1 || !element1.nodeType || !element2 || !element2.nodeType) {\n    return document.documentElement;\n  }\n\n  // Here we make sure to give as \"start\" the element that comes first in the DOM\n  var order = element1.compareDocumentPosition(element2) & Node.DOCUMENT_POSITION_FOLLOWING;\n  var start = order ? element1 : element2;\n  var end = order ? element2 : element1;\n\n  // Get common ancestor container\n  var range = document.createRange();\n  range.setStart(start, 0);\n  range.setEnd(end, 0);\n  var commonAncestorContainer = range.commonAncestorContainer;\n\n  // Both nodes are inside #document\n\n  if (element1 !== commonAncestorContainer && element2 !== commonAncestorContainer || start.contains(end)) {\n    if (isOffsetContainer(commonAncestorContainer)) {\n      return commonAncestorContainer;\n    }\n\n    return getOffsetParent(commonAncestorContainer);\n  }\n\n  // one of the nodes is inside shadowDOM, find which one\n  var element1root = getRoot(element1);\n  if (element1root.host) {\n    return findCommonOffsetParent(element1root.host, element2);\n  } else {\n    return findCommonOffsetParent(element1, getRoot(element2).host);\n  }\n}\n\n/**\n * Gets the scroll value of the given element in the given side (top and left)\n * @method\n * @memberof Popper.Utils\n * @argument {Element} element\n * @argument {String} side `top` or `left`\n * @returns {number} amount of scrolled pixels\n */\nfunction getScroll(element) {\n  var side = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'top';\n\n  var upperSide = side === 'top' ? 'scrollTop' : 'scrollLeft';\n  var nodeName = element.nodeName;\n\n  if (nodeName === 'BODY' || nodeName === 'HTML') {\n    var html = element.ownerDocument.documentElement;\n    var scrollingElement = element.ownerDocument.scrollingElement || html;\n    return scrollingElement[upperSide];\n  }\n\n  return element[upperSide];\n}\n\n/*\n * Sum or subtract the element scroll values (left and top) from a given rect object\n * @method\n * @memberof Popper.Utils\n * @param {Object} rect - Rect object you want to change\n * @param {HTMLElement} element - The element from the function reads the scroll values\n * @param {Boolean} subtract - set to true if you want to subtract the scroll values\n * @return {Object} rect - The modifier rect object\n */\nfunction includeScroll(rect, element) {\n  var subtract = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;\n\n  var scrollTop = getScroll(element, 'top');\n  var scrollLeft = getScroll(element, 'left');\n  var modifier = subtract ? -1 : 1;\n  rect.top += scrollTop * modifier;\n  rect.bottom += scrollTop * modifier;\n  rect.left += scrollLeft * modifier;\n  rect.right += scrollLeft * modifier;\n  return rect;\n}\n\n/*\n * Helper to detect borders of a given element\n * @method\n * @memberof Popper.Utils\n * @param {CSSStyleDeclaration} styles\n * Result of `getStyleComputedProperty` on the given element\n * @param {String} axis - `x` or `y`\n * @return {number} borders - The borders size of the given axis\n */\n\nfunction getBordersSize(styles, axis) {\n  var sideA = axis === 'x' ? 'Left' : 'Top';\n  var sideB = sideA === 'Left' ? 'Right' : 'Bottom';\n\n  return parseFloat(styles['border' + sideA + 'Width'], 10) + parseFloat(styles['border' + sideB + 'Width'], 10);\n}\n\nfunction getSize(axis, body, html, computedStyle) {\n  return Math.max(body['offset' + axis], body['scroll' + axis], html['client' + axis], html['offset' + axis], html['scroll' + axis], isIE(10) ? html['offset' + axis] + computedStyle['margin' + (axis === 'Height' ? 'Top' : 'Left')] + computedStyle['margin' + (axis === 'Height' ? 'Bottom' : 'Right')] : 0);\n}\n\nfunction getWindowSizes() {\n  var body = document.body;\n  var html = document.documentElement;\n  var computedStyle = isIE(10) && getComputedStyle(html);\n\n  return {\n    height: getSize('Height', body, html, computedStyle),\n    width: getSize('Width', body, html, computedStyle)\n  };\n}\n\nvar classCallCheck = function (instance, Constructor) {\n  if (!(instance instanceof Constructor)) {\n    throw new TypeError(\"Cannot call a class as a function\");\n  }\n};\n\nvar createClass = function () {\n  function defineProperties(target, props) {\n    for (var i = 0; i < props.length; i++) {\n      var descriptor = props[i];\n      descriptor.enumerable = descriptor.enumerable || false;\n      descriptor.configurable = true;\n      if (\"value\" in descriptor) descriptor.writable = true;\n      Object.defineProperty(target, descriptor.key, descriptor);\n    }\n  }\n\n  return function (Constructor, protoProps, staticProps) {\n    if (protoProps) defineProperties(Constructor.prototype, protoProps);\n    if (staticProps) defineProperties(Constructor, staticProps);\n    return Constructor;\n  };\n}();\n\n\n\n\n\nvar defineProperty = function (obj, key, value) {\n  if (key in obj) {\n    Object.defineProperty(obj, key, {\n      value: value,\n      enumerable: true,\n      configurable: true,\n      writable: true\n    });\n  } else {\n    obj[key] = value;\n  }\n\n  return obj;\n};\n\nvar _extends = Object.assign || function (target) {\n  for (var i = 1; i < arguments.length; i++) {\n    var source = arguments[i];\n\n    for (var key in source) {\n      if (Object.prototype.hasOwnProperty.call(source, key)) {\n        target[key] = source[key];\n      }\n    }\n  }\n\n  return target;\n};\n\n/**\n * Given element offsets, generate an output similar to getBoundingClientRect\n * @method\n * @memberof Popper.Utils\n * @argument {Object} offsets\n * @returns {Object} ClientRect like output\n */\nfunction getClientRect(offsets) {\n  return _extends({}, offsets, {\n    right: offsets.left + offsets.width,\n    bottom: offsets.top + offsets.height\n  });\n}\n\n/**\n * Get bounding client rect of given element\n * @method\n * @memberof Popper.Utils\n * @param {HTMLElement} element\n * @return {Object} client rect\n */\nfunction getBoundingClientRect(element) {\n  var rect = {};\n\n  // IE10 10 FIX: Please, don't ask, the element isn't\n  // considered in DOM in some circumstances...\n  // This isn't reproducible in IE10 compatibility mode of IE11\n  try {\n    if (isIE(10)) {\n      rect = element.getBoundingClientRect();\n      var scrollTop = getScroll(element, 'top');\n      var scrollLeft = getScroll(element, 'left');\n      rect.top += scrollTop;\n      rect.left += scrollLeft;\n      rect.bottom += scrollTop;\n      rect.right += scrollLeft;\n    } else {\n      rect = element.getBoundingClientRect();\n    }\n  } catch (e) {}\n\n  var result = {\n    left: rect.left,\n    top: rect.top,\n    width: rect.right - rect.left,\n    height: rect.bottom - rect.top\n  };\n\n  // subtract scrollbar size from sizes\n  var sizes = element.nodeName === 'HTML' ? getWindowSizes() : {};\n  var width = sizes.width || element.clientWidth || result.right - result.left;\n  var height = sizes.height || element.clientHeight || result.bottom - result.top;\n\n  var horizScrollbar = element.offsetWidth - width;\n  var vertScrollbar = element.offsetHeight - height;\n\n  // if an hypothetical scrollbar is detected, we must be sure it's not a `border`\n  // we make this check conditional for performance reasons\n  if (horizScrollbar || vertScrollbar) {\n    var styles = getStyleComputedProperty(element);\n    horizScrollbar -= getBordersSize(styles, 'x');\n    vertScrollbar -= getBordersSize(styles, 'y');\n\n    result.width -= horizScrollbar;\n    result.height -= vertScrollbar;\n  }\n\n  return getClientRect(result);\n}\n\nfunction getOffsetRectRelativeToArbitraryNode(children, parent) {\n  var fixedPosition = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;\n\n  var isIE10 = isIE(10);\n  var isHTML = parent.nodeName === 'HTML';\n  var childrenRect = getBoundingClientRect(children);\n  var parentRect = getBoundingClientRect(parent);\n  var scrollParent = getScrollParent(children);\n\n  var styles = getStyleComputedProperty(parent);\n  var borderTopWidth = parseFloat(styles.borderTopWidth, 10);\n  var borderLeftWidth = parseFloat(styles.borderLeftWidth, 10);\n\n  // In cases where the parent is fixed, we must ignore negative scroll in offset calc\n  if (fixedPosition && parent.nodeName === 'HTML') {\n    parentRect.top = Math.max(parentRect.top, 0);\n    parentRect.left = Math.max(parentRect.left, 0);\n  }\n  var offsets = getClientRect({\n    top: childrenRect.top - parentRect.top - borderTopWidth,\n    left: childrenRect.left - parentRect.left - borderLeftWidth,\n    width: childrenRect.width,\n    height: childrenRect.height\n  });\n  offsets.marginTop = 0;\n  offsets.marginLeft = 0;\n\n  // Subtract margins of documentElement in case it's being used as parent\n  // we do this only on HTML because it's the only element that behaves\n  // differently when margins are applied to it. The margins are included in\n  // the box of the documentElement, in the other cases not.\n  if (!isIE10 && isHTML) {\n    var marginTop = parseFloat(styles.marginTop, 10);\n    var marginLeft = parseFloat(styles.marginLeft, 10);\n\n    offsets.top -= borderTopWidth - marginTop;\n    offsets.bottom -= borderTopWidth - marginTop;\n    offsets.left -= borderLeftWidth - marginLeft;\n    offsets.right -= borderLeftWidth - marginLeft;\n\n    // Attach marginTop and marginLeft because in some circumstances we may need them\n    offsets.marginTop = marginTop;\n    offsets.marginLeft = marginLeft;\n  }\n\n  if (isIE10 && !fixedPosition ? parent.contains(scrollParent) : parent === scrollParent && scrollParent.nodeName !== 'BODY') {\n    offsets = includeScroll(offsets, parent);\n  }\n\n  return offsets;\n}\n\nfunction getViewportOffsetRectRelativeToArtbitraryNode(element) {\n  var excludeScroll = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;\n\n  var html = element.ownerDocument.documentElement;\n  var relativeOffset = getOffsetRectRelativeToArbitraryNode(element, html);\n  var width = Math.max(html.clientWidth, window.innerWidth || 0);\n  var height = Math.max(html.clientHeight, window.innerHeight || 0);\n\n  var scrollTop = !excludeScroll ? getScroll(html) : 0;\n  var scrollLeft = !excludeScroll ? getScroll(html, 'left') : 0;\n\n  var offset = {\n    top: scrollTop - relativeOffset.top + relativeOffset.marginTop,\n    left: scrollLeft - relativeOffset.left + relativeOffset.marginLeft,\n    width: width,\n    height: height\n  };\n\n  return getClientRect(offset);\n}\n\n/**\n * Check if the given element is fixed or is inside a fixed parent\n * @method\n * @memberof Popper.Utils\n * @argument {Element} element\n * @argument {Element} customContainer\n * @returns {Boolean} answer to \"isFixed?\"\n */\nfunction isFixed(element) {\n  var nodeName = element.nodeName;\n  if (nodeName === 'BODY' || nodeName === 'HTML') {\n    return false;\n  }\n  if (getStyleComputedProperty(element, 'position') === 'fixed') {\n    return true;\n  }\n  return isFixed(getParentNode(element));\n}\n\n/**\n * Finds the first parent of an element that has a transformed property defined\n * @method\n * @memberof Popper.Utils\n * @argument {Element} element\n * @returns {Element} first transformed parent or documentElement\n */\n\nfunction getFixedPositionOffsetParent(element) {\n  // This check is needed to avoid errors in case one of the elements isn't defined for any reason\n  if (!element || !element.parentElement || isIE()) {\n    return document.documentElement;\n  }\n  var el = element.parentElement;\n  while (el && getStyleComputedProperty(el, 'transform') === 'none') {\n    el = el.parentElement;\n  }\n  return el || document.documentElement;\n}\n\n/**\n * Computed the boundaries limits and return them\n * @method\n * @memberof Popper.Utils\n * @param {HTMLElement} popper\n * @param {HTMLElement} reference\n * @param {number} padding\n * @param {HTMLElement} boundariesElement - Element used to define the boundaries\n * @param {Boolean} fixedPosition - Is in fixed position mode\n * @returns {Object} Coordinates of the boundaries\n */\nfunction getBoundaries(popper, reference, padding, boundariesElement) {\n  var fixedPosition = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;\n\n  // NOTE: 1 DOM access here\n\n  var boundaries = { top: 0, left: 0 };\n  var offsetParent = fixedPosition ? getFixedPositionOffsetParent(popper) : findCommonOffsetParent(popper, reference);\n\n  // Handle viewport case\n  if (boundariesElement === 'viewport') {\n    boundaries = getViewportOffsetRectRelativeToArtbitraryNode(offsetParent, fixedPosition);\n  } else {\n    // Handle other cases based on DOM element used as boundaries\n    var boundariesNode = void 0;\n    if (boundariesElement === 'scrollParent') {\n      boundariesNode = getScrollParent(getParentNode(reference));\n      if (boundariesNode.nodeName === 'BODY') {\n        boundariesNode = popper.ownerDocument.documentElement;\n      }\n    } else if (boundariesElement === 'window') {\n      boundariesNode = popper.ownerDocument.documentElement;\n    } else {\n      boundariesNode = boundariesElement;\n    }\n\n    var offsets = getOffsetRectRelativeToArbitraryNode(boundariesNode, offsetParent, fixedPosition);\n\n    // In case of HTML, we need a different computation\n    if (boundariesNode.nodeName === 'HTML' && !isFixed(offsetParent)) {\n      var _getWindowSizes = getWindowSizes(),\n          height = _getWindowSizes.height,\n          width = _getWindowSizes.width;\n\n      boundaries.top += offsets.top - offsets.marginTop;\n      boundaries.bottom = height + offsets.top;\n      boundaries.left += offsets.left - offsets.marginLeft;\n      boundaries.right = width + offsets.left;\n    } else {\n      // for all the other DOM elements, this one is good\n      boundaries = offsets;\n    }\n  }\n\n  // Add paddings\n  boundaries.left += padding;\n  boundaries.top += padding;\n  boundaries.right -= padding;\n  boundaries.bottom -= padding;\n\n  return boundaries;\n}\n\nfunction getArea(_ref) {\n  var width = _ref.width,\n      height = _ref.height;\n\n  return width * height;\n}\n\n/**\n * Utility used to transform the `auto` placement to the placement with more\n * available space.\n * @method\n * @memberof Popper.Utils\n * @argument {Object} data - The data object generated by update method\n * @argument {Object} options - Modifiers configuration and options\n * @returns {Object} The data object, properly modified\n */\nfunction computeAutoPlacement(placement, refRect, popper, reference, boundariesElement) {\n  var padding = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 0;\n\n  if (placement.indexOf('auto') === -1) {\n    return placement;\n  }\n\n  var boundaries = getBoundaries(popper, reference, padding, boundariesElement);\n\n  var rects = {\n    top: {\n      width: boundaries.width,\n      height: refRect.top - boundaries.top\n    },\n    right: {\n      width: boundaries.right - refRect.right,\n      height: boundaries.height\n    },\n    bottom: {\n      width: boundaries.width,\n      height: boundaries.bottom - refRect.bottom\n    },\n    left: {\n      width: refRect.left - boundaries.left,\n      height: boundaries.height\n    }\n  };\n\n  var sortedAreas = Object.keys(rects).map(function (key) {\n    return _extends({\n      key: key\n    }, rects[key], {\n      area: getArea(rects[key])\n    });\n  }).sort(function (a, b) {\n    return b.area - a.area;\n  });\n\n  var filteredAreas = sortedAreas.filter(function (_ref2) {\n    var width = _ref2.width,\n        height = _ref2.height;\n    return width >= popper.clientWidth && height >= popper.clientHeight;\n  });\n\n  var computedPlacement = filteredAreas.length > 0 ? filteredAreas[0].key : sortedAreas[0].key;\n\n  var variation = placement.split('-')[1];\n\n  return computedPlacement + (variation ? '-' + variation : '');\n}\n\n/**\n * Get offsets to the reference element\n * @method\n * @memberof Popper.Utils\n * @param {Object} state\n * @param {Element} popper - the popper element\n * @param {Element} reference - the reference element (the popper will be relative to this)\n * @param {Element} fixedPosition - is in fixed position mode\n * @returns {Object} An object containing the offsets which will be applied to the popper\n */\nfunction getReferenceOffsets(state, popper, reference) {\n  var fixedPosition = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;\n\n  var commonOffsetParent = fixedPosition ? getFixedPositionOffsetParent(popper) : findCommonOffsetParent(popper, reference);\n  return getOffsetRectRelativeToArbitraryNode(reference, commonOffsetParent, fixedPosition);\n}\n\n/**\n * Get the outer sizes of the given element (offset size + margins)\n * @method\n * @memberof Popper.Utils\n * @argument {Element} element\n * @returns {Object} object containing width and height properties\n */\nfunction getOuterSizes(element) {\n  var styles = getComputedStyle(element);\n  var x = parseFloat(styles.marginTop) + parseFloat(styles.marginBottom);\n  var y = parseFloat(styles.marginLeft) + parseFloat(styles.marginRight);\n  var result = {\n    width: element.offsetWidth + y,\n    height: element.offsetHeight + x\n  };\n  return result;\n}\n\n/**\n * Get the opposite placement of the given one\n * @method\n * @memberof Popper.Utils\n * @argument {String} placement\n * @returns {String} flipped placement\n */\nfunction getOppositePlacement(placement) {\n  var hash = { left: 'right', right: 'left', bottom: 'top', top: 'bottom' };\n  return placement.replace(/left|right|bottom|top/g, function (matched) {\n    return hash[matched];\n  });\n}\n\n/**\n * Get offsets to the popper\n * @method\n * @memberof Popper.Utils\n * @param {Object} position - CSS position the Popper will get applied\n * @param {HTMLElement} popper - the popper element\n * @param {Object} referenceOffsets - the reference offsets (the popper will be relative to this)\n * @param {String} placement - one of the valid placement options\n * @returns {Object} popperOffsets - An object containing the offsets which will be applied to the popper\n */\nfunction getPopperOffsets(popper, referenceOffsets, placement) {\n  placement = placement.split('-')[0];\n\n  // Get popper node sizes\n  var popperRect = getOuterSizes(popper);\n\n  // Add position, width and height to our offsets object\n  var popperOffsets = {\n    width: popperRect.width,\n    height: popperRect.height\n  };\n\n  // depending by the popper placement we have to compute its offsets slightly differently\n  var isHoriz = ['right', 'left'].indexOf(placement) !== -1;\n  var mainSide = isHoriz ? 'top' : 'left';\n  var secondarySide = isHoriz ? 'left' : 'top';\n  var measurement = isHoriz ? 'height' : 'width';\n  var secondaryMeasurement = !isHoriz ? 'height' : 'width';\n\n  popperOffsets[mainSide] = referenceOffsets[mainSide] + referenceOffsets[measurement] / 2 - popperRect[measurement] / 2;\n  if (placement === secondarySide) {\n    popperOffsets[secondarySide] = referenceOffsets[secondarySide] - popperRect[secondaryMeasurement];\n  } else {\n    popperOffsets[secondarySide] = referenceOffsets[getOppositePlacement(secondarySide)];\n  }\n\n  return popperOffsets;\n}\n\n/**\n * Mimics the `find` method of Array\n * @method\n * @memberof Popper.Utils\n * @argument {Array} arr\n * @argument prop\n * @argument value\n * @returns index or -1\n */\nfunction find(arr, check) {\n  // use native find if supported\n  if (Array.prototype.find) {\n    return arr.find(check);\n  }\n\n  // use `filter` to obtain the same behavior of `find`\n  return arr.filter(check)[0];\n}\n\n/**\n * Return the index of the matching object\n * @method\n * @memberof Popper.Utils\n * @argument {Array} arr\n * @argument prop\n * @argument value\n * @returns index or -1\n */\nfunction findIndex(arr, prop, value) {\n  // use native findIndex if supported\n  if (Array.prototype.findIndex) {\n    return arr.findIndex(function (cur) {\n      return cur[prop] === value;\n    });\n  }\n\n  // use `find` + `indexOf` if `findIndex` isn't supported\n  var match = find(arr, function (obj) {\n    return obj[prop] === value;\n  });\n  return arr.indexOf(match);\n}\n\n/**\n * Loop trough the list of modifiers and run them in order,\n * each of them will then edit the data object.\n * @method\n * @memberof Popper.Utils\n * @param {dataObject} data\n * @param {Array} modifiers\n * @param {String} ends - Optional modifier name used as stopper\n * @returns {dataObject}\n */\nfunction runModifiers(modifiers, data, ends) {\n  var modifiersToRun = ends === undefined ? modifiers : modifiers.slice(0, findIndex(modifiers, 'name', ends));\n\n  modifiersToRun.forEach(function (modifier) {\n    if (modifier['function']) {\n      // eslint-disable-line dot-notation\n      console.warn('`modifier.function` is deprecated, use `modifier.fn`!');\n    }\n    var fn = modifier['function'] || modifier.fn; // eslint-disable-line dot-notation\n    if (modifier.enabled && isFunction(fn)) {\n      // Add properties to offsets to make them a complete clientRect object\n      // we do this before each modifier to make sure the previous one doesn't\n      // mess with these values\n      data.offsets.popper = getClientRect(data.offsets.popper);\n      data.offsets.reference = getClientRect(data.offsets.reference);\n\n      data = fn(data, modifier);\n    }\n  });\n\n  return data;\n}\n\n/**\n * Updates the position of the popper, computing the new offsets and applying\n * the new style.<br />\n * Prefer `scheduleUpdate` over `update` because of performance reasons.\n * @method\n * @memberof Popper\n */\nfunction update() {\n  // if popper is destroyed, don't perform any further update\n  if (this.state.isDestroyed) {\n    return;\n  }\n\n  var data = {\n    instance: this,\n    styles: {},\n    arrowStyles: {},\n    attributes: {},\n    flipped: false,\n    offsets: {}\n  };\n\n  // compute reference element offsets\n  data.offsets.reference = getReferenceOffsets(this.state, this.popper, this.reference, this.options.positionFixed);\n\n  // compute auto placement, store placement inside the data object,\n  // modifiers will be able to edit `placement` if needed\n  // and refer to originalPlacement to know the original value\n  data.placement = computeAutoPlacement(this.options.placement, data.offsets.reference, this.popper, this.reference, this.options.modifiers.flip.boundariesElement, this.options.modifiers.flip.padding);\n\n  // store the computed placement inside `originalPlacement`\n  data.originalPlacement = data.placement;\n\n  data.positionFixed = this.options.positionFixed;\n\n  // compute the popper offsets\n  data.offsets.popper = getPopperOffsets(this.popper, data.offsets.reference, data.placement);\n\n  data.offsets.popper.position = this.options.positionFixed ? 'fixed' : 'absolute';\n\n  // run the modifiers\n  data = runModifiers(this.modifiers, data);\n\n  // the first `update` will call `onCreate` callback\n  // the other ones will call `onUpdate` callback\n  if (!this.state.isCreated) {\n    this.state.isCreated = true;\n    this.options.onCreate(data);\n  } else {\n    this.options.onUpdate(data);\n  }\n}\n\n/**\n * Helper used to know if the given modifier is enabled.\n * @method\n * @memberof Popper.Utils\n * @returns {Boolean}\n */\nfunction isModifierEnabled(modifiers, modifierName) {\n  return modifiers.some(function (_ref) {\n    var name = _ref.name,\n        enabled = _ref.enabled;\n    return enabled && name === modifierName;\n  });\n}\n\n/**\n * Get the prefixed supported property name\n * @method\n * @memberof Popper.Utils\n * @argument {String} property (camelCase)\n * @returns {String} prefixed property (camelCase or PascalCase, depending on the vendor prefix)\n */\nfunction getSupportedPropertyName(property) {\n  var prefixes = [false, 'ms', 'Webkit', 'Moz', 'O'];\n  var upperProp = property.charAt(0).toUpperCase() + property.slice(1);\n\n  for (var i = 0; i < prefixes.length; i++) {\n    var prefix = prefixes[i];\n    var toCheck = prefix ? '' + prefix + upperProp : property;\n    if (typeof document.body.style[toCheck] !== 'undefined') {\n      return toCheck;\n    }\n  }\n  return null;\n}\n\n/**\n * Destroy the popper\n * @method\n * @memberof Popper\n */\nfunction destroy() {\n  this.state.isDestroyed = true;\n\n  // touch DOM only if `applyStyle` modifier is enabled\n  if (isModifierEnabled(this.modifiers, 'applyStyle')) {\n    this.popper.removeAttribute('x-placement');\n    this.popper.style.position = '';\n    this.popper.style.top = '';\n    this.popper.style.left = '';\n    this.popper.style.right = '';\n    this.popper.style.bottom = '';\n    this.popper.style.willChange = '';\n    this.popper.style[getSupportedPropertyName('transform')] = '';\n  }\n\n  this.disableEventListeners();\n\n  // remove the popper if user explicity asked for the deletion on destroy\n  // do not use `remove` because IE11 doesn't support it\n  if (this.options.removeOnDestroy) {\n    this.popper.parentNode.removeChild(this.popper);\n  }\n  return this;\n}\n\n/**\n * Get the window associated with the element\n * @argument {Element} element\n * @returns {Window}\n */\nfunction getWindow(element) {\n  var ownerDocument = element.ownerDocument;\n  return ownerDocument && ownerDocument.defaultView ? ownerDocument.defaultView : window;\n}\n\nfunction attachToScrollParents(scrollParent, event, callback, scrollParents) {\n  var isBody = scrollParent.nodeName === 'BODY';\n  var target = isBody ? scrollParent.ownerDocument.defaultView : scrollParent;\n  target.addEventListener(event, callback, { passive: true });\n\n  if (!isBody) {\n    attachToScrollParents(getScrollParent(target.parentNode), event, callback, scrollParents);\n  }\n  scrollParents.push(target);\n}\n\n/**\n * Setup needed event listeners used to update the popper position\n * @method\n * @memberof Popper.Utils\n * @private\n */\nfunction setupEventListeners(reference, options, state, updateBound) {\n  // Resize event listener on window\n  state.updateBound = updateBound;\n  getWindow(reference).addEventListener('resize', state.updateBound, { passive: true });\n\n  // Scroll event listener on scroll parents\n  var scrollElement = getScrollParent(reference);\n  attachToScrollParents(scrollElement, 'scroll', state.updateBound, state.scrollParents);\n  state.scrollElement = scrollElement;\n  state.eventsEnabled = true;\n\n  return state;\n}\n\n/**\n * It will add resize/scroll events and start recalculating\n * position of the popper element when they are triggered.\n * @method\n * @memberof Popper\n */\nfunction enableEventListeners() {\n  if (!this.state.eventsEnabled) {\n    this.state = setupEventListeners(this.reference, this.options, this.state, this.scheduleUpdate);\n  }\n}\n\n/**\n * Remove event listeners used to update the popper position\n * @method\n * @memberof Popper.Utils\n * @private\n */\nfunction removeEventListeners(reference, state) {\n  // Remove resize event listener on window\n  getWindow(reference).removeEventListener('resize', state.updateBound);\n\n  // Remove scroll event listener on scroll parents\n  state.scrollParents.forEach(function (target) {\n    target.removeEventListener('scroll', state.updateBound);\n  });\n\n  // Reset state\n  state.updateBound = null;\n  state.scrollParents = [];\n  state.scrollElement = null;\n  state.eventsEnabled = false;\n  return state;\n}\n\n/**\n * It will remove resize/scroll events and won't recalculate popper position\n * when they are triggered. It also won't trigger onUpdate callback anymore,\n * unless you call `update` method manually.\n * @method\n * @memberof Popper\n */\nfunction disableEventListeners() {\n  if (this.state.eventsEnabled) {\n    cancelAnimationFrame(this.scheduleUpdate);\n    this.state = removeEventListeners(this.reference, this.state);\n  }\n}\n\n/**\n * Tells if a given input is a number\n * @method\n * @memberof Popper.Utils\n * @param {*} input to check\n * @return {Boolean}\n */\nfunction isNumeric(n) {\n  return n !== '' && !isNaN(parseFloat(n)) && isFinite(n);\n}\n\n/**\n * Set the style to the given popper\n * @method\n * @memberof Popper.Utils\n * @argument {Element} element - Element to apply the style to\n * @argument {Object} styles\n * Object with a list of properties and values which will be applied to the element\n */\nfunction setStyles(element, styles) {\n  Object.keys(styles).forEach(function (prop) {\n    var unit = '';\n    // add unit if the value is numeric and is one of the following\n    if (['width', 'height', 'top', 'right', 'bottom', 'left'].indexOf(prop) !== -1 && isNumeric(styles[prop])) {\n      unit = 'px';\n    }\n    element.style[prop] = styles[prop] + unit;\n  });\n}\n\n/**\n * Set the attributes to the given popper\n * @method\n * @memberof Popper.Utils\n * @argument {Element} element - Element to apply the attributes to\n * @argument {Object} styles\n * Object with a list of properties and values which will be applied to the element\n */\nfunction setAttributes(element, attributes) {\n  Object.keys(attributes).forEach(function (prop) {\n    var value = attributes[prop];\n    if (value !== false) {\n      element.setAttribute(prop, attributes[prop]);\n    } else {\n      element.removeAttribute(prop);\n    }\n  });\n}\n\n/**\n * @function\n * @memberof Modifiers\n * @argument {Object} data - The data object generated by `update` method\n * @argument {Object} data.styles - List of style properties - values to apply to popper element\n * @argument {Object} data.attributes - List of attribute properties - values to apply to popper element\n * @argument {Object} options - Modifiers configuration and options\n * @returns {Object} The same data object\n */\nfunction applyStyle(data) {\n  // any property present in `data.styles` will be applied to the popper,\n  // in this way we can make the 3rd party modifiers add custom styles to it\n  // Be aware, modifiers could override the properties defined in the previous\n  // lines of this modifier!\n  setStyles(data.instance.popper, data.styles);\n\n  // any property present in `data.attributes` will be applied to the popper,\n  // they will be set as HTML attributes of the element\n  setAttributes(data.instance.popper, data.attributes);\n\n  // if arrowElement is defined and arrowStyles has some properties\n  if (data.arrowElement && Object.keys(data.arrowStyles).length) {\n    setStyles(data.arrowElement, data.arrowStyles);\n  }\n\n  return data;\n}\n\n/**\n * Set the x-placement attribute before everything else because it could be used\n * to add margins to the popper margins needs to be calculated to get the\n * correct popper offsets.\n * @method\n * @memberof Popper.modifiers\n * @param {HTMLElement} reference - The reference element used to position the popper\n * @param {HTMLElement} popper - The HTML element used as popper\n * @param {Object} options - Popper.js options\n */\nfunction applyStyleOnLoad(reference, popper, options, modifierOptions, state) {\n  // compute reference element offsets\n  var referenceOffsets = getReferenceOffsets(state, popper, reference, options.positionFixed);\n\n  // compute auto placement, store placement inside the data object,\n  // modifiers will be able to edit `placement` if needed\n  // and refer to originalPlacement to know the original value\n  var placement = computeAutoPlacement(options.placement, referenceOffsets, popper, reference, options.modifiers.flip.boundariesElement, options.modifiers.flip.padding);\n\n  popper.setAttribute('x-placement', placement);\n\n  // Apply `position` to popper before anything else because\n  // without the position applied we can't guarantee correct computations\n  setStyles(popper, { position: options.positionFixed ? 'fixed' : 'absolute' });\n\n  return options;\n}\n\n/**\n * @function\n * @memberof Modifiers\n * @argument {Object} data - The data object generated by `update` method\n * @argument {Object} options - Modifiers configuration and options\n * @returns {Object} The data object, properly modified\n */\nfunction computeStyle(data, options) {\n  var x = options.x,\n      y = options.y;\n  var popper = data.offsets.popper;\n\n  // Remove this legacy support in Popper.js v2\n\n  var legacyGpuAccelerationOption = find(data.instance.modifiers, function (modifier) {\n    return modifier.name === 'applyStyle';\n  }).gpuAcceleration;\n  if (legacyGpuAccelerationOption !== undefined) {\n    console.warn('WARNING: `gpuAcceleration` option moved to `computeStyle` modifier and will not be supported in future versions of Popper.js!');\n  }\n  var gpuAcceleration = legacyGpuAccelerationOption !== undefined ? legacyGpuAccelerationOption : options.gpuAcceleration;\n\n  var offsetParent = getOffsetParent(data.instance.popper);\n  var offsetParentRect = getBoundingClientRect(offsetParent);\n\n  // Styles\n  var styles = {\n    position: popper.position\n  };\n\n  // Avoid blurry text by using full pixel integers.\n  // For pixel-perfect positioning, top/bottom prefers rounded\n  // values, while left/right prefers floored values.\n  var offsets = {\n    left: Math.floor(popper.left),\n    top: Math.round(popper.top),\n    bottom: Math.round(popper.bottom),\n    right: Math.floor(popper.right)\n  };\n\n  var sideA = x === 'bottom' ? 'top' : 'bottom';\n  var sideB = y === 'right' ? 'left' : 'right';\n\n  // if gpuAcceleration is set to `true` and transform is supported,\n  //  we use `translate3d` to apply the position to the popper we\n  // automatically use the supported prefixed version if needed\n  var prefixedProperty = getSupportedPropertyName('transform');\n\n  // now, let's make a step back and look at this code closely (wtf?)\n  // If the content of the popper grows once it's been positioned, it\n  // may happen that the popper gets misplaced because of the new content\n  // overflowing its reference element\n  // To avoid this problem, we provide two options (x and y), which allow\n  // the consumer to define the offset origin.\n  // If we position a popper on top of a reference element, we can set\n  // `x` to `top` to make the popper grow towards its top instead of\n  // its bottom.\n  var left = void 0,\n      top = void 0;\n  if (sideA === 'bottom') {\n    top = -offsetParentRect.height + offsets.bottom;\n  } else {\n    top = offsets.top;\n  }\n  if (sideB === 'right') {\n    left = -offsetParentRect.width + offsets.right;\n  } else {\n    left = offsets.left;\n  }\n  if (gpuAcceleration && prefixedProperty) {\n    styles[prefixedProperty] = 'translate3d(' + left + 'px, ' + top + 'px, 0)';\n    styles[sideA] = 0;\n    styles[sideB] = 0;\n    styles.willChange = 'transform';\n  } else {\n    // othwerise, we use the standard `top`, `left`, `bottom` and `right` properties\n    var invertTop = sideA === 'bottom' ? -1 : 1;\n    var invertLeft = sideB === 'right' ? -1 : 1;\n    styles[sideA] = top * invertTop;\n    styles[sideB] = left * invertLeft;\n    styles.willChange = sideA + ', ' + sideB;\n  }\n\n  // Attributes\n  var attributes = {\n    'x-placement': data.placement\n  };\n\n  // Update `data` attributes, styles and arrowStyles\n  data.attributes = _extends({}, attributes, data.attributes);\n  data.styles = _extends({}, styles, data.styles);\n  data.arrowStyles = _extends({}, data.offsets.arrow, data.arrowStyles);\n\n  return data;\n}\n\n/**\n * Helper used to know if the given modifier depends from another one.<br />\n * It checks if the needed modifier is listed and enabled.\n * @method\n * @memberof Popper.Utils\n * @param {Array} modifiers - list of modifiers\n * @param {String} requestingName - name of requesting modifier\n * @param {String} requestedName - name of requested modifier\n * @returns {Boolean}\n */\nfunction isModifierRequired(modifiers, requestingName, requestedName) {\n  var requesting = find(modifiers, function (_ref) {\n    var name = _ref.name;\n    return name === requestingName;\n  });\n\n  var isRequired = !!requesting && modifiers.some(function (modifier) {\n    return modifier.name === requestedName && modifier.enabled && modifier.order < requesting.order;\n  });\n\n  if (!isRequired) {\n    var _requesting = '`' + requestingName + '`';\n    var requested = '`' + requestedName + '`';\n    console.warn(requested + ' modifier is required by ' + _requesting + ' modifier in order to work, be sure to include it before ' + _requesting + '!');\n  }\n  return isRequired;\n}\n\n/**\n * @function\n * @memberof Modifiers\n * @argument {Object} data - The data object generated by update method\n * @argument {Object} options - Modifiers configuration and options\n * @returns {Object} The data object, properly modified\n */\nfunction arrow(data, options) {\n  var _data$offsets$arrow;\n\n  // arrow depends on keepTogether in order to work\n  if (!isModifierRequired(data.instance.modifiers, 'arrow', 'keepTogether')) {\n    return data;\n  }\n\n  var arrowElement = options.element;\n\n  // if arrowElement is a string, suppose it's a CSS selector\n  if (typeof arrowElement === 'string') {\n    arrowElement = data.instance.popper.querySelector(arrowElement);\n\n    // if arrowElement is not found, don't run the modifier\n    if (!arrowElement) {\n      return data;\n    }\n  } else {\n    // if the arrowElement isn't a query selector we must check that the\n    // provided DOM node is child of its popper node\n    if (!data.instance.popper.contains(arrowElement)) {\n      console.warn('WARNING: `arrow.element` must be child of its popper element!');\n      return data;\n    }\n  }\n\n  var placement = data.placement.split('-')[0];\n  var _data$offsets = data.offsets,\n      popper = _data$offsets.popper,\n      reference = _data$offsets.reference;\n\n  var isVertical = ['left', 'right'].indexOf(placement) !== -1;\n\n  var len = isVertical ? 'height' : 'width';\n  var sideCapitalized = isVertical ? 'Top' : 'Left';\n  var side = sideCapitalized.toLowerCase();\n  var altSide = isVertical ? 'left' : 'top';\n  var opSide = isVertical ? 'bottom' : 'right';\n  var arrowElementSize = getOuterSizes(arrowElement)[len];\n\n  //\n  // extends keepTogether behavior making sure the popper and its\n  // reference have enough pixels in conjuction\n  //\n\n  // top/left side\n  if (reference[opSide] - arrowElementSize < popper[side]) {\n    data.offsets.popper[side] -= popper[side] - (reference[opSide] - arrowElementSize);\n  }\n  // bottom/right side\n  if (reference[side] + arrowElementSize > popper[opSide]) {\n    data.offsets.popper[side] += reference[side] + arrowElementSize - popper[opSide];\n  }\n  data.offsets.popper = getClientRect(data.offsets.popper);\n\n  // compute center of the popper\n  var center = reference[side] + reference[len] / 2 - arrowElementSize / 2;\n\n  // Compute the sideValue using the updated popper offsets\n  // take popper margin in account because we don't have this info available\n  var css = getStyleComputedProperty(data.instance.popper);\n  var popperMarginSide = parseFloat(css['margin' + sideCapitalized], 10);\n  var popperBorderSide = parseFloat(css['border' + sideCapitalized + 'Width'], 10);\n  var sideValue = center - data.offsets.popper[side] - popperMarginSide - popperBorderSide;\n\n  // prevent arrowElement from being placed not contiguously to its popper\n  sideValue = Math.max(Math.min(popper[len] - arrowElementSize, sideValue), 0);\n\n  data.arrowElement = arrowElement;\n  data.offsets.arrow = (_data$offsets$arrow = {}, defineProperty(_data$offsets$arrow, side, Math.round(sideValue)), defineProperty(_data$offsets$arrow, altSide, ''), _data$offsets$arrow);\n\n  return data;\n}\n\n/**\n * Get the opposite placement variation of the given one\n * @method\n * @memberof Popper.Utils\n * @argument {String} placement variation\n * @returns {String} flipped placement variation\n */\nfunction getOppositeVariation(variation) {\n  if (variation === 'end') {\n    return 'start';\n  } else if (variation === 'start') {\n    return 'end';\n  }\n  return variation;\n}\n\n/**\n * List of accepted placements to use as values of the `placement` option.<br />\n * Valid placements are:\n * - `auto`\n * - `top`\n * - `right`\n * - `bottom`\n * - `left`\n *\n * Each placement can have a variation from this list:\n * - `-start`\n * - `-end`\n *\n * Variations are interpreted easily if you think of them as the left to right\n * written languages. Horizontally (`top` and `bottom`), `start` is left and `end`\n * is right.<br />\n * Vertically (`left` and `right`), `start` is top and `end` is bottom.\n *\n * Some valid examples are:\n * - `top-end` (on top of reference, right aligned)\n * - `right-start` (on right of reference, top aligned)\n * - `bottom` (on bottom, centered)\n * - `auto-right` (on the side with more space available, alignment depends by placement)\n *\n * @static\n * @type {Array}\n * @enum {String}\n * @readonly\n * @method placements\n * @memberof Popper\n */\nvar placements = ['auto-start', 'auto', 'auto-end', 'top-start', 'top', 'top-end', 'right-start', 'right', 'right-end', 'bottom-end', 'bottom', 'bottom-start', 'left-end', 'left', 'left-start'];\n\n// Get rid of `auto` `auto-start` and `auto-end`\nvar validPlacements = placements.slice(3);\n\n/**\n * Given an initial placement, returns all the subsequent placements\n * clockwise (or counter-clockwise).\n *\n * @method\n * @memberof Popper.Utils\n * @argument {String} placement - A valid placement (it accepts variations)\n * @argument {Boolean} counter - Set to true to walk the placements counterclockwise\n * @returns {Array} placements including their variations\n */\nfunction clockwise(placement) {\n  var counter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;\n\n  var index = validPlacements.indexOf(placement);\n  var arr = validPlacements.slice(index + 1).concat(validPlacements.slice(0, index));\n  return counter ? arr.reverse() : arr;\n}\n\nvar BEHAVIORS = {\n  FLIP: 'flip',\n  CLOCKWISE: 'clockwise',\n  COUNTERCLOCKWISE: 'counterclockwise'\n};\n\n/**\n * @function\n * @memberof Modifiers\n * @argument {Object} data - The data object generated by update method\n * @argument {Object} options - Modifiers configuration and options\n * @returns {Object} The data object, properly modified\n */\nfunction flip(data, options) {\n  // if `inner` modifier is enabled, we can't use the `flip` modifier\n  if (isModifierEnabled(data.instance.modifiers, 'inner')) {\n    return data;\n  }\n\n  if (data.flipped && data.placement === data.originalPlacement) {\n    // seems like flip is trying to loop, probably there's not enough space on any of the flippable sides\n    return data;\n  }\n\n  var boundaries = getBoundaries(data.instance.popper, data.instance.reference, options.padding, options.boundariesElement, data.positionFixed);\n\n  var placement = data.placement.split('-')[0];\n  var placementOpposite = getOppositePlacement(placement);\n  var variation = data.placement.split('-')[1] || '';\n\n  var flipOrder = [];\n\n  switch (options.behavior) {\n    case BEHAVIORS.FLIP:\n      flipOrder = [placement, placementOpposite];\n      break;\n    case BEHAVIORS.CLOCKWISE:\n      flipOrder = clockwise(placement);\n      break;\n    case BEHAVIORS.COUNTERCLOCKWISE:\n      flipOrder = clockwise(placement, true);\n      break;\n    default:\n      flipOrder = options.behavior;\n  }\n\n  flipOrder.forEach(function (step, index) {\n    if (placement !== step || flipOrder.length === index + 1) {\n      return data;\n    }\n\n    placement = data.placement.split('-')[0];\n    placementOpposite = getOppositePlacement(placement);\n\n    var popperOffsets = data.offsets.popper;\n    var refOffsets = data.offsets.reference;\n\n    // using floor because the reference offsets may contain decimals we are not going to consider here\n    var floor = Math.floor;\n    var overlapsRef = placement === 'left' && floor(popperOffsets.right) > floor(refOffsets.left) || placement === 'right' && floor(popperOffsets.left) < floor(refOffsets.right) || placement === 'top' && floor(popperOffsets.bottom) > floor(refOffsets.top) || placement === 'bottom' && floor(popperOffsets.top) < floor(refOffsets.bottom);\n\n    var overflowsLeft = floor(popperOffsets.left) < floor(boundaries.left);\n    var overflowsRight = floor(popperOffsets.right) > floor(boundaries.right);\n    var overflowsTop = floor(popperOffsets.top) < floor(boundaries.top);\n    var overflowsBottom = floor(popperOffsets.bottom) > floor(boundaries.bottom);\n\n    var overflowsBoundaries = placement === 'left' && overflowsLeft || placement === 'right' && overflowsRight || placement === 'top' && overflowsTop || placement === 'bottom' && overflowsBottom;\n\n    // flip the variation if required\n    var isVertical = ['top', 'bottom'].indexOf(placement) !== -1;\n    var flippedVariation = !!options.flipVariations && (isVertical && variation === 'start' && overflowsLeft || isVertical && variation === 'end' && overflowsRight || !isVertical && variation === 'start' && overflowsTop || !isVertical && variation === 'end' && overflowsBottom);\n\n    if (overlapsRef || overflowsBoundaries || flippedVariation) {\n      // this boolean to detect any flip loop\n      data.flipped = true;\n\n      if (overlapsRef || overflowsBoundaries) {\n        placement = flipOrder[index + 1];\n      }\n\n      if (flippedVariation) {\n        variation = getOppositeVariation(variation);\n      }\n\n      data.placement = placement + (variation ? '-' + variation : '');\n\n      // this object contains `position`, we want to preserve it along with\n      // any additional property we may add in the future\n      data.offsets.popper = _extends({}, data.offsets.popper, getPopperOffsets(data.instance.popper, data.offsets.reference, data.placement));\n\n      data = runModifiers(data.instance.modifiers, data, 'flip');\n    }\n  });\n  return data;\n}\n\n/**\n * @function\n * @memberof Modifiers\n * @argument {Object} data - The data object generated by update method\n * @argument {Object} options - Modifiers configuration and options\n * @returns {Object} The data object, properly modified\n */\nfunction keepTogether(data) {\n  var _data$offsets = data.offsets,\n      popper = _data$offsets.popper,\n      reference = _data$offsets.reference;\n\n  var placement = data.placement.split('-')[0];\n  var floor = Math.floor;\n  var isVertical = ['top', 'bottom'].indexOf(placement) !== -1;\n  var side = isVertical ? 'right' : 'bottom';\n  var opSide = isVertical ? 'left' : 'top';\n  var measurement = isVertical ? 'width' : 'height';\n\n  if (popper[side] < floor(reference[opSide])) {\n    data.offsets.popper[opSide] = floor(reference[opSide]) - popper[measurement];\n  }\n  if (popper[opSide] > floor(reference[side])) {\n    data.offsets.popper[opSide] = floor(reference[side]);\n  }\n\n  return data;\n}\n\n/**\n * Converts a string containing value + unit into a px value number\n * @function\n * @memberof {modifiers~offset}\n * @private\n * @argument {String} str - Value + unit string\n * @argument {String} measurement - `height` or `width`\n * @argument {Object} popperOffsets\n * @argument {Object} referenceOffsets\n * @returns {Number|String}\n * Value in pixels, or original string if no values were extracted\n */\nfunction toValue(str, measurement, popperOffsets, referenceOffsets) {\n  // separate value from unit\n  var split = str.match(/((?:\\-|\\+)?\\d*\\.?\\d*)(.*)/);\n  var value = +split[1];\n  var unit = split[2];\n\n  // If it's not a number it's an operator, I guess\n  if (!value) {\n    return str;\n  }\n\n  if (unit.indexOf('%') === 0) {\n    var element = void 0;\n    switch (unit) {\n      case '%p':\n        element = popperOffsets;\n        break;\n      case '%':\n      case '%r':\n      default:\n        element = referenceOffsets;\n    }\n\n    var rect = getClientRect(element);\n    return rect[measurement] / 100 * value;\n  } else if (unit === 'vh' || unit === 'vw') {\n    // if is a vh or vw, we calculate the size based on the viewport\n    var size = void 0;\n    if (unit === 'vh') {\n      size = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);\n    } else {\n      size = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);\n    }\n    return size / 100 * value;\n  } else {\n    // if is an explicit pixel unit, we get rid of the unit and keep the value\n    // if is an implicit unit, it's px, and we return just the value\n    return value;\n  }\n}\n\n/**\n * Parse an `offset` string to extrapolate `x` and `y` numeric offsets.\n * @function\n * @memberof {modifiers~offset}\n * @private\n * @argument {String} offset\n * @argument {Object} popperOffsets\n * @argument {Object} referenceOffsets\n * @argument {String} basePlacement\n * @returns {Array} a two cells array with x and y offsets in numbers\n */\nfunction parseOffset(offset, popperOffsets, referenceOffsets, basePlacement) {\n  var offsets = [0, 0];\n\n  // Use height if placement is left or right and index is 0 otherwise use width\n  // in this way the first offset will use an axis and the second one\n  // will use the other one\n  var useHeight = ['right', 'left'].indexOf(basePlacement) !== -1;\n\n  // Split the offset string to obtain a list of values and operands\n  // The regex addresses values with the plus or minus sign in front (+10, -20, etc)\n  var fragments = offset.split(/(\\+|\\-)/).map(function (frag) {\n    return frag.trim();\n  });\n\n  // Detect if the offset string contains a pair of values or a single one\n  // they could be separated by comma or space\n  var divider = fragments.indexOf(find(fragments, function (frag) {\n    return frag.search(/,|\\s/) !== -1;\n  }));\n\n  if (fragments[divider] && fragments[divider].indexOf(',') === -1) {\n    console.warn('Offsets separated by white space(s) are deprecated, use a comma (,) instead.');\n  }\n\n  // If divider is found, we divide the list of values and operands to divide\n  // them by ofset X and Y.\n  var splitRegex = /\\s*,\\s*|\\s+/;\n  var ops = divider !== -1 ? [fragments.slice(0, divider).concat([fragments[divider].split(splitRegex)[0]]), [fragments[divider].split(splitRegex)[1]].concat(fragments.slice(divider + 1))] : [fragments];\n\n  // Convert the values with units to absolute pixels to allow our computations\n  ops = ops.map(function (op, index) {\n    // Most of the units rely on the orientation of the popper\n    var measurement = (index === 1 ? !useHeight : useHeight) ? 'height' : 'width';\n    var mergeWithPrevious = false;\n    return op\n    // This aggregates any `+` or `-` sign that aren't considered operators\n    // e.g.: 10 + +5 => [10, +, +5]\n    .reduce(function (a, b) {\n      if (a[a.length - 1] === '' && ['+', '-'].indexOf(b) !== -1) {\n        a[a.length - 1] = b;\n        mergeWithPrevious = true;\n        return a;\n      } else if (mergeWithPrevious) {\n        a[a.length - 1] += b;\n        mergeWithPrevious = false;\n        return a;\n      } else {\n        return a.concat(b);\n      }\n    }, [])\n    // Here we convert the string values into number values (in px)\n    .map(function (str) {\n      return toValue(str, measurement, popperOffsets, referenceOffsets);\n    });\n  });\n\n  // Loop trough the offsets arrays and execute the operations\n  ops.forEach(function (op, index) {\n    op.forEach(function (frag, index2) {\n      if (isNumeric(frag)) {\n        offsets[index] += frag * (op[index2 - 1] === '-' ? -1 : 1);\n      }\n    });\n  });\n  return offsets;\n}\n\n/**\n * @function\n * @memberof Modifiers\n * @argument {Object} data - The data object generated by update method\n * @argument {Object} options - Modifiers configuration and options\n * @argument {Number|String} options.offset=0\n * The offset value as described in the modifier description\n * @returns {Object} The data object, properly modified\n */\nfunction offset(data, _ref) {\n  var offset = _ref.offset;\n  var placement = data.placement,\n      _data$offsets = data.offsets,\n      popper = _data$offsets.popper,\n      reference = _data$offsets.reference;\n\n  var basePlacement = placement.split('-')[0];\n\n  var offsets = void 0;\n  if (isNumeric(+offset)) {\n    offsets = [+offset, 0];\n  } else {\n    offsets = parseOffset(offset, popper, reference, basePlacement);\n  }\n\n  if (basePlacement === 'left') {\n    popper.top += offsets[0];\n    popper.left -= offsets[1];\n  } else if (basePlacement === 'right') {\n    popper.top += offsets[0];\n    popper.left += offsets[1];\n  } else if (basePlacement === 'top') {\n    popper.left += offsets[0];\n    popper.top -= offsets[1];\n  } else if (basePlacement === 'bottom') {\n    popper.left += offsets[0];\n    popper.top += offsets[1];\n  }\n\n  data.popper = popper;\n  return data;\n}\n\n/**\n * @function\n * @memberof Modifiers\n * @argument {Object} data - The data object generated by `update` method\n * @argument {Object} options - Modifiers configuration and options\n * @returns {Object} The data object, properly modified\n */\nfunction preventOverflow(data, options) {\n  var boundariesElement = options.boundariesElement || getOffsetParent(data.instance.popper);\n\n  // If offsetParent is the reference element, we really want to\n  // go one step up and use the next offsetParent as reference to\n  // avoid to make this modifier completely useless and look like broken\n  if (data.instance.reference === boundariesElement) {\n    boundariesElement = getOffsetParent(boundariesElement);\n  }\n\n  // NOTE: DOM access here\n  // resets the popper's position so that the document size can be calculated excluding\n  // the size of the popper element itself\n  var transformProp = getSupportedPropertyName('transform');\n  var popperStyles = data.instance.popper.style; // assignment to help minification\n  var top = popperStyles.top,\n      left = popperStyles.left,\n      transform = popperStyles[transformProp];\n\n  popperStyles.top = '';\n  popperStyles.left = '';\n  popperStyles[transformProp] = '';\n\n  var boundaries = getBoundaries(data.instance.popper, data.instance.reference, options.padding, boundariesElement, data.positionFixed);\n\n  // NOTE: DOM access here\n  // restores the original style properties after the offsets have been computed\n  popperStyles.top = top;\n  popperStyles.left = left;\n  popperStyles[transformProp] = transform;\n\n  options.boundaries = boundaries;\n\n  var order = options.priority;\n  var popper = data.offsets.popper;\n\n  var check = {\n    primary: function primary(placement) {\n      var value = popper[placement];\n      if (popper[placement] < boundaries[placement] && !options.escapeWithReference) {\n        value = Math.max(popper[placement], boundaries[placement]);\n      }\n      return defineProperty({}, placement, value);\n    },\n    secondary: function secondary(placement) {\n      var mainSide = placement === 'right' ? 'left' : 'top';\n      var value = popper[mainSide];\n      if (popper[placement] > boundaries[placement] && !options.escapeWithReference) {\n        value = Math.min(popper[mainSide], boundaries[placement] - (placement === 'right' ? popper.width : popper.height));\n      }\n      return defineProperty({}, mainSide, value);\n    }\n  };\n\n  order.forEach(function (placement) {\n    var side = ['left', 'top'].indexOf(placement) !== -1 ? 'primary' : 'secondary';\n    popper = _extends({}, popper, check[side](placement));\n  });\n\n  data.offsets.popper = popper;\n\n  return data;\n}\n\n/**\n * @function\n * @memberof Modifiers\n * @argument {Object} data - The data object generated by `update` method\n * @argument {Object} options - Modifiers configuration and options\n * @returns {Object} The data object, properly modified\n */\nfunction shift(data) {\n  var placement = data.placement;\n  var basePlacement = placement.split('-')[0];\n  var shiftvariation = placement.split('-')[1];\n\n  // if shift shiftvariation is specified, run the modifier\n  if (shiftvariation) {\n    var _data$offsets = data.offsets,\n        reference = _data$offsets.reference,\n        popper = _data$offsets.popper;\n\n    var isVertical = ['bottom', 'top'].indexOf(basePlacement) !== -1;\n    var side = isVertical ? 'left' : 'top';\n    var measurement = isVertical ? 'width' : 'height';\n\n    var shiftOffsets = {\n      start: defineProperty({}, side, reference[side]),\n      end: defineProperty({}, side, reference[side] + reference[measurement] - popper[measurement])\n    };\n\n    data.offsets.popper = _extends({}, popper, shiftOffsets[shiftvariation]);\n  }\n\n  return data;\n}\n\n/**\n * @function\n * @memberof Modifiers\n * @argument {Object} data - The data object generated by update method\n * @argument {Object} options - Modifiers configuration and options\n * @returns {Object} The data object, properly modified\n */\nfunction hide(data) {\n  if (!isModifierRequired(data.instance.modifiers, 'hide', 'preventOverflow')) {\n    return data;\n  }\n\n  var refRect = data.offsets.reference;\n  var bound = find(data.instance.modifiers, function (modifier) {\n    return modifier.name === 'preventOverflow';\n  }).boundaries;\n\n  if (refRect.bottom < bound.top || refRect.left > bound.right || refRect.top > bound.bottom || refRect.right < bound.left) {\n    // Avoid unnecessary DOM access if visibility hasn't changed\n    if (data.hide === true) {\n      return data;\n    }\n\n    data.hide = true;\n    data.attributes['x-out-of-boundaries'] = '';\n  } else {\n    // Avoid unnecessary DOM access if visibility hasn't changed\n    if (data.hide === false) {\n      return data;\n    }\n\n    data.hide = false;\n    data.attributes['x-out-of-boundaries'] = false;\n  }\n\n  return data;\n}\n\n/**\n * @function\n * @memberof Modifiers\n * @argument {Object} data - The data object generated by `update` method\n * @argument {Object} options - Modifiers configuration and options\n * @returns {Object} The data object, properly modified\n */\nfunction inner(data) {\n  var placement = data.placement;\n  var basePlacement = placement.split('-')[0];\n  var _data$offsets = data.offsets,\n      popper = _data$offsets.popper,\n      reference = _data$offsets.reference;\n\n  var isHoriz = ['left', 'right'].indexOf(basePlacement) !== -1;\n\n  var subtractLength = ['top', 'left'].indexOf(basePlacement) === -1;\n\n  popper[isHoriz ? 'left' : 'top'] = reference[basePlacement] - (subtractLength ? popper[isHoriz ? 'width' : 'height'] : 0);\n\n  data.placement = getOppositePlacement(placement);\n  data.offsets.popper = getClientRect(popper);\n\n  return data;\n}\n\n/**\n * Modifier function, each modifier can have a function of this type assigned\n * to its `fn` property.<br />\n * These functions will be called on each update, this means that you must\n * make sure they are performant enough to avoid performance bottlenecks.\n *\n * @function ModifierFn\n * @argument {dataObject} data - The data object generated by `update` method\n * @argument {Object} options - Modifiers configuration and options\n * @returns {dataObject} The data object, properly modified\n */\n\n/**\n * Modifiers are plugins used to alter the behavior of your poppers.<br />\n * Popper.js uses a set of 9 modifiers to provide all the basic functionalities\n * needed by the library.\n *\n * Usually you don't want to override the `order`, `fn` and `onLoad` props.\n * All the other properties are configurations that could be tweaked.\n * @namespace modifiers\n */\nvar modifiers = {\n  /**\n   * Modifier used to shift the popper on the start or end of its reference\n   * element.<br />\n   * It will read the variation of the `placement` property.<br />\n   * It can be one either `-end` or `-start`.\n   * @memberof modifiers\n   * @inner\n   */\n  shift: {\n    /** @prop {number} order=100 - Index used to define the order of execution */\n    order: 100,\n    /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */\n    enabled: true,\n    /** @prop {ModifierFn} */\n    fn: shift\n  },\n\n  /**\n   * The `offset` modifier can shift your popper on both its axis.\n   *\n   * It accepts the following units:\n   * - `px` or unitless, interpreted as pixels\n   * - `%` or `%r`, percentage relative to the length of the reference element\n   * - `%p`, percentage relative to the length of the popper element\n   * - `vw`, CSS viewport width unit\n   * - `vh`, CSS viewport height unit\n   *\n   * For length is intended the main axis relative to the placement of the popper.<br />\n   * This means that if the placement is `top` or `bottom`, the length will be the\n   * `width`. In case of `left` or `right`, it will be the height.\n   *\n   * You can provide a single value (as `Number` or `String`), or a pair of values\n   * as `String` divided by a comma or one (or more) white spaces.<br />\n   * The latter is a deprecated method because it leads to confusion and will be\n   * removed in v2.<br />\n   * Additionally, it accepts additions and subtractions between different units.\n   * Note that multiplications and divisions aren't supported.\n   *\n   * Valid examples are:\n   * ```\n   * 10\n   * '10%'\n   * '10, 10'\n   * '10%, 10'\n   * '10 + 10%'\n   * '10 - 5vh + 3%'\n   * '-10px + 5vh, 5px - 6%'\n   * ```\n   * > **NB**: If you desire to apply offsets to your poppers in a way that may make them overlap\n   * > with their reference element, unfortunately, you will have to disable the `flip` modifier.\n   * > More on this [reading this issue](https://github.com/FezVrasta/popper.js/issues/373)\n   *\n   * @memberof modifiers\n   * @inner\n   */\n  offset: {\n    /** @prop {number} order=200 - Index used to define the order of execution */\n    order: 200,\n    /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */\n    enabled: true,\n    /** @prop {ModifierFn} */\n    fn: offset,\n    /** @prop {Number|String} offset=0\n     * The offset value as described in the modifier description\n     */\n    offset: 0\n  },\n\n  /**\n   * Modifier used to prevent the popper from being positioned outside the boundary.\n   *\n   * An scenario exists where the reference itself is not within the boundaries.<br />\n   * We can say it has \"escaped the boundaries\" \u2014 or just \"escaped\".<br />\n   * In this case we need to decide whether the popper should either:\n   *\n   * - detach from the reference and remain \"trapped\" in the boundaries, or\n   * - if it should ignore the boundary and \"escape with its reference\"\n   *\n   * When `escapeWithReference` is set to`true` and reference is completely\n   * outside its boundaries, the popper will overflow (or completely leave)\n   * the boundaries in order to remain attached to the edge of the reference.\n   *\n   * @memberof modifiers\n   * @inner\n   */\n  preventOverflow: {\n    /** @prop {number} order=300 - Index used to define the order of execution */\n    order: 300,\n    /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */\n    enabled: true,\n    /** @prop {ModifierFn} */\n    fn: preventOverflow,\n    /**\n     * @prop {Array} [priority=['left','right','top','bottom']]\n     * Popper will try to prevent overflow following these priorities by default,\n     * then, it could overflow on the left and on top of the `boundariesElement`\n     */\n    priority: ['left', 'right', 'top', 'bottom'],\n    /**\n     * @prop {number} padding=5\n     * Amount of pixel used to define a minimum distance between the boundaries\n     * and the popper this makes sure the popper has always a little padding\n     * between the edges of its container\n     */\n    padding: 5,\n    /**\n     * @prop {String|HTMLElement} boundariesElement='scrollParent'\n     * Boundaries used by the modifier, can be `scrollParent`, `window`,\n     * `viewport` or any DOM element.\n     */\n    boundariesElement: 'scrollParent'\n  },\n\n  /**\n   * Modifier used to make sure the reference and its popper stay near eachothers\n   * without leaving any gap between the two. Expecially useful when the arrow is\n   * enabled and you want to assure it to point to its reference element.\n   * It cares only about the first axis, you can still have poppers with margin\n   * between the popper and its reference element.\n   * @memberof modifiers\n   * @inner\n   */\n  keepTogether: {\n    /** @prop {number} order=400 - Index used to define the order of execution */\n    order: 400,\n    /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */\n    enabled: true,\n    /** @prop {ModifierFn} */\n    fn: keepTogether\n  },\n\n  /**\n   * This modifier is used to move the `arrowElement` of the popper to make\n   * sure it is positioned between the reference element and its popper element.\n   * It will read the outer size of the `arrowElement` node to detect how many\n   * pixels of conjuction are needed.\n   *\n   * It has no effect if no `arrowElement` is provided.\n   * @memberof modifiers\n   * @inner\n   */\n  arrow: {\n    /** @prop {number} order=500 - Index used to define the order of execution */\n    order: 500,\n    /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */\n    enabled: true,\n    /** @prop {ModifierFn} */\n    fn: arrow,\n    /** @prop {String|HTMLElement} element='[x-arrow]' - Selector or node used as arrow */\n    element: '[x-arrow]'\n  },\n\n  /**\n   * Modifier used to flip the popper's placement when it starts to overlap its\n   * reference element.\n   *\n   * Requires the `preventOverflow` modifier before it in order to work.\n   *\n   * **NOTE:** this modifier will interrupt the current update cycle and will\n   * restart it if it detects the need to flip the placement.\n   * @memberof modifiers\n   * @inner\n   */\n  flip: {\n    /** @prop {number} order=600 - Index used to define the order of execution */\n    order: 600,\n    /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */\n    enabled: true,\n    /** @prop {ModifierFn} */\n    fn: flip,\n    /**\n     * @prop {String|Array} behavior='flip'\n     * The behavior used to change the popper's placement. It can be one of\n     * `flip`, `clockwise`, `counterclockwise` or an array with a list of valid\n     * placements (with optional variations).\n     */\n    behavior: 'flip',\n    /**\n     * @prop {number} padding=5\n     * The popper will flip if it hits the edges of the `boundariesElement`\n     */\n    padding: 5,\n    /**\n     * @prop {String|HTMLElement} boundariesElement='viewport'\n     * The element which will define the boundaries of the popper position,\n     * the popper will never be placed outside of the defined boundaries\n     * (except if keepTogether is enabled)\n     */\n    boundariesElement: 'viewport'\n  },\n\n  /**\n   * Modifier used to make the popper flow toward the inner of the reference element.\n   * By default, when this modifier is disabled, the popper will be placed outside\n   * the reference element.\n   * @memberof modifiers\n   * @inner\n   */\n  inner: {\n    /** @prop {number} order=700 - Index used to define the order of execution */\n    order: 700,\n    /** @prop {Boolean} enabled=false - Whether the modifier is enabled or not */\n    enabled: false,\n    /** @prop {ModifierFn} */\n    fn: inner\n  },\n\n  /**\n   * Modifier used to hide the popper when its reference element is outside of the\n   * popper boundaries. It will set a `x-out-of-boundaries` attribute which can\n   * be used to hide with a CSS selector the popper when its reference is\n   * out of boundaries.\n   *\n   * Requires the `preventOverflow` modifier before it in order to work.\n   * @memberof modifiers\n   * @inner\n   */\n  hide: {\n    /** @prop {number} order=800 - Index used to define the order of execution */\n    order: 800,\n    /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */\n    enabled: true,\n    /** @prop {ModifierFn} */\n    fn: hide\n  },\n\n  /**\n   * Computes the style that will be applied to the popper element to gets\n   * properly positioned.\n   *\n   * Note that this modifier will not touch the DOM, it just prepares the styles\n   * so that `applyStyle` modifier can apply it. This separation is useful\n   * in case you need to replace `applyStyle` with a custom implementation.\n   *\n   * This modifier has `850` as `order` value to maintain backward compatibility\n   * with previous versions of Popper.js. Expect the modifiers ordering method\n   * to change in future major versions of the library.\n   *\n   * @memberof modifiers\n   * @inner\n   */\n  computeStyle: {\n    /** @prop {number} order=850 - Index used to define the order of execution */\n    order: 850,\n    /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */\n    enabled: true,\n    /** @prop {ModifierFn} */\n    fn: computeStyle,\n    /**\n     * @prop {Boolean} gpuAcceleration=true\n     * If true, it uses the CSS 3d transformation to position the popper.\n     * Otherwise, it will use the `top` and `left` properties.\n     */\n    gpuAcceleration: true,\n    /**\n     * @prop {string} [x='bottom']\n     * Where to anchor the X axis (`bottom` or `top`). AKA X offset origin.\n     * Change this if your popper should grow in a direction different from `bottom`\n     */\n    x: 'bottom',\n    /**\n     * @prop {string} [x='left']\n     * Where to anchor the Y axis (`left` or `right`). AKA Y offset origin.\n     * Change this if your popper should grow in a direction different from `right`\n     */\n    y: 'right'\n  },\n\n  /**\n   * Applies the computed styles to the popper element.\n   *\n   * All the DOM manipulations are limited to this modifier. This is useful in case\n   * you want to integrate Popper.js inside a framework or view library and you\n   * want to delegate all the DOM manipulations to it.\n   *\n   * Note that if you disable this modifier, you must make sure the popper element\n   * has its position set to `absolute` before Popper.js can do its work!\n   *\n   * Just disable this modifier and define you own to achieve the desired effect.\n   *\n   * @memberof modifiers\n   * @inner\n   */\n  applyStyle: {\n    /** @prop {number} order=900 - Index used to define the order of execution */\n    order: 900,\n    /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */\n    enabled: true,\n    /** @prop {ModifierFn} */\n    fn: applyStyle,\n    /** @prop {Function} */\n    onLoad: applyStyleOnLoad,\n    /**\n     * @deprecated since version 1.10.0, the property moved to `computeStyle` modifier\n     * @prop {Boolean} gpuAcceleration=true\n     * If true, it uses the CSS 3d transformation to position the popper.\n     * Otherwise, it will use the `top` and `left` properties.\n     */\n    gpuAcceleration: undefined\n  }\n};\n\n/**\n * The `dataObject` is an object containing all the informations used by Popper.js\n * this object get passed to modifiers and to the `onCreate` and `onUpdate` callbacks.\n * @name dataObject\n * @property {Object} data.instance The Popper.js instance\n * @property {String} data.placement Placement applied to popper\n * @property {String} data.originalPlacement Placement originally defined on init\n * @property {Boolean} data.flipped True if popper has been flipped by flip modifier\n * @property {Boolean} data.hide True if the reference element is out of boundaries, useful to know when to hide the popper.\n * @property {HTMLElement} data.arrowElement Node used as arrow by arrow modifier\n * @property {Object} data.styles Any CSS property defined here will be applied to the popper, it expects the JavaScript nomenclature (eg. `marginBottom`)\n * @property {Object} data.arrowStyles Any CSS property defined here will be applied to the popper arrow, it expects the JavaScript nomenclature (eg. `marginBottom`)\n * @property {Object} data.boundaries Offsets of the popper boundaries\n * @property {Object} data.offsets The measurements of popper, reference and arrow elements.\n * @property {Object} data.offsets.popper `top`, `left`, `width`, `height` values\n * @property {Object} data.offsets.reference `top`, `left`, `width`, `height` values\n * @property {Object} data.offsets.arrow] `top` and `left` offsets, only one of them will be different from 0\n */\n\n/**\n * Default options provided to Popper.js constructor.<br />\n * These can be overridden using the `options` argument of Popper.js.<br />\n * To override an option, simply pass as 3rd argument an object with the same\n * structure of this object, example:\n * ```\n * new Popper(ref, pop, {\n *   modifiers: {\n *     preventOverflow: { enabled: false }\n *   }\n * })\n * ```\n * @type {Object}\n * @static\n * @memberof Popper\n */\nvar Defaults = {\n  /**\n   * Popper's placement\n   * @prop {Popper.placements} placement='bottom'\n   */\n  placement: 'bottom',\n\n  /**\n   * Set this to true if you want popper to position it self in 'fixed' mode\n   * @prop {Boolean} positionFixed=false\n   */\n  positionFixed: false,\n\n  /**\n   * Whether events (resize, scroll) are initially enabled\n   * @prop {Boolean} eventsEnabled=true\n   */\n  eventsEnabled: true,\n\n  /**\n   * Set to true if you want to automatically remove the popper when\n   * you call the `destroy` method.\n   * @prop {Boolean} removeOnDestroy=false\n   */\n  removeOnDestroy: false,\n\n  /**\n   * Callback called when the popper is created.<br />\n   * By default, is set to no-op.<br />\n   * Access Popper.js instance with `data.instance`.\n   * @prop {onCreate}\n   */\n  onCreate: function onCreate() {},\n\n  /**\n   * Callback called when the popper is updated, this callback is not called\n   * on the initialization/creation of the popper, but only on subsequent\n   * updates.<br />\n   * By default, is set to no-op.<br />\n   * Access Popper.js instance with `data.instance`.\n   * @prop {onUpdate}\n   */\n  onUpdate: function onUpdate() {},\n\n  /**\n   * List of modifiers used to modify the offsets before they are applied to the popper.\n   * They provide most of the functionalities of Popper.js\n   * @prop {modifiers}\n   */\n  modifiers: modifiers\n};\n\n/**\n * @callback onCreate\n * @param {dataObject} data\n */\n\n/**\n * @callback onUpdate\n * @param {dataObject} data\n */\n\n// Utils\n// Methods\nvar Popper = function () {\n  /**\n   * Create a new Popper.js instance\n   * @class Popper\n   * @param {HTMLElement|referenceObject} reference - The reference element used to position the popper\n   * @param {HTMLElement} popper - The HTML element used as popper.\n   * @param {Object} options - Your custom options to override the ones defined in [Defaults](#defaults)\n   * @return {Object} instance - The generated Popper.js instance\n   */\n  function Popper(reference, popper) {\n    var _this = this;\n\n    var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};\n    classCallCheck(this, Popper);\n\n    this.scheduleUpdate = function () {\n      return requestAnimationFrame(_this.update);\n    };\n\n    // make update() debounced, so that it only runs at most once-per-tick\n    this.update = debounce(this.update.bind(this));\n\n    // with {} we create a new object with the options inside it\n    this.options = _extends({}, Popper.Defaults, options);\n\n    // init state\n    this.state = {\n      isDestroyed: false,\n      isCreated: false,\n      scrollParents: []\n    };\n\n    // get reference and popper elements (allow jQuery wrappers)\n    this.reference = reference && reference.jquery ? reference[0] : reference;\n    this.popper = popper && popper.jquery ? popper[0] : popper;\n\n    // Deep merge modifiers options\n    this.options.modifiers = {};\n    Object.keys(_extends({}, Popper.Defaults.modifiers, options.modifiers)).forEach(function (name) {\n      _this.options.modifiers[name] = _extends({}, Popper.Defaults.modifiers[name] || {}, options.modifiers ? options.modifiers[name] : {});\n    });\n\n    // Refactoring modifiers' list (Object => Array)\n    this.modifiers = Object.keys(this.options.modifiers).map(function (name) {\n      return _extends({\n        name: name\n      }, _this.options.modifiers[name]);\n    })\n    // sort the modifiers by order\n    .sort(function (a, b) {\n      return a.order - b.order;\n    });\n\n    // modifiers have the ability to execute arbitrary code when Popper.js get inited\n    // such code is executed in the same order of its modifier\n    // they could add new properties to their options configuration\n    // BE AWARE: don't add options to `options.modifiers.name` but to `modifierOptions`!\n    this.modifiers.forEach(function (modifierOptions) {\n      if (modifierOptions.enabled && isFunction(modifierOptions.onLoad)) {\n        modifierOptions.onLoad(_this.reference, _this.popper, _this.options, modifierOptions, _this.state);\n      }\n    });\n\n    // fire the first update to position the popper in the right place\n    this.update();\n\n    var eventsEnabled = this.options.eventsEnabled;\n    if (eventsEnabled) {\n      // setup event listeners, they will take care of update the position in specific situations\n      this.enableEventListeners();\n    }\n\n    this.state.eventsEnabled = eventsEnabled;\n  }\n\n  // We can't use class properties because they don't get listed in the\n  // class prototype and break stuff like Sinon stubs\n\n\n  createClass(Popper, [{\n    key: 'update',\n    value: function update$$1() {\n      return update.call(this);\n    }\n  }, {\n    key: 'destroy',\n    value: function destroy$$1() {\n      return destroy.call(this);\n    }\n  }, {\n    key: 'enableEventListeners',\n    value: function enableEventListeners$$1() {\n      return enableEventListeners.call(this);\n    }\n  }, {\n    key: 'disableEventListeners',\n    value: function disableEventListeners$$1() {\n      return disableEventListeners.call(this);\n    }\n\n    /**\n     * Schedule an update, it will run on the next UI update available\n     * @method scheduleUpdate\n     * @memberof Popper\n     */\n\n\n    /**\n     * Collection of utilities useful when writing custom modifiers.\n     * Starting from version 1.7, this method is available only if you\n     * include `popper-utils.js` before `popper.js`.\n     *\n     * **DEPRECATION**: This way to access PopperUtils is deprecated\n     * and will be removed in v2! Use the PopperUtils module directly instead.\n     * Due to the high instability of the methods contained in Utils, we can't\n     * guarantee them to follow semver. Use them at your own risk!\n     * @static\n     * @private\n     * @type {Object}\n     * @deprecated since version 1.8\n     * @member Utils\n     * @memberof Popper\n     */\n\n  }]);\n  return Popper;\n}();\n\n/**\n * The `referenceObject` is an object that provides an interface compatible with Popper.js\n * and lets you use it as replacement of a real DOM node.<br />\n * You can use this method to position a popper relatively to a set of coordinates\n * in case you don't have a DOM node to use as reference.\n *\n * ```\n * new Popper(referenceObject, popperNode);\n * ```\n *\n * NB: This feature isn't supported in Internet Explorer 10\n * @name referenceObject\n * @property {Function} data.getBoundingClientRect\n * A function that returns a set of coordinates compatible with the native `getBoundingClientRect` method.\n * @property {number} data.clientWidth\n * An ES6 getter that will return the width of the virtual reference element.\n * @property {number} data.clientHeight\n * An ES6 getter that will return the height of the virtual reference element.\n */\n\n\nPopper.Utils = (typeof window !== 'undefined' ? window : global).PopperUtils;\nPopper.placements = placements;\nPopper.Defaults = Defaults;\n\nreturn Popper;\n\n})));\n", "/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.3.1): index.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n(function ($) {\n  if (typeof $ === 'undefined') {\n    throw new TypeError('Bootstrap\\'s JavaScript requires jQuery. jQuery must be included before Bootstrap\\'s JavaScript.');\n  }\n\n  var version = $.fn.jquery.split(' ')[0].split('.');\n  var minMajor = 1;\n  var ltMajor = 2;\n  var minMinor = 9;\n  var minPatch = 1;\n  var maxMajor = 4;\n\n  if (version[0] < ltMajor && version[1] < minMinor || version[0] === minMajor && version[1] === minMinor && version[2] < minPatch || version[0] >= maxMajor) {\n    throw new Error('Bootstrap\\'s JavaScript requires at least jQuery v1.9.1 but less than v4.0.0');\n  }\n})($);\n", "/*!\n  * Bootstrap util.js v4.3.1 (https://getbootstrap.com/)\n  * Copyright 2011-2019 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)\n  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n  */\n(function (global, factory) {\n  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('jquery')) :\n  typeof define === 'function' && define.amd ? define(['jquery'], factory) :\n  (global = global || self, global.Util = factory(global.jQuery));\n}(this, function ($) { 'use strict';\n\n  $ = $ && $.hasOwnProperty('default') ? $['default'] : $;\n\n  /**\n   * --------------------------------------------------------------------------\n   * Bootstrap (v4.3.1): util.js\n   * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n   * --------------------------------------------------------------------------\n   */\n  /**\n   * ------------------------------------------------------------------------\n   * Private TransitionEnd Helpers\n   * ------------------------------------------------------------------------\n   */\n\n  var TRANSITION_END = 'transitionend';\n  var MAX_UID = 1000000;\n  var MILLISECONDS_MULTIPLIER = 1000; // Shoutout AngusCroll (https://goo.gl/pxwQGp)\n\n  function toType(obj) {\n    return {}.toString.call(obj).match(/\\s([a-z]+)/i)[1].toLowerCase();\n  }\n\n  function getSpecialTransitionEndEvent() {\n    return {\n      bindType: TRANSITION_END,\n      delegateType: TRANSITION_END,\n      handle: function handle(event) {\n        if ($(event.target).is(this)) {\n          return event.handleObj.handler.apply(this, arguments); // eslint-disable-line prefer-rest-params\n        }\n\n        return undefined; // eslint-disable-line no-undefined\n      }\n    };\n  }\n\n  function transitionEndEmulator(duration) {\n    var _this = this;\n\n    var called = false;\n    $(this).one(Util.TRANSITION_END, function () {\n      called = true;\n    });\n    setTimeout(function () {\n      if (!called) {\n        Util.triggerTransitionEnd(_this);\n      }\n    }, duration);\n    return this;\n  }\n\n  function setTransitionEndSupport() {\n    $.fn.emulateTransitionEnd = transitionEndEmulator;\n    $.event.special[Util.TRANSITION_END] = getSpecialTransitionEndEvent();\n  }\n  /**\n   * --------------------------------------------------------------------------\n   * Public Util Api\n   * --------------------------------------------------------------------------\n   */\n\n\n  var Util = {\n    TRANSITION_END: 'bsTransitionEnd',\n    getUID: function getUID(prefix) {\n      do {\n        // eslint-disable-next-line no-bitwise\n        prefix += ~~(Math.random() * MAX_UID); // \"~~\" acts like a faster Math.floor() here\n      } while (document.getElementById(prefix));\n\n      return prefix;\n    },\n    getSelectorFromElement: function getSelectorFromElement(element) {\n      var selector = element.getAttribute('data-target');\n\n      if (!selector || selector === '#') {\n        var hrefAttr = element.getAttribute('href');\n        selector = hrefAttr && hrefAttr !== '#' ? hrefAttr.trim() : '';\n      }\n\n      try {\n        return document.querySelector(selector) ? selector : null;\n      } catch (err) {\n        return null;\n      }\n    },\n    getTransitionDurationFromElement: function getTransitionDurationFromElement(element) {\n      if (!element) {\n        return 0;\n      } // Get transition-duration of the element\n\n\n      var transitionDuration = $(element).css('transition-duration');\n      var transitionDelay = $(element).css('transition-delay');\n      var floatTransitionDuration = parseFloat(transitionDuration);\n      var floatTransitionDelay = parseFloat(transitionDelay); // Return 0 if element or transition duration is not found\n\n      if (!floatTransitionDuration && !floatTransitionDelay) {\n        return 0;\n      } // If multiple durations are defined, take the first\n\n\n      transitionDuration = transitionDuration.split(',')[0];\n      transitionDelay = transitionDelay.split(',')[0];\n      return (parseFloat(transitionDuration) + parseFloat(transitionDelay)) * MILLISECONDS_MULTIPLIER;\n    },\n    reflow: function reflow(element) {\n      return element.offsetHeight;\n    },\n    triggerTransitionEnd: function triggerTransitionEnd(element) {\n      $(element).trigger(TRANSITION_END);\n    },\n    // TODO: Remove in v5\n    supportsTransitionEnd: function supportsTransitionEnd() {\n      return Boolean(TRANSITION_END);\n    },\n    isElement: function isElement(obj) {\n      return (obj[0] || obj).nodeType;\n    },\n    typeCheckConfig: function typeCheckConfig(componentName, config, configTypes) {\n      for (var property in configTypes) {\n        if (Object.prototype.hasOwnProperty.call(configTypes, property)) {\n          var expectedTypes = configTypes[property];\n          var value = config[property];\n          var valueType = value && Util.isElement(value) ? 'element' : toType(value);\n\n          if (!new RegExp(expectedTypes).test(valueType)) {\n            throw new Error(componentName.toUpperCase() + \": \" + (\"Option \\\"\" + property + \"\\\" provided type \\\"\" + valueType + \"\\\" \") + (\"but expected type \\\"\" + expectedTypes + \"\\\".\"));\n          }\n        }\n      }\n    },\n    findShadowRoot: function findShadowRoot(element) {\n      if (!document.documentElement.attachShadow) {\n        return null;\n      } // Can find the shadow root otherwise it'll return the document\n\n\n      if (typeof element.getRootNode === 'function') {\n        var root = element.getRootNode();\n        return root instanceof ShadowRoot ? root : null;\n      }\n\n      if (element instanceof ShadowRoot) {\n        return element;\n      } // when we don't find a shadow root\n\n\n      if (!element.parentNode) {\n        return null;\n      }\n\n      return Util.findShadowRoot(element.parentNode);\n    }\n  };\n  setTransitionEndSupport();\n\n  return Util;\n\n}));\n", "/*!\n  * Bootstrap alert.js v4.3.1 (https://getbootstrap.com/)\n  * Copyright 2011-2019 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)\n  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n  */\n(function (global, factory) {\n  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('jquery'), require('./util.js')) :\n  typeof define === 'function' && define.amd ? define(['jquery', './util.js'], factory) :\n  (global = global || self, global.Alert = factory(global.jQuery, global.Util));\n}(this, function ($, Util) { 'use strict';\n\n  $ = $ && $.hasOwnProperty('default') ? $['default'] : $;\n  Util = Util && Util.hasOwnProperty('default') ? Util['default'] : Util;\n\n  function _defineProperties(target, props) {\n    for (var i = 0; i < props.length; i++) {\n      var descriptor = props[i];\n      descriptor.enumerable = descriptor.enumerable || false;\n      descriptor.configurable = true;\n      if (\"value\" in descriptor) descriptor.writable = true;\n      Object.defineProperty(target, descriptor.key, descriptor);\n    }\n  }\n\n  function _createClass(Constructor, protoProps, staticProps) {\n    if (protoProps) _defineProperties(Constructor.prototype, protoProps);\n    if (staticProps) _defineProperties(Constructor, staticProps);\n    return Constructor;\n  }\n\n  /**\n   * ------------------------------------------------------------------------\n   * Constants\n   * ------------------------------------------------------------------------\n   */\n\n  var NAME = 'alert';\n  var VERSION = '4.3.1';\n  var DATA_KEY = 'bs.alert';\n  var EVENT_KEY = \".\" + DATA_KEY;\n  var DATA_API_KEY = '.data-api';\n  var JQUERY_NO_CONFLICT = $.fn[NAME];\n  var Selector = {\n    DISMISS: '[data-dismiss=\"alert\"]'\n  };\n  var Event = {\n    CLOSE: \"close\" + EVENT_KEY,\n    CLOSED: \"closed\" + EVENT_KEY,\n    CLICK_DATA_API: \"click\" + EVENT_KEY + DATA_API_KEY\n  };\n  var ClassName = {\n    ALERT: 'alert',\n    FADE: 'fade',\n    SHOW: 'show'\n    /**\n     * ------------------------------------------------------------------------\n     * Class Definition\n     * ------------------------------------------------------------------------\n     */\n\n  };\n\n  var Alert =\n  /*#__PURE__*/\n  function () {\n    function Alert(element) {\n      this._element = element;\n    } // Getters\n\n\n    var _proto = Alert.prototype;\n\n    // Public\n    _proto.close = function close(element) {\n      var rootElement = this._element;\n\n      if (element) {\n        rootElement = this._getRootElement(element);\n      }\n\n      var customEvent = this._triggerCloseEvent(rootElement);\n\n      if (customEvent.isDefaultPrevented()) {\n        return;\n      }\n\n      this._removeElement(rootElement);\n    };\n\n    _proto.dispose = function dispose() {\n      $.removeData(this._element, DATA_KEY);\n      this._element = null;\n    } // Private\n    ;\n\n    _proto._getRootElement = function _getRootElement(element) {\n      var selector = Util.getSelectorFromElement(element);\n      var parent = false;\n\n      if (selector) {\n        parent = document.querySelector(selector);\n      }\n\n      if (!parent) {\n        parent = $(element).closest(\".\" + ClassName.ALERT)[0];\n      }\n\n      return parent;\n    };\n\n    _proto._triggerCloseEvent = function _triggerCloseEvent(element) {\n      var closeEvent = $.Event(Event.CLOSE);\n      $(element).trigger(closeEvent);\n      return closeEvent;\n    };\n\n    _proto._removeElement = function _removeElement(element) {\n      var _this = this;\n\n      $(element).removeClass(ClassName.SHOW);\n\n      if (!$(element).hasClass(ClassName.FADE)) {\n        this._destroyElement(element);\n\n        return;\n      }\n\n      var transitionDuration = Util.getTransitionDurationFromElement(element);\n      $(element).one(Util.TRANSITION_END, function (event) {\n        return _this._destroyElement(element, event);\n      }).emulateTransitionEnd(transitionDuration);\n    };\n\n    _proto._destroyElement = function _destroyElement(element) {\n      $(element).detach().trigger(Event.CLOSED).remove();\n    } // Static\n    ;\n\n    Alert._jQueryInterface = function _jQueryInterface(config) {\n      return this.each(function () {\n        var $element = $(this);\n        var data = $element.data(DATA_KEY);\n\n        if (!data) {\n          data = new Alert(this);\n          $element.data(DATA_KEY, data);\n        }\n\n        if (config === 'close') {\n          data[config](this);\n        }\n      });\n    };\n\n    Alert._handleDismiss = function _handleDismiss(alertInstance) {\n      return function (event) {\n        if (event) {\n          event.preventDefault();\n        }\n\n        alertInstance.close(this);\n      };\n    };\n\n    _createClass(Alert, null, [{\n      key: \"VERSION\",\n      get: function get() {\n        return VERSION;\n      }\n    }]);\n\n    return Alert;\n  }();\n  /**\n   * ------------------------------------------------------------------------\n   * Data Api implementation\n   * ------------------------------------------------------------------------\n   */\n\n\n  $(document).on(Event.CLICK_DATA_API, Selector.DISMISS, Alert._handleDismiss(new Alert()));\n  /**\n   * ------------------------------------------------------------------------\n   * jQuery\n   * ------------------------------------------------------------------------\n   */\n\n  $.fn[NAME] = Alert._jQueryInterface;\n  $.fn[NAME].Constructor = Alert;\n\n  $.fn[NAME].noConflict = function () {\n    $.fn[NAME] = JQUERY_NO_CONFLICT;\n    return Alert._jQueryInterface;\n  };\n\n  return Alert;\n\n}));\n", "/*!\n  * Bootstrap button.js v4.3.1 (https://getbootstrap.com/)\n  * Copyright 2011-2019 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)\n  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n  */\n(function (global, factory) {\n  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('jquery')) :\n  typeof define === 'function' && define.amd ? define(['jquery'], factory) :\n  (global = global || self, global.Button = factory(global.jQuery));\n}(this, function ($) { 'use strict';\n\n  $ = $ && $.hasOwnProperty('default') ? $['default'] : $;\n\n  function _defineProperties(target, props) {\n    for (var i = 0; i < props.length; i++) {\n      var descriptor = props[i];\n      descriptor.enumerable = descriptor.enumerable || false;\n      descriptor.configurable = true;\n      if (\"value\" in descriptor) descriptor.writable = true;\n      Object.defineProperty(target, descriptor.key, descriptor);\n    }\n  }\n\n  function _createClass(Constructor, protoProps, staticProps) {\n    if (protoProps) _defineProperties(Constructor.prototype, protoProps);\n    if (staticProps) _defineProperties(Constructor, staticProps);\n    return Constructor;\n  }\n\n  /**\n   * ------------------------------------------------------------------------\n   * Constants\n   * ------------------------------------------------------------------------\n   */\n\n  var NAME = 'button';\n  var VERSION = '4.3.1';\n  var DATA_KEY = 'bs.button';\n  var EVENT_KEY = \".\" + DATA_KEY;\n  var DATA_API_KEY = '.data-api';\n  var JQUERY_NO_CONFLICT = $.fn[NAME];\n  var ClassName = {\n    ACTIVE: 'active',\n    BUTTON: 'btn',\n    FOCUS: 'focus'\n  };\n  var Selector = {\n    DATA_TOGGLE_CARROT: '[data-toggle^=\"button\"]',\n    DATA_TOGGLE: '[data-toggle=\"buttons\"]',\n    INPUT: 'input:not([type=\"hidden\"])',\n    ACTIVE: '.active',\n    BUTTON: '.btn'\n  };\n  var Event = {\n    CLICK_DATA_API: \"click\" + EVENT_KEY + DATA_API_KEY,\n    FOCUS_BLUR_DATA_API: \"focus\" + EVENT_KEY + DATA_API_KEY + \" \" + (\"blur\" + EVENT_KEY + DATA_API_KEY)\n    /**\n     * ------------------------------------------------------------------------\n     * Class Definition\n     * ------------------------------------------------------------------------\n     */\n\n  };\n\n  var Button =\n  /*#__PURE__*/\n  function () {\n    function Button(element) {\n      this._element = element;\n    } // Getters\n\n\n    var _proto = Button.prototype;\n\n    // Public\n    _proto.toggle = function toggle() {\n      var triggerChangeEvent = true;\n      var addAriaPressed = true;\n      var rootElement = $(this._element).closest(Selector.DATA_TOGGLE)[0];\n\n      if (rootElement) {\n        var input = this._element.querySelector(Selector.INPUT);\n\n        if (input) {\n          if (input.type === 'radio') {\n            if (input.checked && this._element.classList.contains(ClassName.ACTIVE)) {\n              triggerChangeEvent = false;\n            } else {\n              var activeElement = rootElement.querySelector(Selector.ACTIVE);\n\n              if (activeElement) {\n                $(activeElement).removeClass(ClassName.ACTIVE);\n              }\n            }\n          }\n\n          if (triggerChangeEvent) {\n            if (input.hasAttribute('disabled') || rootElement.hasAttribute('disabled') || input.classList.contains('disabled') || rootElement.classList.contains('disabled')) {\n              return;\n            }\n\n            input.checked = !this._element.classList.contains(ClassName.ACTIVE);\n            $(input).trigger('change');\n          }\n\n          input.focus();\n          addAriaPressed = false;\n        }\n      }\n\n      if (addAriaPressed) {\n        this._element.setAttribute('aria-pressed', !this._element.classList.contains(ClassName.ACTIVE));\n      }\n\n      if (triggerChangeEvent) {\n        $(this._element).toggleClass(ClassName.ACTIVE);\n      }\n    };\n\n    _proto.dispose = function dispose() {\n      $.removeData(this._element, DATA_KEY);\n      this._element = null;\n    } // Static\n    ;\n\n    Button._jQueryInterface = function _jQueryInterface(config) {\n      return this.each(function () {\n        var data = $(this).data(DATA_KEY);\n\n        if (!data) {\n          data = new Button(this);\n          $(this).data(DATA_KEY, data);\n        }\n\n        if (config === 'toggle') {\n          data[config]();\n        }\n      });\n    };\n\n    _createClass(Button, null, [{\n      key: \"VERSION\",\n      get: function get() {\n        return VERSION;\n      }\n    }]);\n\n    return Button;\n  }();\n  /**\n   * ------------------------------------------------------------------------\n   * Data Api implementation\n   * ------------------------------------------------------------------------\n   */\n\n\n  $(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE_CARROT, function (event) {\n    event.preventDefault();\n    var button = event.target;\n\n    if (!$(button).hasClass(ClassName.BUTTON)) {\n      button = $(button).closest(Selector.BUTTON);\n    }\n\n    Button._jQueryInterface.call($(button), 'toggle');\n  }).on(Event.FOCUS_BLUR_DATA_API, Selector.DATA_TOGGLE_CARROT, function (event) {\n    var button = $(event.target).closest(Selector.BUTTON)[0];\n    $(button).toggleClass(ClassName.FOCUS, /^focus(in)?$/.test(event.type));\n  });\n  /**\n   * ------------------------------------------------------------------------\n   * jQuery\n   * ------------------------------------------------------------------------\n   */\n\n  $.fn[NAME] = Button._jQueryInterface;\n  $.fn[NAME].Constructor = Button;\n\n  $.fn[NAME].noConflict = function () {\n    $.fn[NAME] = JQUERY_NO_CONFLICT;\n    return Button._jQueryInterface;\n  };\n\n  return Button;\n\n}));\n", "/*!\n  * Bootstrap carousel.js v4.3.1 (https://getbootstrap.com/)\n  * Copyright 2011-2019 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)\n  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n  */\n(function (global, factory) {\n  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('jquery'), require('./util.js')) :\n  typeof define === 'function' && define.amd ? define(['jquery', './util.js'], factory) :\n  (global = global || self, global.Carousel = factory(global.jQuery, global.Util));\n}(this, function ($, Util) { 'use strict';\n\n  $ = $ && $.hasOwnProperty('default') ? $['default'] : $;\n  Util = Util && Util.hasOwnProperty('default') ? Util['default'] : Util;\n\n  function _defineProperties(target, props) {\n    for (var i = 0; i < props.length; i++) {\n      var descriptor = props[i];\n      descriptor.enumerable = descriptor.enumerable || false;\n      descriptor.configurable = true;\n      if (\"value\" in descriptor) descriptor.writable = true;\n      Object.defineProperty(target, descriptor.key, descriptor);\n    }\n  }\n\n  function _createClass(Constructor, protoProps, staticProps) {\n    if (protoProps) _defineProperties(Constructor.prototype, protoProps);\n    if (staticProps) _defineProperties(Constructor, staticProps);\n    return Constructor;\n  }\n\n  function _defineProperty(obj, key, value) {\n    if (key in obj) {\n      Object.defineProperty(obj, key, {\n        value: value,\n        enumerable: true,\n        configurable: true,\n        writable: true\n      });\n    } else {\n      obj[key] = value;\n    }\n\n    return obj;\n  }\n\n  function _objectSpread(target) {\n    for (var i = 1; i < arguments.length; i++) {\n      var source = arguments[i] != null ? arguments[i] : {};\n      var ownKeys = Object.keys(source);\n\n      if (typeof Object.getOwnPropertySymbols === 'function') {\n        ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) {\n          return Object.getOwnPropertyDescriptor(source, sym).enumerable;\n        }));\n      }\n\n      ownKeys.forEach(function (key) {\n        _defineProperty(target, key, source[key]);\n      });\n    }\n\n    return target;\n  }\n\n  /**\n   * ------------------------------------------------------------------------\n   * Constants\n   * ------------------------------------------------------------------------\n   */\n\n  var NAME = 'carousel';\n  var VERSION = '4.3.1';\n  var DATA_KEY = 'bs.carousel';\n  var EVENT_KEY = \".\" + DATA_KEY;\n  var DATA_API_KEY = '.data-api';\n  var JQUERY_NO_CONFLICT = $.fn[NAME];\n  var ARROW_LEFT_KEYCODE = 37; // KeyboardEvent.which value for left arrow key\n\n  var ARROW_RIGHT_KEYCODE = 39; // KeyboardEvent.which value for right arrow key\n\n  var TOUCHEVENT_COMPAT_WAIT = 500; // Time for mouse compat events to fire after touch\n\n  var SWIPE_THRESHOLD = 40;\n  var Default = {\n    interval: 5000,\n    keyboard: true,\n    slide: false,\n    pause: 'hover',\n    wrap: true,\n    touch: true\n  };\n  var DefaultType = {\n    interval: '(number|boolean)',\n    keyboard: 'boolean',\n    slide: '(boolean|string)',\n    pause: '(string|boolean)',\n    wrap: 'boolean',\n    touch: 'boolean'\n  };\n  var Direction = {\n    NEXT: 'next',\n    PREV: 'prev',\n    LEFT: 'left',\n    RIGHT: 'right'\n  };\n  var Event = {\n    SLIDE: \"slide\" + EVENT_KEY,\n    SLID: \"slid\" + EVENT_KEY,\n    KEYDOWN: \"keydown\" + EVENT_KEY,\n    MOUSEENTER: \"mouseenter\" + EVENT_KEY,\n    MOUSELEAVE: \"mouseleave\" + EVENT_KEY,\n    TOUCHSTART: \"touchstart\" + EVENT_KEY,\n    TOUCHMOVE: \"touchmove\" + EVENT_KEY,\n    TOUCHEND: \"touchend\" + EVENT_KEY,\n    POINTERDOWN: \"pointerdown\" + EVENT_KEY,\n    POINTERUP: \"pointerup\" + EVENT_KEY,\n    DRAG_START: \"dragstart\" + EVENT_KEY,\n    LOAD_DATA_API: \"load\" + EVENT_KEY + DATA_API_KEY,\n    CLICK_DATA_API: \"click\" + EVENT_KEY + DATA_API_KEY\n  };\n  var ClassName = {\n    CAROUSEL: 'carousel',\n    ACTIVE: 'active',\n    SLIDE: 'slide',\n    RIGHT: 'carousel-item-right',\n    LEFT: 'carousel-item-left',\n    NEXT: 'carousel-item-next',\n    PREV: 'carousel-item-prev',\n    ITEM: 'carousel-item',\n    POINTER_EVENT: 'pointer-event'\n  };\n  var Selector = {\n    ACTIVE: '.active',\n    ACTIVE_ITEM: '.active.carousel-item',\n    ITEM: '.carousel-item',\n    ITEM_IMG: '.carousel-item img',\n    NEXT_PREV: '.carousel-item-next, .carousel-item-prev',\n    INDICATORS: '.carousel-indicators',\n    DATA_SLIDE: '[data-slide], [data-slide-to]',\n    DATA_RIDE: '[data-ride=\"carousel\"]'\n  };\n  var PointerType = {\n    TOUCH: 'touch',\n    PEN: 'pen'\n    /**\n     * ------------------------------------------------------------------------\n     * Class Definition\n     * ------------------------------------------------------------------------\n     */\n\n  };\n\n  var Carousel =\n  /*#__PURE__*/\n  function () {\n    function Carousel(element, config) {\n      this._items = null;\n      this._interval = null;\n      this._activeElement = null;\n      this._isPaused = false;\n      this._isSliding = false;\n      this.touchTimeout = null;\n      this.touchStartX = 0;\n      this.touchDeltaX = 0;\n      this._config = this._getConfig(config);\n      this._element = element;\n      this._indicatorsElement = this._element.querySelector(Selector.INDICATORS);\n      this._touchSupported = 'ontouchstart' in document.documentElement || navigator.maxTouchPoints > 0;\n      this._pointerEvent = Boolean(window.PointerEvent || window.MSPointerEvent);\n\n      this._addEventListeners();\n    } // Getters\n\n\n    var _proto = Carousel.prototype;\n\n    // Public\n    _proto.next = function next() {\n      if (!this._isSliding) {\n        this._slide(Direction.NEXT);\n      }\n    };\n\n    _proto.nextWhenVisible = function nextWhenVisible() {\n      // Don't call next when the page isn't visible\n      // or the carousel or its parent isn't visible\n      if (!document.hidden && $(this._element).is(':visible') && $(this._element).css('visibility') !== 'hidden') {\n        this.next();\n      }\n    };\n\n    _proto.prev = function prev() {\n      if (!this._isSliding) {\n        this._slide(Direction.PREV);\n      }\n    };\n\n    _proto.pause = function pause(event) {\n      if (!event) {\n        this._isPaused = true;\n      }\n\n      if (this._element.querySelector(Selector.NEXT_PREV)) {\n        Util.triggerTransitionEnd(this._element);\n        this.cycle(true);\n      }\n\n      clearInterval(this._interval);\n      this._interval = null;\n    };\n\n    _proto.cycle = function cycle(event) {\n      if (!event) {\n        this._isPaused = false;\n      }\n\n      if (this._interval) {\n        clearInterval(this._interval);\n        this._interval = null;\n      }\n\n      if (this._config.interval && !this._isPaused) {\n        this._interval = setInterval((document.visibilityState ? this.nextWhenVisible : this.next).bind(this), this._config.interval);\n      }\n    };\n\n    _proto.to = function to(index) {\n      var _this = this;\n\n      this._activeElement = this._element.querySelector(Selector.ACTIVE_ITEM);\n\n      var activeIndex = this._getItemIndex(this._activeElement);\n\n      if (index > this._items.length - 1 || index < 0) {\n        return;\n      }\n\n      if (this._isSliding) {\n        $(this._element).one(Event.SLID, function () {\n          return _this.to(index);\n        });\n        return;\n      }\n\n      if (activeIndex === index) {\n        this.pause();\n        this.cycle();\n        return;\n      }\n\n      var direction = index > activeIndex ? Direction.NEXT : Direction.PREV;\n\n      this._slide(direction, this._items[index]);\n    };\n\n    _proto.dispose = function dispose() {\n      $(this._element).off(EVENT_KEY);\n      $.removeData(this._element, DATA_KEY);\n      this._items = null;\n      this._config = null;\n      this._element = null;\n      this._interval = null;\n      this._isPaused = null;\n      this._isSliding = null;\n      this._activeElement = null;\n      this._indicatorsElement = null;\n    } // Private\n    ;\n\n    _proto._getConfig = function _getConfig(config) {\n      config = _objectSpread({}, Default, config);\n      Util.typeCheckConfig(NAME, config, DefaultType);\n      return config;\n    };\n\n    _proto._handleSwipe = function _handleSwipe() {\n      var absDeltax = Math.abs(this.touchDeltaX);\n\n      if (absDeltax <= SWIPE_THRESHOLD) {\n        return;\n      }\n\n      var direction = absDeltax / this.touchDeltaX; // swipe left\n\n      if (direction > 0) {\n        this.prev();\n      } // swipe right\n\n\n      if (direction < 0) {\n        this.next();\n      }\n    };\n\n    _proto._addEventListeners = function _addEventListeners() {\n      var _this2 = this;\n\n      if (this._config.keyboard) {\n        $(this._element).on(Event.KEYDOWN, function (event) {\n          return _this2._keydown(event);\n        });\n      }\n\n      if (this._config.pause === 'hover') {\n        $(this._element).on(Event.MOUSEENTER, function (event) {\n          return _this2.pause(event);\n        }).on(Event.MOUSELEAVE, function (event) {\n          return _this2.cycle(event);\n        });\n      }\n\n      if (this._config.touch) {\n        this._addTouchEventListeners();\n      }\n    };\n\n    _proto._addTouchEventListeners = function _addTouchEventListeners() {\n      var _this3 = this;\n\n      if (!this._touchSupported) {\n        return;\n      }\n\n      var start = function start(event) {\n        if (_this3._pointerEvent && PointerType[event.originalEvent.pointerType.toUpperCase()]) {\n          _this3.touchStartX = event.originalEvent.clientX;\n        } else if (!_this3._pointerEvent) {\n          _this3.touchStartX = event.originalEvent.touches[0].clientX;\n        }\n      };\n\n      var move = function move(event) {\n        // ensure swiping with one touch and not pinching\n        if (event.originalEvent.touches && event.originalEvent.touches.length > 1) {\n          _this3.touchDeltaX = 0;\n        } else {\n          _this3.touchDeltaX = event.originalEvent.touches[0].clientX - _this3.touchStartX;\n        }\n      };\n\n      var end = function end(event) {\n        if (_this3._pointerEvent && PointerType[event.originalEvent.pointerType.toUpperCase()]) {\n          _this3.touchDeltaX = event.originalEvent.clientX - _this3.touchStartX;\n        }\n\n        _this3._handleSwipe();\n\n        if (_this3._config.pause === 'hover') {\n          // If it's a touch-enabled device, mouseenter/leave are fired as\n          // part of the mouse compatibility events on first tap - the carousel\n          // would stop cycling until user tapped out of it;\n          // here, we listen for touchend, explicitly pause the carousel\n          // (as if it's the second time we tap on it, mouseenter compat event\n          // is NOT fired) and after a timeout (to allow for mouse compatibility\n          // events to fire) we explicitly restart cycling\n          _this3.pause();\n\n          if (_this3.touchTimeout) {\n            clearTimeout(_this3.touchTimeout);\n          }\n\n          _this3.touchTimeout = setTimeout(function (event) {\n            return _this3.cycle(event);\n          }, TOUCHEVENT_COMPAT_WAIT + _this3._config.interval);\n        }\n      };\n\n      $(this._element.querySelectorAll(Selector.ITEM_IMG)).on(Event.DRAG_START, function (e) {\n        return e.preventDefault();\n      });\n\n      if (this._pointerEvent) {\n        $(this._element).on(Event.POINTERDOWN, function (event) {\n          return start(event);\n        });\n        $(this._element).on(Event.POINTERUP, function (event) {\n          return end(event);\n        });\n\n        this._element.classList.add(ClassName.POINTER_EVENT);\n      } else {\n        $(this._element).on(Event.TOUCHSTART, function (event) {\n          return start(event);\n        });\n        $(this._element).on(Event.TOUCHMOVE, function (event) {\n          return move(event);\n        });\n        $(this._element).on(Event.TOUCHEND, function (event) {\n          return end(event);\n        });\n      }\n    };\n\n    _proto._keydown = function _keydown(event) {\n      if (/input|textarea/i.test(event.target.tagName)) {\n        return;\n      }\n\n      switch (event.which) {\n        case ARROW_LEFT_KEYCODE:\n          event.preventDefault();\n          this.prev();\n          break;\n\n        case ARROW_RIGHT_KEYCODE:\n          event.preventDefault();\n          this.next();\n          break;\n\n        default:\n      }\n    };\n\n    _proto._getItemIndex = function _getItemIndex(element) {\n      this._items = element && element.parentNode ? [].slice.call(element.parentNode.querySelectorAll(Selector.ITEM)) : [];\n      return this._items.indexOf(element);\n    };\n\n    _proto._getItemByDirection = function _getItemByDirection(direction, activeElement) {\n      var isNextDirection = direction === Direction.NEXT;\n      var isPrevDirection = direction === Direction.PREV;\n\n      var activeIndex = this._getItemIndex(activeElement);\n\n      var lastItemIndex = this._items.length - 1;\n      var isGoingToWrap = isPrevDirection && activeIndex === 0 || isNextDirection && activeIndex === lastItemIndex;\n\n      if (isGoingToWrap && !this._config.wrap) {\n        return activeElement;\n      }\n\n      var delta = direction === Direction.PREV ? -1 : 1;\n      var itemIndex = (activeIndex + delta) % this._items.length;\n      return itemIndex === -1 ? this._items[this._items.length - 1] : this._items[itemIndex];\n    };\n\n    _proto._triggerSlideEvent = function _triggerSlideEvent(relatedTarget, eventDirectionName) {\n      var targetIndex = this._getItemIndex(relatedTarget);\n\n      var fromIndex = this._getItemIndex(this._element.querySelector(Selector.ACTIVE_ITEM));\n\n      var slideEvent = $.Event(Event.SLIDE, {\n        relatedTarget: relatedTarget,\n        direction: eventDirectionName,\n        from: fromIndex,\n        to: targetIndex\n      });\n      $(this._element).trigger(slideEvent);\n      return slideEvent;\n    };\n\n    _proto._setActiveIndicatorElement = function _setActiveIndicatorElement(element) {\n      if (this._indicatorsElement) {\n        var indicators = [].slice.call(this._indicatorsElement.querySelectorAll(Selector.ACTIVE));\n        $(indicators).removeClass(ClassName.ACTIVE);\n\n        var nextIndicator = this._indicatorsElement.children[this._getItemIndex(element)];\n\n        if (nextIndicator) {\n          $(nextIndicator).addClass(ClassName.ACTIVE);\n        }\n      }\n    };\n\n    _proto._slide = function _slide(direction, element) {\n      var _this4 = this;\n\n      var activeElement = this._element.querySelector(Selector.ACTIVE_ITEM);\n\n      var activeElementIndex = this._getItemIndex(activeElement);\n\n      var nextElement = element || activeElement && this._getItemByDirection(direction, activeElement);\n\n      var nextElementIndex = this._getItemIndex(nextElement);\n\n      var isCycling = Boolean(this._interval);\n      var directionalClassName;\n      var orderClassName;\n      var eventDirectionName;\n\n      if (direction === Direction.NEXT) {\n        directionalClassName = ClassName.LEFT;\n        orderClassName = ClassName.NEXT;\n        eventDirectionName = Direction.LEFT;\n      } else {\n        directionalClassName = ClassName.RIGHT;\n        orderClassName = ClassName.PREV;\n        eventDirectionName = Direction.RIGHT;\n      }\n\n      if (nextElement && $(nextElement).hasClass(ClassName.ACTIVE)) {\n        this._isSliding = false;\n        return;\n      }\n\n      var slideEvent = this._triggerSlideEvent(nextElement, eventDirectionName);\n\n      if (slideEvent.isDefaultPrevented()) {\n        return;\n      }\n\n      if (!activeElement || !nextElement) {\n        // Some weirdness is happening, so we bail\n        return;\n      }\n\n      this._isSliding = true;\n\n      if (isCycling) {\n        this.pause();\n      }\n\n      this._setActiveIndicatorElement(nextElement);\n\n      var slidEvent = $.Event(Event.SLID, {\n        relatedTarget: nextElement,\n        direction: eventDirectionName,\n        from: activeElementIndex,\n        to: nextElementIndex\n      });\n\n      if ($(this._element).hasClass(ClassName.SLIDE)) {\n        $(nextElement).addClass(orderClassName);\n        Util.reflow(nextElement);\n        $(activeElement).addClass(directionalClassName);\n        $(nextElement).addClass(directionalClassName);\n        var nextElementInterval = parseInt(nextElement.getAttribute('data-interval'), 10);\n\n        if (nextElementInterval) {\n          this._config.defaultInterval = this._config.defaultInterval || this._config.interval;\n          this._config.interval = nextElementInterval;\n        } else {\n          this._config.interval = this._config.defaultInterval || this._config.interval;\n        }\n\n        var transitionDuration = Util.getTransitionDurationFromElement(activeElement);\n        $(activeElement).one(Util.TRANSITION_END, function () {\n          $(nextElement).removeClass(directionalClassName + \" \" + orderClassName).addClass(ClassName.ACTIVE);\n          $(activeElement).removeClass(ClassName.ACTIVE + \" \" + orderClassName + \" \" + directionalClassName);\n          _this4._isSliding = false;\n          setTimeout(function () {\n            return $(_this4._element).trigger(slidEvent);\n          }, 0);\n        }).emulateTransitionEnd(transitionDuration);\n      } else {\n        $(activeElement).removeClass(ClassName.ACTIVE);\n        $(nextElement).addClass(ClassName.ACTIVE);\n        this._isSliding = false;\n        $(this._element).trigger(slidEvent);\n      }\n\n      if (isCycling) {\n        this.cycle();\n      }\n    } // Static\n    ;\n\n    Carousel._jQueryInterface = function _jQueryInterface(config) {\n      return this.each(function () {\n        var data = $(this).data(DATA_KEY);\n\n        var _config = _objectSpread({}, Default, $(this).data());\n\n        if (typeof config === 'object') {\n          _config = _objectSpread({}, _config, config);\n        }\n\n        var action = typeof config === 'string' ? config : _config.slide;\n\n        if (!data) {\n          data = new Carousel(this, _config);\n          $(this).data(DATA_KEY, data);\n        }\n\n        if (typeof config === 'number') {\n          data.to(config);\n        } else if (typeof action === 'string') {\n          if (typeof data[action] === 'undefined') {\n            throw new TypeError(\"No method named \\\"\" + action + \"\\\"\");\n          }\n\n          data[action]();\n        } else if (_config.interval && _config.ride) {\n          data.pause();\n          data.cycle();\n        }\n      });\n    };\n\n    Carousel._dataApiClickHandler = function _dataApiClickHandler(event) {\n      var selector = Util.getSelectorFromElement(this);\n\n      if (!selector) {\n        return;\n      }\n\n      var target = $(selector)[0];\n\n      if (!target || !$(target).hasClass(ClassName.CAROUSEL)) {\n        return;\n      }\n\n      var config = _objectSpread({}, $(target).data(), $(this).data());\n\n      var slideIndex = this.getAttribute('data-slide-to');\n\n      if (slideIndex) {\n        config.interval = false;\n      }\n\n      Carousel._jQueryInterface.call($(target), config);\n\n      if (slideIndex) {\n        $(target).data(DATA_KEY).to(slideIndex);\n      }\n\n      event.preventDefault();\n    };\n\n    _createClass(Carousel, null, [{\n      key: \"VERSION\",\n      get: function get() {\n        return VERSION;\n      }\n    }, {\n      key: \"Default\",\n      get: function get() {\n        return Default;\n      }\n    }]);\n\n    return Carousel;\n  }();\n  /**\n   * ------------------------------------------------------------------------\n   * Data Api implementation\n   * ------------------------------------------------------------------------\n   */\n\n\n  $(document).on(Event.CLICK_DATA_API, Selector.DATA_SLIDE, Carousel._dataApiClickHandler);\n  $(window).on(Event.LOAD_DATA_API, function () {\n    var carousels = [].slice.call(document.querySelectorAll(Selector.DATA_RIDE));\n\n    for (var i = 0, len = carousels.length; i < len; i++) {\n      var $carousel = $(carousels[i]);\n\n      Carousel._jQueryInterface.call($carousel, $carousel.data());\n    }\n  });\n  /**\n   * ------------------------------------------------------------------------\n   * jQuery\n   * ------------------------------------------------------------------------\n   */\n\n  $.fn[NAME] = Carousel._jQueryInterface;\n  $.fn[NAME].Constructor = Carousel;\n\n  $.fn[NAME].noConflict = function () {\n    $.fn[NAME] = JQUERY_NO_CONFLICT;\n    return Carousel._jQueryInterface;\n  };\n\n  return Carousel;\n\n}));\n", "/*!\n  * Bootstrap collapse.js v4.3.1 (https://getbootstrap.com/)\n  * Copyright 2011-2019 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)\n  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n  */\n(function (global, factory) {\n  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('jquery'), require('./util.js')) :\n  typeof define === 'function' && define.amd ? define(['jquery', './util.js'], factory) :\n  (global = global || self, global.Collapse = factory(global.jQuery, global.Util));\n}(this, function ($, Util) { 'use strict';\n\n  $ = $ && $.hasOwnProperty('default') ? $['default'] : $;\n  Util = Util && Util.hasOwnProperty('default') ? Util['default'] : Util;\n\n  function _defineProperties(target, props) {\n    for (var i = 0; i < props.length; i++) {\n      var descriptor = props[i];\n      descriptor.enumerable = descriptor.enumerable || false;\n      descriptor.configurable = true;\n      if (\"value\" in descriptor) descriptor.writable = true;\n      Object.defineProperty(target, descriptor.key, descriptor);\n    }\n  }\n\n  function _createClass(Constructor, protoProps, staticProps) {\n    if (protoProps) _defineProperties(Constructor.prototype, protoProps);\n    if (staticProps) _defineProperties(Constructor, staticProps);\n    return Constructor;\n  }\n\n  function _defineProperty(obj, key, value) {\n    if (key in obj) {\n      Object.defineProperty(obj, key, {\n        value: value,\n        enumerable: true,\n        configurable: true,\n        writable: true\n      });\n    } else {\n      obj[key] = value;\n    }\n\n    return obj;\n  }\n\n  function _objectSpread(target) {\n    for (var i = 1; i < arguments.length; i++) {\n      var source = arguments[i] != null ? arguments[i] : {};\n      var ownKeys = Object.keys(source);\n\n      if (typeof Object.getOwnPropertySymbols === 'function') {\n        ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) {\n          return Object.getOwnPropertyDescriptor(source, sym).enumerable;\n        }));\n      }\n\n      ownKeys.forEach(function (key) {\n        _defineProperty(target, key, source[key]);\n      });\n    }\n\n    return target;\n  }\n\n  /**\n   * ------------------------------------------------------------------------\n   * Constants\n   * ------------------------------------------------------------------------\n   */\n\n  var NAME = 'collapse';\n  var VERSION = '4.3.1';\n  var DATA_KEY = 'bs.collapse';\n  var EVENT_KEY = \".\" + DATA_KEY;\n  var DATA_API_KEY = '.data-api';\n  var JQUERY_NO_CONFLICT = $.fn[NAME];\n  var Default = {\n    toggle: true,\n    parent: ''\n  };\n  var DefaultType = {\n    toggle: 'boolean',\n    parent: '(string|element)'\n  };\n  var Event = {\n    SHOW: \"show\" + EVENT_KEY,\n    SHOWN: \"shown\" + EVENT_KEY,\n    HIDE: \"hide\" + EVENT_KEY,\n    HIDDEN: \"hidden\" + EVENT_KEY,\n    CLICK_DATA_API: \"click\" + EVENT_KEY + DATA_API_KEY\n  };\n  var ClassName = {\n    SHOW: 'show',\n    COLLAPSE: 'collapse',\n    COLLAPSING: 'collapsing',\n    COLLAPSED: 'collapsed'\n  };\n  var Dimension = {\n    WIDTH: 'width',\n    HEIGHT: 'height'\n  };\n  var Selector = {\n    ACTIVES: '.show, .collapsing',\n    DATA_TOGGLE: '[data-toggle=\"collapse\"]'\n    /**\n     * ------------------------------------------------------------------------\n     * Class Definition\n     * ------------------------------------------------------------------------\n     */\n\n  };\n\n  var Collapse =\n  /*#__PURE__*/\n  function () {\n    function Collapse(element, config) {\n      this._isTransitioning = false;\n      this._element = element;\n      this._config = this._getConfig(config);\n      this._triggerArray = [].slice.call(document.querySelectorAll(\"[data-toggle=\\\"collapse\\\"][href=\\\"#\" + element.id + \"\\\"],\" + (\"[data-toggle=\\\"collapse\\\"][data-target=\\\"#\" + element.id + \"\\\"]\")));\n      var toggleList = [].slice.call(document.querySelectorAll(Selector.DATA_TOGGLE));\n\n      for (var i = 0, len = toggleList.length; i < len; i++) {\n        var elem = toggleList[i];\n        var selector = Util.getSelectorFromElement(elem);\n        var filterElement = [].slice.call(document.querySelectorAll(selector)).filter(function (foundElem) {\n          return foundElem === element;\n        });\n\n        if (selector !== null && filterElement.length > 0) {\n          this._selector = selector;\n\n          this._triggerArray.push(elem);\n        }\n      }\n\n      this._parent = this._config.parent ? this._getParent() : null;\n\n      if (!this._config.parent) {\n        this._addAriaAndCollapsedClass(this._element, this._triggerArray);\n      }\n\n      if (this._config.toggle) {\n        this.toggle();\n      }\n    } // Getters\n\n\n    var _proto = Collapse.prototype;\n\n    // Public\n    _proto.toggle = function toggle() {\n      if ($(this._element).hasClass(ClassName.SHOW)) {\n        this.hide();\n      } else {\n        this.show();\n      }\n    };\n\n    _proto.show = function show() {\n      var _this = this;\n\n      if (this._isTransitioning || $(this._element).hasClass(ClassName.SHOW)) {\n        return;\n      }\n\n      var actives;\n      var activesData;\n\n      if (this._parent) {\n        actives = [].slice.call(this._parent.querySelectorAll(Selector.ACTIVES)).filter(function (elem) {\n          if (typeof _this._config.parent === 'string') {\n            return elem.getAttribute('data-parent') === _this._config.parent;\n          }\n\n          return elem.classList.contains(ClassName.COLLAPSE);\n        });\n\n        if (actives.length === 0) {\n          actives = null;\n        }\n      }\n\n      if (actives) {\n        activesData = $(actives).not(this._selector).data(DATA_KEY);\n\n        if (activesData && activesData._isTransitioning) {\n          return;\n        }\n      }\n\n      var startEvent = $.Event(Event.SHOW);\n      $(this._element).trigger(startEvent);\n\n      if (startEvent.isDefaultPrevented()) {\n        return;\n      }\n\n      if (actives) {\n        Collapse._jQueryInterface.call($(actives).not(this._selector), 'hide');\n\n        if (!activesData) {\n          $(actives).data(DATA_KEY, null);\n        }\n      }\n\n      var dimension = this._getDimension();\n\n      $(this._element).removeClass(ClassName.COLLAPSE).addClass(ClassName.COLLAPSING);\n      this._element.style[dimension] = 0;\n\n      if (this._triggerArray.length) {\n        $(this._triggerArray).removeClass(ClassName.COLLAPSED).attr('aria-expanded', true);\n      }\n\n      this.setTransitioning(true);\n\n      var complete = function complete() {\n        $(_this._element).removeClass(ClassName.COLLAPSING).addClass(ClassName.COLLAPSE).addClass(ClassName.SHOW);\n        _this._element.style[dimension] = '';\n\n        _this.setTransitioning(false);\n\n        $(_this._element).trigger(Event.SHOWN);\n      };\n\n      var capitalizedDimension = dimension[0].toUpperCase() + dimension.slice(1);\n      var scrollSize = \"scroll\" + capitalizedDimension;\n      var transitionDuration = Util.getTransitionDurationFromElement(this._element);\n      $(this._element).one(Util.TRANSITION_END, complete).emulateTransitionEnd(transitionDuration);\n      this._element.style[dimension] = this._element[scrollSize] + \"px\";\n    };\n\n    _proto.hide = function hide() {\n      var _this2 = this;\n\n      if (this._isTransitioning || !$(this._element).hasClass(ClassName.SHOW)) {\n        return;\n      }\n\n      var startEvent = $.Event(Event.HIDE);\n      $(this._element).trigger(startEvent);\n\n      if (startEvent.isDefaultPrevented()) {\n        return;\n      }\n\n      var dimension = this._getDimension();\n\n      this._element.style[dimension] = this._element.getBoundingClientRect()[dimension] + \"px\";\n      Util.reflow(this._element);\n      $(this._element).addClass(ClassName.COLLAPSING).removeClass(ClassName.COLLAPSE).removeClass(ClassName.SHOW);\n      var triggerArrayLength = this._triggerArray.length;\n\n      if (triggerArrayLength > 0) {\n        for (var i = 0; i < triggerArrayLength; i++) {\n          var trigger = this._triggerArray[i];\n          var selector = Util.getSelectorFromElement(trigger);\n\n          if (selector !== null) {\n            var $elem = $([].slice.call(document.querySelectorAll(selector)));\n\n            if (!$elem.hasClass(ClassName.SHOW)) {\n              $(trigger).addClass(ClassName.COLLAPSED).attr('aria-expanded', false);\n            }\n          }\n        }\n      }\n\n      this.setTransitioning(true);\n\n      var complete = function complete() {\n        _this2.setTransitioning(false);\n\n        $(_this2._element).removeClass(ClassName.COLLAPSING).addClass(ClassName.COLLAPSE).trigger(Event.HIDDEN);\n      };\n\n      this._element.style[dimension] = '';\n      var transitionDuration = Util.getTransitionDurationFromElement(this._element);\n      $(this._element).one(Util.TRANSITION_END, complete).emulateTransitionEnd(transitionDuration);\n    };\n\n    _proto.setTransitioning = function setTransitioning(isTransitioning) {\n      this._isTransitioning = isTransitioning;\n    };\n\n    _proto.dispose = function dispose() {\n      $.removeData(this._element, DATA_KEY);\n      this._config = null;\n      this._parent = null;\n      this._element = null;\n      this._triggerArray = null;\n      this._isTransitioning = null;\n    } // Private\n    ;\n\n    _proto._getConfig = function _getConfig(config) {\n      config = _objectSpread({}, Default, config);\n      config.toggle = Boolean(config.toggle); // Coerce string values\n\n      Util.typeCheckConfig(NAME, config, DefaultType);\n      return config;\n    };\n\n    _proto._getDimension = function _getDimension() {\n      var hasWidth = $(this._element).hasClass(Dimension.WIDTH);\n      return hasWidth ? Dimension.WIDTH : Dimension.HEIGHT;\n    };\n\n    _proto._getParent = function _getParent() {\n      var _this3 = this;\n\n      var parent;\n\n      if (Util.isElement(this._config.parent)) {\n        parent = this._config.parent; // It's a jQuery object\n\n        if (typeof this._config.parent.jquery !== 'undefined') {\n          parent = this._config.parent[0];\n        }\n      } else {\n        parent = document.querySelector(this._config.parent);\n      }\n\n      var selector = \"[data-toggle=\\\"collapse\\\"][data-parent=\\\"\" + this._config.parent + \"\\\"]\";\n      var children = [].slice.call(parent.querySelectorAll(selector));\n      $(children).each(function (i, element) {\n        _this3._addAriaAndCollapsedClass(Collapse._getTargetFromElement(element), [element]);\n      });\n      return parent;\n    };\n\n    _proto._addAriaAndCollapsedClass = function _addAriaAndCollapsedClass(element, triggerArray) {\n      var isOpen = $(element).hasClass(ClassName.SHOW);\n\n      if (triggerArray.length) {\n        $(triggerArray).toggleClass(ClassName.COLLAPSED, !isOpen).attr('aria-expanded', isOpen);\n      }\n    } // Static\n    ;\n\n    Collapse._getTargetFromElement = function _getTargetFromElement(element) {\n      var selector = Util.getSelectorFromElement(element);\n      return selector ? document.querySelector(selector) : null;\n    };\n\n    Collapse._jQueryInterface = function _jQueryInterface(config) {\n      return this.each(function () {\n        var $this = $(this);\n        var data = $this.data(DATA_KEY);\n\n        var _config = _objectSpread({}, Default, $this.data(), typeof config === 'object' && config ? config : {});\n\n        if (!data && _config.toggle && /show|hide/.test(config)) {\n          _config.toggle = false;\n        }\n\n        if (!data) {\n          data = new Collapse(this, _config);\n          $this.data(DATA_KEY, data);\n        }\n\n        if (typeof config === 'string') {\n          if (typeof data[config] === 'undefined') {\n            throw new TypeError(\"No method named \\\"\" + config + \"\\\"\");\n          }\n\n          data[config]();\n        }\n      });\n    };\n\n    _createClass(Collapse, null, [{\n      key: \"VERSION\",\n      get: function get() {\n        return VERSION;\n      }\n    }, {\n      key: \"Default\",\n      get: function get() {\n        return Default;\n      }\n    }]);\n\n    return Collapse;\n  }();\n  /**\n   * ------------------------------------------------------------------------\n   * Data Api implementation\n   * ------------------------------------------------------------------------\n   */\n\n\n  $(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {\n    // preventDefault only for <a> elements (which change the URL) not inside the collapsible element\n    if (event.currentTarget.tagName === 'A') {\n      event.preventDefault();\n    }\n\n    var $trigger = $(this);\n    var selector = Util.getSelectorFromElement(this);\n    var selectors = [].slice.call(document.querySelectorAll(selector));\n    $(selectors).each(function () {\n      var $target = $(this);\n      var data = $target.data(DATA_KEY);\n      var config = data ? 'toggle' : $trigger.data();\n\n      Collapse._jQueryInterface.call($target, config);\n    });\n  });\n  /**\n   * ------------------------------------------------------------------------\n   * jQuery\n   * ------------------------------------------------------------------------\n   */\n\n  $.fn[NAME] = Collapse._jQueryInterface;\n  $.fn[NAME].Constructor = Collapse;\n\n  $.fn[NAME].noConflict = function () {\n    $.fn[NAME] = JQUERY_NO_CONFLICT;\n    return Collapse._jQueryInterface;\n  };\n\n  return Collapse;\n\n}));\n", "/*!\n  * Bootstrap dropdown.js v4.3.1 (https://getbootstrap.com/)\n  * Copyright 2011-2019 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)\n  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n  */\n(function (global, factory) {\n  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('jquery'), require('popper.js'), require('./util.js')) :\n  typeof define === 'function' && define.amd ? define(['jquery', 'popper.js', './util.js'], factory) :\n  (global = global || self, global.Dropdown = factory(global.jQuery, global.Popper, global.Util));\n}(this, function ($, Popper, Util) { 'use strict';\n\n  $ = $ && $.hasOwnProperty('default') ? $['default'] : $;\n  Popper = Popper && Popper.hasOwnProperty('default') ? Popper['default'] : Popper;\n  Util = Util && Util.hasOwnProperty('default') ? Util['default'] : Util;\n\n  function _defineProperties(target, props) {\n    for (var i = 0; i < props.length; i++) {\n      var descriptor = props[i];\n      descriptor.enumerable = descriptor.enumerable || false;\n      descriptor.configurable = true;\n      if (\"value\" in descriptor) descriptor.writable = true;\n      Object.defineProperty(target, descriptor.key, descriptor);\n    }\n  }\n\n  function _createClass(Constructor, protoProps, staticProps) {\n    if (protoProps) _defineProperties(Constructor.prototype, protoProps);\n    if (staticProps) _defineProperties(Constructor, staticProps);\n    return Constructor;\n  }\n\n  function _defineProperty(obj, key, value) {\n    if (key in obj) {\n      Object.defineProperty(obj, key, {\n        value: value,\n        enumerable: true,\n        configurable: true,\n        writable: true\n      });\n    } else {\n      obj[key] = value;\n    }\n\n    return obj;\n  }\n\n  function _objectSpread(target) {\n    for (var i = 1; i < arguments.length; i++) {\n      var source = arguments[i] != null ? arguments[i] : {};\n      var ownKeys = Object.keys(source);\n\n      if (typeof Object.getOwnPropertySymbols === 'function') {\n        ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) {\n          return Object.getOwnPropertyDescriptor(source, sym).enumerable;\n        }));\n      }\n\n      ownKeys.forEach(function (key) {\n        _defineProperty(target, key, source[key]);\n      });\n    }\n\n    return target;\n  }\n\n  /**\n   * ------------------------------------------------------------------------\n   * Constants\n   * ------------------------------------------------------------------------\n   */\n\n  var NAME = 'dropdown';\n  var VERSION = '4.3.1';\n  var DATA_KEY = 'bs.dropdown';\n  var EVENT_KEY = \".\" + DATA_KEY;\n  var DATA_API_KEY = '.data-api';\n  var JQUERY_NO_CONFLICT = $.fn[NAME];\n  var ESCAPE_KEYCODE = 27; // KeyboardEvent.which value for Escape (Esc) key\n\n  var SPACE_KEYCODE = 32; // KeyboardEvent.which value for space key\n\n  var TAB_KEYCODE = 9; // KeyboardEvent.which value for tab key\n\n  var ARROW_UP_KEYCODE = 38; // KeyboardEvent.which value for up arrow key\n\n  var ARROW_DOWN_KEYCODE = 40; // KeyboardEvent.which value for down arrow key\n\n  var RIGHT_MOUSE_BUTTON_WHICH = 3; // MouseEvent.which value for the right button (assuming a right-handed mouse)\n\n  var REGEXP_KEYDOWN = new RegExp(ARROW_UP_KEYCODE + \"|\" + ARROW_DOWN_KEYCODE + \"|\" + ESCAPE_KEYCODE);\n  var Event = {\n    HIDE: \"hide\" + EVENT_KEY,\n    HIDDEN: \"hidden\" + EVENT_KEY,\n    SHOW: \"show\" + EVENT_KEY,\n    SHOWN: \"shown\" + EVENT_KEY,\n    CLICK: \"click\" + EVENT_KEY,\n    CLICK_DATA_API: \"click\" + EVENT_KEY + DATA_API_KEY,\n    KEYDOWN_DATA_API: \"keydown\" + EVENT_KEY + DATA_API_KEY,\n    KEYUP_DATA_API: \"keyup\" + EVENT_KEY + DATA_API_KEY\n  };\n  var ClassName = {\n    DISABLED: 'disabled',\n    SHOW: 'show',\n    DROPUP: 'dropup',\n    DROPRIGHT: 'dropright',\n    DROPLEFT: 'dropleft',\n    MENURIGHT: 'dropdown-menu-right',\n    MENULEFT: 'dropdown-menu-left',\n    POSITION_STATIC: 'position-static'\n  };\n  var Selector = {\n    DATA_TOGGLE: '[data-toggle=\"dropdown\"]',\n    FORM_CHILD: '.dropdown form',\n    MENU: '.dropdown-menu:not(.o-dropdown--menu)', // Odoo fix task-2764821\n    NAVBAR_NAV: '.navbar-nav',\n    VISIBLE_ITEMS: '.dropdown-menu .dropdown-item:not(.disabled):not(:disabled)'\n  };\n  var AttachmentMap = {\n    TOP: 'top-start',\n    TOPEND: 'top-end',\n    BOTTOM: 'bottom-start',\n    BOTTOMEND: 'bottom-end',\n    RIGHT: 'right-start',\n    RIGHTEND: 'right-end',\n    LEFT: 'left-start',\n    LEFTEND: 'left-end'\n  };\n  var Default = {\n    offset: 0,\n    flip: true,\n    boundary: 'scrollParent',\n    reference: 'toggle',\n    display: 'dynamic'\n  };\n  var DefaultType = {\n    offset: '(number|string|function)',\n    flip: 'boolean',\n    boundary: '(string|element)',\n    reference: '(string|element)',\n    display: 'string'\n    /**\n     * ------------------------------------------------------------------------\n     * Class Definition\n     * ------------------------------------------------------------------------\n     */\n\n  };\n\n  var Dropdown =\n  /*#__PURE__*/\n  function () {\n    function Dropdown(element, config) {\n      this._element = element;\n      this._popper = null;\n      this._config = this._getConfig(config);\n      this._menu = this._getMenuElement();\n      this._inNavbar = this._detectNavbar();\n\n      this._addEventListeners();\n    } // Getters\n\n\n    var _proto = Dropdown.prototype;\n\n    // Public\n    _proto.toggle = function toggle() {\n      if (this._element.disabled || $(this._element).hasClass(ClassName.DISABLED)) {\n        return;\n      }\n\n      var parent = Dropdown._getParentFromElement(this._element);\n\n      var isActive = $(this._menu).hasClass(ClassName.SHOW);\n\n      Dropdown._clearMenus();\n\n      if (isActive) {\n        return;\n      }\n\n      var relatedTarget = {\n        relatedTarget: this._element\n      };\n      var showEvent = $.Event(Event.SHOW, relatedTarget);\n      $(parent).trigger(showEvent);\n\n      if (showEvent.isDefaultPrevented()) {\n        return;\n      } // Disable totally Popper.js for Dropdown in Navbar\n\n\n      if (!this._inNavbar) {\n        /**\n         * Check for Popper dependency\n         * Popper - https://popper.js.org\n         */\n        if (typeof Popper === 'undefined') {\n          throw new TypeError('Bootstrap\\'s dropdowns require Popper.js (https://popper.js.org/)');\n        }\n\n        var referenceElement = this._element;\n\n        if (this._config.reference === 'parent') {\n          referenceElement = parent;\n        } else if (Util.isElement(this._config.reference)) {\n          referenceElement = this._config.reference; // Check if it's jQuery element\n\n          if (typeof this._config.reference.jquery !== 'undefined') {\n            referenceElement = this._config.reference[0];\n          }\n        } // If boundary is not `scrollParent`, then set position to `static`\n        // to allow the menu to \"escape\" the scroll parent's boundaries\n        // https://github.com/twbs/bootstrap/issues/24251\n\n\n        if (this._config.boundary !== 'scrollParent') {\n          $(parent).addClass(ClassName.POSITION_STATIC);\n        }\n\n        this._popper = new Popper(referenceElement, this._menu, this._getPopperConfig());\n      } // If this is a touch-enabled device we add extra\n      // empty mouseover listeners to the body's immediate children;\n      // only needed because of broken event delegation on iOS\n      // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html\n\n\n      if ('ontouchstart' in document.documentElement && $(parent).closest(Selector.NAVBAR_NAV).length === 0) {\n        $(document.body).children().on('mouseover', null, $.noop);\n      }\n\n      this._element.focus();\n\n      this._element.setAttribute('aria-expanded', true);\n\n      $(this._menu).toggleClass(ClassName.SHOW);\n      $(parent).toggleClass(ClassName.SHOW).trigger($.Event(Event.SHOWN, relatedTarget));\n    };\n\n    _proto.show = function show() {\n      if (this._element.disabled || $(this._element).hasClass(ClassName.DISABLED) || $(this._menu).hasClass(ClassName.SHOW)) {\n        return;\n      }\n\n      var relatedTarget = {\n        relatedTarget: this._element\n      };\n      var showEvent = $.Event(Event.SHOW, relatedTarget);\n\n      var parent = Dropdown._getParentFromElement(this._element);\n\n      $(parent).trigger(showEvent);\n\n      if (showEvent.isDefaultPrevented()) {\n        return;\n      }\n\n      $(this._menu).toggleClass(ClassName.SHOW);\n      $(parent).toggleClass(ClassName.SHOW).trigger($.Event(Event.SHOWN, relatedTarget));\n    };\n\n    _proto.hide = function hide() {\n      if (this._element.disabled || $(this._element).hasClass(ClassName.DISABLED) || !$(this._menu).hasClass(ClassName.SHOW)) {\n        return;\n      }\n\n      var relatedTarget = {\n        relatedTarget: this._element\n      };\n      var hideEvent = $.Event(Event.HIDE, relatedTarget);\n\n      var parent = Dropdown._getParentFromElement(this._element);\n\n      $(parent).trigger(hideEvent);\n\n      if (hideEvent.isDefaultPrevented()) {\n        return;\n      }\n\n      $(this._menu).toggleClass(ClassName.SHOW);\n      $(parent).toggleClass(ClassName.SHOW).trigger($.Event(Event.HIDDEN, relatedTarget));\n    };\n\n    _proto.dispose = function dispose() {\n      $.removeData(this._element, DATA_KEY);\n      $(this._element).off(EVENT_KEY);\n      this._element = null;\n      this._menu = null;\n\n      if (this._popper !== null) {\n        this._popper.destroy();\n\n        this._popper = null;\n      }\n    };\n\n    _proto.update = function update() {\n      this._inNavbar = this._detectNavbar();\n\n      if (this._popper !== null) {\n        this._popper.scheduleUpdate();\n      }\n    } // Private\n    ;\n\n    _proto._addEventListeners = function _addEventListeners() {\n      var _this = this;\n\n      $(this._element).on(Event.CLICK, function (event) {\n        event.preventDefault();\n        event.stopPropagation();\n\n        _this.toggle();\n      });\n    };\n\n    _proto._getConfig = function _getConfig(config) {\n      config = _objectSpread({}, this.constructor.Default, $(this._element).data(), config);\n      Util.typeCheckConfig(NAME, config, this.constructor.DefaultType);\n      return config;\n    };\n\n    _proto._getMenuElement = function _getMenuElement() {\n      if (!this._menu) {\n        var parent = Dropdown._getParentFromElement(this._element);\n\n        if (parent) {\n          this._menu = parent.querySelector(Selector.MENU);\n        }\n      }\n\n      return this._menu;\n    };\n\n    _proto._getPlacement = function _getPlacement() {\n      var $parentDropdown = $(this._element.parentNode);\n      var placement = AttachmentMap.BOTTOM; // Handle dropup\n\n      if ($parentDropdown.hasClass(ClassName.DROPUP)) {\n        placement = AttachmentMap.TOP;\n\n        if ($(this._menu).hasClass(ClassName.MENURIGHT)) {\n          placement = AttachmentMap.TOPEND;\n        }\n      } else if ($parentDropdown.hasClass(ClassName.DROPRIGHT)) {\n        placement = AttachmentMap.RIGHT;\n      } else if ($parentDropdown.hasClass(ClassName.DROPLEFT)) {\n        placement = AttachmentMap.LEFT;\n      } else if ($(this._menu).hasClass(ClassName.MENURIGHT)) {\n        placement = AttachmentMap.BOTTOMEND;\n      }\n\n      return placement;\n    };\n\n    _proto._detectNavbar = function _detectNavbar() {\n      return $(this._element).closest('.navbar').length > 0;\n    };\n\n    _proto._getOffset = function _getOffset() {\n      var _this2 = this;\n\n      var offset = {};\n\n      if (typeof this._config.offset === 'function') {\n        offset.fn = function (data) {\n          data.offsets = _objectSpread({}, data.offsets, _this2._config.offset(data.offsets, _this2._element) || {});\n          return data;\n        };\n      } else {\n        offset.offset = this._config.offset;\n      }\n\n      return offset;\n    };\n\n    _proto._getPopperConfig = function _getPopperConfig() {\n      var popperConfig = {\n        placement: this._getPlacement(),\n        modifiers: {\n          offset: this._getOffset(),\n          flip: {\n            enabled: this._config.flip\n          },\n          preventOverflow: {\n            boundariesElement: this._config.boundary\n          }\n        } // Disable Popper.js if we have a static display\n\n      };\n\n      if (this._config.display === 'static') {\n        popperConfig.modifiers.applyStyle = {\n          enabled: false\n        };\n      }\n\n      return popperConfig;\n    } // Static\n    ;\n\n    Dropdown._jQueryInterface = function _jQueryInterface(config) {\n      return this.each(function () {\n        var data = $(this).data(DATA_KEY);\n\n        var _config = typeof config === 'object' ? config : null;\n\n        if (!data) {\n          data = new Dropdown(this, _config);\n          $(this).data(DATA_KEY, data);\n        }\n\n        if (typeof config === 'string') {\n          if (typeof data[config] === 'undefined') {\n            throw new TypeError(\"No method named \\\"\" + config + \"\\\"\");\n          }\n\n          data[config]();\n        }\n      });\n    };\n\n    Dropdown._clearMenus = function _clearMenus(event) {\n      if (event && (event.which === RIGHT_MOUSE_BUTTON_WHICH || event.type === 'keyup' && event.which !== TAB_KEYCODE)) {\n        return;\n      }\n\n      var toggles = [].slice.call(document.querySelectorAll(Selector.DATA_TOGGLE));\n\n      for (var i = 0, len = toggles.length; i < len; i++) {\n        var parent = Dropdown._getParentFromElement(toggles[i]);\n\n        var context = $(toggles[i]).data(DATA_KEY);\n        var relatedTarget = {\n          relatedTarget: toggles[i]\n        };\n\n        if (event && event.type === 'click') {\n          relatedTarget.clickEvent = event;\n        }\n\n        if (!context) {\n          continue;\n        }\n\n        var dropdownMenu = context._menu;\n\n        if (!$(parent).hasClass(ClassName.SHOW)) {\n          continue;\n        }\n\n        if (event && (event.type === 'click' && /input|textarea/i.test(event.target.tagName) || event.type === 'keyup' && event.which === TAB_KEYCODE) && $.contains(parent, event.target)) {\n          continue;\n        }\n\n        var hideEvent = $.Event(Event.HIDE, relatedTarget);\n        $(parent).trigger(hideEvent);\n\n        if (hideEvent.isDefaultPrevented()) {\n          continue;\n        } // If this is a touch-enabled device we remove the extra\n        // empty mouseover listeners we added for iOS support\n\n\n        if ('ontouchstart' in document.documentElement) {\n          $(document.body).children().off('mouseover', null, $.noop);\n        }\n\n        toggles[i].setAttribute('aria-expanded', 'false');\n        $(dropdownMenu).removeClass(ClassName.SHOW);\n        $(parent).removeClass(ClassName.SHOW).trigger($.Event(Event.HIDDEN, relatedTarget));\n      }\n    };\n\n    Dropdown._getParentFromElement = function _getParentFromElement(element) {\n      var parent;\n      var selector = Util.getSelectorFromElement(element);\n\n      if (selector) {\n        parent = document.querySelector(selector);\n      }\n\n      return parent || element.parentNode;\n    } // eslint-disable-next-line complexity\n    ;\n\n    Dropdown._dataApiKeydownHandler = function _dataApiKeydownHandler(event) {\n      // If not input/textarea:\n      //  - And not a key in REGEXP_KEYDOWN => not a dropdown command\n      // If input/textarea:\n      //  - If space key => not a dropdown command\n      //  - If key is other than escape\n      //    - If key is not up or down => not a dropdown command\n      //    - If trigger inside the menu => not a dropdown command\n      if (/input|textarea/i.test(event.target.tagName) ? event.which === SPACE_KEYCODE || event.which !== ESCAPE_KEYCODE && (event.which !== ARROW_DOWN_KEYCODE && event.which !== ARROW_UP_KEYCODE || $(event.target).closest(Selector.MENU).length) : !REGEXP_KEYDOWN.test(event.which)) {\n        return;\n      }\n\n      event.preventDefault();\n      event.stopPropagation();\n\n      if (this.disabled || $(this).hasClass(ClassName.DISABLED)) {\n        return;\n      }\n\n      var parent = Dropdown._getParentFromElement(this);\n\n      var isActive = $(parent).hasClass(ClassName.SHOW);\n\n      if (!isActive || isActive && (event.which === ESCAPE_KEYCODE || event.which === SPACE_KEYCODE)) {\n        if (event.which === ESCAPE_KEYCODE) {\n          var toggle = parent.querySelector(Selector.DATA_TOGGLE);\n          $(toggle).trigger('focus');\n        }\n\n        $(this).trigger('click');\n        return;\n      }\n\n      var items = [].slice.call(parent.querySelectorAll(Selector.VISIBLE_ITEMS));\n\n      if (items.length === 0) {\n        return;\n      }\n\n      var index = items.indexOf(event.target);\n\n      if (event.which === ARROW_UP_KEYCODE && index > 0) {\n        // Up\n        index--;\n      }\n\n      if (event.which === ARROW_DOWN_KEYCODE && index < items.length - 1) {\n        // Down\n        index++;\n      }\n\n      if (index < 0) {\n        index = 0;\n      }\n\n      items[index].focus();\n    };\n\n    _createClass(Dropdown, null, [{\n      key: \"VERSION\",\n      get: function get() {\n        return VERSION;\n      }\n    }, {\n      key: \"Default\",\n      get: function get() {\n        return Default;\n      }\n    }, {\n      key: \"DefaultType\",\n      get: function get() {\n        return DefaultType;\n      }\n    }]);\n\n    return Dropdown;\n  }();\n  /**\n   * ------------------------------------------------------------------------\n   * Data Api implementation\n   * ------------------------------------------------------------------------\n   */\n\n\n  $(document).on(Event.KEYDOWN_DATA_API, Selector.DATA_TOGGLE, Dropdown._dataApiKeydownHandler).on(Event.KEYDOWN_DATA_API, Selector.MENU, Dropdown._dataApiKeydownHandler).on(Event.CLICK_DATA_API + \" \" + Event.KEYUP_DATA_API, Dropdown._clearMenus).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {\n    event.preventDefault();\n    event.stopPropagation();\n\n    Dropdown._jQueryInterface.call($(this), 'toggle');\n  }).on(Event.CLICK_DATA_API, Selector.FORM_CHILD, function (e) {\n    e.stopPropagation();\n  });\n  /**\n   * ------------------------------------------------------------------------\n   * jQuery\n   * ------------------------------------------------------------------------\n   */\n\n  $.fn[NAME] = Dropdown._jQueryInterface;\n  $.fn[NAME].Constructor = Dropdown;\n\n  $.fn[NAME].noConflict = function () {\n    $.fn[NAME] = JQUERY_NO_CONFLICT;\n    return Dropdown._jQueryInterface;\n  };\n\n  return Dropdown;\n\n}));\n", "/*!\n  * Bootstrap modal.js v4.3.1 (https://getbootstrap.com/)\n  * Copyright 2011-2019 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)\n  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n  */\n(function (global, factory) {\n  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('jquery'), require('./util.js')) :\n  typeof define === 'function' && define.amd ? define(['jquery', './util.js'], factory) :\n  (global = global || self, global.Modal = factory(global.jQuery, global.Util));\n}(this, function ($, Util) { 'use strict';\n\n  $ = $ && $.hasOwnProperty('default') ? $['default'] : $;\n  Util = Util && Util.hasOwnProperty('default') ? Util['default'] : Util;\n\n  function _defineProperties(target, props) {\n    for (var i = 0; i < props.length; i++) {\n      var descriptor = props[i];\n      descriptor.enumerable = descriptor.enumerable || false;\n      descriptor.configurable = true;\n      if (\"value\" in descriptor) descriptor.writable = true;\n      Object.defineProperty(target, descriptor.key, descriptor);\n    }\n  }\n\n  function _createClass(Constructor, protoProps, staticProps) {\n    if (protoProps) _defineProperties(Constructor.prototype, protoProps);\n    if (staticProps) _defineProperties(Constructor, staticProps);\n    return Constructor;\n  }\n\n  function _defineProperty(obj, key, value) {\n    if (key in obj) {\n      Object.defineProperty(obj, key, {\n        value: value,\n        enumerable: true,\n        configurable: true,\n        writable: true\n      });\n    } else {\n      obj[key] = value;\n    }\n\n    return obj;\n  }\n\n  function _objectSpread(target) {\n    for (var i = 1; i < arguments.length; i++) {\n      var source = arguments[i] != null ? arguments[i] : {};\n      var ownKeys = Object.keys(source);\n\n      if (typeof Object.getOwnPropertySymbols === 'function') {\n        ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) {\n          return Object.getOwnPropertyDescriptor(source, sym).enumerable;\n        }));\n      }\n\n      ownKeys.forEach(function (key) {\n        _defineProperty(target, key, source[key]);\n      });\n    }\n\n    return target;\n  }\n\n  /**\n   * ------------------------------------------------------------------------\n   * Constants\n   * ------------------------------------------------------------------------\n   */\n\n  var NAME = 'modal';\n  var VERSION = '4.3.1';\n  var DATA_KEY = 'bs.modal';\n  var EVENT_KEY = \".\" + DATA_KEY;\n  var DATA_API_KEY = '.data-api';\n  var JQUERY_NO_CONFLICT = $.fn[NAME];\n  var ESCAPE_KEYCODE = 27; // KeyboardEvent.which value for Escape (Esc) key\n\n  var Default = {\n    backdrop: true,\n    keyboard: true,\n    focus: true,\n    show: true\n  };\n  var DefaultType = {\n    backdrop: '(boolean|string)',\n    keyboard: 'boolean',\n    focus: 'boolean',\n    show: 'boolean'\n  };\n  var Event = {\n    HIDE: \"hide\" + EVENT_KEY,\n    HIDDEN: \"hidden\" + EVENT_KEY,\n    SHOW: \"show\" + EVENT_KEY,\n    SHOWN: \"shown\" + EVENT_KEY,\n    FOCUSIN: \"focusin\" + EVENT_KEY,\n    RESIZE: \"resize\" + EVENT_KEY,\n    CLICK_DISMISS: \"click.dismiss\" + EVENT_KEY,\n    KEYDOWN_DISMISS: \"keydown.dismiss\" + EVENT_KEY,\n    MOUSEUP_DISMISS: \"mouseup.dismiss\" + EVENT_KEY,\n    MOUSEDOWN_DISMISS: \"mousedown.dismiss\" + EVENT_KEY,\n    CLICK_DATA_API: \"click\" + EVENT_KEY + DATA_API_KEY\n  };\n  var ClassName = {\n    SCROLLABLE: 'modal-dialog-scrollable',\n    SCROLLBAR_MEASURER: 'modal-scrollbar-measure',\n    BACKDROP: 'modal-backdrop',\n    OPEN: 'modal-open',\n    FADE: 'fade',\n    SHOW: 'show'\n  };\n  var Selector = {\n    DIALOG: '.modal-dialog',\n    MODAL_BODY: '.modal-body',\n    DATA_TOGGLE: '[data-toggle=\"modal\"]',\n    DATA_DISMISS: '[data-dismiss=\"modal\"]',\n    FIXED_CONTENT: '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top',\n    STICKY_CONTENT: '.sticky-top'\n    /**\n     * ------------------------------------------------------------------------\n     * Class Definition\n     * ------------------------------------------------------------------------\n     */\n\n  };\n\n  var Modal =\n  /*#__PURE__*/\n  function () {\n    function Modal(element, config) {\n      this._config = this._getConfig(config);\n      this._element = element;\n      this._dialog = element.querySelector(Selector.DIALOG);\n      this._backdrop = null;\n      this._isShown = false;\n      this._isBodyOverflowing = false;\n      this._ignoreBackdropClick = false;\n      this._isTransitioning = false;\n      this._scrollbarWidth = 0;\n    } // Getters\n\n\n    var _proto = Modal.prototype;\n\n    // Public\n    _proto.toggle = function toggle(relatedTarget) {\n      return this._isShown ? this.hide() : this.show(relatedTarget);\n    };\n\n    _proto.show = function show(relatedTarget) {\n      var _this = this;\n\n      if (this._isShown || this._isTransitioning) {\n        return;\n      }\n\n      if ($(this._element).hasClass(ClassName.FADE)) {\n        this._isTransitioning = true;\n      }\n\n      var showEvent = $.Event(Event.SHOW, {\n        relatedTarget: relatedTarget\n      });\n      $(this._element).trigger(showEvent);\n\n      if (this._isShown || showEvent.isDefaultPrevented()) {\n        return;\n      }\n\n      this._isShown = true;\n\n      this._checkScrollbar();\n\n      this._setScrollbar();\n\n      this._adjustDialog();\n\n      this._setEscapeEvent();\n\n      this._setResizeEvent();\n\n      $(this._element).on(Event.CLICK_DISMISS, Selector.DATA_DISMISS, function (event) {\n        return _this.hide(event);\n      });\n      $(this._dialog).on(Event.MOUSEDOWN_DISMISS, function () {\n        $(_this._element).one(Event.MOUSEUP_DISMISS, function (event) {\n          if ($(event.target).is(_this._element)) {\n            _this._ignoreBackdropClick = true;\n          }\n        });\n      });\n\n      this._showBackdrop(function () {\n        return _this._showElement(relatedTarget);\n      });\n    };\n\n    _proto.hide = function hide(event) {\n      var _this2 = this;\n\n      if (event) {\n        event.preventDefault();\n      }\n\n      if (!this._isShown || this._isTransitioning) {\n        return;\n      }\n\n      var hideEvent = $.Event(Event.HIDE);\n      $(this._element).trigger(hideEvent);\n\n      if (!this._isShown || hideEvent.isDefaultPrevented()) {\n        return;\n      }\n\n      this._isShown = false;\n      var transition = $(this._element).hasClass(ClassName.FADE);\n\n      if (transition) {\n        this._isTransitioning = true;\n      }\n\n      this._setEscapeEvent();\n\n      this._setResizeEvent();\n\n      $(document).off(Event.FOCUSIN);\n      $(this._element).removeClass(ClassName.SHOW);\n      $(this._element).off(Event.CLICK_DISMISS);\n      $(this._dialog).off(Event.MOUSEDOWN_DISMISS);\n\n      if (transition) {\n        var transitionDuration = Util.getTransitionDurationFromElement(this._element);\n        $(this._element).one(Util.TRANSITION_END, function (event) {\n          return _this2._hideModal(event);\n        }).emulateTransitionEnd(transitionDuration);\n      } else {\n        this._hideModal();\n      }\n    };\n\n    _proto.dispose = function dispose() {\n      [window, this._element, this._dialog].forEach(function (htmlElement) {\n        return $(htmlElement).off(EVENT_KEY);\n      });\n      /**\n       * `document` has 2 events `Event.FOCUSIN` and `Event.CLICK_DATA_API`\n       * Do not move `document` in `htmlElements` array\n       * It will remove `Event.CLICK_DATA_API` event that should remain\n       */\n\n      $(document).off(Event.FOCUSIN);\n      $.removeData(this._element, DATA_KEY);\n      this._config = null;\n      this._element = null;\n      this._dialog = null;\n      this._backdrop = null;\n      this._isShown = null;\n      this._isBodyOverflowing = null;\n      this._ignoreBackdropClick = null;\n      this._isTransitioning = null;\n      this._scrollbarWidth = null;\n    };\n\n    _proto.handleUpdate = function handleUpdate() {\n      this._adjustDialog();\n    } // Private\n    ;\n\n    _proto._getConfig = function _getConfig(config) {\n      config = _objectSpread({}, Default, config);\n      Util.typeCheckConfig(NAME, config, DefaultType);\n      return config;\n    };\n\n    _proto._showElement = function _showElement(relatedTarget) {\n      var _this3 = this;\n\n      var transition = $(this._element).hasClass(ClassName.FADE);\n\n      if (!this._element.parentNode || this._element.parentNode.nodeType !== Node.ELEMENT_NODE) {\n        // Don't move modal's DOM position\n        document.body.appendChild(this._element);\n      }\n\n      this._element.style.display = 'block';\n\n      this._element.removeAttribute('aria-hidden');\n\n      this._element.setAttribute('aria-modal', true);\n\n      if ($(this._dialog).hasClass(ClassName.SCROLLABLE)) {\n        this._dialog.querySelector(Selector.MODAL_BODY).scrollTop = 0;\n      } else {\n        this._element.scrollTop = 0;\n      }\n\n      if (transition) {\n        Util.reflow(this._element);\n      }\n\n      $(this._element).addClass(ClassName.SHOW);\n\n      if (this._config.focus) {\n        this._enforceFocus();\n      }\n\n      var shownEvent = $.Event(Event.SHOWN, {\n        relatedTarget: relatedTarget\n      });\n\n      var transitionComplete = function transitionComplete() {\n        if (_this3._config.focus) {\n          _this3._element.focus();\n        }\n\n        _this3._isTransitioning = false;\n        $(_this3._element).trigger(shownEvent);\n      };\n\n      if (transition) {\n        var transitionDuration = Util.getTransitionDurationFromElement(this._dialog);\n        $(this._dialog).one(Util.TRANSITION_END, transitionComplete).emulateTransitionEnd(transitionDuration);\n      } else {\n        transitionComplete();\n      }\n    };\n\n    _proto._enforceFocus = function _enforceFocus() {\n      var _this4 = this;\n\n      $(document).off(Event.FOCUSIN) // Guard against infinite focus loop\n      .on(Event.FOCUSIN, function (event) {\n        if (document !== event.target && _this4._element !== event.target && $(_this4._element).has(event.target).length === 0) {\n          _this4._element.focus();\n        }\n      });\n    };\n\n    _proto._setEscapeEvent = function _setEscapeEvent() {\n      var _this5 = this;\n\n      if (this._isShown && this._config.keyboard) {\n        $(this._element).on(Event.KEYDOWN_DISMISS, function (event) {\n          if (event.which === ESCAPE_KEYCODE) {\n            event.preventDefault();\n\n            _this5.hide();\n          }\n        });\n      } else if (!this._isShown) {\n        $(this._element).off(Event.KEYDOWN_DISMISS);\n      }\n    };\n\n    _proto._setResizeEvent = function _setResizeEvent() {\n      var _this6 = this;\n\n      if (this._isShown) {\n        $(window).on(Event.RESIZE, function (event) {\n          return _this6.handleUpdate(event);\n        });\n      } else {\n        $(window).off(Event.RESIZE);\n      }\n    };\n\n    _proto._hideModal = function _hideModal() {\n      var _this7 = this;\n\n      this._element.style.display = 'none';\n\n      this._element.setAttribute('aria-hidden', true);\n\n      this._element.removeAttribute('aria-modal');\n\n      this._isTransitioning = false;\n\n      this._showBackdrop(function () {\n        $(document.body).removeClass(ClassName.OPEN);\n\n        _this7._resetAdjustments();\n\n        _this7._resetScrollbar();\n\n        $(_this7._element).trigger(Event.HIDDEN);\n      });\n    };\n\n    _proto._removeBackdrop = function _removeBackdrop() {\n      if (this._backdrop) {\n        $(this._backdrop).remove();\n        this._backdrop = null;\n      }\n    };\n\n    _proto._showBackdrop = function _showBackdrop(callback) {\n      var _this8 = this;\n\n      var animate = $(this._element).hasClass(ClassName.FADE) ? ClassName.FADE : '';\n\n      if (this._isShown && this._config.backdrop) {\n        this._backdrop = document.createElement('div');\n        this._backdrop.className = ClassName.BACKDROP;\n\n        if (animate) {\n          this._backdrop.classList.add(animate);\n        }\n\n        $(this._backdrop).appendTo(document.body);\n        $(this._element).on(Event.CLICK_DISMISS, function (event) {\n          if (_this8._ignoreBackdropClick) {\n            _this8._ignoreBackdropClick = false;\n            return;\n          }\n\n          if (event.target !== event.currentTarget) {\n            return;\n          }\n\n          if (_this8._config.backdrop === 'static') {\n            _this8._element.focus();\n          } else {\n            _this8.hide();\n          }\n        });\n\n        if (animate) {\n          Util.reflow(this._backdrop);\n        }\n\n        $(this._backdrop).addClass(ClassName.SHOW);\n\n        if (!callback) {\n          return;\n        }\n\n        if (!animate) {\n          callback();\n          return;\n        }\n\n        var backdropTransitionDuration = Util.getTransitionDurationFromElement(this._backdrop);\n        $(this._backdrop).one(Util.TRANSITION_END, callback).emulateTransitionEnd(backdropTransitionDuration);\n      } else if (!this._isShown && this._backdrop) {\n        $(this._backdrop).removeClass(ClassName.SHOW);\n\n        var callbackRemove = function callbackRemove() {\n          _this8._removeBackdrop();\n\n          if (callback) {\n            callback();\n          }\n        };\n\n        if ($(this._element).hasClass(ClassName.FADE)) {\n          var _backdropTransitionDuration = Util.getTransitionDurationFromElement(this._backdrop);\n\n          $(this._backdrop).one(Util.TRANSITION_END, callbackRemove).emulateTransitionEnd(_backdropTransitionDuration);\n        } else {\n          callbackRemove();\n        }\n      } else if (callback) {\n        callback();\n      }\n    } // ----------------------------------------------------------------------\n    // the following methods are used to handle overflowing modals\n    // todo (fat): these should probably be refactored out of modal.js\n    // ----------------------------------------------------------------------\n    ;\n\n    _proto._adjustDialog = function _adjustDialog() {\n      var isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight;\n\n      if (!this._isBodyOverflowing && isModalOverflowing) {\n        this._element.style.paddingLeft = this._scrollbarWidth + \"px\";\n      }\n\n      if (this._isBodyOverflowing && !isModalOverflowing) {\n        this._element.style.paddingRight = this._scrollbarWidth + \"px\";\n      }\n    };\n\n    _proto._resetAdjustments = function _resetAdjustments() {\n      this._element.style.paddingLeft = '';\n      this._element.style.paddingRight = '';\n    };\n\n    _proto._checkScrollbar = function _checkScrollbar() {\n      var rect = document.body.getBoundingClientRect();\n      this._isBodyOverflowing = rect.left + rect.right < window.innerWidth;\n      this._scrollbarWidth = this._getScrollbarWidth();\n    };\n\n    _proto._setScrollbar = function _setScrollbar() {\n      var _this9 = this;\n\n      if (this._isBodyOverflowing) {\n        // Note: DOMNode.style.paddingRight returns the actual value or '' if not set\n        //   while $(DOMNode).css('padding-right') returns the calculated value or 0 if not set\n        var fixedContent = [].slice.call(document.querySelectorAll(Selector.FIXED_CONTENT));\n        var stickyContent = [].slice.call(document.querySelectorAll(Selector.STICKY_CONTENT)); // Adjust fixed content padding\n\n        $(fixedContent).each(function (index, element) {\n          var actualPadding = element.style.paddingRight;\n          var calculatedPadding = $(element).css('padding-right');\n          $(element).data('padding-right', actualPadding).css('padding-right', parseFloat(calculatedPadding) + _this9._scrollbarWidth + \"px\");\n        }); // Adjust sticky content margin\n\n        $(stickyContent).each(function (index, element) {\n          var actualMargin = element.style.marginRight;\n          var calculatedMargin = $(element).css('margin-right');\n          $(element).data('margin-right', actualMargin).css('margin-right', parseFloat(calculatedMargin) - _this9._scrollbarWidth + \"px\");\n        }); // Adjust body padding\n\n        var actualPadding = document.body.style.paddingRight;\n        var calculatedPadding = $(document.body).css('padding-right');\n        $(document.body).data('padding-right', actualPadding).css('padding-right', parseFloat(calculatedPadding) + this._scrollbarWidth + \"px\");\n      }\n\n      $(document.body).addClass(ClassName.OPEN);\n    };\n\n    _proto._resetScrollbar = function _resetScrollbar() {\n      // Restore fixed content padding\n      var fixedContent = [].slice.call(document.querySelectorAll(Selector.FIXED_CONTENT));\n      $(fixedContent).each(function (index, element) {\n        var padding = $(element).data('padding-right');\n        $(element).removeData('padding-right');\n        element.style.paddingRight = padding ? padding : '';\n      }); // Restore sticky content\n\n      var elements = [].slice.call(document.querySelectorAll(\"\" + Selector.STICKY_CONTENT));\n      $(elements).each(function (index, element) {\n        var margin = $(element).data('margin-right');\n\n        if (typeof margin !== 'undefined') {\n          $(element).css('margin-right', margin).removeData('margin-right');\n        }\n      }); // Restore body padding\n\n      var padding = $(document.body).data('padding-right');\n      $(document.body).removeData('padding-right');\n      document.body.style.paddingRight = padding ? padding : '';\n    };\n\n    _proto._getScrollbarWidth = function _getScrollbarWidth() {\n      // thx d.walsh\n      var scrollDiv = document.createElement('div');\n      scrollDiv.className = ClassName.SCROLLBAR_MEASURER;\n      document.body.appendChild(scrollDiv);\n      var scrollbarWidth = scrollDiv.getBoundingClientRect().width - scrollDiv.clientWidth;\n      document.body.removeChild(scrollDiv);\n      return scrollbarWidth;\n    } // Static\n    ;\n\n    Modal._jQueryInterface = function _jQueryInterface(config, relatedTarget) {\n      return this.each(function () {\n        var data = $(this).data(DATA_KEY);\n\n        var _config = _objectSpread({}, Default, $(this).data(), typeof config === 'object' && config ? config : {});\n\n        if (!data) {\n          data = new Modal(this, _config);\n          $(this).data(DATA_KEY, data);\n        }\n\n        if (typeof config === 'string') {\n          if (typeof data[config] === 'undefined') {\n            throw new TypeError(\"No method named \\\"\" + config + \"\\\"\");\n          }\n\n          data[config](relatedTarget);\n        } else if (_config.show) {\n          data.show(relatedTarget);\n        }\n      });\n    };\n\n    _createClass(Modal, null, [{\n      key: \"VERSION\",\n      get: function get() {\n        return VERSION;\n      }\n    }, {\n      key: \"Default\",\n      get: function get() {\n        return Default;\n      }\n    }]);\n\n    return Modal;\n  }();\n  /**\n   * ------------------------------------------------------------------------\n   * Data Api implementation\n   * ------------------------------------------------------------------------\n   */\n\n\n  $(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {\n    var _this10 = this;\n\n    var target;\n    var selector = Util.getSelectorFromElement(this);\n\n    if (selector) {\n      target = document.querySelector(selector);\n    }\n\n    var config = $(target).data(DATA_KEY) ? 'toggle' : _objectSpread({}, $(target).data(), $(this).data());\n\n    if (this.tagName === 'A' || this.tagName === 'AREA') {\n      event.preventDefault();\n    }\n\n    var $target = $(target).one(Event.SHOW, function (showEvent) {\n      if (showEvent.isDefaultPrevented()) {\n        // Only register focus restorer if modal will actually get shown\n        return;\n      }\n\n      $target.one(Event.HIDDEN, function () {\n        if ($(_this10).is(':visible')) {\n          _this10.focus();\n        }\n      });\n    });\n\n    Modal._jQueryInterface.call($(target), config, this);\n  });\n  /**\n   * ------------------------------------------------------------------------\n   * jQuery\n   * ------------------------------------------------------------------------\n   */\n\n  $.fn[NAME] = Modal._jQueryInterface;\n  $.fn[NAME].Constructor = Modal;\n\n  $.fn[NAME].noConflict = function () {\n    $.fn[NAME] = JQUERY_NO_CONFLICT;\n    return Modal._jQueryInterface;\n  };\n\n  return Modal;\n\n}));\n", "/*!\n  * Bootstrap tooltip.js v4.3.1 (https://getbootstrap.com/)\n  * Copyright 2011-2019 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)\n  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n  */\n(function (global, factory) {\n  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('jquery'), require('popper.js'), require('./util.js')) :\n  typeof define === 'function' && define.amd ? define(['jquery', 'popper.js', './util.js'], factory) :\n  (global = global || self, global.Tooltip = factory(global.jQuery, global.Popper, global.Util));\n}(this, function ($, Popper, Util) { 'use strict';\n\n  $ = $ && $.hasOwnProperty('default') ? $['default'] : $;\n  Popper = Popper && Popper.hasOwnProperty('default') ? Popper['default'] : Popper;\n  Util = Util && Util.hasOwnProperty('default') ? Util['default'] : Util;\n\n  function _defineProperties(target, props) {\n    for (var i = 0; i < props.length; i++) {\n      var descriptor = props[i];\n      descriptor.enumerable = descriptor.enumerable || false;\n      descriptor.configurable = true;\n      if (\"value\" in descriptor) descriptor.writable = true;\n      Object.defineProperty(target, descriptor.key, descriptor);\n    }\n  }\n\n  function _createClass(Constructor, protoProps, staticProps) {\n    if (protoProps) _defineProperties(Constructor.prototype, protoProps);\n    if (staticProps) _defineProperties(Constructor, staticProps);\n    return Constructor;\n  }\n\n  function _defineProperty(obj, key, value) {\n    if (key in obj) {\n      Object.defineProperty(obj, key, {\n        value: value,\n        enumerable: true,\n        configurable: true,\n        writable: true\n      });\n    } else {\n      obj[key] = value;\n    }\n\n    return obj;\n  }\n\n  function _objectSpread(target) {\n    for (var i = 1; i < arguments.length; i++) {\n      var source = arguments[i] != null ? arguments[i] : {};\n      var ownKeys = Object.keys(source);\n\n      if (typeof Object.getOwnPropertySymbols === 'function') {\n        ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) {\n          return Object.getOwnPropertyDescriptor(source, sym).enumerable;\n        }));\n      }\n\n      ownKeys.forEach(function (key) {\n        _defineProperty(target, key, source[key]);\n      });\n    }\n\n    return target;\n  }\n\n  /**\n   * --------------------------------------------------------------------------\n   * Bootstrap (v4.3.1): tools/sanitizer.js\n   * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n   * --------------------------------------------------------------------------\n   */\n  var uriAttrs = ['background', 'cite', 'href', 'itemtype', 'longdesc', 'poster', 'src', 'xlink:href'];\n  var ARIA_ATTRIBUTE_PATTERN = /^aria-[\\w-]*$/i;\n  var DefaultWhitelist = {\n    // Global attributes allowed on any supplied element below.\n    '*': ['class', 'dir', 'id', 'lang', 'role', ARIA_ATTRIBUTE_PATTERN],\n    a: ['target', 'href', 'title', 'rel'],\n    area: [],\n    b: [],\n    br: [],\n    col: [],\n    code: [],\n    div: [],\n    em: [],\n    hr: [],\n    h1: [],\n    h2: [],\n    h3: [],\n    h4: [],\n    h5: [],\n    h6: [],\n    i: [],\n    img: ['src', 'alt', 'title', 'width', 'height'],\n    li: [],\n    ol: [],\n    p: [],\n    pre: [],\n    s: [],\n    small: [],\n    span: [],\n    sub: [],\n    sup: [],\n    strong: [],\n    u: [],\n    ul: []\n    /**\n     * A pattern that recognizes a commonly useful subset of URLs that are safe.\n     *\n     * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts\n     */\n\n  };\n  var SAFE_URL_PATTERN = /^(?:(?:https?|mailto|ftp|tel|file):|[^&:/?#]*(?:[/?#]|$))/gi;\n  /**\n   * A pattern that matches safe data URLs. Only matches image, video and audio types.\n   *\n   * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts\n   */\n\n  var DATA_URL_PATTERN = /^data:(?:image\\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\\/(?:mpeg|mp4|ogg|webm)|audio\\/(?:mp3|oga|ogg|opus));base64,[a-z0-9+/]+=*$/i;\n\n  function allowedAttribute(attr, allowedAttributeList) {\n    var attrName = attr.nodeName.toLowerCase();\n\n    if (allowedAttributeList.indexOf(attrName) !== -1) {\n      if (uriAttrs.indexOf(attrName) !== -1) {\n        return Boolean(attr.nodeValue.match(SAFE_URL_PATTERN) || attr.nodeValue.match(DATA_URL_PATTERN));\n      }\n\n      return true;\n    }\n\n    var regExp = allowedAttributeList.filter(function (attrRegex) {\n      return attrRegex instanceof RegExp;\n    }); // Check if a regular expression validates the attribute.\n\n    for (var i = 0, l = regExp.length; i < l; i++) {\n      if (attrName.match(regExp[i])) {\n        return true;\n      }\n    }\n\n    return false;\n  }\n\n  function sanitizeHtml(unsafeHtml, whiteList, sanitizeFn) {\n    if (unsafeHtml.length === 0) {\n      return unsafeHtml;\n    }\n\n    if (sanitizeFn && typeof sanitizeFn === 'function') {\n      return sanitizeFn(unsafeHtml);\n    }\n\n    var domParser = new window.DOMParser();\n    var createdDocument = domParser.parseFromString(unsafeHtml, 'text/html');\n    var whitelistKeys = Object.keys(whiteList);\n    var elements = [].slice.call(createdDocument.body.querySelectorAll('*'));\n\n    var _loop = function _loop(i, len) {\n      var el = elements[i];\n      var elName = el.nodeName.toLowerCase();\n\n      if (whitelistKeys.indexOf(el.nodeName.toLowerCase()) === -1) {\n        el.parentNode.removeChild(el);\n        return \"continue\";\n      }\n\n      var attributeList = [].slice.call(el.attributes);\n      var whitelistedAttributes = [].concat(whiteList['*'] || [], whiteList[elName] || []);\n      attributeList.forEach(function (attr) {\n        if (!allowedAttribute(attr, whitelistedAttributes)) {\n          el.removeAttribute(attr.nodeName);\n        }\n      });\n    };\n\n    for (var i = 0, len = elements.length; i < len; i++) {\n      var _ret = _loop(i, len);\n\n      if (_ret === \"continue\") continue;\n    }\n\n    return createdDocument.body.innerHTML;\n  }\n\n  /**\n   * ------------------------------------------------------------------------\n   * Constants\n   * ------------------------------------------------------------------------\n   */\n\n  var NAME = 'tooltip';\n  var VERSION = '4.3.1';\n  var DATA_KEY = 'bs.tooltip';\n  var EVENT_KEY = \".\" + DATA_KEY;\n  var JQUERY_NO_CONFLICT = $.fn[NAME];\n  var CLASS_PREFIX = 'bs-tooltip';\n  var BSCLS_PREFIX_REGEX = new RegExp(\"(^|\\\\s)\" + CLASS_PREFIX + \"\\\\S+\", 'g');\n  var DISALLOWED_ATTRIBUTES = ['sanitize', 'whiteList', 'sanitizeFn'];\n  var DefaultType = {\n    animation: 'boolean',\n    template: 'string',\n    title: '(string|element|function)',\n    trigger: 'string',\n    delay: '(number|object)',\n    html: 'boolean',\n    selector: '(string|boolean)',\n    placement: '(string|function)',\n    offset: '(number|string|function)',\n    container: '(string|element|boolean)',\n    fallbackPlacement: '(string|array)',\n    boundary: '(string|element)',\n    sanitize: 'boolean',\n    sanitizeFn: '(null|function)',\n    whiteList: 'object'\n  };\n  var AttachmentMap = {\n    AUTO: 'auto',\n    TOP: 'top',\n    RIGHT: 'right',\n    BOTTOM: 'bottom',\n    LEFT: 'left'\n  };\n  var Default = {\n    animation: true,\n    template: '<div class=\"tooltip\" role=\"tooltip\">' + '<div class=\"arrow\"></div>' + '<div class=\"tooltip-inner\"></div></div>',\n    trigger: 'hover focus',\n    title: '',\n    delay: 0,\n    html: false,\n    selector: false,\n    placement: 'top',\n    offset: 0,\n    container: false,\n    fallbackPlacement: 'flip',\n    boundary: 'scrollParent',\n    sanitize: true,\n    sanitizeFn: null,\n    whiteList: DefaultWhitelist\n  };\n  var HoverState = {\n    SHOW: 'show',\n    OUT: 'out'\n  };\n  var Event = {\n    HIDE: \"hide\" + EVENT_KEY,\n    HIDDEN: \"hidden\" + EVENT_KEY,\n    SHOW: \"show\" + EVENT_KEY,\n    SHOWN: \"shown\" + EVENT_KEY,\n    INSERTED: \"inserted\" + EVENT_KEY,\n    CLICK: \"click\" + EVENT_KEY,\n    FOCUSIN: \"focusin\" + EVENT_KEY,\n    FOCUSOUT: \"focusout\" + EVENT_KEY,\n    MOUSEENTER: \"mouseenter\" + EVENT_KEY,\n    MOUSELEAVE: \"mouseleave\" + EVENT_KEY\n  };\n  var ClassName = {\n    FADE: 'fade',\n    SHOW: 'show'\n  };\n  var Selector = {\n    TOOLTIP: '.tooltip',\n    TOOLTIP_INNER: '.tooltip-inner',\n    ARROW: '.arrow'\n  };\n  var Trigger = {\n    HOVER: 'hover',\n    FOCUS: 'focus',\n    CLICK: 'click',\n    MANUAL: 'manual'\n    /**\n     * ------------------------------------------------------------------------\n     * Class Definition\n     * ------------------------------------------------------------------------\n     */\n\n  };\n\n  var Tooltip =\n  /*#__PURE__*/\n  function () {\n    function Tooltip(element, config) {\n      /**\n       * Check for Popper dependency\n       * Popper - https://popper.js.org\n       */\n      if (typeof Popper === 'undefined') {\n        throw new TypeError('Bootstrap\\'s tooltips require Popper.js (https://popper.js.org/)');\n      } // private\n\n\n      this._isEnabled = true;\n      this._timeout = 0;\n      this._hoverState = '';\n      this._activeTrigger = {};\n      this._popper = null; // Protected\n\n      this.element = element;\n      this.config = this._getConfig(config);\n      this.tip = null;\n\n      this._setListeners();\n    } // Getters\n\n\n    var _proto = Tooltip.prototype;\n\n    // Public\n    _proto.enable = function enable() {\n      this._isEnabled = true;\n    };\n\n    _proto.disable = function disable() {\n      this._isEnabled = false;\n    };\n\n    _proto.toggleEnabled = function toggleEnabled() {\n      this._isEnabled = !this._isEnabled;\n    };\n\n    _proto.toggle = function toggle(event) {\n      if (!this._isEnabled) {\n        return;\n      }\n\n      if (event) {\n        var dataKey = this.constructor.DATA_KEY;\n        var context = $(event.currentTarget).data(dataKey);\n\n        if (!context) {\n          context = new this.constructor(event.currentTarget, this._getDelegateConfig());\n          $(event.currentTarget).data(dataKey, context);\n        }\n\n        context._activeTrigger.click = !context._activeTrigger.click;\n\n        if (context._isWithActiveTrigger()) {\n          context._enter(null, context);\n        } else {\n          context._leave(null, context);\n        }\n      } else {\n        if ($(this.getTipElement()).hasClass(ClassName.SHOW)) {\n          this._leave(null, this);\n\n          return;\n        }\n\n        this._enter(null, this);\n      }\n    };\n\n    _proto.dispose = function dispose() {\n      clearTimeout(this._timeout);\n      $.removeData(this.element, this.constructor.DATA_KEY);\n      $(this.element).off(this.constructor.EVENT_KEY);\n      $(this.element).closest('.modal').off('hide.bs.modal');\n\n      if (this.tip) {\n        $(this.tip).remove();\n      }\n\n      this._isEnabled = null;\n      this._timeout = null;\n      this._hoverState = null;\n      this._activeTrigger = null;\n\n      if (this._popper !== null) {\n        this._popper.destroy();\n      }\n\n      this._popper = null;\n      this.element = null;\n      this.config = null;\n      this.tip = null;\n    };\n\n    _proto.show = function show() {\n      var _this = this;\n\n      if ($(this.element).css('display') === 'none') {\n        throw new Error('Please use show on visible elements');\n      }\n\n      var showEvent = $.Event(this.constructor.Event.SHOW);\n\n      if (this.isWithContent() && this._isEnabled) {\n        $(this.element).trigger(showEvent);\n        var shadowRoot = Util.findShadowRoot(this.element);\n        var isInTheDom = $.contains(shadowRoot !== null ? shadowRoot : this.element.ownerDocument.documentElement, this.element);\n\n        if (showEvent.isDefaultPrevented() || !isInTheDom) {\n          return;\n        }\n\n        var tip = this.getTipElement();\n        var tipId = Util.getUID(this.constructor.NAME);\n        tip.setAttribute('id', tipId);\n        this.element.setAttribute('aria-describedby', tipId);\n        this.setContent();\n\n        if (this.config.animation) {\n          $(tip).addClass(ClassName.FADE);\n        }\n\n        var placement = typeof this.config.placement === 'function' ? this.config.placement.call(this, tip, this.element) : this.config.placement;\n\n        var attachment = this._getAttachment(placement);\n\n        this.addAttachmentClass(attachment);\n\n        var container = this._getContainer();\n\n        $(tip).data(this.constructor.DATA_KEY, this);\n\n        if (!$.contains(this.element.ownerDocument.documentElement, this.tip)) {\n          $(tip).appendTo(container);\n        }\n\n        $(this.element).trigger(this.constructor.Event.INSERTED);\n        this._popper = new Popper(this.element, tip, {\n          placement: attachment,\n          modifiers: {\n            offset: this._getOffset(),\n            flip: {\n              behavior: this.config.fallbackPlacement\n            },\n            arrow: {\n              element: Selector.ARROW\n            },\n            preventOverflow: {\n              boundariesElement: this.config.boundary\n            }\n          },\n          onCreate: function onCreate(data) {\n            if (data.originalPlacement !== data.placement) {\n              _this._handlePopperPlacementChange(data);\n            }\n          },\n          onUpdate: function onUpdate(data) {\n            return _this._handlePopperPlacementChange(data);\n          }\n        });\n        $(tip).addClass(ClassName.SHOW); // If this is a touch-enabled device we add extra\n        // empty mouseover listeners to the body's immediate children;\n        // only needed because of broken event delegation on iOS\n        // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html\n\n        if ('ontouchstart' in document.documentElement) {\n          $(document.body).children().on('mouseover', null, $.noop);\n        }\n\n        var complete = function complete() {\n          if (_this.config.animation) {\n            _this._fixTransition();\n          }\n\n          var prevHoverState = _this._hoverState;\n          _this._hoverState = null;\n          $(_this.element).trigger(_this.constructor.Event.SHOWN);\n\n          if (prevHoverState === HoverState.OUT) {\n            _this._leave(null, _this);\n          }\n        };\n\n        if ($(this.tip).hasClass(ClassName.FADE)) {\n          var transitionDuration = Util.getTransitionDurationFromElement(this.tip);\n          $(this.tip).one(Util.TRANSITION_END, complete).emulateTransitionEnd(transitionDuration);\n        } else {\n          complete();\n        }\n      }\n    };\n\n    _proto.hide = function hide(callback) {\n      var _this2 = this;\n\n      var tip = this.getTipElement();\n      var hideEvent = $.Event(this.constructor.Event.HIDE);\n\n      var complete = function complete() {\n        if (_this2._hoverState !== HoverState.SHOW && tip.parentNode) {\n          tip.parentNode.removeChild(tip);\n        }\n\n        _this2._cleanTipClass();\n\n        _this2.element.removeAttribute('aria-describedby');\n\n        $(_this2.element).trigger(_this2.constructor.Event.HIDDEN);\n\n        if (_this2._popper !== null) {\n          _this2._popper.destroy();\n        }\n\n        if (callback) {\n          callback();\n        }\n      };\n\n      $(this.element).trigger(hideEvent);\n\n      if (hideEvent.isDefaultPrevented()) {\n        return;\n      }\n\n      $(tip).removeClass(ClassName.SHOW); // If this is a touch-enabled device we remove the extra\n      // empty mouseover listeners we added for iOS support\n\n      if ('ontouchstart' in document.documentElement) {\n        $(document.body).children().off('mouseover', null, $.noop);\n      }\n\n      this._activeTrigger[Trigger.CLICK] = false;\n      this._activeTrigger[Trigger.FOCUS] = false;\n      this._activeTrigger[Trigger.HOVER] = false;\n\n      if ($(this.tip).hasClass(ClassName.FADE)) {\n        var transitionDuration = Util.getTransitionDurationFromElement(tip);\n        $(tip).one(Util.TRANSITION_END, complete).emulateTransitionEnd(transitionDuration);\n      } else {\n        complete();\n      }\n\n      this._hoverState = '';\n    };\n\n    _proto.update = function update() {\n      if (this._popper !== null) {\n        this._popper.scheduleUpdate();\n      }\n    } // Protected\n    ;\n\n    _proto.isWithContent = function isWithContent() {\n      return Boolean(this.getTitle());\n    };\n\n    _proto.addAttachmentClass = function addAttachmentClass(attachment) {\n      $(this.getTipElement()).addClass(CLASS_PREFIX + \"-\" + attachment);\n    };\n\n    _proto.getTipElement = function getTipElement() {\n      this.tip = this.tip || $(this.config.template)[0];\n      return this.tip;\n    };\n\n    _proto.setContent = function setContent() {\n      var tip = this.getTipElement();\n      this.setElementContent($(tip.querySelectorAll(Selector.TOOLTIP_INNER)), this.getTitle());\n      $(tip).removeClass(ClassName.FADE + \" \" + ClassName.SHOW);\n    };\n\n    _proto.setElementContent = function setElementContent($element, content) {\n      if (typeof content === 'object' && (content.nodeType || content.jquery)) {\n        // Content is a DOM node or a jQuery\n        if (this.config.html) {\n          if (!$(content).parent().is($element)) {\n            $element.empty().append(content);\n          }\n        } else {\n          $element.text($(content).text());\n        }\n\n        return;\n      }\n\n      if (this.config.html) {\n        if (this.config.sanitize) {\n          content = sanitizeHtml(content, this.config.whiteList, this.config.sanitizeFn);\n        }\n\n        $element.html(content);\n      } else {\n        $element.text(content);\n      }\n    };\n\n    _proto.getTitle = function getTitle() {\n      var title = this.element.getAttribute('data-original-title');\n\n      if (!title) {\n        title = typeof this.config.title === 'function' ? this.config.title.call(this.element) : this.config.title;\n      }\n\n      return title;\n    } // Private\n    ;\n\n    _proto._getOffset = function _getOffset() {\n      var _this3 = this;\n\n      var offset = {};\n\n      if (typeof this.config.offset === 'function') {\n        offset.fn = function (data) {\n          data.offsets = _objectSpread({}, data.offsets, _this3.config.offset(data.offsets, _this3.element) || {});\n          return data;\n        };\n      } else {\n        offset.offset = this.config.offset;\n      }\n\n      return offset;\n    };\n\n    _proto._getContainer = function _getContainer() {\n      if (this.config.container === false) {\n        return document.body;\n      }\n\n      if (Util.isElement(this.config.container)) {\n        return $(this.config.container);\n      }\n\n      return $(document).find(this.config.container);\n    };\n\n    _proto._getAttachment = function _getAttachment(placement) {\n      return AttachmentMap[placement.toUpperCase()];\n    };\n\n    _proto._setListeners = function _setListeners() {\n      var _this4 = this;\n\n      var triggers = this.config.trigger.split(' ');\n      triggers.forEach(function (trigger) {\n        if (trigger === 'click') {\n          $(_this4.element).on(_this4.constructor.Event.CLICK, _this4.config.selector, function (event) {\n            return _this4.toggle(event);\n          });\n        } else if (trigger !== Trigger.MANUAL) {\n          var eventIn = trigger === Trigger.HOVER ? _this4.constructor.Event.MOUSEENTER : _this4.constructor.Event.FOCUSIN;\n          var eventOut = trigger === Trigger.HOVER ? _this4.constructor.Event.MOUSELEAVE : _this4.constructor.Event.FOCUSOUT;\n          $(_this4.element).on(eventIn, _this4.config.selector, function (event) {\n            return _this4._enter(event);\n          }).on(eventOut, _this4.config.selector, function (event) {\n            return _this4._leave(event);\n          });\n        }\n      });\n      $(this.element).closest('.modal').on('hide.bs.modal', function () {\n        if (_this4.element) {\n          _this4.hide();\n        }\n      });\n\n      if (this.config.selector) {\n        this.config = _objectSpread({}, this.config, {\n          trigger: 'manual',\n          selector: ''\n        });\n      } else {\n        this._fixTitle();\n      }\n    };\n\n    _proto._fixTitle = function _fixTitle() {\n      var titleType = typeof this.element.getAttribute('data-original-title');\n\n      if (this.element.getAttribute('title') || titleType !== 'string') {\n        this.element.setAttribute('data-original-title', this.element.getAttribute('title') || '');\n        this.element.setAttribute('title', '');\n      }\n    };\n\n    _proto._enter = function _enter(event, context) {\n      var dataKey = this.constructor.DATA_KEY;\n      context = context || $(event.currentTarget).data(dataKey);\n\n      if (!context) {\n        context = new this.constructor(event.currentTarget, this._getDelegateConfig());\n        $(event.currentTarget).data(dataKey, context);\n      }\n\n      if (event) {\n        context._activeTrigger[event.type === 'focusin' ? Trigger.FOCUS : Trigger.HOVER] = true;\n      }\n\n      if ($(context.getTipElement()).hasClass(ClassName.SHOW) || context._hoverState === HoverState.SHOW) {\n        context._hoverState = HoverState.SHOW;\n        return;\n      }\n\n      clearTimeout(context._timeout);\n      context._hoverState = HoverState.SHOW;\n\n      if (!context.config.delay || !context.config.delay.show) {\n        context.show();\n        return;\n      }\n\n      context._timeout = setTimeout(function () {\n        if (context._hoverState === HoverState.SHOW) {\n          context.show();\n        }\n      }, context.config.delay.show);\n    };\n\n    _proto._leave = function _leave(event, context) {\n      var dataKey = this.constructor.DATA_KEY;\n      context = context || $(event.currentTarget).data(dataKey);\n\n      if (!context) {\n        context = new this.constructor(event.currentTarget, this._getDelegateConfig());\n        $(event.currentTarget).data(dataKey, context);\n      }\n\n      if (event) {\n        context._activeTrigger[event.type === 'focusout' ? Trigger.FOCUS : Trigger.HOVER] = false;\n      }\n\n      if (context._isWithActiveTrigger()) {\n        return;\n      }\n\n      clearTimeout(context._timeout);\n      context._hoverState = HoverState.OUT;\n\n      if (!context.config.delay || !context.config.delay.hide) {\n        context.hide();\n        return;\n      }\n\n      context._timeout = setTimeout(function () {\n        if (context._hoverState === HoverState.OUT) {\n          context.hide();\n        }\n      }, context.config.delay.hide);\n    };\n\n    _proto._isWithActiveTrigger = function _isWithActiveTrigger() {\n      for (var trigger in this._activeTrigger) {\n        if (this._activeTrigger[trigger]) {\n          return true;\n        }\n      }\n\n      return false;\n    };\n\n    _proto._getConfig = function _getConfig(config) {\n      var dataAttributes = $(this.element).data();\n      Object.keys(dataAttributes).forEach(function (dataAttr) {\n        if (DISALLOWED_ATTRIBUTES.indexOf(dataAttr) !== -1) {\n          delete dataAttributes[dataAttr];\n        }\n      });\n      config = _objectSpread({}, this.constructor.Default, dataAttributes, typeof config === 'object' && config ? config : {});\n\n      if (typeof config.delay === 'number') {\n        config.delay = {\n          show: config.delay,\n          hide: config.delay\n        };\n      }\n\n      if (typeof config.title === 'number') {\n        config.title = config.title.toString();\n      }\n\n      if (typeof config.content === 'number') {\n        config.content = config.content.toString();\n      }\n\n      Util.typeCheckConfig(NAME, config, this.constructor.DefaultType);\n\n      if (config.sanitize) {\n        config.template = sanitizeHtml(config.template, config.whiteList, config.sanitizeFn);\n      }\n\n      return config;\n    };\n\n    _proto._getDelegateConfig = function _getDelegateConfig() {\n      var config = {};\n\n      if (this.config) {\n        for (var key in this.config) {\n          if (this.constructor.Default[key] !== this.config[key]) {\n            config[key] = this.config[key];\n          }\n        }\n      }\n\n      return config;\n    };\n\n    _proto._cleanTipClass = function _cleanTipClass() {\n      var $tip = $(this.getTipElement());\n      var tabClass = $tip.attr('class').match(BSCLS_PREFIX_REGEX);\n\n      if (tabClass !== null && tabClass.length) {\n        $tip.removeClass(tabClass.join(''));\n      }\n    };\n\n    _proto._handlePopperPlacementChange = function _handlePopperPlacementChange(popperData) {\n      var popperInstance = popperData.instance;\n      this.tip = popperInstance.popper;\n\n      this._cleanTipClass();\n\n      this.addAttachmentClass(this._getAttachment(popperData.placement));\n    };\n\n    _proto._fixTransition = function _fixTransition() {\n      var tip = this.getTipElement();\n      var initConfigAnimation = this.config.animation;\n\n      if (tip.getAttribute('x-placement') !== null) {\n        return;\n      }\n\n      $(tip).removeClass(ClassName.FADE);\n      this.config.animation = false;\n      this.hide();\n      this.show();\n      this.config.animation = initConfigAnimation;\n    } // Static\n    ;\n\n    Tooltip._jQueryInterface = function _jQueryInterface(config) {\n      return this.each(function () {\n        var data = $(this).data(DATA_KEY);\n\n        var _config = typeof config === 'object' && config;\n\n        if (!data && /dispose|hide/.test(config)) {\n          return;\n        }\n\n        if (!data) {\n          data = new Tooltip(this, _config);\n          $(this).data(DATA_KEY, data);\n        }\n\n        if (typeof config === 'string') {\n          if (typeof data[config] === 'undefined') {\n            throw new TypeError(\"No method named \\\"\" + config + \"\\\"\");\n          }\n\n          data[config]();\n        }\n      });\n    };\n\n    _createClass(Tooltip, null, [{\n      key: \"VERSION\",\n      get: function get() {\n        return VERSION;\n      }\n    }, {\n      key: \"Default\",\n      get: function get() {\n        return Default;\n      }\n    }, {\n      key: \"NAME\",\n      get: function get() {\n        return NAME;\n      }\n    }, {\n      key: \"DATA_KEY\",\n      get: function get() {\n        return DATA_KEY;\n      }\n    }, {\n      key: \"Event\",\n      get: function get() {\n        return Event;\n      }\n    }, {\n      key: \"EVENT_KEY\",\n      get: function get() {\n        return EVENT_KEY;\n      }\n    }, {\n      key: \"DefaultType\",\n      get: function get() {\n        return DefaultType;\n      }\n    }]);\n\n    return Tooltip;\n  }();\n  /**\n   * ------------------------------------------------------------------------\n   * jQuery\n   * ------------------------------------------------------------------------\n   */\n\n\n  $.fn[NAME] = Tooltip._jQueryInterface;\n  $.fn[NAME].Constructor = Tooltip;\n\n  $.fn[NAME].noConflict = function () {\n    $.fn[NAME] = JQUERY_NO_CONFLICT;\n    return Tooltip._jQueryInterface;\n  };\n\n  return Tooltip;\n\n}));\n", "/*!\n  * Bootstrap popover.js v4.3.1 (https://getbootstrap.com/)\n  * Copyright 2011-2019 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)\n  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n  */\n(function (global, factory) {\n  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('jquery'), require('./tooltip.js')) :\n  typeof define === 'function' && define.amd ? define(['jquery', './tooltip.js'], factory) :\n  (global = global || self, global.Popover = factory(global.jQuery, global.Tooltip));\n}(this, function ($, Tooltip) { 'use strict';\n\n  $ = $ && $.hasOwnProperty('default') ? $['default'] : $;\n  Tooltip = Tooltip && Tooltip.hasOwnProperty('default') ? Tooltip['default'] : Tooltip;\n\n  function _defineProperties(target, props) {\n    for (var i = 0; i < props.length; i++) {\n      var descriptor = props[i];\n      descriptor.enumerable = descriptor.enumerable || false;\n      descriptor.configurable = true;\n      if (\"value\" in descriptor) descriptor.writable = true;\n      Object.defineProperty(target, descriptor.key, descriptor);\n    }\n  }\n\n  function _createClass(Constructor, protoProps, staticProps) {\n    if (protoProps) _defineProperties(Constructor.prototype, protoProps);\n    if (staticProps) _defineProperties(Constructor, staticProps);\n    return Constructor;\n  }\n\n  function _defineProperty(obj, key, value) {\n    if (key in obj) {\n      Object.defineProperty(obj, key, {\n        value: value,\n        enumerable: true,\n        configurable: true,\n        writable: true\n      });\n    } else {\n      obj[key] = value;\n    }\n\n    return obj;\n  }\n\n  function _objectSpread(target) {\n    for (var i = 1; i < arguments.length; i++) {\n      var source = arguments[i] != null ? arguments[i] : {};\n      var ownKeys = Object.keys(source);\n\n      if (typeof Object.getOwnPropertySymbols === 'function') {\n        ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) {\n          return Object.getOwnPropertyDescriptor(source, sym).enumerable;\n        }));\n      }\n\n      ownKeys.forEach(function (key) {\n        _defineProperty(target, key, source[key]);\n      });\n    }\n\n    return target;\n  }\n\n  function _inheritsLoose(subClass, superClass) {\n    subClass.prototype = Object.create(superClass.prototype);\n    subClass.prototype.constructor = subClass;\n    subClass.__proto__ = superClass;\n  }\n\n  /**\n   * ------------------------------------------------------------------------\n   * Constants\n   * ------------------------------------------------------------------------\n   */\n\n  var NAME = 'popover';\n  var VERSION = '4.3.1';\n  var DATA_KEY = 'bs.popover';\n  var EVENT_KEY = \".\" + DATA_KEY;\n  var JQUERY_NO_CONFLICT = $.fn[NAME];\n  var CLASS_PREFIX = 'bs-popover';\n  var BSCLS_PREFIX_REGEX = new RegExp(\"(^|\\\\s)\" + CLASS_PREFIX + \"\\\\S+\", 'g');\n\n  var Default = _objectSpread({}, Tooltip.Default, {\n    placement: 'right',\n    trigger: 'click',\n    content: '',\n    template: '<div class=\"popover\" role=\"tooltip\">' + '<div class=\"arrow\"></div>' + '<h3 class=\"popover-header\"></h3>' + '<div class=\"popover-body\"></div></div>'\n  });\n\n  var DefaultType = _objectSpread({}, Tooltip.DefaultType, {\n    content: '(string|element|function)'\n  });\n\n  var ClassName = {\n    FADE: 'fade',\n    SHOW: 'show'\n  };\n  var Selector = {\n    TITLE: '.popover-header',\n    CONTENT: '.popover-body'\n  };\n  var Event = {\n    HIDE: \"hide\" + EVENT_KEY,\n    HIDDEN: \"hidden\" + EVENT_KEY,\n    SHOW: \"show\" + EVENT_KEY,\n    SHOWN: \"shown\" + EVENT_KEY,\n    INSERTED: \"inserted\" + EVENT_KEY,\n    CLICK: \"click\" + EVENT_KEY,\n    FOCUSIN: \"focusin\" + EVENT_KEY,\n    FOCUSOUT: \"focusout\" + EVENT_KEY,\n    MOUSEENTER: \"mouseenter\" + EVENT_KEY,\n    MOUSELEAVE: \"mouseleave\" + EVENT_KEY\n    /**\n     * ------------------------------------------------------------------------\n     * Class Definition\n     * ------------------------------------------------------------------------\n     */\n\n  };\n\n  var Popover =\n  /*#__PURE__*/\n  function (_Tooltip) {\n    _inheritsLoose(Popover, _Tooltip);\n\n    function Popover() {\n      return _Tooltip.apply(this, arguments) || this;\n    }\n\n    var _proto = Popover.prototype;\n\n    // Overrides\n    _proto.isWithContent = function isWithContent() {\n      return this.getTitle() || this._getContent();\n    };\n\n    _proto.addAttachmentClass = function addAttachmentClass(attachment) {\n      $(this.getTipElement()).addClass(CLASS_PREFIX + \"-\" + attachment);\n    };\n\n    _proto.getTipElement = function getTipElement() {\n      this.tip = this.tip || $(this.config.template)[0];\n      return this.tip;\n    };\n\n    _proto.setContent = function setContent() {\n      var $tip = $(this.getTipElement()); // We use append for html objects to maintain js events\n\n      this.setElementContent($tip.find(Selector.TITLE), this.getTitle());\n\n      var content = this._getContent();\n\n      if (typeof content === 'function') {\n        content = content.call(this.element);\n      }\n\n      this.setElementContent($tip.find(Selector.CONTENT), content);\n      $tip.removeClass(ClassName.FADE + \" \" + ClassName.SHOW);\n    } // Private\n    ;\n\n    _proto._getContent = function _getContent() {\n      return this.element.getAttribute('data-content') || this.config.content;\n    };\n\n    _proto._cleanTipClass = function _cleanTipClass() {\n      var $tip = $(this.getTipElement());\n      var tabClass = $tip.attr('class').match(BSCLS_PREFIX_REGEX);\n\n      if (tabClass !== null && tabClass.length > 0) {\n        $tip.removeClass(tabClass.join(''));\n      }\n    } // Static\n    ;\n\n    Popover._jQueryInterface = function _jQueryInterface(config) {\n      return this.each(function () {\n        var data = $(this).data(DATA_KEY);\n\n        var _config = typeof config === 'object' ? config : null;\n\n        if (!data && /dispose|hide/.test(config)) {\n          return;\n        }\n\n        if (!data) {\n          data = new Popover(this, _config);\n          $(this).data(DATA_KEY, data);\n        }\n\n        if (typeof config === 'string') {\n          if (typeof data[config] === 'undefined') {\n            throw new TypeError(\"No method named \\\"\" + config + \"\\\"\");\n          }\n\n          data[config]();\n        }\n      });\n    };\n\n    _createClass(Popover, null, [{\n      key: \"VERSION\",\n      // Getters\n      get: function get() {\n        return VERSION;\n      }\n    }, {\n      key: \"Default\",\n      get: function get() {\n        return Default;\n      }\n    }, {\n      key: \"NAME\",\n      get: function get() {\n        return NAME;\n      }\n    }, {\n      key: \"DATA_KEY\",\n      get: function get() {\n        return DATA_KEY;\n      }\n    }, {\n      key: \"Event\",\n      get: function get() {\n        return Event;\n      }\n    }, {\n      key: \"EVENT_KEY\",\n      get: function get() {\n        return EVENT_KEY;\n      }\n    }, {\n      key: \"DefaultType\",\n      get: function get() {\n        return DefaultType;\n      }\n    }]);\n\n    return Popover;\n  }(Tooltip);\n  /**\n   * ------------------------------------------------------------------------\n   * jQuery\n   * ------------------------------------------------------------------------\n   */\n\n\n  $.fn[NAME] = Popover._jQueryInterface;\n  $.fn[NAME].Constructor = Popover;\n\n  $.fn[NAME].noConflict = function () {\n    $.fn[NAME] = JQUERY_NO_CONFLICT;\n    return Popover._jQueryInterface;\n  };\n\n  return Popover;\n\n}));\n", "/*!\n  * Bootstrap scrollspy.js v4.3.1 (https://getbootstrap.com/)\n  * Copyright 2011-2019 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)\n  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n  */\n(function (global, factory) {\n  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('jquery'), require('./util.js')) :\n  typeof define === 'function' && define.amd ? define(['jquery', './util.js'], factory) :\n  (global = global || self, global.ScrollSpy = factory(global.jQuery, global.Util));\n}(this, function ($, Util) { 'use strict';\n\n  $ = $ && $.hasOwnProperty('default') ? $['default'] : $;\n  Util = Util && Util.hasOwnProperty('default') ? Util['default'] : Util;\n\n  function _defineProperties(target, props) {\n    for (var i = 0; i < props.length; i++) {\n      var descriptor = props[i];\n      descriptor.enumerable = descriptor.enumerable || false;\n      descriptor.configurable = true;\n      if (\"value\" in descriptor) descriptor.writable = true;\n      Object.defineProperty(target, descriptor.key, descriptor);\n    }\n  }\n\n  function _createClass(Constructor, protoProps, staticProps) {\n    if (protoProps) _defineProperties(Constructor.prototype, protoProps);\n    if (staticProps) _defineProperties(Constructor, staticProps);\n    return Constructor;\n  }\n\n  function _defineProperty(obj, key, value) {\n    if (key in obj) {\n      Object.defineProperty(obj, key, {\n        value: value,\n        enumerable: true,\n        configurable: true,\n        writable: true\n      });\n    } else {\n      obj[key] = value;\n    }\n\n    return obj;\n  }\n\n  function _objectSpread(target) {\n    for (var i = 1; i < arguments.length; i++) {\n      var source = arguments[i] != null ? arguments[i] : {};\n      var ownKeys = Object.keys(source);\n\n      if (typeof Object.getOwnPropertySymbols === 'function') {\n        ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) {\n          return Object.getOwnPropertyDescriptor(source, sym).enumerable;\n        }));\n      }\n\n      ownKeys.forEach(function (key) {\n        _defineProperty(target, key, source[key]);\n      });\n    }\n\n    return target;\n  }\n\n  /**\n   * ------------------------------------------------------------------------\n   * Constants\n   * ------------------------------------------------------------------------\n   */\n\n  var NAME = 'scrollspy';\n  var VERSION = '4.3.1';\n  var DATA_KEY = 'bs.scrollspy';\n  var EVENT_KEY = \".\" + DATA_KEY;\n  var DATA_API_KEY = '.data-api';\n  var JQUERY_NO_CONFLICT = $.fn[NAME];\n  var Default = {\n    offset: 10,\n    method: 'auto',\n    target: ''\n  };\n  var DefaultType = {\n    offset: 'number',\n    method: 'string',\n    target: '(string|element)'\n  };\n  var Event = {\n    ACTIVATE: \"activate\" + EVENT_KEY,\n    SCROLL: \"scroll\" + EVENT_KEY,\n    LOAD_DATA_API: \"load\" + EVENT_KEY + DATA_API_KEY\n  };\n  var ClassName = {\n    DROPDOWN_ITEM: 'dropdown-item',\n    DROPDOWN_MENU: 'dropdown-menu',\n    ACTIVE: 'active'\n  };\n  var Selector = {\n    DATA_SPY: '[data-spy=\"scroll\"]',\n    ACTIVE: '.active',\n    NAV_LIST_GROUP: '.nav, .list-group',\n    NAV_LINKS: '.nav-link',\n    NAV_ITEMS: '.nav-item',\n    LIST_ITEMS: '.list-group-item',\n    DROPDOWN: '.dropdown',\n    DROPDOWN_ITEMS: '.dropdown-item',\n    DROPDOWN_TOGGLE: '.dropdown-toggle'\n  };\n  var OffsetMethod = {\n    OFFSET: 'offset',\n    POSITION: 'position'\n    /**\n     * ------------------------------------------------------------------------\n     * Class Definition\n     * ------------------------------------------------------------------------\n     */\n\n  };\n\n  var ScrollSpy =\n  /*#__PURE__*/\n  function () {\n    function ScrollSpy(element, config) {\n      var _this = this;\n\n      this._element = element;\n      this._scrollElement = element.tagName === 'BODY' ? window : element;\n      this._config = this._getConfig(config);\n      this._selector = this._config.target + \" \" + Selector.NAV_LINKS + \",\" + (this._config.target + \" \" + Selector.LIST_ITEMS + \",\") + (this._config.target + \" \" + Selector.DROPDOWN_ITEMS);\n      this._offsets = [];\n      this._targets = [];\n      this._activeTarget = null;\n      this._scrollHeight = 0;\n      $(this._scrollElement).on(Event.SCROLL, function (event) {\n        return _this._process(event);\n      });\n      this.refresh();\n\n      this._process();\n    } // Getters\n\n\n    var _proto = ScrollSpy.prototype;\n\n    // Public\n    _proto.refresh = function refresh() {\n      var _this2 = this;\n\n      var autoMethod = this._scrollElement === this._scrollElement.window ? OffsetMethod.OFFSET : OffsetMethod.POSITION;\n      var offsetMethod = this._config.method === 'auto' ? autoMethod : this._config.method;\n      var offsetBase = offsetMethod === OffsetMethod.POSITION ? this._getScrollTop() : 0;\n      this._offsets = [];\n      this._targets = [];\n      this._scrollHeight = this._getScrollHeight();\n      var targets = [].slice.call(document.querySelectorAll(this._selector));\n      targets.map(function (element) {\n        var target;\n        var targetSelector = Util.getSelectorFromElement(element);\n\n        if (targetSelector) {\n          target = document.querySelector(targetSelector);\n        }\n\n        if (target) {\n          var targetBCR = target.getBoundingClientRect();\n\n          if (targetBCR.width || targetBCR.height) {\n            // TODO (fat): remove sketch reliance on jQuery position/offset\n            return [$(target)[offsetMethod]().top + offsetBase, targetSelector];\n          }\n        }\n\n        return null;\n      }).filter(function (item) {\n        return item;\n      }).sort(function (a, b) {\n        return a[0] - b[0];\n      }).forEach(function (item) {\n        _this2._offsets.push(item[0]);\n\n        _this2._targets.push(item[1]);\n      });\n    };\n\n    _proto.dispose = function dispose() {\n      $.removeData(this._element, DATA_KEY);\n      $(this._scrollElement).off(EVENT_KEY);\n      this._element = null;\n      this._scrollElement = null;\n      this._config = null;\n      this._selector = null;\n      this._offsets = null;\n      this._targets = null;\n      this._activeTarget = null;\n      this._scrollHeight = null;\n    } // Private\n    ;\n\n    _proto._getConfig = function _getConfig(config) {\n      config = _objectSpread({}, Default, typeof config === 'object' && config ? config : {});\n\n      if (typeof config.target !== 'string') {\n        var id = $(config.target).attr('id');\n\n        if (!id) {\n          id = Util.getUID(NAME);\n          $(config.target).attr('id', id);\n        }\n\n        config.target = \"#\" + id;\n      }\n\n      Util.typeCheckConfig(NAME, config, DefaultType);\n      return config;\n    };\n\n    _proto._getScrollTop = function _getScrollTop() {\n      return this._scrollElement === window ? this._scrollElement.pageYOffset : this._scrollElement.scrollTop;\n    };\n\n    _proto._getScrollHeight = function _getScrollHeight() {\n      return this._scrollElement.scrollHeight || Math.max(document.body.scrollHeight, document.documentElement.scrollHeight);\n    };\n\n    _proto._getOffsetHeight = function _getOffsetHeight() {\n      return this._scrollElement === window ? window.innerHeight : this._scrollElement.getBoundingClientRect().height;\n    };\n\n    _proto._process = function _process() {\n      var scrollTop = this._getScrollTop() + this._config.offset;\n\n      var scrollHeight = this._getScrollHeight();\n\n      var maxScroll = this._config.offset + scrollHeight - this._getOffsetHeight();\n\n      if (this._scrollHeight !== scrollHeight) {\n        this.refresh();\n      }\n\n      if (scrollTop >= maxScroll) {\n        var target = this._targets[this._targets.length - 1];\n\n        if (this._activeTarget !== target) {\n          this._activate(target);\n        }\n\n        return;\n      }\n\n      if (this._activeTarget && scrollTop < this._offsets[0] && this._offsets[0] > 0) {\n        this._activeTarget = null;\n\n        this._clear();\n\n        return;\n      }\n\n      var offsetLength = this._offsets.length;\n\n      for (var i = offsetLength; i--;) {\n        var isActiveTarget = this._activeTarget !== this._targets[i] && scrollTop >= this._offsets[i] && (typeof this._offsets[i + 1] === 'undefined' || scrollTop < this._offsets[i + 1]);\n\n        if (isActiveTarget) {\n          this._activate(this._targets[i]);\n        }\n      }\n    };\n\n    _proto._activate = function _activate(target) {\n      this._activeTarget = target;\n\n      this._clear();\n\n      var queries = this._selector.split(',').map(function (selector) {\n        return selector + \"[data-target=\\\"\" + target + \"\\\"],\" + selector + \"[href=\\\"\" + target + \"\\\"]\";\n      });\n\n      var $link = $([].slice.call(document.querySelectorAll(queries.join(','))));\n\n      if ($link.hasClass(ClassName.DROPDOWN_ITEM)) {\n        $link.closest(Selector.DROPDOWN).find(Selector.DROPDOWN_TOGGLE).addClass(ClassName.ACTIVE);\n        $link.addClass(ClassName.ACTIVE);\n      } else {\n        // Set triggered link as active\n        $link.addClass(ClassName.ACTIVE); // Set triggered links parents as active\n        // With both <ul> and <nav> markup a parent is the previous sibling of any nav ancestor\n\n        $link.parents(Selector.NAV_LIST_GROUP).prev(Selector.NAV_LINKS + \", \" + Selector.LIST_ITEMS).addClass(ClassName.ACTIVE); // Handle special case when .nav-link is inside .nav-item\n\n        $link.parents(Selector.NAV_LIST_GROUP).prev(Selector.NAV_ITEMS).children(Selector.NAV_LINKS).addClass(ClassName.ACTIVE);\n      }\n\n      $(this._scrollElement).trigger(Event.ACTIVATE, {\n        relatedTarget: target\n      });\n    };\n\n    _proto._clear = function _clear() {\n      [].slice.call(document.querySelectorAll(this._selector)).filter(function (node) {\n        return node.classList.contains(ClassName.ACTIVE);\n      }).forEach(function (node) {\n        return node.classList.remove(ClassName.ACTIVE);\n      });\n    } // Static\n    ;\n\n    ScrollSpy._jQueryInterface = function _jQueryInterface(config) {\n      return this.each(function () {\n        var data = $(this).data(DATA_KEY);\n\n        var _config = typeof config === 'object' && config;\n\n        if (!data) {\n          data = new ScrollSpy(this, _config);\n          $(this).data(DATA_KEY, data);\n        }\n\n        if (typeof config === 'string') {\n          if (typeof data[config] === 'undefined') {\n            throw new TypeError(\"No method named \\\"\" + config + \"\\\"\");\n          }\n\n          data[config]();\n        }\n      });\n    };\n\n    _createClass(ScrollSpy, null, [{\n      key: \"VERSION\",\n      get: function get() {\n        return VERSION;\n      }\n    }, {\n      key: \"Default\",\n      get: function get() {\n        return Default;\n      }\n    }]);\n\n    return ScrollSpy;\n  }();\n  /**\n   * ------------------------------------------------------------------------\n   * Data Api implementation\n   * ------------------------------------------------------------------------\n   */\n\n\n  $(window).on(Event.LOAD_DATA_API, function () {\n    var scrollSpys = [].slice.call(document.querySelectorAll(Selector.DATA_SPY));\n    var scrollSpysLength = scrollSpys.length;\n\n    for (var i = scrollSpysLength; i--;) {\n      var $spy = $(scrollSpys[i]);\n\n      ScrollSpy._jQueryInterface.call($spy, $spy.data());\n    }\n  });\n  /**\n   * ------------------------------------------------------------------------\n   * jQuery\n   * ------------------------------------------------------------------------\n   */\n\n  $.fn[NAME] = ScrollSpy._jQueryInterface;\n  $.fn[NAME].Constructor = ScrollSpy;\n\n  $.fn[NAME].noConflict = function () {\n    $.fn[NAME] = JQUERY_NO_CONFLICT;\n    return ScrollSpy._jQueryInterface;\n  };\n\n  return ScrollSpy;\n\n}));\n", "/*!\n  * Bootstrap tab.js v4.3.1 (https://getbootstrap.com/)\n  * Copyright 2011-2019 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)\n  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n  */\n(function (global, factory) {\n  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('jquery'), require('./util.js')) :\n  typeof define === 'function' && define.amd ? define(['jquery', './util.js'], factory) :\n  (global = global || self, global.Tab = factory(global.jQuery, global.Util));\n}(this, function ($, Util) { 'use strict';\n\n  $ = $ && $.hasOwnProperty('default') ? $['default'] : $;\n  Util = Util && Util.hasOwnProperty('default') ? Util['default'] : Util;\n\n  function _defineProperties(target, props) {\n    for (var i = 0; i < props.length; i++) {\n      var descriptor = props[i];\n      descriptor.enumerable = descriptor.enumerable || false;\n      descriptor.configurable = true;\n      if (\"value\" in descriptor) descriptor.writable = true;\n      Object.defineProperty(target, descriptor.key, descriptor);\n    }\n  }\n\n  function _createClass(Constructor, protoProps, staticProps) {\n    if (protoProps) _defineProperties(Constructor.prototype, protoProps);\n    if (staticProps) _defineProperties(Constructor, staticProps);\n    return Constructor;\n  }\n\n  /**\n   * ------------------------------------------------------------------------\n   * Constants\n   * ------------------------------------------------------------------------\n   */\n\n  var NAME = 'tab';\n  var VERSION = '4.3.1';\n  var DATA_KEY = 'bs.tab';\n  var EVENT_KEY = \".\" + DATA_KEY;\n  var DATA_API_KEY = '.data-api';\n  var JQUERY_NO_CONFLICT = $.fn[NAME];\n  var Event = {\n    HIDE: \"hide\" + EVENT_KEY,\n    HIDDEN: \"hidden\" + EVENT_KEY,\n    SHOW: \"show\" + EVENT_KEY,\n    SHOWN: \"shown\" + EVENT_KEY,\n    CLICK_DATA_API: \"click\" + EVENT_KEY + DATA_API_KEY\n  };\n  var ClassName = {\n    DROPDOWN_MENU: 'dropdown-menu',\n    ACTIVE: 'active',\n    DISABLED: 'disabled',\n    FADE: 'fade',\n    SHOW: 'show'\n  };\n  var Selector = {\n    DROPDOWN: '.dropdown',\n    NAV_LIST_GROUP: '.nav, .list-group',\n    ACTIVE: '.active',\n    ACTIVE_UL: '> li > .active',\n    DATA_TOGGLE: '[data-toggle=\"tab\"], [data-toggle=\"pill\"], [data-toggle=\"list\"]',\n    DROPDOWN_TOGGLE: '.dropdown-toggle',\n    DROPDOWN_ACTIVE_CHILD: '> .dropdown-menu .active'\n    /**\n     * ------------------------------------------------------------------------\n     * Class Definition\n     * ------------------------------------------------------------------------\n     */\n\n  };\n\n  var Tab =\n  /*#__PURE__*/\n  function () {\n    function Tab(element) {\n      this._element = element;\n    } // Getters\n\n\n    var _proto = Tab.prototype;\n\n    // Public\n    _proto.show = function show() {\n      var _this = this;\n\n      if (this._element.parentNode && this._element.parentNode.nodeType === Node.ELEMENT_NODE && $(this._element).hasClass(ClassName.ACTIVE) || $(this._element).hasClass(ClassName.DISABLED)) {\n        return;\n      }\n\n      var target;\n      var previous;\n      var listElement = $(this._element).closest(Selector.NAV_LIST_GROUP)[0];\n      var selector = Util.getSelectorFromElement(this._element);\n\n      if (listElement) {\n        var itemSelector = listElement.nodeName === 'UL' || listElement.nodeName === 'OL' ? Selector.ACTIVE_UL : Selector.ACTIVE;\n        previous = $.makeArray($(listElement).find(itemSelector));\n        previous = previous[previous.length - 1];\n      }\n\n      var hideEvent = $.Event(Event.HIDE, {\n        relatedTarget: this._element\n      });\n      var showEvent = $.Event(Event.SHOW, {\n        relatedTarget: previous\n      });\n\n      if (previous) {\n        $(previous).trigger(hideEvent);\n      }\n\n      $(this._element).trigger(showEvent);\n\n      if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) {\n        return;\n      }\n\n      if (selector) {\n        target = document.querySelector(selector);\n      }\n\n      this._activate(this._element, listElement);\n\n      var complete = function complete() {\n        var hiddenEvent = $.Event(Event.HIDDEN, {\n          relatedTarget: _this._element\n        });\n        var shownEvent = $.Event(Event.SHOWN, {\n          relatedTarget: previous\n        });\n        $(previous).trigger(hiddenEvent);\n        $(_this._element).trigger(shownEvent);\n      };\n\n      if (target) {\n        this._activate(target, target.parentNode, complete);\n      } else {\n        complete();\n      }\n    };\n\n    _proto.dispose = function dispose() {\n      $.removeData(this._element, DATA_KEY);\n      this._element = null;\n    } // Private\n    ;\n\n    _proto._activate = function _activate(element, container, callback) {\n      var _this2 = this;\n\n      var activeElements = container && (container.nodeName === 'UL' || container.nodeName === 'OL') ? $(container).find(Selector.ACTIVE_UL) : $(container).children(Selector.ACTIVE);\n      var active = activeElements[0];\n      var isTransitioning = callback && active && $(active).hasClass(ClassName.FADE);\n\n      var complete = function complete() {\n        return _this2._transitionComplete(element, active, callback);\n      };\n\n      if (active && isTransitioning) {\n        var transitionDuration = Util.getTransitionDurationFromElement(active);\n        $(active).removeClass(ClassName.SHOW).one(Util.TRANSITION_END, complete).emulateTransitionEnd(transitionDuration);\n      } else {\n        complete();\n      }\n    };\n\n    _proto._transitionComplete = function _transitionComplete(element, active, callback) {\n      if (active) {\n        $(active).removeClass(ClassName.ACTIVE);\n        var dropdownChild = $(active.parentNode).find(Selector.DROPDOWN_ACTIVE_CHILD)[0];\n\n        if (dropdownChild) {\n          $(dropdownChild).removeClass(ClassName.ACTIVE);\n        }\n\n        if (active.getAttribute('role') === 'tab') {\n          active.setAttribute('aria-selected', false);\n        }\n      }\n\n      $(element).addClass(ClassName.ACTIVE);\n\n      if (element.getAttribute('role') === 'tab') {\n        element.setAttribute('aria-selected', true);\n      }\n\n      Util.reflow(element);\n\n      if (element.classList.contains(ClassName.FADE)) {\n        element.classList.add(ClassName.SHOW);\n      }\n\n      if (element.parentNode && $(element.parentNode).hasClass(ClassName.DROPDOWN_MENU)) {\n        var dropdownElement = $(element).closest(Selector.DROPDOWN)[0];\n\n        if (dropdownElement) {\n          var dropdownToggleList = [].slice.call(dropdownElement.querySelectorAll(Selector.DROPDOWN_TOGGLE));\n          $(dropdownToggleList).addClass(ClassName.ACTIVE);\n        }\n\n        element.setAttribute('aria-expanded', true);\n      }\n\n      if (callback) {\n        callback();\n      }\n    } // Static\n    ;\n\n    Tab._jQueryInterface = function _jQueryInterface(config) {\n      return this.each(function () {\n        var $this = $(this);\n        var data = $this.data(DATA_KEY);\n\n        if (!data) {\n          data = new Tab(this);\n          $this.data(DATA_KEY, data);\n        }\n\n        if (typeof config === 'string') {\n          if (typeof data[config] === 'undefined') {\n            throw new TypeError(\"No method named \\\"\" + config + \"\\\"\");\n          }\n\n          data[config]();\n        }\n      });\n    };\n\n    _createClass(Tab, null, [{\n      key: \"VERSION\",\n      get: function get() {\n        return VERSION;\n      }\n    }]);\n\n    return Tab;\n  }();\n  /**\n   * ------------------------------------------------------------------------\n   * Data Api implementation\n   * ------------------------------------------------------------------------\n   */\n\n\n  $(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {\n    event.preventDefault();\n\n    Tab._jQueryInterface.call($(this), 'show');\n  });\n  /**\n   * ------------------------------------------------------------------------\n   * jQuery\n   * ------------------------------------------------------------------------\n   */\n\n  $.fn[NAME] = Tab._jQueryInterface;\n  $.fn[NAME].Constructor = Tab;\n\n  $.fn[NAME].noConflict = function () {\n    $.fn[NAME] = JQUERY_NO_CONFLICT;\n    return Tab._jQueryInterface;\n  };\n\n  return Tab;\n\n}));\n", "/*!\n  * Bootstrap toast.js v4.3.1 (https://getbootstrap.com/)\n  * Copyright 2011-2019 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)\n  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n  */\n(function (global, factory) {\n  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('jquery'), require('./util.js')) :\n  typeof define === 'function' && define.amd ? define(['jquery', './util.js'], factory) :\n  (global = global || self, global.Toast = factory(global.jQuery, global.Util));\n}(this, function ($, Util) { 'use strict';\n\n  $ = $ && $.hasOwnProperty('default') ? $['default'] : $;\n  Util = Util && Util.hasOwnProperty('default') ? Util['default'] : Util;\n\n  function _defineProperties(target, props) {\n    for (var i = 0; i < props.length; i++) {\n      var descriptor = props[i];\n      descriptor.enumerable = descriptor.enumerable || false;\n      descriptor.configurable = true;\n      if (\"value\" in descriptor) descriptor.writable = true;\n      Object.defineProperty(target, descriptor.key, descriptor);\n    }\n  }\n\n  function _createClass(Constructor, protoProps, staticProps) {\n    if (protoProps) _defineProperties(Constructor.prototype, protoProps);\n    if (staticProps) _defineProperties(Constructor, staticProps);\n    return Constructor;\n  }\n\n  function _defineProperty(obj, key, value) {\n    if (key in obj) {\n      Object.defineProperty(obj, key, {\n        value: value,\n        enumerable: true,\n        configurable: true,\n        writable: true\n      });\n    } else {\n      obj[key] = value;\n    }\n\n    return obj;\n  }\n\n  function _objectSpread(target) {\n    for (var i = 1; i < arguments.length; i++) {\n      var source = arguments[i] != null ? arguments[i] : {};\n      var ownKeys = Object.keys(source);\n\n      if (typeof Object.getOwnPropertySymbols === 'function') {\n        ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) {\n          return Object.getOwnPropertyDescriptor(source, sym).enumerable;\n        }));\n      }\n\n      ownKeys.forEach(function (key) {\n        _defineProperty(target, key, source[key]);\n      });\n    }\n\n    return target;\n  }\n\n  /**\n   * ------------------------------------------------------------------------\n   * Constants\n   * ------------------------------------------------------------------------\n   */\n\n  var NAME = 'toast';\n  var VERSION = '4.3.1';\n  var DATA_KEY = 'bs.toast';\n  var EVENT_KEY = \".\" + DATA_KEY;\n  var JQUERY_NO_CONFLICT = $.fn[NAME];\n  var Event = {\n    CLICK_DISMISS: \"click.dismiss\" + EVENT_KEY,\n    HIDE: \"hide\" + EVENT_KEY,\n    HIDDEN: \"hidden\" + EVENT_KEY,\n    SHOW: \"show\" + EVENT_KEY,\n    SHOWN: \"shown\" + EVENT_KEY\n  };\n  var ClassName = {\n    FADE: 'fade',\n    HIDE: 'hide',\n    SHOW: 'show',\n    SHOWING: 'showing'\n  };\n  var DefaultType = {\n    animation: 'boolean',\n    autohide: 'boolean',\n    delay: 'number'\n  };\n  var Default = {\n    animation: true,\n    autohide: true,\n    delay: 500\n  };\n  var Selector = {\n    DATA_DISMISS: '[data-dismiss=\"toast\"]'\n    /**\n     * ------------------------------------------------------------------------\n     * Class Definition\n     * ------------------------------------------------------------------------\n     */\n\n  };\n\n  var Toast =\n  /*#__PURE__*/\n  function () {\n    function Toast(element, config) {\n      this._element = element;\n      this._config = this._getConfig(config);\n      this._timeout = null;\n\n      this._setListeners();\n    } // Getters\n\n\n    var _proto = Toast.prototype;\n\n    // Public\n    _proto.show = function show() {\n      var _this = this;\n\n      $(this._element).trigger(Event.SHOW);\n\n      if (this._config.animation) {\n        this._element.classList.add(ClassName.FADE);\n      }\n\n      var complete = function complete() {\n        _this._element.classList.remove(ClassName.SHOWING);\n\n        _this._element.classList.add(ClassName.SHOW);\n\n        $(_this._element).trigger(Event.SHOWN);\n\n        if (_this._config.autohide) {\n          _this.hide();\n        }\n      };\n\n      this._element.classList.remove(ClassName.HIDE);\n\n      this._element.classList.add(ClassName.SHOWING);\n\n      if (this._config.animation) {\n        var transitionDuration = Util.getTransitionDurationFromElement(this._element);\n        $(this._element).one(Util.TRANSITION_END, complete).emulateTransitionEnd(transitionDuration);\n      } else {\n        complete();\n      }\n    };\n\n    _proto.hide = function hide(withoutTimeout) {\n      var _this2 = this;\n\n      if (!this._element.classList.contains(ClassName.SHOW)) {\n        return;\n      }\n\n      $(this._element).trigger(Event.HIDE);\n\n      if (withoutTimeout) {\n        this._close();\n      } else {\n        this._timeout = setTimeout(function () {\n          _this2._close();\n        }, this._config.delay);\n      }\n    };\n\n    _proto.dispose = function dispose() {\n      clearTimeout(this._timeout);\n      this._timeout = null;\n\n      if (this._element.classList.contains(ClassName.SHOW)) {\n        this._element.classList.remove(ClassName.SHOW);\n      }\n\n      $(this._element).off(Event.CLICK_DISMISS);\n      $.removeData(this._element, DATA_KEY);\n      this._element = null;\n      this._config = null;\n    } // Private\n    ;\n\n    _proto._getConfig = function _getConfig(config) {\n      config = _objectSpread({}, Default, $(this._element).data(), typeof config === 'object' && config ? config : {});\n      Util.typeCheckConfig(NAME, config, this.constructor.DefaultType);\n      return config;\n    };\n\n    _proto._setListeners = function _setListeners() {\n      var _this3 = this;\n\n      $(this._element).on(Event.CLICK_DISMISS, Selector.DATA_DISMISS, function () {\n        return _this3.hide(true);\n      });\n    };\n\n    _proto._close = function _close() {\n      var _this4 = this;\n\n      var complete = function complete() {\n        _this4._element.classList.add(ClassName.HIDE);\n\n        $(_this4._element).trigger(Event.HIDDEN);\n      };\n\n      this._element.classList.remove(ClassName.SHOW);\n\n      if (this._config.animation) {\n        var transitionDuration = Util.getTransitionDurationFromElement(this._element);\n        $(this._element).one(Util.TRANSITION_END, complete).emulateTransitionEnd(transitionDuration);\n      } else {\n        complete();\n      }\n    } // Static\n    ;\n\n    Toast._jQueryInterface = function _jQueryInterface(config) {\n      return this.each(function () {\n        var $element = $(this);\n        var data = $element.data(DATA_KEY);\n\n        var _config = typeof config === 'object' && config;\n\n        if (!data) {\n          data = new Toast(this, _config);\n          $element.data(DATA_KEY, data);\n        }\n\n        if (typeof config === 'string') {\n          if (typeof data[config] === 'undefined') {\n            throw new TypeError(\"No method named \\\"\" + config + \"\\\"\");\n          }\n\n          data[config](this);\n        }\n      });\n    };\n\n    _createClass(Toast, null, [{\n      key: \"VERSION\",\n      get: function get() {\n        return VERSION;\n      }\n    }, {\n      key: \"DefaultType\",\n      get: function get() {\n        return DefaultType;\n      }\n    }, {\n      key: \"Default\",\n      get: function get() {\n        return Default;\n      }\n    }]);\n\n    return Toast;\n  }();\n  /**\n   * ------------------------------------------------------------------------\n   * jQuery\n   * ------------------------------------------------------------------------\n   */\n\n\n  $.fn[NAME] = Toast._jQueryInterface;\n  $.fn[NAME].Constructor = Toast;\n\n  $.fn[NAME].noConflict = function () {\n    $.fn[NAME] = JQUERY_NO_CONFLICT;\n    return Toast._jQueryInterface;\n  };\n\n  return Toast;\n\n}));\n", "/*@preserve\n * Tempus Dominus Bootstrap4 v5.0.1 (https://tempusdominus.github.io/bootstrap-4/)\n * Copyright 2016-2018 Jonathan Peterson\n * Licensed under MIT (https://github.com/tempusdominus/bootstrap-3/blob/master/LICENSE)\n */\n\nif (typeof jQuery === 'undefined') {\n  throw new Error('Tempus Dominus Bootstrap4\\'s requires jQuery. jQuery must be included before Tempus Dominus Bootstrap4\\'s JavaScript.');\n}\n\n+function ($) {\n  var version = $.fn.jquery.split(' ')[0].split('.');\n  if ((version[0] < 2 && version[1] < 9) || (version[0] === 1 && version[1] === 9 && version[2] < 1) || (version[0] >= 4)) {\n    throw new Error('Tempus Dominus Bootstrap4\\'s requires at least jQuery v3.0.0 but less than v4.0.0');\n  }\n}(jQuery);\n\n\nif (typeof moment === 'undefined') {\n  throw new Error('Tempus Dominus Bootstrap4\\'s requires moment.js. Moment.js must be included before Tempus Dominus Bootstrap4\\'s JavaScript.');\n}\n\nvar version = moment.version.split('.')\nif ((version[0] <= 2 && version[1] < 17) || (version[0] >= 3)) {\n  throw new Error('Tempus Dominus Bootstrap4\\'s requires at least moment.js v2.17.0 but less than v3.0.0');\n}\n\n+function () {\n\nvar _typeof = typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; };\n\nvar _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();\n\nfunction _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return call && (typeof call === \"object\" || typeof call === \"function\") ? call : self; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function, not \" + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\n// ReSharper disable once InconsistentNaming\nvar DateTimePicker = function ($, moment) {\n    // ReSharper disable InconsistentNaming\n    var NAME = 'datetimepicker',\n        DATA_KEY = '' + NAME,\n        EVENT_KEY = '.' + DATA_KEY,\n        DATA_API_KEY = '.data-api',\n        Selector = {\n        // /!\\ ODOO PATCH: ensure the datetimepickers can be toggled only after\n        // the Odoo lazy loader finished loading all lazy scripts. Another\n        // solution could have been to temporarily removing the data-toggle\n        // attributes during lazyloading but that would not have been stable as\n        // custom code could search for data-toggle elements while the lazy\n        // loading is being performed. Without this, clicking too soon on a\n        // datetimepicker would not use the right format and UI options.\n        DATA_TOGGLE: 'body:not(.o_lazy_js_waiting) [data-toggle=\"' + DATA_KEY + '\"]'\n    },\n        ClassName = {\n        INPUT: NAME + '-input'\n    },\n        Event = {\n        CHANGE: 'change' + EVENT_KEY,\n        BLUR: 'blur' + EVENT_KEY,\n        KEYUP: 'keyup' + EVENT_KEY,\n        KEYDOWN: 'keydown' + EVENT_KEY,\n        FOCUS: 'focus' + EVENT_KEY,\n        CLICK_DATA_API: 'click' + EVENT_KEY + DATA_API_KEY,\n        //emitted\n        UPDATE: 'update' + EVENT_KEY,\n        ERROR: 'error' + EVENT_KEY,\n        HIDE: 'hide' + EVENT_KEY,\n        SHOW: 'show' + EVENT_KEY\n    },\n        DatePickerModes = [{\n        CLASS_NAME: 'days',\n        NAV_FUNCTION: 'M',\n        NAV_STEP: 1\n    }, {\n        CLASS_NAME: 'months',\n        NAV_FUNCTION: 'y',\n        NAV_STEP: 1\n    }, {\n        CLASS_NAME: 'years',\n        NAV_FUNCTION: 'y',\n        NAV_STEP: 10\n    }, {\n        CLASS_NAME: 'decades',\n        NAV_FUNCTION: 'y',\n        NAV_STEP: 100\n    }],\n        KeyMap = {\n        'up': 38,\n        38: 'up',\n        'down': 40,\n        40: 'down',\n        'left': 37,\n        37: 'left',\n        'right': 39,\n        39: 'right',\n        'tab': 9,\n        9: 'tab',\n        'escape': 27,\n        27: 'escape',\n        'enter': 13,\n        13: 'enter',\n        'pageUp': 33,\n        33: 'pageUp',\n        'pageDown': 34,\n        34: 'pageDown',\n        'shift': 16,\n        16: 'shift',\n        'control': 17,\n        17: 'control',\n        'space': 32,\n        32: 'space',\n        't': 84,\n        84: 't',\n        'delete': 46,\n        46: 'delete'\n    },\n        ViewModes = ['times', 'days', 'months', 'years', 'decades'],\n        keyState = {},\n        keyPressHandled = {};\n\n    var MinViewModeNumber = 0,\n        Default = {\n        timeZone: '',\n        format: false,\n        dayViewHeaderFormat: 'MMMM YYYY',\n        extraFormats: false,\n        stepping: 1,\n        minDate: false,\n        maxDate: false,\n        useCurrent: true,\n        collapse: true,\n        locale: moment.locale(),\n        defaultDate: false,\n        disabledDates: false,\n        enabledDates: false,\n        icons: {\n            time: 'fa fa-clock-o',\n            date: 'fa fa-calendar',\n            up: 'fa fa-arrow-up',\n            down: 'fa fa-arrow-down',\n            previous: 'fa fa-chevron-left',\n            next: 'fa fa-chevron-right',\n            today: 'fa fa-calendar-check-o',\n            clear: 'fa fa-trash',\n            close: 'fa fa-times'\n        },\n        tooltips: {\n            today: 'Go to today',\n            clear: 'Clear selection',\n            close: 'Close the picker',\n            selectMonth: 'Select Month',\n            prevMonth: 'Previous Month',\n            nextMonth: 'Next Month',\n            selectYear: 'Select Year',\n            prevYear: 'Previous Year',\n            nextYear: 'Next Year',\n            selectDecade: 'Select Decade',\n            prevDecade: 'Previous Decade',\n            nextDecade: 'Next Decade',\n            prevCentury: 'Previous Century',\n            nextCentury: 'Next Century',\n            pickHour: 'Pick Hour',\n            incrementHour: 'Increment Hour',\n            decrementHour: 'Decrement Hour',\n            pickMinute: 'Pick Minute',\n            incrementMinute: 'Increment Minute',\n            decrementMinute: 'Decrement Minute',\n            pickSecond: 'Pick Second',\n            incrementSecond: 'Increment Second',\n            decrementSecond: 'Decrement Second',\n            togglePeriod: 'Toggle Period',\n            selectTime: 'Select Time',\n            selectDate: 'Select Date'\n        },\n        useStrict: false,\n        sideBySide: false,\n        daysOfWeekDisabled: false,\n        calendarWeeks: false,\n        viewMode: 'days',\n        toolbarPlacement: 'default',\n        buttons: {\n            showToday: false,\n            showClear: false,\n            showClose: false\n        },\n        widgetPositioning: {\n            horizontal: 'auto',\n            vertical: 'auto'\n        },\n        widgetParent: null,\n        ignoreReadonly: false,\n        keepOpen: false,\n        focusOnShow: true,\n        inline: false,\n        keepInvalid: false,\n        keyBinds: {\n            up: function up() {\n                if (!this.widget) {\n                    return false;\n                }\n                var d = this._dates[0] || this.getMoment();\n                if (this.widget.find('.datepicker').is(':visible')) {\n                    this.date(d.clone().subtract(7, 'd'));\n                } else {\n                    this.date(d.clone().add(this.stepping(), 'm'));\n                }\n                return true;\n            },\n            down: function down() {\n                if (!this.widget) {\n                    this.show();\n                    return false;\n                }\n                var d = this._dates[0] || this.getMoment();\n                if (this.widget.find('.datepicker').is(':visible')) {\n                    this.date(d.clone().add(7, 'd'));\n                } else {\n                    this.date(d.clone().subtract(this.stepping(), 'm'));\n                }\n                return true;\n            },\n            'control up': function controlUp() {\n                if (!this.widget) {\n                    return false;\n                }\n                var d = this._dates[0] || this.getMoment();\n                if (this.widget.find('.datepicker').is(':visible')) {\n                    this.date(d.clone().subtract(1, 'y'));\n                } else {\n                    this.date(d.clone().add(1, 'h'));\n                }\n                return true;\n            },\n            'control down': function controlDown() {\n                if (!this.widget) {\n                    return false;\n                }\n                var d = this._dates[0] || this.getMoment();\n                if (this.widget.find('.datepicker').is(':visible')) {\n                    this.date(d.clone().add(1, 'y'));\n                } else {\n                    this.date(d.clone().subtract(1, 'h'));\n                }\n                return true;\n            },\n            left: function left() {\n                if (!this.widget) {\n                    return false;\n                }\n                var d = this._dates[0] || this.getMoment();\n                if (this.widget.find('.datepicker').is(':visible')) {\n                    this.date(d.clone().subtract(1, 'd'));\n                }\n                return true;\n            },\n            right: function right() {\n                if (!this.widget) {\n                    return false;\n                }\n                var d = this._dates[0] || this.getMoment();\n                if (this.widget.find('.datepicker').is(':visible')) {\n                    this.date(d.clone().add(1, 'd'));\n                }\n                return true;\n            },\n            pageUp: function pageUp() {\n                if (!this.widget) {\n                    return false;\n                }\n                var d = this._dates[0] || this.getMoment();\n                if (this.widget.find('.datepicker').is(':visible')) {\n                    this.date(d.clone().subtract(1, 'M'));\n                }\n                return true;\n            },\n            pageDown: function pageDown() {\n                if (!this.widget) {\n                    return false;\n                }\n                var d = this._dates[0] || this.getMoment();\n                if (this.widget.find('.datepicker').is(':visible')) {\n                    this.date(d.clone().add(1, 'M'));\n                }\n                return true;\n            },\n            enter: function enter() {\n                if (!this.widget) {\n                    return false;\n                }\n                this.hide();\n                return true;\n            },\n            escape: function escape() {\n                if (!this.widget) {\n                    return false;\n                }\n                this.hide();\n                return true;\n            },\n            'control space': function controlSpace() {\n                if (!this.widget) {\n                    return false;\n                }\n                if (this.widget.find('.timepicker').is(':visible')) {\n                    this.widget.find('.btn[data-action=\"togglePeriod\"]').click();\n                }\n                return true;\n            },\n            t: function t() {\n                if (!this.widget) {\n                    return false;\n                }\n                this.date(this.getMoment());\n                return true;\n            },\n            'delete': function _delete() {\n                if (!this.widget) {\n                    return false;\n                }\n                this.clear();\n                return true;\n            }\n        },\n        debug: false,\n        allowInputToggle: false,\n        disabledTimeIntervals: false,\n        disabledHours: false,\n        enabledHours: false,\n        viewDate: false,\n        allowMultidate: false,\n        multidateSeparator: ','\n    };\n\n    // ReSharper restore InconsistentNaming\n\n    // ReSharper disable once DeclarationHides\n    // ReSharper disable once InconsistentNaming\n\n    var DateTimePicker = function () {\n        /** @namespace eData.dateOptions */\n        /** @namespace moment.tz */\n\n        function DateTimePicker(element, options) {\n            _classCallCheck(this, DateTimePicker);\n\n            this._options = this._getOptions(options);\n            this._element = element;\n            this._dates = [];\n            this._datesFormatted = [];\n            this._viewDate = null;\n            this.unset = true;\n            this.component = false;\n            this.widget = false;\n            this.use24Hours = null;\n            this.actualFormat = null;\n            this.parseFormats = null;\n            this.currentViewMode = null;\n\n            this._int();\n        }\n\n        /**\n         * @return {string}\n         */\n\n\n        //private\n\n        DateTimePicker.prototype._int = function _int() {\n            var targetInput = this._element.data('target-input');\n            if (this._element.is('input')) {\n                this.input = this._element;\n            } else if (targetInput !== undefined) {\n                if (targetInput === 'nearest') {\n                    this.input = this._element.find('input');\n                } else {\n                    this.input = $(targetInput);\n                }\n            }\n\n            this._dates = [];\n            this._dates[0] = this.getMoment();\n            this._viewDate = this.getMoment().clone();\n\n            $.extend(true, this._options, this._dataToOptions());\n\n            this.options(this._options);\n\n            this._initFormatting();\n\n            if (this.input !== undefined && this.input.is('input') && this.input.val().trim().length !== 0) {\n                this._setValue(this._parseInputDate(this.input.val().trim()), 0);\n            } else if (this._options.defaultDate && this.input !== undefined && this.input.attr('placeholder') === undefined) {\n                this._setValue(this._options.defaultDate, 0);\n            }\n            if (this._options.inline) {\n                this.show();\n            }\n        };\n\n        DateTimePicker.prototype._update = function _update() {\n            if (!this.widget) {\n                return;\n            }\n            this._fillDate();\n            this._fillTime();\n        };\n\n        DateTimePicker.prototype._setValue = function _setValue(targetMoment, index) {\n            var oldDate = this.unset ? null : this._dates[index];\n            var outpValue = '';\n            // case of calling setValue(null or false)\n            if (!targetMoment) {\n                if (!this._options.allowMultidate || this._dates.length === 1) {\n                    this.unset = true;\n                    this._dates = [];\n                    this._datesFormatted = [];\n                } else {\n                    outpValue = this._element.data('date') + ',';\n                    outpValue = outpValue.replace(oldDate.format(this.actualFormat) + ',', '').replace(',,', '').replace(/,\\s*$/, '');\n                    this._dates.splice(index, 1);\n                    this._datesFormatted.splice(index, 1);\n                }\n                if (this.input !== undefined) {\n                    this.input.val(outpValue);\n                    this.input.trigger('input');\n                }\n                this._element.data('date', outpValue);\n                this._notifyEvent({\n                    type: DateTimePicker.Event.CHANGE,\n                    date: false,\n                    oldDate: oldDate\n                });\n                this._update();\n                return;\n            }\n\n            targetMoment = targetMoment.clone().locale(this._options.locale);\n\n            if (this._hasTimeZone()) {\n                targetMoment.tz(this._options.timeZone);\n            }\n\n            if (this._options.stepping !== 1) {\n                targetMoment.minutes(Math.round(targetMoment.minutes() / this._options.stepping) * this._options.stepping).seconds(0);\n            }\n\n            if (this._isValid(targetMoment)) {\n                this._dates[index] = targetMoment;\n                this._datesFormatted[index] = targetMoment.format('YYYY-MM-DD');\n                this._viewDate = targetMoment.clone();\n                if (this._options.allowMultidate && this._dates.length > 1) {\n                    for (var i = 0; i < this._dates.length; i++) {\n                        outpValue += '' + this._dates[i].format(this.actualFormat) + this._options.multidateSeparator;\n                    }\n                    outpValue = outpValue.replace(/,\\s*$/, '');\n                } else {\n                    outpValue = this._dates[index].format(this.actualFormat);\n                }\n                if (this.input !== undefined) {\n                    this.input.val(outpValue);\n                    this.input.trigger('input');\n                }\n                this._element.data('date', outpValue);\n\n                this.unset = false;\n                this._update();\n                this._notifyEvent({\n                    type: DateTimePicker.Event.CHANGE,\n                    date: this._dates[index].clone(),\n                    oldDate: oldDate\n                });\n            } else {\n                if (!this._options.keepInvalid) {\n                    if (this.input !== undefined) {\n                        this.input.val('' + (this.unset ? '' : this._dates[index].format(this.actualFormat)));\n                        this.input.trigger('input');\n                    }\n                } else {\n                    this._notifyEvent({\n                        type: DateTimePicker.Event.CHANGE,\n                        date: targetMoment,\n                        oldDate: oldDate\n                    });\n                }\n                this._notifyEvent({\n                    type: DateTimePicker.Event.ERROR,\n                    date: targetMoment,\n                    oldDate: oldDate\n                });\n            }\n        };\n\n        DateTimePicker.prototype._change = function _change(e) {\n            var val = $(e.target).val().trim(),\n                parsedDate = val ? this._parseInputDate(val) : null;\n            this._setValue(parsedDate, 0); // Odoo FIX: if a valid date is replaced by an invalid one, lib will crash, see https://github.com/tempusdominus/bootstrap-4/issues/223\n            e.stopImmediatePropagation();\n            return false;\n        };\n\n        //noinspection JSMethodCanBeStatic\n\n\n        DateTimePicker.prototype._getOptions = function _getOptions(options) {\n            options = $.extend(true, {}, Default, options);\n            return options;\n        };\n\n        DateTimePicker.prototype._hasTimeZone = function _hasTimeZone() {\n            return moment.tz !== undefined && this._options.timeZone !== undefined && this._options.timeZone !== null && this._options.timeZone !== '';\n        };\n\n        DateTimePicker.prototype._isEnabled = function _isEnabled(granularity) {\n            if (typeof granularity !== 'string' || granularity.length > 1) {\n                throw new TypeError('isEnabled expects a single character string parameter');\n            }\n            switch (granularity) {\n                case 'y':\n                    return this.actualFormat.indexOf('Y') !== -1;\n                case 'M':\n                    return this.actualFormat.indexOf('M') !== -1;\n                case 'd':\n                    return this.actualFormat.toLowerCase().indexOf('d') !== -1;\n                case 'h':\n                case 'H':\n                    return this.actualFormat.toLowerCase().indexOf('h') !== -1;\n                case 'm':\n                    return this.actualFormat.indexOf('m') !== -1;\n                case 's':\n                    return this.actualFormat.indexOf('s') !== -1;\n                case 'a':\n                case 'A':\n                    return this.actualFormat.toLowerCase().indexOf('a') !== -1;\n                default:\n                    return false;\n            }\n        };\n\n        DateTimePicker.prototype._hasTime = function _hasTime() {\n            return this._isEnabled('h') || this._isEnabled('m') || this._isEnabled('s');\n        };\n\n        DateTimePicker.prototype._hasDate = function _hasDate() {\n            return this._isEnabled('y') || this._isEnabled('M') || this._isEnabled('d');\n        };\n\n        DateTimePicker.prototype._dataToOptions = function _dataToOptions() {\n            var eData = this._element.data();\n            var dataOptions = {};\n\n            if (eData.dateOptions && eData.dateOptions instanceof Object) {\n                dataOptions = $.extend(true, dataOptions, eData.dateOptions);\n            }\n\n            $.each(this._options, function (key) {\n                var attributeName = 'date' + key.charAt(0).toUpperCase() + key.slice(1); //todo data api key\n                if (eData[attributeName] !== undefined) {\n                    dataOptions[key] = eData[attributeName];\n                } else {\n                    delete dataOptions[key];\n                }\n            });\n            return dataOptions;\n        };\n\n        DateTimePicker.prototype._notifyEvent = function _notifyEvent(e) {\n            // /!\\ ODOO FIX: these next conditions have been modified by odoo\n            // FIXME should write a test about the tricky case this handles\n            if (e.type === DateTimePicker.Event.CHANGE) {\n                if (!e.date && !e.oldDate) {\n                    return;\n                }\n                // check _isUTC flag to ensure that we are not comparing apples and oranges\n                var bothUTC = e.date && e.oldDate && e.date._isUTC === e.oldDate._isUTC;\n                if (bothUTC && e.date.isSame(e.oldDate)) {\n                    return;\n                }\n            }\n            this._element.trigger(e);\n        };\n\n        DateTimePicker.prototype._viewUpdate = function _viewUpdate(e) {\n            if (e === 'y') {\n                e = 'YYYY';\n            }\n            this._notifyEvent({\n                type: DateTimePicker.Event.UPDATE,\n                change: e,\n                viewDate: this._viewDate.clone()\n            });\n        };\n\n        DateTimePicker.prototype._showMode = function _showMode(dir) {\n            if (!this.widget) {\n                return;\n            }\n            if (dir) {\n                this.currentViewMode = Math.max(MinViewModeNumber, Math.min(3, this.currentViewMode + dir));\n            }\n            this.widget.find('.datepicker > div').hide().filter('.datepicker-' + DatePickerModes[this.currentViewMode].CLASS_NAME).show();\n        };\n\n        DateTimePicker.prototype._isInDisabledDates = function _isInDisabledDates(testDate) {\n            return this._options.disabledDates[testDate.format('YYYY-MM-DD')] === true;\n        };\n\n        DateTimePicker.prototype._isInEnabledDates = function _isInEnabledDates(testDate) {\n            return this._options.enabledDates[testDate.format('YYYY-MM-DD')] === true;\n        };\n\n        DateTimePicker.prototype._isInDisabledHours = function _isInDisabledHours(testDate) {\n            return this._options.disabledHours[testDate.format('H')] === true;\n        };\n\n        DateTimePicker.prototype._isInEnabledHours = function _isInEnabledHours(testDate) {\n            return this._options.enabledHours[testDate.format('H')] === true;\n        };\n\n        DateTimePicker.prototype._isValid = function _isValid(targetMoment, granularity) {\n            if (!targetMoment.isValid()) {\n                return false;\n            }\n            if (this._options.disabledDates && granularity === 'd' && this._isInDisabledDates(targetMoment)) {\n                return false;\n            }\n            if (this._options.enabledDates && granularity === 'd' && !this._isInEnabledDates(targetMoment)) {\n                return false;\n            }\n            if (this._options.minDate && targetMoment.isBefore(this._options.minDate, granularity)) {\n                return false;\n            }\n            if (this._options.maxDate && targetMoment.isAfter(this._options.maxDate, granularity)) {\n                return false;\n            }\n            if (this._options.daysOfWeekDisabled && granularity === 'd' && this._options.daysOfWeekDisabled.indexOf(targetMoment.day()) !== -1) {\n                return false;\n            }\n            if (this._options.disabledHours && (granularity === 'h' || granularity === 'm' || granularity === 's') && this._isInDisabledHours(targetMoment)) {\n                return false;\n            }\n            if (this._options.enabledHours && (granularity === 'h' || granularity === 'm' || granularity === 's') && !this._isInEnabledHours(targetMoment)) {\n                return false;\n            }\n            if (this._options.disabledTimeIntervals && (granularity === 'h' || granularity === 'm' || granularity === 's')) {\n                var found = false;\n                $.each(this._options.disabledTimeIntervals, function () {\n                    if (targetMoment.isBetween(this[0], this[1])) {\n                        found = true;\n                        return false;\n                    }\n                });\n                if (found) {\n                    return false;\n                }\n            }\n            return true;\n        };\n\n        DateTimePicker.prototype._parseInputDate = function _parseInputDate(inputDate) {\n            if (this._options.parseInputDate === undefined) {\n                if (!moment.isMoment(inputDate)) {\n                    inputDate = this.getMoment(inputDate);\n                }\n            } else {\n                inputDate = this._options.parseInputDate(inputDate);\n            }\n            //inputDate.locale(this.options.locale);\n            return inputDate;\n        };\n\n        DateTimePicker.prototype._keydown = function _keydown(e) {\n            var handler = null,\n                index = void 0,\n                index2 = void 0,\n                keyBindKeys = void 0,\n                allModifiersPressed = void 0;\n            var pressedKeys = [],\n                pressedModifiers = {},\n                currentKey = e.which,\n                pressed = 'p';\n\n            keyState[currentKey] = pressed;\n\n            for (index in keyState) {\n                if (keyState.hasOwnProperty(index) && keyState[index] === pressed) {\n                    pressedKeys.push(index);\n                    if (parseInt(index, 10) !== currentKey) {\n                        pressedModifiers[index] = true;\n                    }\n                }\n            }\n\n            for (index in this._options.keyBinds) {\n                if (this._options.keyBinds.hasOwnProperty(index) && typeof this._options.keyBinds[index] === 'function') {\n                    keyBindKeys = index.split(' ');\n                    if (keyBindKeys.length === pressedKeys.length && KeyMap[currentKey] === keyBindKeys[keyBindKeys.length - 1]) {\n                        allModifiersPressed = true;\n                        for (index2 = keyBindKeys.length - 2; index2 >= 0; index2--) {\n                            if (!(KeyMap[keyBindKeys[index2]] in pressedModifiers)) {\n                                allModifiersPressed = false;\n                                break;\n                            }\n                        }\n                        if (allModifiersPressed) {\n                            handler = this._options.keyBinds[index];\n                            break;\n                        }\n                    }\n                }\n            }\n\n            if (handler) {\n                if (handler.call(this)) {\n                    e.stopPropagation();\n                    e.preventDefault();\n                }\n            }\n        };\n\n        //noinspection JSMethodCanBeStatic,SpellCheckingInspection\n\n\n        DateTimePicker.prototype._keyup = function _keyup(e) {\n            keyState[e.which] = 'r';\n            if (keyPressHandled[e.which]) {\n                keyPressHandled[e.which] = false;\n                e.stopPropagation();\n                e.preventDefault();\n            }\n        };\n\n        DateTimePicker.prototype._indexGivenDates = function _indexGivenDates(givenDatesArray) {\n            // Store given enabledDates and disabledDates as keys.\n            // This way we can check their existence in O(1) time instead of looping through whole array.\n            // (for example: options.enabledDates['2014-02-27'] === true)\n            var givenDatesIndexed = {},\n                self = this;\n            $.each(givenDatesArray, function () {\n                var dDate = self._parseInputDate(this);\n                if (dDate.isValid()) {\n                    givenDatesIndexed[dDate.format('YYYY-MM-DD')] = true;\n                }\n            });\n            return Object.keys(givenDatesIndexed).length ? givenDatesIndexed : false;\n        };\n\n        DateTimePicker.prototype._indexGivenHours = function _indexGivenHours(givenHoursArray) {\n            // Store given enabledHours and disabledHours as keys.\n            // This way we can check their existence in O(1) time instead of looping through whole array.\n            // (for example: options.enabledHours['2014-02-27'] === true)\n            var givenHoursIndexed = {};\n            $.each(givenHoursArray, function () {\n                givenHoursIndexed[this] = true;\n            });\n            return Object.keys(givenHoursIndexed).length ? givenHoursIndexed : false;\n        };\n\n        DateTimePicker.prototype._initFormatting = function _initFormatting() {\n            var format = this._options.format || 'L LT',\n                self = this;\n\n            this.actualFormat = format.replace(/(\\[[^\\[]*])|(\\\\)?(LTS|LT|LL?L?L?|l{1,4})/g, function (formatInput) {\n                return self._dates[0].localeData().longDateFormat(formatInput) || formatInput; //todo taking the first date should be ok\n            });\n\n            this.parseFormats = this._options.extraFormats ? this._options.extraFormats.slice() : [];\n            if (this.parseFormats.indexOf(format) < 0 && this.parseFormats.indexOf(this.actualFormat) < 0) {\n                this.parseFormats.push(this.actualFormat);\n            }\n\n            this.use24Hours = this.actualFormat.toLowerCase().indexOf('a') < 1 && this.actualFormat.replace(/\\[.*?]/g, '').indexOf('h') < 1;\n\n            if (this._isEnabled('y')) {\n                MinViewModeNumber = 2;\n            }\n            if (this._isEnabled('M')) {\n                MinViewModeNumber = 1;\n            }\n            if (this._isEnabled('d')) {\n                MinViewModeNumber = 0;\n            }\n\n            this.currentViewMode = Math.max(MinViewModeNumber, this.currentViewMode);\n\n            if (!this.unset) {\n                this._setValue(this._dates[0], 0);\n            }\n        };\n\n        DateTimePicker.prototype._getLastPickedDate = function _getLastPickedDate() {\n            return this._dates[this._getLastPickedDateIndex()] || this.getMoment(); // FIXME changed by Odoo\n        };\n\n        DateTimePicker.prototype._getLastPickedDateIndex = function _getLastPickedDateIndex() {\n            return this._dates.length - 1;\n        };\n\n        //public\n\n\n        DateTimePicker.prototype.getMoment = function getMoment(d, f) { // ODOO FIX: give optional format\n            var returnMoment = void 0;\n\n            // ODOO FIX: default to original `parseFormats` attribute\n            if (!f) {\n                f = this.parseFormats;\n            }\n\n            if (d === undefined || d === null) {\n                returnMoment = moment(); //TODO should this use format? and locale?\n            } else if (this._hasTimeZone()) {\n                // There is a string to parse and a default time zone\n                // parse with the tz function which takes a default time zone if it is not in the format string\n                returnMoment = moment.tz(d, f, this._options.locale, this._options.useStrict, this._options.timeZone); // ODOO FIX: use format argument\n            } else {\n                returnMoment = moment(d, f, this._options.locale, this._options.useStrict); // ODOO FIX: use format argument\n            }\n\n            if (this._hasTimeZone()) {\n                returnMoment.tz(this._options.timeZone);\n            }\n\n            return returnMoment;\n        };\n\n        DateTimePicker.prototype.toggle = function toggle() {\n            return this.widget ? this.hide() : this.show();\n        };\n\n        DateTimePicker.prototype.ignoreReadonly = function ignoreReadonly(_ignoreReadonly) {\n            if (arguments.length === 0) {\n                return this._options.ignoreReadonly;\n            }\n            if (typeof _ignoreReadonly !== 'boolean') {\n                throw new TypeError('ignoreReadonly () expects a boolean parameter');\n            }\n            this._options.ignoreReadonly = _ignoreReadonly;\n        };\n\n        DateTimePicker.prototype.options = function options(newOptions) {\n            if (arguments.length === 0) {\n                return $.extend(true, {}, this._options);\n            }\n\n            if (!(newOptions instanceof Object)) {\n                throw new TypeError('options() this.options parameter should be an object');\n            }\n            $.extend(true, this._options, newOptions);\n            var self = this;\n            $.each(this._options, function (key, value) {\n                if (self[key] !== undefined) {\n                    self[key](value);\n                }\n            });\n        };\n\n        DateTimePicker.prototype.date = function date(newDate, index) {\n            index = index || 0;\n            if (arguments.length === 0) {\n                if (this.unset) {\n                    return null;\n                }\n                if (this._options.allowMultidate) {\n                    return this._dates.join(this._options.multidateSeparator);\n                } else {\n                    return this._dates[index].clone();\n                }\n            }\n\n            if (newDate !== null && typeof newDate !== 'string' && !moment.isMoment(newDate) && !(newDate instanceof Date)) {\n                throw new TypeError('date() parameter must be one of [null, string, moment or Date]');\n            }\n\n            this._setValue(newDate === null ? null : this._parseInputDate(newDate), index);\n        };\n\n        DateTimePicker.prototype.format = function format(newFormat) {\n            if (arguments.length === 0) {\n                return this._options.format;\n            }\n\n            if (typeof newFormat !== 'string' && (typeof newFormat !== 'boolean' || newFormat !== false)) {\n                throw new TypeError('format() expects a string or boolean:false parameter ' + newFormat);\n            }\n\n            this._options.format = newFormat;\n            if (this.actualFormat) {\n                this._initFormatting(); // reinitialize formatting\n            }\n        };\n\n        DateTimePicker.prototype.timeZone = function timeZone(newZone) {\n            if (arguments.length === 0) {\n                return this._options.timeZone;\n            }\n\n            if (typeof newZone !== 'string') {\n                throw new TypeError('newZone() expects a string parameter');\n            }\n\n            this._options.timeZone = newZone;\n        };\n\n        DateTimePicker.prototype.dayViewHeaderFormat = function dayViewHeaderFormat(newFormat) {\n            if (arguments.length === 0) {\n                return this._options.dayViewHeaderFormat;\n            }\n\n            if (typeof newFormat !== 'string') {\n                throw new TypeError('dayViewHeaderFormat() expects a string parameter');\n            }\n\n            this._options.dayViewHeaderFormat = newFormat;\n        };\n\n        DateTimePicker.prototype.extraFormats = function extraFormats(formats) {\n            if (arguments.length === 0) {\n                return this._options.extraFormats;\n            }\n\n            if (formats !== false && !(formats instanceof Array)) {\n                throw new TypeError('extraFormats() expects an array or false parameter');\n            }\n\n            this._options.extraFormats = formats;\n            if (this.parseFormats) {\n                this._initFormatting(); // reinit formatting\n            }\n        };\n\n        DateTimePicker.prototype.disabledDates = function disabledDates(dates) {\n            if (arguments.length === 0) {\n                return this._options.disabledDates ? $.extend({}, this._options.disabledDates) : this._options.disabledDates;\n            }\n\n            if (!dates) {\n                this._options.disabledDates = false;\n                this._update();\n                return true;\n            }\n            if (!(dates instanceof Array)) {\n                throw new TypeError('disabledDates() expects an array parameter');\n            }\n            this._options.disabledDates = this._indexGivenDates(dates);\n            this._options.enabledDates = false;\n            this._update();\n        };\n\n        DateTimePicker.prototype.enabledDates = function enabledDates(dates) {\n            if (arguments.length === 0) {\n                return this._options.enabledDates ? $.extend({}, this._options.enabledDates) : this._options.enabledDates;\n            }\n\n            if (!dates) {\n                this._options.enabledDates = false;\n                this._update();\n                return true;\n            }\n            if (!(dates instanceof Array)) {\n                throw new TypeError('enabledDates() expects an array parameter');\n            }\n            this._options.enabledDates = this._indexGivenDates(dates);\n            this._options.disabledDates = false;\n            this._update();\n        };\n\n        DateTimePicker.prototype.daysOfWeekDisabled = function daysOfWeekDisabled(_daysOfWeekDisabled) {\n            if (arguments.length === 0) {\n                return this._options.daysOfWeekDisabled.splice(0);\n            }\n\n            if (typeof _daysOfWeekDisabled === 'boolean' && !_daysOfWeekDisabled) {\n                this._options.daysOfWeekDisabled = false;\n                this._update();\n                return true;\n            }\n\n            if (!(_daysOfWeekDisabled instanceof Array)) {\n                throw new TypeError('daysOfWeekDisabled() expects an array parameter');\n            }\n            this._options.daysOfWeekDisabled = _daysOfWeekDisabled.reduce(function (previousValue, currentValue) {\n                currentValue = parseInt(currentValue, 10);\n                if (currentValue > 6 || currentValue < 0 || isNaN(currentValue)) {\n                    return previousValue;\n                }\n                if (previousValue.indexOf(currentValue) === -1) {\n                    previousValue.push(currentValue);\n                }\n                return previousValue;\n            }, []).sort();\n            if (this._options.useCurrent && !this._options.keepInvalid) {\n                for (var i = 0; i < this._dates.length; i++) {\n                    var tries = 0;\n                    while (!this._isValid(this._dates[i], 'd')) {\n                        this._dates[i].add(1, 'd');\n                        if (tries === 31) {\n                            throw 'Tried 31 times to find a valid date';\n                        }\n                        tries++;\n                    }\n                    this._setValue(this._dates[i], i);\n                }\n            }\n            this._update();\n        };\n\n        DateTimePicker.prototype.maxDate = function maxDate(_maxDate) {\n            if (arguments.length === 0) {\n                return this._options.maxDate ? this._options.maxDate.clone() : this._options.maxDate;\n            }\n\n            if (typeof _maxDate === 'boolean' && _maxDate === false) {\n                this._options.maxDate = false;\n                this._update();\n                return true;\n            }\n\n            if (typeof _maxDate === 'string') {\n                if (_maxDate === 'now' || _maxDate === 'moment') {\n                    _maxDate = this.getMoment();\n                }\n            }\n\n            var parsedDate = this._parseInputDate(_maxDate);\n\n            if (!parsedDate.isValid()) {\n                throw new TypeError('maxDate() Could not parse date parameter: ' + _maxDate);\n            }\n            if (this._options.minDate && parsedDate.isBefore(this._options.minDate)) {\n                throw new TypeError('maxDate() date parameter is before this.options.minDate: ' + parsedDate.format(this.actualFormat));\n            }\n            this._options.maxDate = parsedDate;\n            for (var i = 0; i < this._dates.length; i++) {\n                if (this._options.useCurrent && !this._options.keepInvalid && this._dates[i].isAfter(_maxDate)) {\n                    this._setValue(this._options.maxDate, i);\n                }\n            }\n            if (this._viewDate.isAfter(parsedDate)) {\n                this._viewDate = parsedDate.clone().subtract(this._options.stepping, 'm');\n            }\n            this._update();\n        };\n\n        DateTimePicker.prototype.minDate = function minDate(_minDate) {\n            if (arguments.length === 0) {\n                return this._options.minDate ? this._options.minDate.clone() : this._options.minDate;\n            }\n\n            if (typeof _minDate === 'boolean' && _minDate === false) {\n                this._options.minDate = false;\n                this._update();\n                return true;\n            }\n\n            if (typeof _minDate === 'string') {\n                if (_minDate === 'now' || _minDate === 'moment') {\n                    _minDate = this.getMoment();\n                }\n            }\n\n            var parsedDate = this._parseInputDate(_minDate);\n\n            if (!parsedDate.isValid()) {\n                throw new TypeError('minDate() Could not parse date parameter: ' + _minDate);\n            }\n            if (this._options.maxDate && parsedDate.isAfter(this._options.maxDate)) {\n                throw new TypeError('minDate() date parameter is after this.options.maxDate: ' + parsedDate.format(this.actualFormat));\n            }\n            this._options.minDate = parsedDate;\n            for (var i = 0; i < this._dates.length; i++) {\n                if (this._options.useCurrent && !this._options.keepInvalid && this._dates[i].isBefore(_minDate)) {\n                    this._setValue(this._options.minDate, i);\n                }\n            }\n            if (this._viewDate.isBefore(parsedDate)) {\n                this._viewDate = parsedDate.clone().add(this._options.stepping, 'm');\n            }\n            this._update();\n        };\n\n        DateTimePicker.prototype.defaultDate = function defaultDate(_defaultDate) {\n            if (arguments.length === 0) {\n                return this._options.defaultDate ? this._options.defaultDate.clone() : this._options.defaultDate;\n            }\n            if (!_defaultDate) {\n                this._options.defaultDate = false;\n                return true;\n            }\n\n            if (typeof _defaultDate === 'string') {\n                if (_defaultDate === 'now' || _defaultDate === 'moment') {\n                    _defaultDate = this.getMoment();\n                } else {\n                    _defaultDate = this.getMoment(_defaultDate);\n                }\n            }\n\n            var parsedDate = this._parseInputDate(_defaultDate);\n            if (!parsedDate.isValid()) {\n                throw new TypeError('defaultDate() Could not parse date parameter: ' + _defaultDate);\n            }\n            if (!this._isValid(parsedDate)) {\n                throw new TypeError('defaultDate() date passed is invalid according to component setup validations');\n            }\n\n            this._options.defaultDate = parsedDate;\n\n            if (this._options.defaultDate && this._options.inline || this.input !== undefined && this.input.val().trim() === '') {\n                this._setValue(this._options.defaultDate, 0);\n            }\n        };\n\n        DateTimePicker.prototype.locale = function locale(_locale) {\n            if (arguments.length === 0) {\n                return this._options.locale;\n            }\n\n            if (!moment.localeData(_locale)) {\n                throw new TypeError('locale() locale ' + _locale + ' is not loaded from moment locales!');\n            }\n\n            this._options.locale = _locale;\n\n            for (var i = 0; i < this._dates.length; i++) {\n                this._dates[i].locale(this._options.locale);\n            }\n            this._viewDate.locale(this._options.locale);\n\n            if (this.actualFormat) {\n                this._initFormatting(); // reinitialize formatting\n            }\n            if (this.widget) {\n                this.hide();\n                this.show();\n            }\n        };\n\n        DateTimePicker.prototype.stepping = function stepping(_stepping) {\n            if (arguments.length === 0) {\n                return this._options.stepping;\n            }\n\n            _stepping = parseInt(_stepping, 10);\n            if (isNaN(_stepping) || _stepping < 1) {\n                _stepping = 1;\n            }\n            this._options.stepping = _stepping;\n        };\n\n        DateTimePicker.prototype.useCurrent = function useCurrent(_useCurrent) {\n            var useCurrentOptions = ['year', 'month', 'day', 'hour', 'minute'];\n            if (arguments.length === 0) {\n                return this._options.useCurrent;\n            }\n\n            if (typeof _useCurrent !== 'boolean' && typeof _useCurrent !== 'string') {\n                throw new TypeError('useCurrent() expects a boolean or string parameter');\n            }\n            if (typeof _useCurrent === 'string' && useCurrentOptions.indexOf(_useCurrent.toLowerCase()) === -1) {\n                throw new TypeError('useCurrent() expects a string parameter of ' + useCurrentOptions.join(', '));\n            }\n            this._options.useCurrent = _useCurrent;\n        };\n\n        DateTimePicker.prototype.collapse = function collapse(_collapse) {\n            if (arguments.length === 0) {\n                return this._options.collapse;\n            }\n\n            if (typeof _collapse !== 'boolean') {\n                throw new TypeError('collapse() expects a boolean parameter');\n            }\n            if (this._options.collapse === _collapse) {\n                return true;\n            }\n            this._options.collapse = _collapse;\n            if (this.widget) {\n                this.hide();\n                this.show();\n            }\n        };\n\n        DateTimePicker.prototype.icons = function icons(_icons) {\n            if (arguments.length === 0) {\n                return $.extend({}, this._options.icons);\n            }\n\n            if (!(_icons instanceof Object)) {\n                throw new TypeError('icons() expects parameter to be an Object');\n            }\n\n            $.extend(this._options.icons, _icons);\n\n            if (this.widget) {\n                this.hide();\n                this.show();\n            }\n        };\n\n        DateTimePicker.prototype.tooltips = function tooltips(_tooltips) {\n            if (arguments.length === 0) {\n                return $.extend({}, this._options.tooltips);\n            }\n\n            if (!(_tooltips instanceof Object)) {\n                throw new TypeError('tooltips() expects parameter to be an Object');\n            }\n            $.extend(this._options.tooltips, _tooltips);\n            if (this.widget) {\n                this.hide();\n                this.show();\n            }\n        };\n\n        DateTimePicker.prototype.useStrict = function useStrict(_useStrict) {\n            if (arguments.length === 0) {\n                return this._options.useStrict;\n            }\n\n            if (typeof _useStrict !== 'boolean') {\n                throw new TypeError('useStrict() expects a boolean parameter');\n            }\n            this._options.useStrict = _useStrict;\n        };\n\n        DateTimePicker.prototype.sideBySide = function sideBySide(_sideBySide) {\n            if (arguments.length === 0) {\n                return this._options.sideBySide;\n            }\n\n            if (typeof _sideBySide !== 'boolean') {\n                throw new TypeError('sideBySide() expects a boolean parameter');\n            }\n            this._options.sideBySide = _sideBySide;\n            if (this.widget) {\n                this.hide();\n                this.show();\n            }\n        };\n\n        DateTimePicker.prototype.viewMode = function viewMode(_viewMode) {\n            if (arguments.length === 0) {\n                return this._options.viewMode;\n            }\n\n            if (typeof _viewMode !== 'string') {\n                throw new TypeError('viewMode() expects a string parameter');\n            }\n\n            if (DateTimePicker.ViewModes.indexOf(_viewMode) === -1) {\n                throw new TypeError('viewMode() parameter must be one of (' + DateTimePicker.ViewModes.join(', ') + ') value');\n            }\n\n            this._options.viewMode = _viewMode;\n            this.currentViewMode = Math.max(DateTimePicker.ViewModes.indexOf(_viewMode) - 1, DateTimePicker.MinViewModeNumber);\n\n            this._showMode();\n        };\n\n        DateTimePicker.prototype.calendarWeeks = function calendarWeeks(_calendarWeeks) {\n            if (arguments.length === 0) {\n                return this._options.calendarWeeks;\n            }\n\n            if (typeof _calendarWeeks !== 'boolean') {\n                throw new TypeError('calendarWeeks() expects parameter to be a boolean value');\n            }\n\n            this._options.calendarWeeks = _calendarWeeks;\n            this._update();\n        };\n\n        DateTimePicker.prototype.buttons = function buttons(_buttons) {\n            if (arguments.length === 0) {\n                return $.extend({}, this._options.buttons);\n            }\n\n            if (!(_buttons instanceof Object)) {\n                throw new TypeError('buttons() expects parameter to be an Object');\n            }\n\n            $.extend(this._options.buttons, _buttons);\n\n            if (typeof this._options.buttons.showToday !== 'boolean') {\n                throw new TypeError('buttons.showToday expects a boolean parameter');\n            }\n            if (typeof this._options.buttons.showClear !== 'boolean') {\n                throw new TypeError('buttons.showClear expects a boolean parameter');\n            }\n            if (typeof this._options.buttons.showClose !== 'boolean') {\n                throw new TypeError('buttons.showClose expects a boolean parameter');\n            }\n\n            if (this.widget) {\n                this.hide();\n                this.show();\n            }\n        };\n\n        DateTimePicker.prototype.keepOpen = function keepOpen(_keepOpen) {\n            if (arguments.length === 0) {\n                return this._options.keepOpen;\n            }\n\n            if (typeof _keepOpen !== 'boolean') {\n                throw new TypeError('keepOpen() expects a boolean parameter');\n            }\n\n            this._options.keepOpen = _keepOpen;\n        };\n\n        DateTimePicker.prototype.focusOnShow = function focusOnShow(_focusOnShow) {\n            if (arguments.length === 0) {\n                return this._options.focusOnShow;\n            }\n\n            if (typeof _focusOnShow !== 'boolean') {\n                throw new TypeError('focusOnShow() expects a boolean parameter');\n            }\n\n            this._options.focusOnShow = _focusOnShow;\n        };\n\n        DateTimePicker.prototype.inline = function inline(_inline) {\n            if (arguments.length === 0) {\n                return this._options.inline;\n            }\n\n            if (typeof _inline !== 'boolean') {\n                throw new TypeError('inline() expects a boolean parameter');\n            }\n\n            this._options.inline = _inline;\n        };\n\n        DateTimePicker.prototype.clear = function clear() {\n            this._setValue(null); //todo\n        };\n\n        DateTimePicker.prototype.keyBinds = function keyBinds(_keyBinds) {\n            if (arguments.length === 0) {\n                return this._options.keyBinds;\n            }\n\n            this._options.keyBinds = _keyBinds;\n        };\n\n        DateTimePicker.prototype.debug = function debug(_debug) {\n            if (typeof _debug !== 'boolean') {\n                throw new TypeError('debug() expects a boolean parameter');\n            }\n\n            this._options.debug = _debug;\n        };\n\n        DateTimePicker.prototype.allowInputToggle = function allowInputToggle(_allowInputToggle) {\n            if (arguments.length === 0) {\n                return this._options.allowInputToggle;\n            }\n\n            if (typeof _allowInputToggle !== 'boolean') {\n                throw new TypeError('allowInputToggle() expects a boolean parameter');\n            }\n\n            this._options.allowInputToggle = _allowInputToggle;\n        };\n\n        DateTimePicker.prototype.keepInvalid = function keepInvalid(_keepInvalid) {\n            if (arguments.length === 0) {\n                return this._options.keepInvalid;\n            }\n\n            if (typeof _keepInvalid !== 'boolean') {\n                throw new TypeError('keepInvalid() expects a boolean parameter');\n            }\n            this._options.keepInvalid = _keepInvalid;\n        };\n\n        DateTimePicker.prototype.datepickerInput = function datepickerInput(_datepickerInput) {\n            if (arguments.length === 0) {\n                return this._options.datepickerInput;\n            }\n\n            if (typeof _datepickerInput !== 'string') {\n                throw new TypeError('datepickerInput() expects a string parameter');\n            }\n\n            this._options.datepickerInput = _datepickerInput;\n        };\n\n        DateTimePicker.prototype.parseInputDate = function parseInputDate(_parseInputDate2) {\n            if (arguments.length === 0) {\n                return this._options.parseInputDate;\n            }\n\n            if (typeof _parseInputDate2 !== 'function') {\n                throw new TypeError('parseInputDate() should be as function');\n            }\n\n            this._options.parseInputDate = _parseInputDate2;\n        };\n\n        DateTimePicker.prototype.disabledTimeIntervals = function disabledTimeIntervals(_disabledTimeIntervals) {\n            if (arguments.length === 0) {\n                return this._options.disabledTimeIntervals ? $.extend({}, this._options.disabledTimeIntervals) : this._options.disabledTimeIntervals;\n            }\n\n            if (!_disabledTimeIntervals) {\n                this._options.disabledTimeIntervals = false;\n                this._update();\n                return true;\n            }\n            if (!(_disabledTimeIntervals instanceof Array)) {\n                throw new TypeError('disabledTimeIntervals() expects an array parameter');\n            }\n            this._options.disabledTimeIntervals = _disabledTimeIntervals;\n            this._update();\n        };\n\n        DateTimePicker.prototype.disabledHours = function disabledHours(hours) {\n            if (arguments.length === 0) {\n                return this._options.disabledHours ? $.extend({}, this._options.disabledHours) : this._options.disabledHours;\n            }\n\n            if (!hours) {\n                this._options.disabledHours = false;\n                this._update();\n                return true;\n            }\n            if (!(hours instanceof Array)) {\n                throw new TypeError('disabledHours() expects an array parameter');\n            }\n            this._options.disabledHours = this._indexGivenHours(hours);\n            this._options.enabledHours = false;\n            if (this._options.useCurrent && !this._options.keepInvalid) {\n                for (var i = 0; i < this._dates.length; i++) {\n                    var tries = 0;\n                    while (!this._isValid(this._dates[i], 'h')) {\n                        this._dates[i].add(1, 'h');\n                        if (tries === 24) {\n                            throw 'Tried 24 times to find a valid date';\n                        }\n                        tries++;\n                    }\n                    this._setValue(this._dates[i], i);\n                }\n            }\n            this._update();\n        };\n\n        DateTimePicker.prototype.enabledHours = function enabledHours(hours) {\n            if (arguments.length === 0) {\n                return this._options.enabledHours ? $.extend({}, this._options.enabledHours) : this._options.enabledHours;\n            }\n\n            if (!hours) {\n                this._options.enabledHours = false;\n                this._update();\n                return true;\n            }\n            if (!(hours instanceof Array)) {\n                throw new TypeError('enabledHours() expects an array parameter');\n            }\n            this._options.enabledHours = this._indexGivenHours(hours);\n            this._options.disabledHours = false;\n            if (this._options.useCurrent && !this._options.keepInvalid) {\n                for (var i = 0; i < this._dates.length; i++) {\n                    var tries = 0;\n                    while (!this._isValid(this._dates[i], 'h')) {\n                        this._dates[i].add(1, 'h');\n                        if (tries === 24) {\n                            throw 'Tried 24 times to find a valid date';\n                        }\n                        tries++;\n                    }\n                    this._setValue(this._dates[i], i);\n                }\n            }\n            this._update();\n        };\n\n        DateTimePicker.prototype.viewDate = function viewDate(newDate) {\n            if (arguments.length === 0) {\n                return this._viewDate.clone();\n            }\n\n            if (!newDate) {\n                this._viewDate = (this._dates[0] || this.getMoment()).clone();\n                return true;\n            }\n\n            if (typeof newDate !== 'string' && !moment.isMoment(newDate) && !(newDate instanceof Date)) {\n                throw new TypeError('viewDate() parameter must be one of [string, moment or Date]');\n            }\n\n            this._viewDate = this._parseInputDate(newDate);\n            this._viewUpdate();\n        };\n\n        DateTimePicker.prototype.allowMultidate = function allowMultidate(_allowMultidate) {\n            if (typeof _allowMultidate !== 'boolean') {\n                throw new TypeError('allowMultidate() expects a boolean parameter');\n            }\n\n            this._options.allowMultidate = _allowMultidate;\n        };\n\n        DateTimePicker.prototype.multidateSeparator = function multidateSeparator(_multidateSeparator) {\n            if (arguments.length === 0) {\n                return this._options.multidateSeparator;\n            }\n\n            if (typeof _multidateSeparator !== 'string' || _multidateSeparator.length > 1) {\n                throw new TypeError('multidateSeparator expects a single character string parameter');\n            }\n\n            this._options.multidateSeparator = _multidateSeparator;\n        };\n\n        _createClass(DateTimePicker, null, [{\n            key: 'NAME',\n            get: function get() {\n                return NAME;\n            }\n\n            /**\n             * @return {string}\n             */\n\n        }, {\n            key: 'DATA_KEY',\n            get: function get() {\n                return DATA_KEY;\n            }\n\n            /**\n             * @return {string}\n             */\n\n        }, {\n            key: 'EVENT_KEY',\n            get: function get() {\n                return EVENT_KEY;\n            }\n\n            /**\n             * @return {string}\n             */\n\n        }, {\n            key: 'DATA_API_KEY',\n            get: function get() {\n                return DATA_API_KEY;\n            }\n        }, {\n            key: 'DatePickerModes',\n            get: function get() {\n                return DatePickerModes;\n            }\n        }, {\n            key: 'ViewModes',\n            get: function get() {\n                return ViewModes;\n            }\n\n            /**\n             * @return {number}\n             */\n\n        }, {\n            key: 'MinViewModeNumber',\n            get: function get() {\n                return MinViewModeNumber;\n            }\n        }, {\n            key: 'Event',\n            get: function get() {\n                return Event;\n            }\n        }, {\n            key: 'Selector',\n            get: function get() {\n                return Selector;\n            }\n        }, {\n            key: 'Default',\n            get: function get() {\n                return Default;\n            },\n            set: function set(value) {\n                Default = value;\n            }\n        }, {\n            key: 'ClassName',\n            get: function get() {\n                return ClassName;\n            }\n        }]);\n\n        return DateTimePicker;\n    }();\n\n    return DateTimePicker;\n}(jQuery, moment);\n\n//noinspection JSUnusedGlobalSymbols\n/* global DateTimePicker */\nvar TempusDominusBootstrap4 = function ($) {\n    // eslint-disable-line no-unused-vars\n    // ReSharper disable once InconsistentNaming\n    var JQUERY_NO_CONFLICT = $.fn[DateTimePicker.NAME],\n        verticalModes = ['top', 'bottom', 'auto'],\n        horizontalModes = ['left', 'right', 'auto'],\n        toolbarPlacements = ['default', 'top', 'bottom'],\n        getSelectorFromElement = function getSelectorFromElement($element) {\n        var selector = $element.data('target'),\n            $selector = void 0;\n\n        if (!selector) {\n            selector = $element.attr('href') || '';\n            selector = /^#[a-z]/i.test(selector) ? selector : null;\n        }\n        $selector = $(selector);\n        if ($selector.length === 0) {\n            return $selector;\n        }\n\n        if (!$selector.data(DateTimePicker.DATA_KEY)) {\n            $.extend({}, $selector.data(), $(this).data());\n        }\n\n        return $selector;\n    };\n\n    // ReSharper disable once InconsistentNaming\n\n    var TempusDominusBootstrap4 = function (_DateTimePicker) {\n        _inherits(TempusDominusBootstrap4, _DateTimePicker);\n\n        function TempusDominusBootstrap4(element, options) {\n            _classCallCheck(this, TempusDominusBootstrap4);\n\n            var _this = _possibleConstructorReturn(this, _DateTimePicker.call(this, element, options));\n\n            _this._init();\n            return _this;\n        }\n\n        TempusDominusBootstrap4.prototype._init = function _init() {\n            if (this._element.hasClass('input-group')) {\n                var datepickerButton = this._element.find('.datepickerbutton');\n                if (datepickerButton.length === 0) {\n                    this.component = this._element.find('[data-toggle=\"datetimepicker\"]');\n                } else {\n                    this.component = datepickerButton;\n                }\n            }\n        };\n\n        TempusDominusBootstrap4.prototype._getDatePickerTemplate = function _getDatePickerTemplate() {\n            var headTemplate = $('<thead>').append($('<tr>').append($('<th>').addClass('prev').attr('data-action', 'previous').append($('<span>').addClass(this._options.icons.previous))).append($('<th>').addClass('picker-switch').attr('data-action', 'pickerSwitch').attr('colspan', '' + (this._options.calendarWeeks ? '6' : '5'))).append($('<th>').addClass('next').attr('data-action', 'next').append($('<span>').addClass(this._options.icons.next)))),\n                contTemplate = $('<tbody>').append($('<tr>').append($('<td>').attr('colspan', '' + (this._options.calendarWeeks ? '8' : '7'))));\n\n            return [$('<div>').addClass('datepicker-days').append($('<table>').addClass('table table-sm').append(headTemplate).append($('<tbody>'))), $('<div>').addClass('datepicker-months').append($('<table>').addClass('table-condensed').append(headTemplate.clone()).append(contTemplate.clone())), $('<div>').addClass('datepicker-years').append($('<table>').addClass('table-condensed').append(headTemplate.clone()).append(contTemplate.clone())), $('<div>').addClass('datepicker-decades').append($('<table>').addClass('table-condensed').append(headTemplate.clone()).append(contTemplate.clone()))];\n        };\n\n        TempusDominusBootstrap4.prototype._getTimePickerMainTemplate = function _getTimePickerMainTemplate() {\n            var topRow = $('<tr>'),\n                middleRow = $('<tr>'),\n                bottomRow = $('<tr>');\n\n            if (this._isEnabled('h')) {\n                topRow.append($('<td>').append($('<a>').attr({\n                    href: '#',\n                    tabindex: '-1',\n                    'title': this._options.tooltips.incrementHour\n                }).addClass('btn').attr('data-action', 'incrementHours').append($('<span>').addClass(this._options.icons.up))));\n                middleRow.append($('<td>').append($('<span>').addClass('timepicker-hour').attr({\n                    'data-time-component': 'hours',\n                    'title': this._options.tooltips.pickHour\n                }).attr('data-action', 'showHours')));\n                bottomRow.append($('<td>').append($('<a>').attr({\n                    href: '#',\n                    tabindex: '-1',\n                    'title': this._options.tooltips.decrementHour\n                }).addClass('btn').attr('data-action', 'decrementHours').append($('<span>').addClass(this._options.icons.down))));\n            }\n            if (this._isEnabled('m')) {\n                if (this._isEnabled('h')) {\n                    topRow.append($('<td>').addClass('separator'));\n                    middleRow.append($('<td>').addClass('separator').html(':'));\n                    bottomRow.append($('<td>').addClass('separator'));\n                }\n                topRow.append($('<td>').append($('<a>').attr({\n                    href: '#',\n                    tabindex: '-1',\n                    'title': this._options.tooltips.incrementMinute\n                }).addClass('btn').attr('data-action', 'incrementMinutes').append($('<span>').addClass(this._options.icons.up))));\n                middleRow.append($('<td>').append($('<span>').addClass('timepicker-minute').attr({\n                    'data-time-component': 'minutes',\n                    'title': this._options.tooltips.pickMinute\n                }).attr('data-action', 'showMinutes')));\n                bottomRow.append($('<td>').append($('<a>').attr({\n                    href: '#',\n                    tabindex: '-1',\n                    'title': this._options.tooltips.decrementMinute\n                }).addClass('btn').attr('data-action', 'decrementMinutes').append($('<span>').addClass(this._options.icons.down))));\n            }\n            if (this._isEnabled('s')) {\n                if (this._isEnabled('m')) {\n                    topRow.append($('<td>').addClass('separator'));\n                    middleRow.append($('<td>').addClass('separator').html(':'));\n                    bottomRow.append($('<td>').addClass('separator'));\n                }\n                topRow.append($('<td>').append($('<a>').attr({\n                    href: '#',\n                    tabindex: '-1',\n                    'title': this._options.tooltips.incrementSecond\n                }).addClass('btn').attr('data-action', 'incrementSeconds').append($('<span>').addClass(this._options.icons.up))));\n                middleRow.append($('<td>').append($('<span>').addClass('timepicker-second').attr({\n                    'data-time-component': 'seconds',\n                    'title': this._options.tooltips.pickSecond\n                }).attr('data-action', 'showSeconds')));\n                bottomRow.append($('<td>').append($('<a>').attr({\n                    href: '#',\n                    tabindex: '-1',\n                    'title': this._options.tooltips.decrementSecond\n                }).addClass('btn').attr('data-action', 'decrementSeconds').append($('<span>').addClass(this._options.icons.down))));\n            }\n\n            if (!this.use24Hours) {\n                topRow.append($('<td>').addClass('separator'));\n                middleRow.append($('<td>').append($('<button>').addClass('btn btn-primary').attr({\n                    'data-action': 'togglePeriod',\n                    tabindex: '-1',\n                    'title': this._options.tooltips.togglePeriod\n                })));\n                bottomRow.append($('<td>').addClass('separator'));\n            }\n\n            return $('<div>').addClass('timepicker-picker').append($('<table>').addClass('table-condensed').append([topRow, middleRow, bottomRow]));\n        };\n\n        TempusDominusBootstrap4.prototype._getTimePickerTemplate = function _getTimePickerTemplate() {\n            var hoursView = $('<div>').addClass('timepicker-hours').append($('<table>').addClass('table-condensed')),\n                minutesView = $('<div>').addClass('timepicker-minutes').append($('<table>').addClass('table-condensed')),\n                secondsView = $('<div>').addClass('timepicker-seconds').append($('<table>').addClass('table-condensed')),\n                ret = [this._getTimePickerMainTemplate()];\n\n            if (this._isEnabled('h')) {\n                ret.push(hoursView);\n            }\n            if (this._isEnabled('m')) {\n                ret.push(minutesView);\n            }\n            if (this._isEnabled('s')) {\n                ret.push(secondsView);\n            }\n\n            return ret;\n        };\n\n        TempusDominusBootstrap4.prototype._getToolbar = function _getToolbar() {\n            var row = [];\n            if (this._options.buttons.showToday) {\n                row.push($('<td>').append($('<a>').attr({\n                    href: '#',\n                    tabindex: '-1',\n                    'data-action': 'today',\n                    'title': this._options.tooltips.today\n                }).append($('<span>').addClass(this._options.icons.today))));\n            }\n            if (!this._options.sideBySide && this._hasDate() && this._hasTime()) {\n                var title = void 0,\n                    icon = void 0;\n                if (this._options.viewMode === 'times') {\n                    title = this._options.tooltips.selectDate;\n                    icon = this._options.icons.date;\n                } else {\n                    title = this._options.tooltips.selectTime;\n                    icon = this._options.icons.time;\n                }\n                row.push($('<td>').append($('<a>').attr({\n                    href: '#',\n                    tabindex: '-1',\n                    'data-action': 'togglePicker',\n                    'title': title\n                }).append($('<span>').addClass(icon))));\n            }\n            if (this._options.buttons.showClear) {\n                row.push($('<td>').append($('<a>').attr({\n                    href: '#',\n                    tabindex: '-1',\n                    'data-action': 'clear',\n                    'title': this._options.tooltips.clear\n                }).append($('<span>').addClass(this._options.icons.clear))));\n            }\n            if (this._options.buttons.showClose) {\n                row.push($('<td>').append($('<a>').attr({\n                    href: '#',\n                    tabindex: '-1',\n                    'data-action': 'close',\n                    'title': this._options.tooltips.close\n                }).append($('<span>').addClass(this._options.icons.close))));\n            }\n            return row.length === 0 ? '' : $('<table>').addClass('table-condensed').append($('<tbody>').append($('<tr>').append(row)));\n        };\n\n        TempusDominusBootstrap4.prototype._getTemplate = function _getTemplate() {\n            var template = $('<div>').addClass('bootstrap-datetimepicker-widget dropdown-menu'),\n                dateView = $('<div>').addClass('datepicker').append(this._getDatePickerTemplate()),\n                timeView = $('<div>').addClass('timepicker').append(this._getTimePickerTemplate()),\n                content = $('<ul>').addClass('list-unstyled'),\n                toolbar = $('<li>').addClass('picker-switch' + (this._options.collapse ? ' accordion-toggle' : '')).append(this._getToolbar());\n\n            if (this._options.inline) {\n                template.removeClass('dropdown-menu');\n            }\n\n            if (this.use24Hours) {\n                template.addClass('usetwentyfour');\n            }\n            if (this._isEnabled('s') && !this.use24Hours) {\n                template.addClass('wider');\n            }\n\n            if (this._options.sideBySide && this._hasDate() && this._hasTime()) {\n                template.addClass('timepicker-sbs');\n                if (this._options.toolbarPlacement === 'top') {\n                    template.append(toolbar);\n                }\n                template.append($('<div>').addClass('row').append(dateView.addClass('col-md-6')).append(timeView.addClass('col-md-6')));\n                if (this._options.toolbarPlacement === 'bottom' || this._options.toolbarPlacement === 'default') {\n                    template.append(toolbar);\n                }\n                return template;\n            }\n\n            if (this._options.toolbarPlacement === 'top') {\n                content.append(toolbar);\n            }\n            if (this._hasDate()) {\n                content.append($('<li>').addClass(this._options.collapse && this._hasTime() ? 'collapse' : '').addClass(this._options.collapse && this._hasTime() && this._options.viewMode === 'times' ? '' : 'show').append(dateView));\n            }\n            if (this._options.toolbarPlacement === 'default') {\n                content.append(toolbar);\n            }\n            if (this._hasTime()) {\n                content.append($('<li>').addClass(this._options.collapse && this._hasDate() ? 'collapse' : '').addClass(this._options.collapse && this._hasDate() && this._options.viewMode === 'times' ? 'show' : '').append(timeView));\n            }\n            if (this._options.toolbarPlacement === 'bottom') {\n                content.append(toolbar);\n            }\n            return template.append(content);\n        };\n\n        TempusDominusBootstrap4.prototype._place = function _place(e) {\n            var self = e && e.data && e.data.picker || this,\n                vertical = self._options.widgetPositioning.vertical,\n                horizontal = self._options.widgetPositioning.horizontal,\n                parent = void 0;\n            var position = (self.component && self.component.length ? self.component : self._element).position(),\n                offset = (self.component && self.component.length ? self.component : self._element).offset();\n            if (self._options.widgetParent) {\n                parent = self._options.widgetParent.append(self.widget);\n            } else if (self._element.is('input')) {\n                parent = self._element.after(self.widget).parent();\n            } else if (self._options.inline) {\n                parent = self._element.append(self.widget);\n                return;\n            } else {\n                parent = self._element;\n                self._element.children().first().after(self.widget);\n            }\n\n            // /!\\ ODOO FIX: the 3 next lines have been *added* by odoo\n            var parentOffset = parent.offset();\n            position.top = offset.top - parentOffset.top;\n            position.left = offset.left - parentOffset.left;\n\n            // Top and bottom logic\n            if (vertical === 'auto') {\n                //noinspection JSValidateTypes\n                if (offset.top + self.widget.height() * 1.5 >= $(window).height() + $(window).scrollTop() && self.widget.height() + self._element.outerHeight() < offset.top) {\n                    vertical = 'top';\n                } else {\n                    vertical = 'bottom';\n                }\n            }\n\n            // Left and right logic\n            if (horizontal === 'auto') {\n                if (parent.width() < offset.left + self.widget.outerWidth() / 2 && offset.left + self.widget.outerWidth() > $(window).width()) {\n                    horizontal = 'right';\n                } else {\n                    horizontal = 'left';\n                }\n            }\n\n            if (vertical === 'top') {\n                self.widget.addClass('top').removeClass('bottom');\n            } else {\n                self.widget.addClass('bottom').removeClass('top');\n            }\n\n            if (horizontal === 'right') {\n                self.widget.addClass('float-right');\n            } else {\n                self.widget.removeClass('float-right');\n            }\n\n            // find the first parent element that has a relative css positioning\n            if (parent.css('position') !== 'relative') {\n                parent = parent.parents().filter(function () {\n                    return $(this).css('position') === 'relative';\n                }).first();\n            }\n\n            if (parent.length === 0) {\n                throw new Error('datetimepicker component should be placed within a relative positioned container');\n            }\n\n            self.widget.css({\n                top: vertical === 'top' ? 'auto' : position.top + self._element.outerHeight() + 'px',\n                bottom: vertical === 'top' ? parent.outerHeight() - (parent === self._element ? 0 : position.top) + 'px' : 'auto',\n                left: horizontal === 'left' ? (parent === self._element ? 0 : position.left) + 'px' : 'auto',\n                right: horizontal === 'left' ? 'auto' : parent.outerWidth() - self._element.outerWidth() - (parent === self._element ? 0 : position.left) + 'px'\n            });\n        };\n\n        TempusDominusBootstrap4.prototype._fillDow = function _fillDow() {\n            var row = $('<tr>'),\n                currentDate = this._viewDate.clone().startOf('w').startOf('d');\n\n            if (this._options.calendarWeeks === true) {\n                row.append($('<th>').addClass('cw').text('#'));\n            }\n\n            while (currentDate.isBefore(this._viewDate.clone().endOf('w'))) {\n                row.append($('<th>').addClass('dow').text(currentDate.format('dd')));\n                currentDate.add(1, 'd');\n            }\n            this.widget.find('.datepicker-days thead').append(row);\n        };\n\n        TempusDominusBootstrap4.prototype._fillMonths = function _fillMonths() {\n            var spans = [],\n                monthsShort = this._viewDate.clone().startOf('y').startOf('d');\n            while (monthsShort.isSame(this._viewDate, 'y')) {\n                spans.push($('<span>').attr('data-action', 'selectMonth').addClass('month').text(monthsShort.format('MMM')));\n                monthsShort.add(1, 'M');\n            }\n            this.widget.find('.datepicker-months td').empty().append(spans);\n        };\n\n        TempusDominusBootstrap4.prototype._updateMonths = function _updateMonths() {\n            var monthsView = this.widget.find('.datepicker-months'),\n                monthsViewHeader = monthsView.find('th'),\n                months = monthsView.find('tbody').find('span'),\n                self = this;\n\n            monthsViewHeader.eq(0).find('span').attr('title', this._options.tooltips.prevYear);\n            monthsViewHeader.eq(1).attr('title', this._options.tooltips.selectYear);\n            monthsViewHeader.eq(2).find('span').attr('title', this._options.tooltips.nextYear);\n\n            monthsView.find('.disabled').removeClass('disabled');\n\n            if (!this._isValid(this._viewDate.clone().subtract(1, 'y'), 'y')) {\n                monthsViewHeader.eq(0).addClass('disabled');\n            }\n\n            monthsViewHeader.eq(1).text(this._viewDate.year());\n\n            if (!this._isValid(this._viewDate.clone().add(1, 'y'), 'y')) {\n                monthsViewHeader.eq(2).addClass('disabled');\n            }\n\n            months.removeClass('active');\n            if (this._getLastPickedDate().isSame(this._viewDate, 'y') && !this.unset) {\n                months.eq(this._getLastPickedDate().month()).addClass('active');\n            }\n\n            months.each(function (index) {\n                if (!self._isValid(self._viewDate.clone().month(index), 'M')) {\n                    $(this).addClass('disabled');\n                }\n            });\n        };\n\n        TempusDominusBootstrap4.prototype._getStartEndYear = function _getStartEndYear(factor, year) {\n            var step = factor / 10,\n                startYear = Math.floor(year / factor) * factor,\n                endYear = startYear + step * 9,\n                focusValue = Math.floor(year / step) * step;\n            return [startYear, endYear, focusValue];\n        };\n\n        TempusDominusBootstrap4.prototype._updateYears = function _updateYears() {\n            var yearsView = this.widget.find('.datepicker-years'),\n                yearsViewHeader = yearsView.find('th'),\n                yearCaps = this._getStartEndYear(10, this._viewDate.year()),\n                startYear = this._viewDate.clone().year(yearCaps[0]),\n                endYear = this._viewDate.clone().year(yearCaps[1]);\n            var html = '';\n\n            yearsViewHeader.eq(0).find('span').attr('title', this._options.tooltips.prevDecade);\n            yearsViewHeader.eq(1).attr('title', this._options.tooltips.selectDecade);\n            yearsViewHeader.eq(2).find('span').attr('title', this._options.tooltips.nextDecade);\n\n            yearsView.find('.disabled').removeClass('disabled');\n\n            if (this._options.minDate && this._options.minDate.isAfter(startYear, 'y')) {\n                yearsViewHeader.eq(0).addClass('disabled');\n            }\n\n            yearsViewHeader.eq(1).text(startYear.year() + '-' + endYear.year());\n\n            if (this._options.maxDate && this._options.maxDate.isBefore(endYear, 'y')) {\n                yearsViewHeader.eq(2).addClass('disabled');\n            }\n\n            html += '<span data-action=\"selectYear\" class=\"year old' + (!this._isValid(startYear, 'y') ? ' disabled' : '') + '\">' + (startYear.year() - 1) + '</span>';\n            while (!startYear.isAfter(endYear, 'y')) {\n                html += '<span data-action=\"selectYear\" class=\"year' + (startYear.isSame(this._getLastPickedDate(), 'y') && !this.unset ? ' active' : '') + (!this._isValid(startYear, 'y') ? ' disabled' : '') + '\">' + startYear.year() + '</span>';\n                startYear.add(1, 'y');\n            }\n            html += '<span data-action=\"selectYear\" class=\"year old' + (!this._isValid(startYear, 'y') ? ' disabled' : '') + '\">' + startYear.year() + '</span>';\n\n            yearsView.find('td').html(html);\n        };\n\n        TempusDominusBootstrap4.prototype._updateDecades = function _updateDecades() {\n            var decadesView = this.widget.find('.datepicker-decades'),\n                decadesViewHeader = decadesView.find('th'),\n                yearCaps = this._getStartEndYear(100, this._viewDate.year()),\n                startDecade = this._viewDate.clone().year(yearCaps[0]),\n                endDecade = this._viewDate.clone().year(yearCaps[1]);\n            var minDateDecade = false,\n                maxDateDecade = false,\n                endDecadeYear = void 0,\n                html = '';\n\n            decadesViewHeader.eq(0).find('span').attr('title', this._options.tooltips.prevCentury);\n            decadesViewHeader.eq(2).find('span').attr('title', this._options.tooltips.nextCentury);\n\n            decadesView.find('.disabled').removeClass('disabled');\n\n            if (startDecade.year() === 0 || this._options.minDate && this._options.minDate.isAfter(startDecade, 'y')) {\n                decadesViewHeader.eq(0).addClass('disabled');\n            }\n\n            decadesViewHeader.eq(1).text(startDecade.year() + '-' + endDecade.year());\n\n            if (this._options.maxDate && this._options.maxDate.isBefore(endDecade, 'y')) {\n                decadesViewHeader.eq(2).addClass('disabled');\n            }\n\n            if (startDecade.year() - 10 < 0) {\n                html += '<span>&nbsp;</span>';\n            } else {\n                html += '<span data-action=\"selectDecade\" class=\"decade old\" data-selection=\"' + (startDecade.year() + 6) + '\">' + (startDecade.year() - 10) + '</span>';\n            }\n\n            while (!startDecade.isAfter(endDecade, 'y')) {\n                endDecadeYear = startDecade.year() + 11;\n                minDateDecade = this._options.minDate && this._options.minDate.isAfter(startDecade, 'y') && this._options.minDate.year() <= endDecadeYear;\n                maxDateDecade = this._options.maxDate && this._options.maxDate.isAfter(startDecade, 'y') && this._options.maxDate.year() <= endDecadeYear;\n                html += '<span data-action=\"selectDecade\" class=\"decade' + (this._getLastPickedDate().isAfter(startDecade) && this._getLastPickedDate().year() <= endDecadeYear ? ' active' : '') + (!this._isValid(startDecade, 'y') && !minDateDecade && !maxDateDecade ? ' disabled' : '') + '\" data-selection=\"' + (startDecade.year() + 6) + '\">' + startDecade.year() + '</span>';\n                startDecade.add(10, 'y');\n            }\n            html += '<span data-action=\"selectDecade\" class=\"decade old\" data-selection=\"' + (startDecade.year() + 6) + '\">' + startDecade.year() + '</span>';\n\n            decadesView.find('td').html(html);\n        };\n\n        TempusDominusBootstrap4.prototype._fillDate = function _fillDate() {\n            var daysView = this.widget.find('.datepicker-days'),\n                daysViewHeader = daysView.find('th'),\n                html = [];\n            var currentDate = void 0,\n                row = void 0,\n                clsName = void 0,\n                i = void 0;\n\n            if (!this._hasDate()) {\n                return;\n            }\n\n            daysViewHeader.eq(0).find('span').attr('title', this._options.tooltips.prevMonth);\n            daysViewHeader.eq(1).attr('title', this._options.tooltips.selectMonth);\n            daysViewHeader.eq(2).find('span').attr('title', this._options.tooltips.nextMonth);\n\n            daysView.find('.disabled').removeClass('disabled');\n            daysViewHeader.eq(1).text(this._viewDate.format(this._options.dayViewHeaderFormat));\n\n            if (!this._isValid(this._viewDate.clone().subtract(1, 'M'), 'M')) {\n                daysViewHeader.eq(0).addClass('disabled');\n            }\n            if (!this._isValid(this._viewDate.clone().add(1, 'M'), 'M')) {\n                daysViewHeader.eq(2).addClass('disabled');\n            }\n\n            // !! ODOO FIX START !!\n            var now = this.getMoment();\n            // currentDate = this._viewDate.clone().startOf('M').startOf('w').startOf('d');\n            // avoid issue of safari + DST at midnight\n            currentDate = this._viewDate.clone().startOf('M').startOf('w').add(12, 'hours');\n            // !! ODOO FIX END !!\n\n            for (i = 0; i < 42; i++) {\n                //always display 42 days (should show 6 weeks)\n                if (currentDate.weekday() === 0) {\n                    row = $('<tr>');\n                    if (this._options.calendarWeeks) {\n                        row.append('<td class=\"cw\">' + currentDate.week() + '</td>');\n                    }\n                    html.push(row);\n                }\n                clsName = '';\n                if (currentDate.isBefore(this._viewDate, 'M')) {\n                    clsName += ' old';\n                }\n                if (currentDate.isAfter(this._viewDate, 'M')) {\n                    clsName += ' new';\n                }\n                if (this._options.allowMultidate) {\n                    var index = this._datesFormatted.indexOf(currentDate.format('YYYY-MM-DD'));\n                    if (index !== -1) {\n                        if (currentDate.isSame(this._datesFormatted[index], 'd') && !this.unset) {\n                            clsName += ' active';\n                        }\n                    }\n                } else {\n                    if (currentDate.isSame(this._getLastPickedDate(), 'd') && !this.unset) {\n                        clsName += ' active';\n                    }\n                }\n                if (!this._isValid(currentDate, 'd')) {\n                    clsName += ' disabled';\n                }\n                // !! ODOO FIX START !!\n                if (currentDate.date() === now.date() && currentDate.month() === now.month() && currentDate.year() === now.year()) {\n                // !! ODOO FIX END !!\n                    clsName += ' today';\n                }\n                if (currentDate.day() === 0 || currentDate.day() === 6) {\n                    clsName += ' weekend';\n                }\n                row.append('<td data-action=\"selectDay\" data-day=\"' + currentDate.format('L') + '\" class=\"day' + clsName + '\">' + currentDate.date() + '</td>');\n                currentDate.add(1, 'd');\n            }\n\n            daysView.find('tbody').empty().append(html);\n\n            this._updateMonths();\n\n            this._updateYears();\n\n            this._updateDecades();\n        };\n\n        TempusDominusBootstrap4.prototype._fillHours = function _fillHours() {\n            var table = this.widget.find('.timepicker-hours table'),\n                currentHour = this._viewDate.clone().startOf('d'),\n                html = [];\n            var row = $('<tr>');\n\n            if (this._viewDate.hour() > 11 && !this.use24Hours) {\n                currentHour.hour(12);\n            }\n            while (currentHour.isSame(this._viewDate, 'd') && (this.use24Hours || this._viewDate.hour() < 12 && currentHour.hour() < 12 || this._viewDate.hour() > 11)) {\n                if (currentHour.hour() % 4 === 0) {\n                    row = $('<tr>');\n                    html.push(row);\n                }\n                row.append('<td data-action=\"selectHour\" class=\"hour' + (!this._isValid(currentHour, 'h') ? ' disabled' : '') + '\">' + currentHour.format(this.use24Hours ? 'HH' : 'hh') + '</td>');\n                currentHour.add(1, 'h');\n            }\n            table.empty().append(html);\n        };\n\n        TempusDominusBootstrap4.prototype._fillMinutes = function _fillMinutes() {\n            var table = this.widget.find('.timepicker-minutes table'),\n                currentMinute = this._viewDate.clone().startOf('h'),\n                html = [],\n                step = this._options.stepping === 1 ? 5 : this._options.stepping;\n            var row = $('<tr>');\n\n            while (this._viewDate.isSame(currentMinute, 'h')) {\n                if (currentMinute.minute() % (step * 4) === 0) {\n                    row = $('<tr>');\n                    html.push(row);\n                }\n                row.append('<td data-action=\"selectMinute\" class=\"minute' + (!this._isValid(currentMinute, 'm') ? ' disabled' : '') + '\">' + currentMinute.format('mm') + '</td>');\n                currentMinute.add(step, 'm');\n            }\n            table.empty().append(html);\n        };\n\n        TempusDominusBootstrap4.prototype._fillSeconds = function _fillSeconds() {\n            var table = this.widget.find('.timepicker-seconds table'),\n                currentSecond = this._viewDate.clone().startOf('m'),\n                html = [];\n            var row = $('<tr>');\n\n            while (this._viewDate.isSame(currentSecond, 'm')) {\n                if (currentSecond.second() % 20 === 0) {\n                    row = $('<tr>');\n                    html.push(row);\n                }\n                row.append('<td data-action=\"selectSecond\" class=\"second' + (!this._isValid(currentSecond, 's') ? ' disabled' : '') + '\">' + currentSecond.format('ss') + '</td>');\n                currentSecond.add(5, 's');\n            }\n\n            table.empty().append(html);\n        };\n\n        TempusDominusBootstrap4.prototype._fillTime = function _fillTime() {\n            var toggle = void 0,\n                newDate = void 0;\n            var timeComponents = this.widget.find('.timepicker span[data-time-component]');\n\n            if (!this.use24Hours) {\n                toggle = this.widget.find('.timepicker [data-action=togglePeriod]');\n                newDate = this._getLastPickedDate().clone().add(this._getLastPickedDate().hours() >= 12 ? -12 : 12, 'h');\n\n                toggle.text(this._getLastPickedDate().format('A'));\n\n                if (this._isValid(newDate, 'h')) {\n                    toggle.removeClass('disabled');\n                } else {\n                    toggle.addClass('disabled');\n                }\n            }\n            timeComponents.filter('[data-time-component=hours]').text(this._getLastPickedDate().format('' + (this.use24Hours ? 'HH' : 'hh')));\n            timeComponents.filter('[data-time-component=minutes]').text(this._getLastPickedDate().format('mm'));\n            timeComponents.filter('[data-time-component=seconds]').text(this._getLastPickedDate().format('ss'));\n\n            this._fillHours();\n            this._fillMinutes();\n            this._fillSeconds();\n        };\n\n        TempusDominusBootstrap4.prototype._doAction = function _doAction(e, action) {\n            var lastPicked = this._getLastPickedDate();\n            if ($(e.currentTarget).is('.disabled')) {\n                return false;\n            }\n            action = action || $(e.currentTarget).data('action');\n            switch (action) {\n                case 'next':\n                    {\n                        var navFnc = DateTimePicker.DatePickerModes[this.currentViewMode].NAV_FUNCTION;\n                        this._viewDate.add(DateTimePicker.DatePickerModes[this.currentViewMode].NAV_STEP, navFnc);\n                        this._fillDate();\n                        this._viewUpdate(navFnc);\n                        break;\n                    }\n                case 'previous':\n                    {\n                        var _navFnc = DateTimePicker.DatePickerModes[this.currentViewMode].NAV_FUNCTION;\n                        this._viewDate.subtract(DateTimePicker.DatePickerModes[this.currentViewMode].NAV_STEP, _navFnc);\n                        this._fillDate();\n                        this._viewUpdate(_navFnc);\n                        break;\n                    }\n                case 'pickerSwitch':\n                    this._showMode(1);\n                    break;\n                case 'selectMonth':\n                    {\n                        var month = $(e.target).closest('tbody').find('span').index($(e.target));\n                        this._viewDate.month(month);\n                        if (this.currentViewMode === DateTimePicker.MinViewModeNumber) {\n                            this._setValue(lastPicked.clone().year(this._viewDate.year()).month(this._viewDate.month()), this._getLastPickedDateIndex());\n                            if (!this._options.inline) {\n                                this.hide();\n                            }\n                        } else {\n                            this._showMode(-1);\n                            this._fillDate();\n                        }\n                        this._viewUpdate('M');\n                        break;\n                    }\n                case 'selectYear':\n                    {\n                        var year = parseInt($(e.target).text(), 10) || 0;\n                        this._viewDate.year(year);\n                        if (this.currentViewMode === DateTimePicker.MinViewModeNumber) {\n                            this._setValue(lastPicked.clone().year(this._viewDate.year()), this._getLastPickedDateIndex());\n                            if (!this._options.inline) {\n                                this.hide();\n                            }\n                        } else {\n                            this._showMode(-1);\n                            this._fillDate();\n                        }\n                        this._viewUpdate('YYYY');\n                        break;\n                    }\n                case 'selectDecade':\n                    {\n                        var _year = parseInt($(e.target).data('selection'), 10) || 0;\n                        this._viewDate.year(_year);\n                        if (this.currentViewMode === DateTimePicker.MinViewModeNumber) {\n                            this._setValue(lastPicked.clone().year(this._viewDate.year()), this._getLastPickedDateIndex());\n                            if (!this._options.inline) {\n                                this.hide();\n                            }\n                        } else {\n                            this._showMode(-1);\n                            this._fillDate();\n                        }\n                        this._viewUpdate('YYYY');\n                        break;\n                    }\n                case 'selectDay':\n                    {\n                        var day = this._viewDate.clone();\n                        if ($(e.target).is('.old')) {\n                            day.subtract(1, 'M');\n                        }\n                        if ($(e.target).is('.new')) {\n                            day.add(1, 'M');\n                        }\n                        this._setValue(day.date(parseInt($(e.target).text(), 10)), this._getLastPickedDateIndex());\n                        if (!this._hasTime() && !this._options.keepOpen && !this._options.inline) {\n                            this.hide();\n                        }\n                        break;\n                    }\n                case 'incrementHours':\n                    {\n                        var newDate = lastPicked.clone().add(1, 'h');\n                        if (this._isValid(newDate, 'h')) {\n                            this._setValue(newDate, this._getLastPickedDateIndex());\n                        }\n                        break;\n                    }\n                case 'incrementMinutes':\n                    {\n                        var _newDate = lastPicked.clone().add(this._options.stepping, 'm');\n                        if (this._isValid(_newDate, 'm')) {\n                            this._setValue(_newDate, this._getLastPickedDateIndex());\n                        }\n                        break;\n                    }\n                case 'incrementSeconds':\n                    {\n                        var _newDate2 = lastPicked.clone().add(1, 's');\n                        if (this._isValid(_newDate2, 's')) {\n                            this._setValue(_newDate2, this._getLastPickedDateIndex());\n                        }\n                        break;\n                    }\n                case 'decrementHours':\n                    {\n                        var _newDate3 = lastPicked.clone().subtract(1, 'h');\n                        if (this._isValid(_newDate3, 'h')) {\n                            this._setValue(_newDate3, this._getLastPickedDateIndex());\n                        }\n                        break;\n                    }\n                case 'decrementMinutes':\n                    {\n                        var _newDate4 = lastPicked.clone().subtract(this._options.stepping, 'm');\n                        if (this._isValid(_newDate4, 'm')) {\n                            this._setValue(_newDate4, this._getLastPickedDateIndex());\n                        }\n                        break;\n                    }\n                case 'decrementSeconds':\n                    {\n                        var _newDate5 = lastPicked.clone().subtract(1, 's');\n                        if (this._isValid(_newDate5, 's')) {\n                            this._setValue(_newDate5, this._getLastPickedDateIndex());\n                        }\n                        break;\n                    }\n                case 'togglePeriod':\n                    {\n                        this._setValue(lastPicked.clone().add(lastPicked.hours() >= 12 ? -12 : 12, 'h'), this._getLastPickedDateIndex());\n                        break;\n                    }\n                case 'togglePicker':\n                    {\n                        var $this = $(e.target),\n                            $link = $this.closest('a'),\n                            $parent = $this.closest('ul'),\n                            expanded = $parent.find('.show'),\n                            closed = $parent.find('.collapse:not(.show)'),\n                            $span = $this.is('span') ? $this : $this.find('span');\n                        var collapseData = void 0;\n\n                        if (expanded && expanded.length) {\n                            collapseData = expanded.data('collapse');\n                            if (collapseData && collapseData.transitioning) {\n                                return true;\n                            }\n                            if (expanded.collapse) {\n                                // if collapse plugin is available through bootstrap.js then use it\n                                expanded.collapse('hide');\n                                closed.collapse('show');\n                            } else {\n                                // otherwise just toggle in class on the two views\n                                expanded.removeClass('show');\n                                closed.addClass('show');\n                            }\n                            $span.toggleClass(this._options.icons.time + ' ' + this._options.icons.date);\n\n                            if ($span.hasClass(this._options.icons.date)) {\n                                $link.attr('title', this._options.tooltips.selectDate);\n                            } else {\n                                $link.attr('title', this._options.tooltips.selectTime);\n                            }\n                        }\n                    }\n                    break;\n                case 'showPicker':\n                    this.widget.find('.timepicker > div:not(.timepicker-picker)').hide();\n                    this.widget.find('.timepicker .timepicker-picker').show();\n                    break;\n                case 'showHours':\n                    this.widget.find('.timepicker .timepicker-picker').hide();\n                    this.widget.find('.timepicker .timepicker-hours').show();\n                    break;\n                case 'showMinutes':\n                    this.widget.find('.timepicker .timepicker-picker').hide();\n                    this.widget.find('.timepicker .timepicker-minutes').show();\n                    break;\n                case 'showSeconds':\n                    this.widget.find('.timepicker .timepicker-picker').hide();\n                    this.widget.find('.timepicker .timepicker-seconds').show();\n                    break;\n                case 'selectHour':\n                    {\n                        var hour = this.getMoment($(e.target).text(), this.use24Hours ? 'HH' : 'hh').hour(); // ODOO FIX: use moment format to get the proper value (not necessarily latn numbers)\n\n                        if (!this.use24Hours) {\n                            if (lastPicked.hours() >= 12) {\n                                if (hour !== 12) {\n                                    hour += 12;\n                                }\n                            } else {\n                                if (hour === 12) {\n                                    hour = 0;\n                                }\n                            }\n                        }\n                        this._setValue(lastPicked.clone().hours(hour), this._getLastPickedDateIndex());\n                        if (!this._isEnabled('a') && !this._isEnabled('m') && !this._options.keepOpen && !this._options.inline) {\n                            this.hide();\n                        } else {\n                            this._doAction(e, 'showPicker');\n                        }\n                        break;\n                    }\n                case 'selectMinute':\n                    this._setValue(lastPicked.clone().minutes(this.getMoment($(e.target).text(), 'mm').minute()), this._getLastPickedDateIndex()); // ODOO FIX: use moment format to get the proper value (not necessarily latn numbers)\n                    if (!this._isEnabled('a') && !this._isEnabled('s') && !this._options.keepOpen && !this._options.inline) {\n                        this.hide();\n                    } else {\n                        this._doAction(e, 'showPicker');\n                    }\n                    break;\n                case 'selectSecond':\n                    this._setValue(lastPicked.clone().seconds(this.getMoment($(e.target).text(), 'ss').second()), this._getLastPickedDateIndex()); // ODOO FIX: use moment format to get the proper value (not necessarily latn numbers)\n                    if (!this._isEnabled('a') && !this._options.keepOpen && !this._options.inline) {\n                        this.hide();\n                    } else {\n                        this._doAction(e, 'showPicker');\n                    }\n                    break;\n                case 'clear':\n                    this.clear();\n                    break;\n                case 'close':\n                    this.hide();\n                    break;\n                case 'today':\n                    {\n                        var todaysDate = this.getMoment();\n                        if (this._isValid(todaysDate, 'd')) {\n                            this._setValue(todaysDate, this._getLastPickedDateIndex());\n                        }\n                        break;\n                    }\n            }\n            return false;\n        };\n\n        //public\n\n\n        TempusDominusBootstrap4.prototype.hide = function hide() {\n            var transitioning = false;\n            if (!this.widget) {\n                return;\n            }\n            // Ignore event if in the middle of a picker transition\n            this.widget.find('.collapse').each(function () {\n                var collapseData = $(this).data('collapse');\n                if (collapseData && collapseData.transitioning) {\n                    transitioning = true;\n                    return false;\n                }\n                return true;\n            });\n            if (transitioning) {\n                return;\n            }\n            if (this.component && this.component.hasClass('btn')) {\n                this.component.toggleClass('active');\n            }\n            this.widget.hide();\n\n            $(window).off('resize', this._place());\n            this.widget.off('click', '[data-action]');\n            this.widget.off('mousedown', false);\n\n            this.widget.remove();\n            this.widget = false;\n\n            this._notifyEvent({\n                type: DateTimePicker.Event.HIDE,\n                date: this._getLastPickedDate().clone()\n            });\n\n            if (this.input !== undefined) {\n                this.input.blur();\n            }\n\n            this._viewDate = this._getLastPickedDate().clone();\n        };\n\n        TempusDominusBootstrap4.prototype.show = function show() {\n            var currentMoment = void 0;\n            var useCurrentGranularity = {\n                'year': function year(m) {\n                    return m.month(0).date(1).hours(0).seconds(0).minutes(0);\n                },\n                'month': function month(m) {\n                    return m.date(1).hours(0).seconds(0).minutes(0);\n                },\n                'day': function day(m) {\n                    return m.hours(0).seconds(0).minutes(0);\n                },\n                'hour': function hour(m) {\n                    return m.seconds(0).minutes(0);\n                },\n                'minute': function minute(m) {\n                    return m.seconds(0);\n                }\n            };\n\n            if (this.input !== undefined) {\n                if (this.input.prop('disabled') || !this._options.ignoreReadonly && this.input.prop('readonly') || this.widget) {\n                    return;\n                }\n                if (this.input.val() !== undefined && this.input.val().trim().length !== 0) {\n                    this._setValue(this._parseInputDate(this.input.val().trim()), 0);\n                } else if (this.unset && this._options.useCurrent) {\n                    currentMoment = this.getMoment();\n                    if (typeof this._options.useCurrent === 'string') {\n                        currentMoment = useCurrentGranularity[this._options.useCurrent](currentMoment);\n                    }\n                    this._setValue(currentMoment, 0);\n                }\n            } else if (this.unset && this._options.useCurrent) {\n                currentMoment = this.getMoment();\n                if (typeof this._options.useCurrent === 'string') {\n                    currentMoment = useCurrentGranularity[this._options.useCurrent](currentMoment);\n                }\n                this._setValue(currentMoment, 0);\n            }\n\n            this.widget = this._getTemplate();\n\n            this._fillDow();\n            this._fillMonths();\n\n            this.widget.find('.timepicker-hours').hide();\n            this.widget.find('.timepicker-minutes').hide();\n            this.widget.find('.timepicker-seconds').hide();\n\n            this._update();\n            this._showMode();\n\n            $(window).on('resize', { picker: this }, this._place);\n            this.widget.on('click', '[data-action]', $.proxy(this._doAction, this)); // this handles clicks on the widget\n            this.widget.on('mousedown', false);\n\n            if (this.component && this.component.hasClass('btn')) {\n                this.component.toggleClass('active');\n            }\n            this._place();\n            this.widget.show();\n            if (this.input !== undefined && this._options.focusOnShow && !this.input.is(':focus')) {\n                this.input.focus();\n            }\n\n            this._notifyEvent({\n                type: DateTimePicker.Event.SHOW\n            });\n        };\n\n        TempusDominusBootstrap4.prototype.destroy = function destroy() {\n            this.hide();\n            //todo doc off?\n            this._element.removeData(DateTimePicker.DATA_KEY);\n            this._element.removeData('date');\n        };\n\n        TempusDominusBootstrap4.prototype.disable = function disable() {\n            this.hide();\n            if (this.component && this.component.hasClass('btn')) {\n                this.component.addClass('disabled');\n            }\n            if (this.input !== undefined) {\n                this.input.prop('disabled', true); //todo disable this/comp if input is null\n            }\n        };\n\n        TempusDominusBootstrap4.prototype.enable = function enable() {\n            if (this.component && this.component.hasClass('btn')) {\n                this.component.removeClass('disabled');\n            }\n            if (this.input !== undefined) {\n                this.input.prop('disabled', false); //todo enable comp/this if input is null\n            }\n        };\n\n        TempusDominusBootstrap4.prototype.toolbarPlacement = function toolbarPlacement(_toolbarPlacement) {\n            if (arguments.length === 0) {\n                return this._options.toolbarPlacement;\n            }\n\n            if (typeof _toolbarPlacement !== 'string') {\n                throw new TypeError('toolbarPlacement() expects a string parameter');\n            }\n            if (toolbarPlacements.indexOf(_toolbarPlacement) === -1) {\n                throw new TypeError('toolbarPlacement() parameter must be one of (' + toolbarPlacements.join(', ') + ') value');\n            }\n            this._options.toolbarPlacement = _toolbarPlacement;\n\n            if (this.widget) {\n                this.hide();\n                this.show();\n            }\n        };\n\n        TempusDominusBootstrap4.prototype.widgetPositioning = function widgetPositioning(_widgetPositioning) {\n            if (arguments.length === 0) {\n                return $.extend({}, this._options.widgetPositioning);\n            }\n\n            if ({}.toString.call(_widgetPositioning) !== '[object Object]') {\n                throw new TypeError('widgetPositioning() expects an object variable');\n            }\n            if (_widgetPositioning.horizontal) {\n                if (typeof _widgetPositioning.horizontal !== 'string') {\n                    throw new TypeError('widgetPositioning() horizontal variable must be a string');\n                }\n                _widgetPositioning.horizontal = _widgetPositioning.horizontal.toLowerCase();\n                if (horizontalModes.indexOf(_widgetPositioning.horizontal) === -1) {\n                    throw new TypeError('widgetPositioning() expects horizontal parameter to be one of (' + horizontalModes.join(', ') + ')');\n                }\n                this._options.widgetPositioning.horizontal = _widgetPositioning.horizontal;\n            }\n            if (_widgetPositioning.vertical) {\n                if (typeof _widgetPositioning.vertical !== 'string') {\n                    throw new TypeError('widgetPositioning() vertical variable must be a string');\n                }\n                _widgetPositioning.vertical = _widgetPositioning.vertical.toLowerCase();\n                if (verticalModes.indexOf(_widgetPositioning.vertical) === -1) {\n                    throw new TypeError('widgetPositioning() expects vertical parameter to be one of (' + verticalModes.join(', ') + ')');\n                }\n                this._options.widgetPositioning.vertical = _widgetPositioning.vertical;\n            }\n            this._update();\n        };\n\n        TempusDominusBootstrap4.prototype.widgetParent = function widgetParent(_widgetParent) {\n            if (arguments.length === 0) {\n                return this._options.widgetParent;\n            }\n\n            if (typeof _widgetParent === 'string') {\n                _widgetParent = $(_widgetParent);\n            }\n\n            if (_widgetParent !== null && typeof _widgetParent !== 'string' && !(_widgetParent instanceof $)) {\n                throw new TypeError('widgetParent() expects a string or a jQuery object parameter');\n            }\n\n            this._options.widgetParent = _widgetParent;\n            if (this.widget) {\n                this.hide();\n                this.show();\n            }\n        };\n\n        //static\n\n\n        TempusDominusBootstrap4._jQueryHandleThis = function _jQueryHandleThis(me, option, argument) {\n            var data = $(me).data(DateTimePicker.DATA_KEY);\n            if ((typeof option === 'undefined' ? 'undefined' : _typeof(option)) === 'object') {\n                $.extend({}, DateTimePicker.Default, option);\n            }\n\n            if (!data) {\n                data = new TempusDominusBootstrap4($(me), option);\n                $(me).data(DateTimePicker.DATA_KEY, data);\n            }\n\n            if (typeof option === 'string') {\n                if (data[option] === undefined) {\n                    throw new Error('No method named \"' + option + '\"');\n                }\n                if (argument === undefined) {\n                    return data[option]();\n                } else {\n                    return data[option](argument);\n                }\n            }\n        };\n\n        TempusDominusBootstrap4._jQueryInterface = function _jQueryInterface(option, argument) {\n            if (this.length === 1) {\n                return TempusDominusBootstrap4._jQueryHandleThis(this[0], option, argument);\n            }\n            return this.each(function () {\n                TempusDominusBootstrap4._jQueryHandleThis(this, option, argument);\n            });\n        };\n\n        return TempusDominusBootstrap4;\n    }(DateTimePicker);\n\n    /**\n    * ------------------------------------------------------------------------\n    * jQuery\n    * ------------------------------------------------------------------------\n    */\n\n\n    $(document).on(DateTimePicker.Event.CLICK_DATA_API, DateTimePicker.Selector.DATA_TOGGLE, function () {\n        var $target = getSelectorFromElement($(this));\n        if ($target.length === 0) {\n            return;\n        }\n        TempusDominusBootstrap4._jQueryInterface.call($target, 'toggle');\n    }).on(DateTimePicker.Event.CHANGE, '.' + DateTimePicker.ClassName.INPUT, function (event) {\n        var $target = getSelectorFromElement($(this));\n        if ($target.length === 0) {\n            return;\n        }\n        TempusDominusBootstrap4._jQueryInterface.call($target, '_change', event);\n    }).on(DateTimePicker.Event.BLUR, '.' + DateTimePicker.ClassName.INPUT, function (event) {\n        var $target = getSelectorFromElement($(this)),\n            config = $target.data(DateTimePicker.DATA_KEY);\n        if ($target.length === 0) {\n            return;\n        }\n        // /!\\ ODOO FIX: check on 'config' existence added by odoo\n        if (config && config._options.debug || window.debug) {\n            return;\n        }\n        TempusDominusBootstrap4._jQueryInterface.call($target, 'hide', event);\n    }).on(DateTimePicker.Event.KEYDOWN, '.' + DateTimePicker.ClassName.INPUT, function (event) {\n        var $target = getSelectorFromElement($(this));\n        if ($target.length === 0) {\n            return;\n        }\n        TempusDominusBootstrap4._jQueryInterface.call($target, '_keydown', event);\n    }).on(DateTimePicker.Event.KEYUP, '.' + DateTimePicker.ClassName.INPUT, function (event) {\n        var $target = getSelectorFromElement($(this));\n        if ($target.length === 0) {\n            return;\n        }\n        TempusDominusBootstrap4._jQueryInterface.call($target, '_keyup', event);\n    }).on(DateTimePicker.Event.FOCUS, '.' + DateTimePicker.ClassName.INPUT, function (event) {\n        var $target = getSelectorFromElement($(this)),\n            config = $target.data(DateTimePicker.DATA_KEY);\n        if ($target.length === 0) {\n            return;\n        }\n        // /!\\ ODOO FIX: check on 'config' existence added by odoo\n        if (!(config && config._options.allowInputToggle)) {\n            return;\n        }\n        TempusDominusBootstrap4._jQueryInterface.call($target, 'show', event);\n    });\n\n    $.fn[DateTimePicker.NAME] = TempusDominusBootstrap4._jQueryInterface;\n    $.fn[DateTimePicker.NAME].Constructor = TempusDominusBootstrap4;\n    $.fn[DateTimePicker.NAME].noConflict = function () {\n        $.fn[DateTimePicker.NAME] = JQUERY_NO_CONFLICT;\n        return TempusDominusBootstrap4._jQueryInterface;\n    };\n\n    return TempusDominusBootstrap4;\n}(jQuery);\n\n}();\n", "/*\nCopyright 2012 Igor Vaynberg\n\nVersion: 3.5.4 Timestamp: Sun Aug 30 13:30:32 EDT 2015\n\nThis software is licensed under the Apache License, Version 2.0 (the \"Apache License\") or the GNU\nGeneral Public License version 2 (the \"GPL License\"). You may choose either license to govern your\nuse of this software only upon the condition that you accept all of the terms of either the Apache\nLicense or the GPL License.\n\nYou may obtain a copy of the Apache License and the GPL License at:\n\n    http://www.apache.org/licenses/LICENSE-2.0\n    http://www.gnu.org/licenses/gpl-2.0.html\n\nUnless required by applicable law or agreed to in writing, software distributed under the\nApache License or the GPL License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR\nCONDITIONS OF ANY KIND, either express or implied. See the Apache License and the GPL License for\nthe specific language governing permissions and limitations under the Apache License and the GPL License.\n*/\n(function ($) {\n    if(typeof $.fn.each2 == \"undefined\") {\n        $.extend($.fn, {\n            /*\n            * 4-10 times faster .each replacement\n            * use it carefully, as it overrides jQuery context of element on each iteration\n            */\n            each2 : function (c) {\n                var j = $([0]), i = -1, l = this.length;\n                while (\n                    ++i < l\n                    && (j.context = j[0] = this[i])\n                    && c.call(j[0], i, j) !== false //\"this\"=DOM, i=index, j=jQuery object\n                );\n                return this;\n            }\n        });\n    }\n})(jQuery);\n\n(function ($, undefined) {\n    \"use strict\";\n    /*global document, window, jQuery, console */\n\n    if (window.Select2 !== undefined) {\n        return;\n    }\n\n    var AbstractSelect2, SingleSelect2, MultiSelect2, nextUid, sizer,\n        lastMousePosition={x:0,y:0}, $document, scrollBarDimensions,\n\n    KEY = {\n        TAB: 9,\n        ENTER: 13,\n        ESC: 27,\n        SPACE: 32,\n        LEFT: 37,\n        UP: 38,\n        RIGHT: 39,\n        DOWN: 40,\n        SHIFT: 16,\n        CTRL: 17,\n        ALT: 18,\n        PAGE_UP: 33,\n        PAGE_DOWN: 34,\n        HOME: 36,\n        END: 35,\n        BACKSPACE: 8,\n        DELETE: 46,\n        isArrow: function (k) {\n            k = k.which ? k.which : k;\n            switch (k) {\n            case KEY.LEFT:\n            case KEY.RIGHT:\n            case KEY.UP:\n            case KEY.DOWN:\n                return true;\n            }\n            return false;\n        },\n        isControl: function (e) {\n            var k = e.which;\n            switch (k) {\n            case KEY.SHIFT:\n            case KEY.CTRL:\n            case KEY.ALT:\n                return true;\n            }\n\n            if (e.metaKey) return true;\n\n            return false;\n        },\n        isFunctionKey: function (k) {\n            k = k.which ? k.which : k;\n            return k >= 112 && k <= 123;\n        }\n    },\n    MEASURE_SCROLLBAR_TEMPLATE = \"<div class='select2-measure-scrollbar'></div>\",\n\n    DIACRITICS = {\"\\u24B6\":\"A\",\"\\uFF21\":\"A\",\"\\u00C0\":\"A\",\"\\u00C1\":\"A\",\"\\u00C2\":\"A\",\"\\u1EA6\":\"A\",\"\\u1EA4\":\"A\",\"\\u1EAA\":\"A\",\"\\u1EA8\":\"A\",\"\\u00C3\":\"A\",\"\\u0100\":\"A\",\"\\u0102\":\"A\",\"\\u1EB0\":\"A\",\"\\u1EAE\":\"A\",\"\\u1EB4\":\"A\",\"\\u1EB2\":\"A\",\"\\u0226\":\"A\",\"\\u01E0\":\"A\",\"\\u00C4\":\"A\",\"\\u01DE\":\"A\",\"\\u1EA2\":\"A\",\"\\u00C5\":\"A\",\"\\u01FA\":\"A\",\"\\u01CD\":\"A\",\"\\u0200\":\"A\",\"\\u0202\":\"A\",\"\\u1EA0\":\"A\",\"\\u1EAC\":\"A\",\"\\u1EB6\":\"A\",\"\\u1E00\":\"A\",\"\\u0104\":\"A\",\"\\u023A\":\"A\",\"\\u2C6F\":\"A\",\"\\uA732\":\"AA\",\"\\u00C6\":\"AE\",\"\\u01FC\":\"AE\",\"\\u01E2\":\"AE\",\"\\uA734\":\"AO\",\"\\uA736\":\"AU\",\"\\uA738\":\"AV\",\"\\uA73A\":\"AV\",\"\\uA73C\":\"AY\",\"\\u24B7\":\"B\",\"\\uFF22\":\"B\",\"\\u1E02\":\"B\",\"\\u1E04\":\"B\",\"\\u1E06\":\"B\",\"\\u0243\":\"B\",\"\\u0182\":\"B\",\"\\u0181\":\"B\",\"\\u24B8\":\"C\",\"\\uFF23\":\"C\",\"\\u0106\":\"C\",\"\\u0108\":\"C\",\"\\u010A\":\"C\",\"\\u010C\":\"C\",\"\\u00C7\":\"C\",\"\\u1E08\":\"C\",\"\\u0187\":\"C\",\"\\u023B\":\"C\",\"\\uA73E\":\"C\",\"\\u24B9\":\"D\",\"\\uFF24\":\"D\",\"\\u1E0A\":\"D\",\"\\u010E\":\"D\",\"\\u1E0C\":\"D\",\"\\u1E10\":\"D\",\"\\u1E12\":\"D\",\"\\u1E0E\":\"D\",\"\\u0110\":\"D\",\"\\u018B\":\"D\",\"\\u018A\":\"D\",\"\\u0189\":\"D\",\"\\uA779\":\"D\",\"\\u01F1\":\"DZ\",\"\\u01C4\":\"DZ\",\"\\u01F2\":\"Dz\",\"\\u01C5\":\"Dz\",\"\\u24BA\":\"E\",\"\\uFF25\":\"E\",\"\\u00C8\":\"E\",\"\\u00C9\":\"E\",\"\\u00CA\":\"E\",\"\\u1EC0\":\"E\",\"\\u1EBE\":\"E\",\"\\u1EC4\":\"E\",\"\\u1EC2\":\"E\",\"\\u1EBC\":\"E\",\"\\u0112\":\"E\",\"\\u1E14\":\"E\",\"\\u1E16\":\"E\",\"\\u0114\":\"E\",\"\\u0116\":\"E\",\"\\u00CB\":\"E\",\"\\u1EBA\":\"E\",\"\\u011A\":\"E\",\"\\u0204\":\"E\",\"\\u0206\":\"E\",\"\\u1EB8\":\"E\",\"\\u1EC6\":\"E\",\"\\u0228\":\"E\",\"\\u1E1C\":\"E\",\"\\u0118\":\"E\",\"\\u1E18\":\"E\",\"\\u1E1A\":\"E\",\"\\u0190\":\"E\",\"\\u018E\":\"E\",\"\\u24BB\":\"F\",\"\\uFF26\":\"F\",\"\\u1E1E\":\"F\",\"\\u0191\":\"F\",\"\\uA77B\":\"F\",\"\\u24BC\":\"G\",\"\\uFF27\":\"G\",\"\\u01F4\":\"G\",\"\\u011C\":\"G\",\"\\u1E20\":\"G\",\"\\u011E\":\"G\",\"\\u0120\":\"G\",\"\\u01E6\":\"G\",\"\\u0122\":\"G\",\"\\u01E4\":\"G\",\"\\u0193\":\"G\",\"\\uA7A0\":\"G\",\"\\uA77D\":\"G\",\"\\uA77E\":\"G\",\"\\u24BD\":\"H\",\"\\uFF28\":\"H\",\"\\u0124\":\"H\",\"\\u1E22\":\"H\",\"\\u1E26\":\"H\",\"\\u021E\":\"H\",\"\\u1E24\":\"H\",\"\\u1E28\":\"H\",\"\\u1E2A\":\"H\",\"\\u0126\":\"H\",\"\\u2C67\":\"H\",\"\\u2C75\":\"H\",\"\\uA78D\":\"H\",\"\\u24BE\":\"I\",\"\\uFF29\":\"I\",\"\\u00CC\":\"I\",\"\\u00CD\":\"I\",\"\\u00CE\":\"I\",\"\\u0128\":\"I\",\"\\u012A\":\"I\",\"\\u012C\":\"I\",\"\\u0130\":\"I\",\"\\u00CF\":\"I\",\"\\u1E2E\":\"I\",\"\\u1EC8\":\"I\",\"\\u01CF\":\"I\",\"\\u0208\":\"I\",\"\\u020A\":\"I\",\"\\u1ECA\":\"I\",\"\\u012E\":\"I\",\"\\u1E2C\":\"I\",\"\\u0197\":\"I\",\"\\u24BF\":\"J\",\"\\uFF2A\":\"J\",\"\\u0134\":\"J\",\"\\u0248\":\"J\",\"\\u24C0\":\"K\",\"\\uFF2B\":\"K\",\"\\u1E30\":\"K\",\"\\u01E8\":\"K\",\"\\u1E32\":\"K\",\"\\u0136\":\"K\",\"\\u1E34\":\"K\",\"\\u0198\":\"K\",\"\\u2C69\":\"K\",\"\\uA740\":\"K\",\"\\uA742\":\"K\",\"\\uA744\":\"K\",\"\\uA7A2\":\"K\",\"\\u24C1\":\"L\",\"\\uFF2C\":\"L\",\"\\u013F\":\"L\",\"\\u0139\":\"L\",\"\\u013D\":\"L\",\"\\u1E36\":\"L\",\"\\u1E38\":\"L\",\"\\u013B\":\"L\",\"\\u1E3C\":\"L\",\"\\u1E3A\":\"L\",\"\\u0141\":\"L\",\"\\u023D\":\"L\",\"\\u2C62\":\"L\",\"\\u2C60\":\"L\",\"\\uA748\":\"L\",\"\\uA746\":\"L\",\"\\uA780\":\"L\",\"\\u01C7\":\"LJ\",\"\\u01C8\":\"Lj\",\"\\u24C2\":\"M\",\"\\uFF2D\":\"M\",\"\\u1E3E\":\"M\",\"\\u1E40\":\"M\",\"\\u1E42\":\"M\",\"\\u2C6E\":\"M\",\"\\u019C\":\"M\",\"\\u24C3\":\"N\",\"\\uFF2E\":\"N\",\"\\u01F8\":\"N\",\"\\u0143\":\"N\",\"\\u00D1\":\"N\",\"\\u1E44\":\"N\",\"\\u0147\":\"N\",\"\\u1E46\":\"N\",\"\\u0145\":\"N\",\"\\u1E4A\":\"N\",\"\\u1E48\":\"N\",\"\\u0220\":\"N\",\"\\u019D\":\"N\",\"\\uA790\":\"N\",\"\\uA7A4\":\"N\",\"\\u01CA\":\"NJ\",\"\\u01CB\":\"Nj\",\"\\u24C4\":\"O\",\"\\uFF2F\":\"O\",\"\\u00D2\":\"O\",\"\\u00D3\":\"O\",\"\\u00D4\":\"O\",\"\\u1ED2\":\"O\",\"\\u1ED0\":\"O\",\"\\u1ED6\":\"O\",\"\\u1ED4\":\"O\",\"\\u00D5\":\"O\",\"\\u1E4C\":\"O\",\"\\u022C\":\"O\",\"\\u1E4E\":\"O\",\"\\u014C\":\"O\",\"\\u1E50\":\"O\",\"\\u1E52\":\"O\",\"\\u014E\":\"O\",\"\\u022E\":\"O\",\"\\u0230\":\"O\",\"\\u00D6\":\"O\",\"\\u022A\":\"O\",\"\\u1ECE\":\"O\",\"\\u0150\":\"O\",\"\\u01D1\":\"O\",\"\\u020C\":\"O\",\"\\u020E\":\"O\",\"\\u01A0\":\"O\",\"\\u1EDC\":\"O\",\"\\u1EDA\":\"O\",\"\\u1EE0\":\"O\",\"\\u1EDE\":\"O\",\"\\u1EE2\":\"O\",\"\\u1ECC\":\"O\",\"\\u1ED8\":\"O\",\"\\u01EA\":\"O\",\"\\u01EC\":\"O\",\"\\u00D8\":\"O\",\"\\u01FE\":\"O\",\"\\u0186\":\"O\",\"\\u019F\":\"O\",\"\\uA74A\":\"O\",\"\\uA74C\":\"O\",\"\\u01A2\":\"OI\",\"\\uA74E\":\"OO\",\"\\u0222\":\"OU\",\"\\u24C5\":\"P\",\"\\uFF30\":\"P\",\"\\u1E54\":\"P\",\"\\u1E56\":\"P\",\"\\u01A4\":\"P\",\"\\u2C63\":\"P\",\"\\uA750\":\"P\",\"\\uA752\":\"P\",\"\\uA754\":\"P\",\"\\u24C6\":\"Q\",\"\\uFF31\":\"Q\",\"\\uA756\":\"Q\",\"\\uA758\":\"Q\",\"\\u024A\":\"Q\",\"\\u24C7\":\"R\",\"\\uFF32\":\"R\",\"\\u0154\":\"R\",\"\\u1E58\":\"R\",\"\\u0158\":\"R\",\"\\u0210\":\"R\",\"\\u0212\":\"R\",\"\\u1E5A\":\"R\",\"\\u1E5C\":\"R\",\"\\u0156\":\"R\",\"\\u1E5E\":\"R\",\"\\u024C\":\"R\",\"\\u2C64\":\"R\",\"\\uA75A\":\"R\",\"\\uA7A6\":\"R\",\"\\uA782\":\"R\",\"\\u24C8\":\"S\",\"\\uFF33\":\"S\",\"\\u1E9E\":\"S\",\"\\u015A\":\"S\",\"\\u1E64\":\"S\",\"\\u015C\":\"S\",\"\\u1E60\":\"S\",\"\\u0160\":\"S\",\"\\u1E66\":\"S\",\"\\u1E62\":\"S\",\"\\u1E68\":\"S\",\"\\u0218\":\"S\",\"\\u015E\":\"S\",\"\\u2C7E\":\"S\",\"\\uA7A8\":\"S\",\"\\uA784\":\"S\",\"\\u24C9\":\"T\",\"\\uFF34\":\"T\",\"\\u1E6A\":\"T\",\"\\u0164\":\"T\",\"\\u1E6C\":\"T\",\"\\u021A\":\"T\",\"\\u0162\":\"T\",\"\\u1E70\":\"T\",\"\\u1E6E\":\"T\",\"\\u0166\":\"T\",\"\\u01AC\":\"T\",\"\\u01AE\":\"T\",\"\\u023E\":\"T\",\"\\uA786\":\"T\",\"\\uA728\":\"TZ\",\"\\u24CA\":\"U\",\"\\uFF35\":\"U\",\"\\u00D9\":\"U\",\"\\u00DA\":\"U\",\"\\u00DB\":\"U\",\"\\u0168\":\"U\",\"\\u1E78\":\"U\",\"\\u016A\":\"U\",\"\\u1E7A\":\"U\",\"\\u016C\":\"U\",\"\\u00DC\":\"U\",\"\\u01DB\":\"U\",\"\\u01D7\":\"U\",\"\\u01D5\":\"U\",\"\\u01D9\":\"U\",\"\\u1EE6\":\"U\",\"\\u016E\":\"U\",\"\\u0170\":\"U\",\"\\u01D3\":\"U\",\"\\u0214\":\"U\",\"\\u0216\":\"U\",\"\\u01AF\":\"U\",\"\\u1EEA\":\"U\",\"\\u1EE8\":\"U\",\"\\u1EEE\":\"U\",\"\\u1EEC\":\"U\",\"\\u1EF0\":\"U\",\"\\u1EE4\":\"U\",\"\\u1E72\":\"U\",\"\\u0172\":\"U\",\"\\u1E76\":\"U\",\"\\u1E74\":\"U\",\"\\u0244\":\"U\",\"\\u24CB\":\"V\",\"\\uFF36\":\"V\",\"\\u1E7C\":\"V\",\"\\u1E7E\":\"V\",\"\\u01B2\":\"V\",\"\\uA75E\":\"V\",\"\\u0245\":\"V\",\"\\uA760\":\"VY\",\"\\u24CC\":\"W\",\"\\uFF37\":\"W\",\"\\u1E80\":\"W\",\"\\u1E82\":\"W\",\"\\u0174\":\"W\",\"\\u1E86\":\"W\",\"\\u1E84\":\"W\",\"\\u1E88\":\"W\",\"\\u2C72\":\"W\",\"\\u24CD\":\"X\",\"\\uFF38\":\"X\",\"\\u1E8A\":\"X\",\"\\u1E8C\":\"X\",\"\\u24CE\":\"Y\",\"\\uFF39\":\"Y\",\"\\u1EF2\":\"Y\",\"\\u00DD\":\"Y\",\"\\u0176\":\"Y\",\"\\u1EF8\":\"Y\",\"\\u0232\":\"Y\",\"\\u1E8E\":\"Y\",\"\\u0178\":\"Y\",\"\\u1EF6\":\"Y\",\"\\u1EF4\":\"Y\",\"\\u01B3\":\"Y\",\"\\u024E\":\"Y\",\"\\u1EFE\":\"Y\",\"\\u24CF\":\"Z\",\"\\uFF3A\":\"Z\",\"\\u0179\":\"Z\",\"\\u1E90\":\"Z\",\"\\u017B\":\"Z\",\"\\u017D\":\"Z\",\"\\u1E92\":\"Z\",\"\\u1E94\":\"Z\",\"\\u01B5\":\"Z\",\"\\u0224\":\"Z\",\"\\u2C7F\":\"Z\",\"\\u2C6B\":\"Z\",\"\\uA762\":\"Z\",\"\\u24D0\":\"a\",\"\\uFF41\":\"a\",\"\\u1E9A\":\"a\",\"\\u00E0\":\"a\",\"\\u00E1\":\"a\",\"\\u00E2\":\"a\",\"\\u1EA7\":\"a\",\"\\u1EA5\":\"a\",\"\\u1EAB\":\"a\",\"\\u1EA9\":\"a\",\"\\u00E3\":\"a\",\"\\u0101\":\"a\",\"\\u0103\":\"a\",\"\\u1EB1\":\"a\",\"\\u1EAF\":\"a\",\"\\u1EB5\":\"a\",\"\\u1EB3\":\"a\",\"\\u0227\":\"a\",\"\\u01E1\":\"a\",\"\\u00E4\":\"a\",\"\\u01DF\":\"a\",\"\\u1EA3\":\"a\",\"\\u00E5\":\"a\",\"\\u01FB\":\"a\",\"\\u01CE\":\"a\",\"\\u0201\":\"a\",\"\\u0203\":\"a\",\"\\u1EA1\":\"a\",\"\\u1EAD\":\"a\",\"\\u1EB7\":\"a\",\"\\u1E01\":\"a\",\"\\u0105\":\"a\",\"\\u2C65\":\"a\",\"\\u0250\":\"a\",\"\\uA733\":\"aa\",\"\\u00E6\":\"ae\",\"\\u01FD\":\"ae\",\"\\u01E3\":\"ae\",\"\\uA735\":\"ao\",\"\\uA737\":\"au\",\"\\uA739\":\"av\",\"\\uA73B\":\"av\",\"\\uA73D\":\"ay\",\"\\u24D1\":\"b\",\"\\uFF42\":\"b\",\"\\u1E03\":\"b\",\"\\u1E05\":\"b\",\"\\u1E07\":\"b\",\"\\u0180\":\"b\",\"\\u0183\":\"b\",\"\\u0253\":\"b\",\"\\u24D2\":\"c\",\"\\uFF43\":\"c\",\"\\u0107\":\"c\",\"\\u0109\":\"c\",\"\\u010B\":\"c\",\"\\u010D\":\"c\",\"\\u00E7\":\"c\",\"\\u1E09\":\"c\",\"\\u0188\":\"c\",\"\\u023C\":\"c\",\"\\uA73F\":\"c\",\"\\u2184\":\"c\",\"\\u24D3\":\"d\",\"\\uFF44\":\"d\",\"\\u1E0B\":\"d\",\"\\u010F\":\"d\",\"\\u1E0D\":\"d\",\"\\u1E11\":\"d\",\"\\u1E13\":\"d\",\"\\u1E0F\":\"d\",\"\\u0111\":\"d\",\"\\u018C\":\"d\",\"\\u0256\":\"d\",\"\\u0257\":\"d\",\"\\uA77A\":\"d\",\"\\u01F3\":\"dz\",\"\\u01C6\":\"dz\",\"\\u24D4\":\"e\",\"\\uFF45\":\"e\",\"\\u00E8\":\"e\",\"\\u00E9\":\"e\",\"\\u00EA\":\"e\",\"\\u1EC1\":\"e\",\"\\u1EBF\":\"e\",\"\\u1EC5\":\"e\",\"\\u1EC3\":\"e\",\"\\u1EBD\":\"e\",\"\\u0113\":\"e\",\"\\u1E15\":\"e\",\"\\u1E17\":\"e\",\"\\u0115\":\"e\",\"\\u0117\":\"e\",\"\\u00EB\":\"e\",\"\\u1EBB\":\"e\",\"\\u011B\":\"e\",\"\\u0205\":\"e\",\"\\u0207\":\"e\",\"\\u1EB9\":\"e\",\"\\u1EC7\":\"e\",\"\\u0229\":\"e\",\"\\u1E1D\":\"e\",\"\\u0119\":\"e\",\"\\u1E19\":\"e\",\"\\u1E1B\":\"e\",\"\\u0247\":\"e\",\"\\u025B\":\"e\",\"\\u01DD\":\"e\",\"\\u24D5\":\"f\",\"\\uFF46\":\"f\",\"\\u1E1F\":\"f\",\"\\u0192\":\"f\",\"\\uA77C\":\"f\",\"\\u24D6\":\"g\",\"\\uFF47\":\"g\",\"\\u01F5\":\"g\",\"\\u011D\":\"g\",\"\\u1E21\":\"g\",\"\\u011F\":\"g\",\"\\u0121\":\"g\",\"\\u01E7\":\"g\",\"\\u0123\":\"g\",\"\\u01E5\":\"g\",\"\\u0260\":\"g\",\"\\uA7A1\":\"g\",\"\\u1D79\":\"g\",\"\\uA77F\":\"g\",\"\\u24D7\":\"h\",\"\\uFF48\":\"h\",\"\\u0125\":\"h\",\"\\u1E23\":\"h\",\"\\u1E27\":\"h\",\"\\u021F\":\"h\",\"\\u1E25\":\"h\",\"\\u1E29\":\"h\",\"\\u1E2B\":\"h\",\"\\u1E96\":\"h\",\"\\u0127\":\"h\",\"\\u2C68\":\"h\",\"\\u2C76\":\"h\",\"\\u0265\":\"h\",\"\\u0195\":\"hv\",\"\\u24D8\":\"i\",\"\\uFF49\":\"i\",\"\\u00EC\":\"i\",\"\\u00ED\":\"i\",\"\\u00EE\":\"i\",\"\\u0129\":\"i\",\"\\u012B\":\"i\",\"\\u012D\":\"i\",\"\\u00EF\":\"i\",\"\\u1E2F\":\"i\",\"\\u1EC9\":\"i\",\"\\u01D0\":\"i\",\"\\u0209\":\"i\",\"\\u020B\":\"i\",\"\\u1ECB\":\"i\",\"\\u012F\":\"i\",\"\\u1E2D\":\"i\",\"\\u0268\":\"i\",\"\\u0131\":\"i\",\"\\u24D9\":\"j\",\"\\uFF4A\":\"j\",\"\\u0135\":\"j\",\"\\u01F0\":\"j\",\"\\u0249\":\"j\",\"\\u24DA\":\"k\",\"\\uFF4B\":\"k\",\"\\u1E31\":\"k\",\"\\u01E9\":\"k\",\"\\u1E33\":\"k\",\"\\u0137\":\"k\",\"\\u1E35\":\"k\",\"\\u0199\":\"k\",\"\\u2C6A\":\"k\",\"\\uA741\":\"k\",\"\\uA743\":\"k\",\"\\uA745\":\"k\",\"\\uA7A3\":\"k\",\"\\u24DB\":\"l\",\"\\uFF4C\":\"l\",\"\\u0140\":\"l\",\"\\u013A\":\"l\",\"\\u013E\":\"l\",\"\\u1E37\":\"l\",\"\\u1E39\":\"l\",\"\\u013C\":\"l\",\"\\u1E3D\":\"l\",\"\\u1E3B\":\"l\",\"\\u017F\":\"l\",\"\\u0142\":\"l\",\"\\u019A\":\"l\",\"\\u026B\":\"l\",\"\\u2C61\":\"l\",\"\\uA749\":\"l\",\"\\uA781\":\"l\",\"\\uA747\":\"l\",\"\\u01C9\":\"lj\",\"\\u24DC\":\"m\",\"\\uFF4D\":\"m\",\"\\u1E3F\":\"m\",\"\\u1E41\":\"m\",\"\\u1E43\":\"m\",\"\\u0271\":\"m\",\"\\u026F\":\"m\",\"\\u24DD\":\"n\",\"\\uFF4E\":\"n\",\"\\u01F9\":\"n\",\"\\u0144\":\"n\",\"\\u00F1\":\"n\",\"\\u1E45\":\"n\",\"\\u0148\":\"n\",\"\\u1E47\":\"n\",\"\\u0146\":\"n\",\"\\u1E4B\":\"n\",\"\\u1E49\":\"n\",\"\\u019E\":\"n\",\"\\u0272\":\"n\",\"\\u0149\":\"n\",\"\\uA791\":\"n\",\"\\uA7A5\":\"n\",\"\\u01CC\":\"nj\",\"\\u24DE\":\"o\",\"\\uFF4F\":\"o\",\"\\u00F2\":\"o\",\"\\u00F3\":\"o\",\"\\u00F4\":\"o\",\"\\u1ED3\":\"o\",\"\\u1ED1\":\"o\",\"\\u1ED7\":\"o\",\"\\u1ED5\":\"o\",\"\\u00F5\":\"o\",\"\\u1E4D\":\"o\",\"\\u022D\":\"o\",\"\\u1E4F\":\"o\",\"\\u014D\":\"o\",\"\\u1E51\":\"o\",\"\\u1E53\":\"o\",\"\\u014F\":\"o\",\"\\u022F\":\"o\",\"\\u0231\":\"o\",\"\\u00F6\":\"o\",\"\\u022B\":\"o\",\"\\u1ECF\":\"o\",\"\\u0151\":\"o\",\"\\u01D2\":\"o\",\"\\u020D\":\"o\",\"\\u020F\":\"o\",\"\\u01A1\":\"o\",\"\\u1EDD\":\"o\",\"\\u1EDB\":\"o\",\"\\u1EE1\":\"o\",\"\\u1EDF\":\"o\",\"\\u1EE3\":\"o\",\"\\u1ECD\":\"o\",\"\\u1ED9\":\"o\",\"\\u01EB\":\"o\",\"\\u01ED\":\"o\",\"\\u00F8\":\"o\",\"\\u01FF\":\"o\",\"\\u0254\":\"o\",\"\\uA74B\":\"o\",\"\\uA74D\":\"o\",\"\\u0275\":\"o\",\"\\u01A3\":\"oi\",\"\\u0223\":\"ou\",\"\\uA74F\":\"oo\",\"\\u24DF\":\"p\",\"\\uFF50\":\"p\",\"\\u1E55\":\"p\",\"\\u1E57\":\"p\",\"\\u01A5\":\"p\",\"\\u1D7D\":\"p\",\"\\uA751\":\"p\",\"\\uA753\":\"p\",\"\\uA755\":\"p\",\"\\u24E0\":\"q\",\"\\uFF51\":\"q\",\"\\u024B\":\"q\",\"\\uA757\":\"q\",\"\\uA759\":\"q\",\"\\u24E1\":\"r\",\"\\uFF52\":\"r\",\"\\u0155\":\"r\",\"\\u1E59\":\"r\",\"\\u0159\":\"r\",\"\\u0211\":\"r\",\"\\u0213\":\"r\",\"\\u1E5B\":\"r\",\"\\u1E5D\":\"r\",\"\\u0157\":\"r\",\"\\u1E5F\":\"r\",\"\\u024D\":\"r\",\"\\u027D\":\"r\",\"\\uA75B\":\"r\",\"\\uA7A7\":\"r\",\"\\uA783\":\"r\",\"\\u24E2\":\"s\",\"\\uFF53\":\"s\",\"\\u00DF\":\"s\",\"\\u015B\":\"s\",\"\\u1E65\":\"s\",\"\\u015D\":\"s\",\"\\u1E61\":\"s\",\"\\u0161\":\"s\",\"\\u1E67\":\"s\",\"\\u1E63\":\"s\",\"\\u1E69\":\"s\",\"\\u0219\":\"s\",\"\\u015F\":\"s\",\"\\u023F\":\"s\",\"\\uA7A9\":\"s\",\"\\uA785\":\"s\",\"\\u1E9B\":\"s\",\"\\u24E3\":\"t\",\"\\uFF54\":\"t\",\"\\u1E6B\":\"t\",\"\\u1E97\":\"t\",\"\\u0165\":\"t\",\"\\u1E6D\":\"t\",\"\\u021B\":\"t\",\"\\u0163\":\"t\",\"\\u1E71\":\"t\",\"\\u1E6F\":\"t\",\"\\u0167\":\"t\",\"\\u01AD\":\"t\",\"\\u0288\":\"t\",\"\\u2C66\":\"t\",\"\\uA787\":\"t\",\"\\uA729\":\"tz\",\"\\u24E4\":\"u\",\"\\uFF55\":\"u\",\"\\u00F9\":\"u\",\"\\u00FA\":\"u\",\"\\u00FB\":\"u\",\"\\u0169\":\"u\",\"\\u1E79\":\"u\",\"\\u016B\":\"u\",\"\\u1E7B\":\"u\",\"\\u016D\":\"u\",\"\\u00FC\":\"u\",\"\\u01DC\":\"u\",\"\\u01D8\":\"u\",\"\\u01D6\":\"u\",\"\\u01DA\":\"u\",\"\\u1EE7\":\"u\",\"\\u016F\":\"u\",\"\\u0171\":\"u\",\"\\u01D4\":\"u\",\"\\u0215\":\"u\",\"\\u0217\":\"u\",\"\\u01B0\":\"u\",\"\\u1EEB\":\"u\",\"\\u1EE9\":\"u\",\"\\u1EEF\":\"u\",\"\\u1EED\":\"u\",\"\\u1EF1\":\"u\",\"\\u1EE5\":\"u\",\"\\u1E73\":\"u\",\"\\u0173\":\"u\",\"\\u1E77\":\"u\",\"\\u1E75\":\"u\",\"\\u0289\":\"u\",\"\\u24E5\":\"v\",\"\\uFF56\":\"v\",\"\\u1E7D\":\"v\",\"\\u1E7F\":\"v\",\"\\u028B\":\"v\",\"\\uA75F\":\"v\",\"\\u028C\":\"v\",\"\\uA761\":\"vy\",\"\\u24E6\":\"w\",\"\\uFF57\":\"w\",\"\\u1E81\":\"w\",\"\\u1E83\":\"w\",\"\\u0175\":\"w\",\"\\u1E87\":\"w\",\"\\u1E85\":\"w\",\"\\u1E98\":\"w\",\"\\u1E89\":\"w\",\"\\u2C73\":\"w\",\"\\u24E7\":\"x\",\"\\uFF58\":\"x\",\"\\u1E8B\":\"x\",\"\\u1E8D\":\"x\",\"\\u24E8\":\"y\",\"\\uFF59\":\"y\",\"\\u1EF3\":\"y\",\"\\u00FD\":\"y\",\"\\u0177\":\"y\",\"\\u1EF9\":\"y\",\"\\u0233\":\"y\",\"\\u1E8F\":\"y\",\"\\u00FF\":\"y\",\"\\u1EF7\":\"y\",\"\\u1E99\":\"y\",\"\\u1EF5\":\"y\",\"\\u01B4\":\"y\",\"\\u024F\":\"y\",\"\\u1EFF\":\"y\",\"\\u24E9\":\"z\",\"\\uFF5A\":\"z\",\"\\u017A\":\"z\",\"\\u1E91\":\"z\",\"\\u017C\":\"z\",\"\\u017E\":\"z\",\"\\u1E93\":\"z\",\"\\u1E95\":\"z\",\"\\u01B6\":\"z\",\"\\u0225\":\"z\",\"\\u0240\":\"z\",\"\\u2C6C\":\"z\",\"\\uA763\":\"z\",\"\\u0386\":\"\\u0391\",\"\\u0388\":\"\\u0395\",\"\\u0389\":\"\\u0397\",\"\\u038A\":\"\\u0399\",\"\\u03AA\":\"\\u0399\",\"\\u038C\":\"\\u039F\",\"\\u038E\":\"\\u03A5\",\"\\u03AB\":\"\\u03A5\",\"\\u038F\":\"\\u03A9\",\"\\u03AC\":\"\\u03B1\",\"\\u03AD\":\"\\u03B5\",\"\\u03AE\":\"\\u03B7\",\"\\u03AF\":\"\\u03B9\",\"\\u03CA\":\"\\u03B9\",\"\\u0390\":\"\\u03B9\",\"\\u03CC\":\"\\u03BF\",\"\\u03CD\":\"\\u03C5\",\"\\u03CB\":\"\\u03C5\",\"\\u03B0\":\"\\u03C5\",\"\\u03C9\":\"\\u03C9\",\"\\u03C2\":\"\\u03C3\"};\n\n    $document = $(document);\n\n    nextUid=(function() { var counter=1; return function() { return counter++; }; }());\n\n\n    function reinsertElement(element) {\n        var placeholder = $(document.createTextNode(''));\n\n        element.before(placeholder);\n        placeholder.before(element);\n        placeholder.remove();\n    }\n\n    function stripDiacritics(str) {\n        // Used 'uni range + named function' from http://jsperf.com/diacritics/18\n        function match(a) {\n            return DIACRITICS[a] || a;\n        }\n\n        return str.replace(/[^\\u0000-\\u007E]/g, match);\n    }\n\n    function indexOf(value, array) {\n        var i = 0, l = array.length;\n        for (; i < l; i = i + 1) {\n            if (equal(value, array[i])) return i;\n        }\n        return -1;\n    }\n\n    function measureScrollbar () {\n        var $template = $( MEASURE_SCROLLBAR_TEMPLATE );\n        $template.appendTo(document.body);\n\n        var dim = {\n            width: $template.width() - $template[0].clientWidth,\n            height: $template.height() - $template[0].clientHeight\n        };\n        $template.remove();\n\n        return dim;\n    }\n\n    /**\n     * Compares equality of a and b\n     * @param a\n     * @param b\n     */\n    function equal(a, b) {\n        if (a === b) return true;\n        if (a === undefined || b === undefined) return false;\n        if (a === null || b === null) return false;\n        // Check whether 'a' or 'b' is a string (primitive or object).\n        // The concatenation of an empty string (+'') converts its argument to a string's primitive.\n        if (a.constructor === String) return a+'' === b+''; // a+'' - in case 'a' is a String object\n        if (b.constructor === String) return b+'' === a+''; // b+'' - in case 'b' is a String object\n        return false;\n    }\n\n    /**\n     * Splits the string into an array of values, transforming each value. An empty array is returned for nulls or empty\n     * strings\n     * @param string\n     * @param separator\n     */\n    function splitVal(string, separator, transform) {\n        var val, i, l;\n        if (string === null || string.length < 1) return [];\n        val = string.split(separator);\n        for (i = 0, l = val.length; i < l; i = i + 1) val[i] = transform(val[i]);\n        return val;\n    }\n\n    function getSideBorderPadding(element) {\n        return element.outerWidth(false) - element.width();\n    }\n\n    function installKeyUpChangeEvent(element) {\n        var key=\"keyup-change-value\";\n        element.on(\"keydown\", function () {\n            if ($.data(element, key) === undefined) {\n                $.data(element, key, element.val());\n            }\n        });\n        element.on(\"keyup\", function () {\n            var val= $.data(element, key);\n            if (val !== undefined && element.val() !== val) {\n                $.removeData(element, key);\n                element.trigger(\"keyup-change\");\n            }\n        });\n    }\n\n\n    /**\n     * filters mouse events so an event is fired only if the mouse moved.\n     *\n     * filters out mouse events that occur when mouse is stationary but\n     * the elements under the pointer are scrolled.\n     */\n    function installFilteredMouseMove(element) {\n        element.on(\"mousemove\", function (e) {\n            var lastpos = lastMousePosition;\n            if (lastpos === undefined || lastpos.x !== e.pageX || lastpos.y !== e.pageY) {\n                $(e.target).trigger(\"mousemove-filtered\", e);\n            }\n        });\n    }\n\n    /**\n     * Debounces a function. Returns a function that calls the original fn function only if no invocations have been made\n     * within the last quietMillis milliseconds.\n     *\n     * @param quietMillis number of milliseconds to wait before invoking fn\n     * @param fn function to be debounced\n     * @param ctx object to be used as this reference within fn\n     * @return debounced version of fn\n     */\n    function debounce(quietMillis, fn, ctx) {\n        ctx = ctx || undefined;\n        var timeout;\n        return function () {\n            var args = arguments;\n            window.clearTimeout(timeout);\n            timeout = window.setTimeout(function() {\n                fn.apply(ctx, args);\n            }, quietMillis);\n        };\n    }\n\n    function installDebouncedScroll(threshold, element) {\n        var notify = debounce(threshold, function (e) { element.trigger(\"scroll-debounced\", e);});\n        element.on(\"scroll\", function (e) {\n            if (indexOf(e.target, element.get()) >= 0) notify(e);\n        });\n    }\n\n    function focus($el) {\n        if ($el[0] === document.activeElement) return;\n\n        /* set the focus in a 0 timeout - that way the focus is set after the processing\n            of the current event has finished - which seems like the only reliable way\n            to set focus */\n        window.setTimeout(function() {\n            var el=$el[0], pos=$el.val().length, range;\n\n            $el.focus();\n\n            /* make sure el received focus so we do not error out when trying to manipulate the caret.\n                sometimes modals or others listeners may steal it after its set */\n            var isVisible = (el.offsetWidth > 0 || el.offsetHeight > 0);\n            if (isVisible && el === document.activeElement) {\n\n                /* after the focus is set move the caret to the end, necessary when we val()\n                    just before setting focus */\n                if(el.setSelectionRange)\n                {\n                    el.setSelectionRange(pos, pos);\n                }\n                else if (el.createTextRange) {\n                    range = el.createTextRange();\n                    range.collapse(false);\n                    range.select();\n                }\n            }\n        }, 0);\n    }\n\n    function getCursorInfo(el) {\n        el = $(el)[0];\n        var offset = 0;\n        var length = 0;\n        if ('selectionStart' in el) {\n            offset = el.selectionStart;\n            length = el.selectionEnd - offset;\n        } else if ('selection' in document) {\n            el.focus();\n            var sel = document.selection.createRange();\n            length = document.selection.createRange().text.length;\n            sel.moveStart('character', -el.value.length);\n            offset = sel.text.length - length;\n        }\n        return { offset: offset, length: length };\n    }\n\n    function killEvent(event) {\n        event.preventDefault();\n        event.stopPropagation();\n    }\n    function killEventImmediately(event) {\n        event.preventDefault();\n        event.stopImmediatePropagation();\n    }\n\n    function measureTextWidth(e) {\n        if (!sizer){\n            var style = e[0].currentStyle || window.getComputedStyle(e[0], null);\n            sizer = $(document.createElement(\"div\")).css({\n                position: \"absolute\",\n                left: \"-10000px\",\n                top: \"-10000px\",\n                display: \"none\",\n                fontSize: style.fontSize,\n                fontFamily: style.fontFamily,\n                fontStyle: style.fontStyle,\n                fontWeight: style.fontWeight,\n                letterSpacing: style.letterSpacing,\n                textTransform: style.textTransform,\n                whiteSpace: \"nowrap\"\n            });\n            sizer.attr(\"class\",\"select2-sizer\");\n            $(document.body).append(sizer);\n        }\n        sizer.text(e.val());\n        return sizer.width();\n    }\n\n    function syncCssClasses(dest, src, adapter) {\n        var classes, replacements = [], adapted;\n\n        classes = $.trim(dest.attr(\"class\"));\n\n        if (classes) {\n            classes = '' + classes; // for IE which returns object\n\n            $(classes.split(/\\s+/)).each2(function() {\n                if (this.indexOf(\"select2-\") === 0) {\n                    replacements.push(this);\n                }\n            });\n        }\n\n        classes = $.trim(src.attr(\"class\"));\n\n        if (classes) {\n            classes = '' + classes; // for IE which returns object\n\n            $(classes.split(/\\s+/)).each2(function() {\n                if (this.indexOf(\"select2-\") !== 0) {\n                    adapted = adapter(this);\n\n                    if (adapted) {\n                        replacements.push(adapted);\n                    }\n                }\n            });\n        }\n\n        dest.attr(\"class\", replacements.join(\" \"));\n    }\n\n\n    function markMatch(text, term, markup, escapeMarkup) {\n        var match=stripDiacritics(text.toUpperCase()).indexOf(stripDiacritics(term.toUpperCase())),\n            tl=term.length;\n\n        if (match<0) {\n            markup.push(escapeMarkup(text));\n            return;\n        }\n\n        markup.push(escapeMarkup(text.substring(0, match)));\n        markup.push(\"<span class='select2-match'>\");\n        markup.push(escapeMarkup(text.substring(match, match + tl)));\n        markup.push(\"</span>\");\n        markup.push(escapeMarkup(text.substring(match + tl, text.length)));\n    }\n\n    function defaultEscapeMarkup(markup) {\n        var replace_map = {\n            '\\\\': '&#92;',\n            '&': '&amp;',\n            '<': '&lt;',\n            '>': '&gt;',\n            '\"': '&quot;',\n            \"'\": '&#39;',\n            \"/\": '&#47;'\n        };\n\n        return String(markup).replace(/[&<>\"'\\/\\\\]/g, function (match) {\n            return replace_map[match];\n        });\n    }\n\n    /**\n     * Produces an ajax-based query function\n     *\n     * @param options object containing configuration parameters\n     * @param options.params parameter map for the transport ajax call, can contain such options as cache, jsonpCallback, etc. see $.ajax\n     * @param options.transport function that will be used to execute the ajax request. must be compatible with parameters supported by $.ajax\n     * @param options.url url for the data\n     * @param options.data a function(searchTerm, pageNumber, context) that should return an object containing query string parameters for the above url.\n     * @param options.dataType request data type: ajax, jsonp, other datatypes supported by jQuery's $.ajax function or the transport function if specified\n     * @param options.quietMillis (optional) milliseconds to wait before making the ajaxRequest, helps debounce the ajax function if invoked too often\n     * @param options.results a function(remoteData, pageNumber, query) that converts data returned form the remote request to the format expected by Select2.\n     *      The expected format is an object containing the following keys:\n     *      results array of objects that will be used as choices\n     *      more (optional) boolean indicating whether there are more results available\n     *      Example: {results:[{id:1, text:'Red'},{id:2, text:'Blue'}], more:true}\n     */\n    function ajax(options) {\n        var timeout, // current scheduled but not yet executed request\n            handler = null,\n            quietMillis = options.quietMillis || 100,\n            ajaxUrl = options.url,\n            self = this;\n\n        return function (query) {\n            window.clearTimeout(timeout);\n            timeout = window.setTimeout(function () {\n                var data = options.data, // ajax data function\n                    url = ajaxUrl, // ajax url string or function\n                    transport = options.transport || $.fn.select2.ajaxDefaults.transport,\n                    // deprecated - to be removed in 4.0  - use params instead\n                    deprecated = {\n                        type: options.type || 'GET', // set type of request (GET or POST)\n                        cache: options.cache || false,\n                        jsonpCallback: options.jsonpCallback||undefined,\n                        dataType: options.dataType||\"json\"\n                    },\n                    params = $.extend({}, $.fn.select2.ajaxDefaults.params, deprecated);\n\n                data = data ? data.call(self, query.term, query.page, query.context) : null;\n                url = (typeof url === 'function') ? url.call(self, query.term, query.page, query.context) : url;\n\n                if (handler && typeof handler.abort === \"function\") { handler.abort(); }\n\n                if (options.params) {\n                    if ($.isFunction(options.params)) {\n                        $.extend(params, options.params.call(self));\n                    } else {\n                        $.extend(params, options.params);\n                    }\n                }\n\n                $.extend(params, {\n                    url: url,\n                    dataType: options.dataType,\n                    data: data,\n                    success: function (data) {\n                        // TODO - replace query.page with query so users have access to term, page, etc.\n                        // added query as third paramter to keep backwards compatibility\n                        var results = options.results(data, query.page, query);\n                        query.callback(results);\n                    },\n                    error: function(jqXHR, textStatus, errorThrown){\n                        var results = {\n                            hasError: true,\n                            jqXHR: jqXHR,\n                            textStatus: textStatus,\n                            errorThrown: errorThrown\n                        };\n\n                        query.callback(results);\n                    }\n                });\n                handler = transport.call(self, params);\n            }, quietMillis);\n        };\n    }\n\n    /**\n     * Produces a query function that works with a local array\n     *\n     * @param options object containing configuration parameters. The options parameter can either be an array or an\n     * object.\n     *\n     * If the array form is used it is assumed that it contains objects with 'id' and 'text' keys.\n     *\n     * If the object form is used it is assumed that it contains 'data' and 'text' keys. The 'data' key should contain\n     * an array of objects that will be used as choices. These objects must contain at least an 'id' key. The 'text'\n     * key can either be a String in which case it is expected that each element in the 'data' array has a key with the\n     * value of 'text' which will be used to match choices. Alternatively, text can be a function(item) that can extract\n     * the text.\n     */\n    function local(options) {\n        var data = options, // data elements\n            dataText,\n            tmp,\n            text = function (item) { return \"\"+item.text; }; // function used to retrieve the text portion of a data item that is matched against the search\n\n         if ($.isArray(data)) {\n            tmp = data;\n            data = { results: tmp };\n        }\n\n         if ($.isFunction(data) === false) {\n            tmp = data;\n            data = function() { return tmp; };\n        }\n\n        var dataItem = data();\n        if (dataItem.text) {\n            text = dataItem.text;\n            // if text is not a function we assume it to be a key name\n            if (!$.isFunction(text)) {\n                dataText = dataItem.text; // we need to store this in a separate variable because in the next step data gets reset and data.text is no longer available\n                text = function (item) { return item[dataText]; };\n            }\n        }\n\n        return function (query) {\n            var t = query.term, filtered = { results: [] }, process;\n            if (t === \"\") {\n                query.callback(data());\n                return;\n            }\n\n            process = function(datum, collection) {\n                var group, attr;\n                datum = datum[0];\n                if (datum.children) {\n                    group = {};\n                    for (attr in datum) {\n                        if (datum.hasOwnProperty(attr)) group[attr]=datum[attr];\n                    }\n                    group.children=[];\n                    $(datum.children).each2(function(i, childDatum) { process(childDatum, group.children); });\n                    if (group.children.length || query.matcher(t, text(group), datum)) {\n                        collection.push(group);\n                    }\n                } else {\n                    if (query.matcher(t, text(datum), datum)) {\n                        collection.push(datum);\n                    }\n                }\n            };\n\n            $(data().results).each2(function(i, datum) { process(datum, filtered.results); });\n            query.callback(filtered);\n        };\n    }\n\n    // TODO javadoc\n    function tags(data) {\n        var isFunc = $.isFunction(data);\n        return function (query) {\n            var t = query.term, filtered = {results: []};\n            var result = isFunc ? data(query) : data;\n            if ($.isArray(result)) {\n                $(result).each(function () {\n                    var isObject = this.text !== undefined,\n                        text = isObject ? this.text : this;\n                    if (t === \"\" || query.matcher(t, text)) {\n                        filtered.results.push(isObject ? this : {id: this, text: this});\n                    }\n                });\n                query.callback(filtered);\n            }\n        };\n    }\n\n    /**\n     * Checks if the formatter function should be used.\n     *\n     * Throws an error if it is not a function. Returns true if it should be used,\n     * false if no formatting should be performed.\n     *\n     * @param formatter\n     */\n    function checkFormatter(formatter, formatterName) {\n        if ($.isFunction(formatter)) return true;\n        if (!formatter) return false;\n        if (typeof(formatter) === 'string') return true;\n        throw new Error(formatterName +\" must be a string, function, or falsy value\");\n    }\n\n  /**\n   * Returns a given value\n   * If given a function, returns its output\n   *\n   * @param val string|function\n   * @param context value of \"this\" to be passed to function\n   * @returns {*}\n   */\n    function evaluate(val, context) {\n        if ($.isFunction(val)) {\n            var args = Array.prototype.slice.call(arguments, 2);\n            return val.apply(context, args);\n        }\n        return val;\n    }\n\n    function countResults(results) {\n        var count = 0;\n        $.each(results, function(i, item) {\n            if (item.children) {\n                count += countResults(item.children);\n            } else {\n                count++;\n            }\n        });\n        return count;\n    }\n\n    /**\n     * Default tokenizer. This function uses breaks the input on substring match of any string from the\n     * opts.tokenSeparators array and uses opts.createSearchChoice to create the choice object. Both of those\n     * two options have to be defined in order for the tokenizer to work.\n     *\n     * @param input text user has typed so far or pasted into the search field\n     * @param selection currently selected choices\n     * @param selectCallback function(choice) callback tho add the choice to selection\n     * @param opts select2's opts\n     * @return undefined/null to leave the current input unchanged, or a string to change the input to the returned value\n     */\n    function defaultTokenizer(input, selection, selectCallback, opts) {\n        var original = input, // store the original so we can compare and know if we need to tell the search to update its text\n            dupe = false, // check for whether a token we extracted represents a duplicate selected choice\n            token, // token\n            index, // position at which the separator was found\n            i, l, // looping variables\n            separator; // the matched separator\n\n        if (!opts.createSearchChoice || !opts.tokenSeparators || opts.tokenSeparators.length < 1) return undefined;\n\n        while (true) {\n            index = -1;\n\n            for (i = 0, l = opts.tokenSeparators.length; i < l; i++) {\n                separator = opts.tokenSeparators[i];\n                index = input.indexOf(separator);\n                if (index >= 0) break;\n            }\n\n            if (index < 0) break; // did not find any token separator in the input string, bail\n\n            token = input.substring(0, index);\n            input = input.substring(index + separator.length);\n\n            if (token.length > 0) {\n                token = opts.createSearchChoice.call(this, token, selection);\n                if (token !== undefined && token !== null && opts.id(token) !== undefined && opts.id(token) !== null) {\n                    dupe = false;\n                    for (i = 0, l = selection.length; i < l; i++) {\n                        if (equal(opts.id(token), opts.id(selection[i]))) {\n                            dupe = true; break;\n                        }\n                    }\n\n                    if (!dupe) selectCallback(token);\n                }\n            }\n        }\n\n        if (original!==input) return input;\n    }\n\n    function cleanupJQueryElements() {\n        var self = this;\n\n        $.each(arguments, function (i, element) {\n            self[element].remove();\n            self[element] = null;\n        });\n    }\n\n    /**\n     * Creates a new class\n     *\n     * @param superClass\n     * @param methods\n     */\n    function clazz(SuperClass, methods) {\n        var constructor = function () {};\n        constructor.prototype = new SuperClass;\n        constructor.prototype.constructor = constructor;\n        constructor.prototype.parent = SuperClass.prototype;\n        constructor.prototype = $.extend(constructor.prototype, methods);\n        return constructor;\n    }\n\n    AbstractSelect2 = clazz(Object, {\n\n        // abstract\n        bind: function (func) {\n            var self = this;\n            return function () {\n                func.apply(self, arguments);\n            };\n        },\n\n        // abstract\n        init: function (opts) {\n            var results, search, resultsSelector = \".select2-results\";\n\n            // prepare options\n            this.opts = opts = this.prepareOpts(opts);\n\n            this.id=opts.id;\n\n            // destroy if called on an existing component\n            if (opts.element.data(\"select2\") !== undefined &&\n                opts.element.data(\"select2\") !== null) {\n                opts.element.data(\"select2\").destroy();\n            }\n\n            this.container = this.createContainer();\n\n            this.liveRegion = $('.select2-hidden-accessible');\n            if (this.liveRegion.length == 0) {\n                this.liveRegion = $(\"<span>\", {\n                        role: \"status\",\n                        \"aria-live\": \"polite\"\n                    })\n                    .addClass(\"select2-hidden-accessible\")\n                    .appendTo(document.body);\n            }\n\n            this.containerId=\"s2id_\"+(opts.element.attr(\"id\") || \"autogen\"+nextUid());\n            this.containerEventName= this.containerId\n                .replace(/([.])/g, '_')\n                .replace(/([;&,\\-\\.\\+\\*\\~':\"\\!\\^#$%@\\[\\]\\(\\)=>\\|])/g, '\\\\$1');\n            this.container.attr(\"id\", this.containerId);\n\n            this.container.attr(\"title\", opts.element.attr(\"title\"));\n\n            this.body = $(document.body);\n\n            syncCssClasses(this.container, this.opts.element, this.opts.adaptContainerCssClass);\n\n            this.container.attr(\"style\", opts.element.attr(\"style\"));\n            this.container.css(evaluate(opts.containerCss, this.opts.element));\n            this.container.addClass(evaluate(opts.containerCssClass, this.opts.element));\n\n            this.elementTabIndex = this.opts.element.attr(\"tabindex\");\n\n            // swap container for the element\n            this.opts.element\n                .data(\"select2\", this)\n                .attr(\"tabindex\", \"-1\")\n                .before(this.container)\n                .on(\"click.select2\", killEvent); // do not leak click events\n\n            this.container.data(\"select2\", this);\n\n            this.dropdown = this.container.find(\".select2-drop\");\n\n            syncCssClasses(this.dropdown, this.opts.element, this.opts.adaptDropdownCssClass);\n\n            this.dropdown.addClass(evaluate(opts.dropdownCssClass, this.opts.element));\n            this.dropdown.data(\"select2\", this);\n            this.dropdown.on(\"click\", killEvent);\n\n            this.results = results = this.container.find(resultsSelector);\n            this.search = search = this.container.find(\"input.select2-input\");\n\n            this.queryCount = 0;\n            this.resultsPage = 0;\n            this.context = null;\n\n            // initialize the container\n            this.initContainer();\n\n            this.container.on(\"click\", killEvent);\n\n            installFilteredMouseMove(this.results);\n\n            this.dropdown.on(\"mousemove-filtered\", resultsSelector, this.bind(this.highlightUnderEvent));\n            this.dropdown.on(\"touchstart touchmove touchend\", resultsSelector, this.bind(function (event) {\n                this._touchEvent = true;\n                this.highlightUnderEvent(event);\n            }));\n            this.dropdown.on(\"touchmove\", resultsSelector, this.bind(this.touchMoved));\n            this.dropdown.on(\"touchstart touchend\", resultsSelector, this.bind(this.clearTouchMoved));\n\n            // Waiting for a click event on touch devices to select option and hide dropdown\n            // otherwise click will be triggered on an underlying element\n            this.dropdown.on('click', this.bind(function (event) {\n                if (this._touchEvent) {\n                    this._touchEvent = false;\n                    this.selectHighlighted();\n                }\n            }));\n\n            installDebouncedScroll(80, this.results);\n            this.dropdown.on(\"scroll-debounced\", resultsSelector, this.bind(this.loadMoreIfNeeded));\n\n            // do not propagate change event from the search field out of the component\n            $(this.container).on(\"change\", \".select2-input\", function(e) {e.stopPropagation();});\n            $(this.dropdown).on(\"change\", \".select2-input\", function(e) {e.stopPropagation();});\n\n            // if jquery.mousewheel plugin is installed we can prevent out-of-bounds scrolling of results via mousewheel\n            if ($.fn.mousewheel) {\n                results.mousewheel(function (e, delta, deltaX, deltaY) {\n                    var top = results.scrollTop();\n                    if (deltaY > 0 && top - deltaY <= 0) {\n                        results.scrollTop(0);\n                        killEvent(e);\n                    } else if (deltaY < 0 && results.get(0).scrollHeight - results.scrollTop() + deltaY <= results.height()) {\n                        results.scrollTop(results.get(0).scrollHeight - results.height());\n                        killEvent(e);\n                    }\n                });\n            }\n\n            installKeyUpChangeEvent(search);\n            search.on(\"keyup-change input paste\", this.bind(this.updateResults));\n            search.on(\"focus\", function () { search.addClass(\"select2-focused\"); });\n            search.on(\"blur\", function () { search.removeClass(\"select2-focused\");});\n\n            this.dropdown.on(\"mouseup\", resultsSelector, this.bind(function (e) {\n                if ($(e.target).closest(\".select2-result-selectable\").length > 0) {\n                    this.highlightUnderEvent(e);\n                    this.selectHighlighted(e);\n                }\n            }));\n\n            // trap all mouse events from leaving the dropdown. sometimes there may be a modal that is listening\n            // for mouse events outside of itself so it can close itself. since the dropdown is now outside the select2's\n            // dom it will trigger the popup close, which is not what we want\n            // focusin can cause focus wars between modals and select2 since the dropdown is outside the modal.\n            this.dropdown.on(\"click mouseup mousedown touchstart touchend focusin\", function (e) { e.stopPropagation(); });\n\n            this.lastSearchTerm = undefined;\n\n            if ($.isFunction(this.opts.initSelection)) {\n                // initialize selection based on the current value of the source element\n                this.initSelection();\n\n                // if the user has provided a function that can set selection based on the value of the source element\n                // we monitor the change event on the element and trigger it, allowing for two way synchronization\n                this.monitorSource();\n            }\n\n            if (opts.maximumInputLength !== null) {\n                this.search.attr(\"maxlength\", opts.maximumInputLength);\n            }\n\n            var disabled = opts.element.prop(\"disabled\");\n            if (disabled === undefined) disabled = false;\n            this.enable(!disabled);\n\n            var readonly = opts.element.prop(\"readonly\");\n            if (readonly === undefined) readonly = false;\n            this.readonly(readonly);\n\n            // Calculate size of scrollbar\n            scrollBarDimensions = scrollBarDimensions || measureScrollbar();\n\n            this.autofocus = opts.element.prop(\"autofocus\");\n            opts.element.prop(\"autofocus\", false);\n            if (this.autofocus) this.focus();\n\n            this.search.attr(\"placeholder\", opts.searchInputPlaceholder);\n        },\n\n        // abstract\n        destroy: function () {\n            var element=this.opts.element, select2 = element.data(\"select2\"), self = this;\n\n            this.close();\n\n            if (element.length && element[0].detachEvent && self._sync) {\n                element.each(function () {\n                    if (self._sync) {\n                        this.detachEvent(\"onpropertychange\", self._sync);\n                    }\n                });\n            }\n            if (this.propertyObserver) {\n                this.propertyObserver.disconnect();\n                this.propertyObserver = null;\n            }\n            this._sync = null;\n\n            if (select2 !== undefined) {\n                select2.container.remove();\n                select2.liveRegion.remove();\n                select2.dropdown.remove();\n                element.removeData(\"select2\")\n                    .off(\".select2\");\n                if (!element.is(\"input[type='hidden']\")) {\n                    element\n                        .show()\n                        .prop(\"autofocus\", this.autofocus || false);\n                    if (this.elementTabIndex) {\n                        element.attr({tabindex: this.elementTabIndex});\n                    } else {\n                        element.removeAttr(\"tabindex\");\n                    }\n                    element.show();\n                } else {\n                    element.css(\"display\", \"\");\n                }\n            }\n\n            cleanupJQueryElements.call(this,\n                \"container\",\n                \"liveRegion\",\n                \"dropdown\",\n                \"results\",\n                \"search\"\n            );\n        },\n\n        // abstract\n        optionToData: function(element) {\n            if (element.is(\"option\")) {\n                return {\n                    id:element.prop(\"value\"),\n                    text:element.text(),\n                    element: element.get(),\n                    css: element.attr(\"class\"),\n                    disabled: element.prop(\"disabled\"),\n                    locked: equal(element.attr(\"locked\"), \"locked\") || equal(element.data(\"locked\"), true)\n                };\n            } else if (element.is(\"optgroup\")) {\n                return {\n                    text:element.attr(\"label\"),\n                    children:[],\n                    element: element.get(),\n                    css: element.attr(\"class\")\n                };\n            }\n        },\n\n        // abstract\n        prepareOpts: function (opts) {\n            var element, select, idKey, ajaxUrl, self = this;\n\n            element = opts.element;\n\n            if (element.get(0).tagName.toLowerCase() === \"select\") {\n                this.select = select = opts.element;\n            }\n\n            if (select) {\n                // these options are not allowed when attached to a select because they are picked up off the element itself\n                $.each([\"id\", \"multiple\", \"ajax\", \"query\", \"createSearchChoice\", \"initSelection\", \"data\", \"tags\"], function () {\n                    if (this in opts) {\n                        throw new Error(\"Option '\" + this + \"' is not allowed for Select2 when attached to a <select> element.\");\n                    }\n                });\n            }\n\n            opts.debug = opts.debug || $.fn.select2.defaults.debug;\n\n            // Warnings for options renamed/removed in Select2 4.0.0\n            // Only when it's enabled through debug mode\n            if (opts.debug && console && console.warn) {\n                // id was removed\n                if (opts.id != null) {\n                    console.warn(\n                        'Select2: The `id` option has been removed in Select2 4.0.0, ' +\n                        'consider renaming your `id` property or mapping the property before your data makes it to Select2. ' +\n                        'You can read more at https://select2.github.io/announcements-4.0.html#changed-id'\n                    );\n                }\n\n                // text was removed\n                if (opts.text != null) {\n                    console.warn(\n                        'Select2: The `text` option has been removed in Select2 4.0.0, ' +\n                        'consider renaming your `text` property or mapping the property before your data makes it to Select2. ' +\n                        'You can read more at https://select2.github.io/announcements-4.0.html#changed-id'\n                    );\n                }\n\n                // sortResults was renamed to results\n                if (opts.sortResults != null) {\n                    console.warn(\n                        'Select2: the `sortResults` option has been renamed to `sorter` in Select2 4.0.0. '\n                    );\n                }\n\n                // selectOnBlur was renamed to selectOnClose\n                if (opts.selectOnBlur != null) {\n                    console.warn(\n                        'Select2: The `selectOnBlur` option has been renamed to `selectOnClose` in Select2 4.0.0.'\n                    );\n                }\n\n                // ajax.results was renamed to ajax.processResults\n                if (opts.ajax != null && opts.ajax.results != null) {\n                    console.warn(\n                        'Select2: The `ajax.results` option has been renamed to `ajax.processResults` in Select2 4.0.0.'\n                    );\n                }\n\n                // format* options were renamed to language.*\n                if (opts.formatNoResults != null) {\n                    console.warn(\n                        'Select2: The `formatNoResults` option has been renamed to `language.noResults` in Select2 4.0.0.'\n                    );\n                }\n                if (opts.formatSearching != null) {\n                    console.warn(\n                        'Select2: The `formatSearching` option has been renamed to `language.searching` in Select2 4.0.0.'\n                    );\n                }\n                if (opts.formatInputTooShort != null) {\n                    console.warn(\n                        'Select2: The `formatInputTooShort` option has been renamed to `language.inputTooShort` in Select2 4.0.0.'\n                    );\n                }\n                if (opts.formatInputTooLong != null) {\n                    console.warn(\n                        'Select2: The `formatInputTooLong` option has been renamed to `language.inputTooLong` in Select2 4.0.0.'\n                    );\n                }\n                if (opts.formatLoading != null) {\n                    console.warn(\n                        'Select2: The `formatLoading` option has been renamed to `language.loadingMore` in Select2 4.0.0.'\n                    );\n                }\n                if (opts.formatSelectionTooBig != null) {\n                    console.warn(\n                        'Select2: The `formatSelectionTooBig` option has been renamed to `language.maximumSelected` in Select2 4.0.0.'\n                    );\n                }\n\n                if (opts.element.data('select2Tags')) {\n                    console.warn(\n                        'Select2: The `data-select2-tags` attribute has been renamed to `data-tags` in Select2 4.0.0.'\n                    );\n                }\n            }\n\n            // Aliasing options renamed in Select2 4.0.0\n\n            // data-select2-tags -> data-tags\n            if (opts.element.data('tags') != null) {\n                var elemTags = opts.element.data('tags');\n\n                // data-tags should actually be a boolean\n                if (!$.isArray(elemTags)) {\n                    elemTags = [];\n                }\n\n                opts.element.data('select2Tags', elemTags);\n            }\n\n            // sortResults -> sorter\n            if (opts.sorter != null) {\n                opts.sortResults = opts.sorter;\n            }\n\n            // selectOnBlur -> selectOnClose\n            if (opts.selectOnClose != null) {\n                opts.selectOnBlur = opts.selectOnClose;\n            }\n\n            // ajax.results -> ajax.processResults\n            if (opts.ajax != null) {\n                if ($.isFunction(opts.ajax.processResults)) {\n                    opts.ajax.results = opts.ajax.processResults;\n                }\n            }\n\n            // Formatters/language options\n            if (opts.language != null) {\n                var lang = opts.language;\n\n                // formatNoMatches -> language.noMatches\n                if ($.isFunction(lang.noMatches)) {\n                    opts.formatNoMatches = lang.noMatches;\n                }\n\n                // formatSearching -> language.searching\n                if ($.isFunction(lang.searching)) {\n                    opts.formatSearching = lang.searching;\n                }\n\n                // formatInputTooShort -> language.inputTooShort\n                if ($.isFunction(lang.inputTooShort)) {\n                    opts.formatInputTooShort = lang.inputTooShort;\n                }\n\n                // formatInputTooLong -> language.inputTooLong\n                if ($.isFunction(lang.inputTooLong)) {\n                    opts.formatInputTooLong = lang.inputTooLong;\n                }\n\n                // formatLoading -> language.loadingMore\n                if ($.isFunction(lang.loadingMore)) {\n                    opts.formatLoading = lang.loadingMore;\n                }\n\n                // formatSelectionTooBig -> language.maximumSelected\n                if ($.isFunction(lang.maximumSelected)) {\n                    opts.formatSelectionTooBig = lang.maximumSelected;\n                }\n            }\n\n            opts = $.extend({}, {\n                populateResults: function(container, results, query) {\n                    var populate, id=this.opts.id, liveRegion=this.liveRegion;\n\n                    populate=function(results, container, depth) {\n\n                        var i, l, result, selectable, disabled, compound, node, label, innerContainer, formatted;\n\n                        results = opts.sortResults(results, container, query);\n\n                        // collect the created nodes for bulk append\n                        var nodes = [];\n                        for (i = 0, l = results.length; i < l; i = i + 1) {\n\n                            result=results[i];\n\n                            disabled = (result.disabled === true);\n                            selectable = (!disabled) && (id(result) !== undefined);\n\n                            compound=result.children && result.children.length > 0;\n\n                            node=$(\"<li></li>\");\n                            node.addClass(\"select2-results-dept-\"+depth);\n                            node.addClass(\"select2-result\");\n                            node.addClass(selectable ? \"select2-result-selectable\" : \"select2-result-unselectable\");\n                            if (disabled) { node.addClass(\"select2-disabled\"); }\n                            if (compound) { node.addClass(\"select2-result-with-children\"); }\n                            node.addClass(self.opts.formatResultCssClass(result));\n                            node.attr(\"role\", \"presentation\");\n\n                            label=$(document.createElement(\"div\"));\n                            label.addClass(\"select2-result-label\");\n                            label.attr(\"id\", \"select2-result-label-\" + nextUid());\n                            label.attr(\"role\", \"option\");\n\n                            formatted=opts.formatResult(result, label, query, self.opts.escapeMarkup);\n                            if (formatted!==undefined) {\n                                label.html(formatted);\n                                node.append(label);\n                            }\n\n\n                            if (compound) {\n                                innerContainer=$(\"<ul></ul>\");\n                                innerContainer.addClass(\"select2-result-sub\");\n                                populate(result.children, innerContainer, depth+1);\n                                node.append(innerContainer);\n                            }\n\n                            node.data(\"select2-data\", result);\n                            nodes.push(node[0]);\n                        }\n\n                        // bulk append the created nodes\n                        container.append(nodes);\n                        liveRegion.text(opts.formatMatches(results.length));\n                    };\n\n                    populate(results, container, 0);\n                }\n            }, $.fn.select2.defaults, opts);\n\n            if (typeof(opts.id) !== \"function\") {\n                idKey = opts.id;\n                opts.id = function (e) { return e[idKey]; };\n            }\n\n            if ($.isArray(opts.element.data(\"select2Tags\"))) {\n                if (\"tags\" in opts) {\n                    throw \"tags specified as both an attribute 'data-select2-tags' and in options of Select2 \" + opts.element.attr(\"id\");\n                }\n                opts.tags=opts.element.data(\"select2Tags\");\n            }\n\n            if (select) {\n                opts.query = this.bind(function (query) {\n                    var data = { results: [], more: false },\n                        term = query.term,\n                        children, placeholderOption, process;\n\n                    process=function(element, collection) {\n                        var group;\n                        if (element.is(\"option\")) {\n                            if (query.matcher(term, element.text(), element)) {\n                                collection.push(self.optionToData(element));\n                            }\n                        } else if (element.is(\"optgroup\")) {\n                            group=self.optionToData(element);\n                            element.children().each2(function(i, elm) { process(elm, group.children); });\n                            if (group.children.length>0) {\n                                collection.push(group);\n                            }\n                        }\n                    };\n\n                    children=element.children();\n\n                    // ignore the placeholder option if there is one\n                    if (this.getPlaceholder() !== undefined && children.length > 0) {\n                        placeholderOption = this.getPlaceholderOption();\n                        if (placeholderOption) {\n                            children=children.not(placeholderOption);\n                        }\n                    }\n\n                    children.each2(function(i, elm) { process(elm, data.results); });\n\n                    query.callback(data);\n                });\n                // this is needed because inside val() we construct choices from options and their id is hardcoded\n                opts.id=function(e) { return e.id; };\n            } else {\n                if (!(\"query\" in opts)) {\n                    if (\"ajax\" in opts) {\n                        ajaxUrl = opts.element.data(\"ajax-url\");\n                        if (ajaxUrl && ajaxUrl.length > 0) {\n                            opts.ajax.url = ajaxUrl;\n                        }\n                        opts.query = ajax.call(opts.element, opts.ajax);\n                    } else if (\"data\" in opts) {\n                        opts.query = local(opts.data);\n                    } else if (\"tags\" in opts) {\n                        opts.query = tags(opts.tags);\n                        if (opts.createSearchChoice === undefined) {\n                            opts.createSearchChoice = function (term) { return {id: $.trim(term), text: $.trim(term)}; };\n                        }\n                        if (opts.initSelection === undefined) {\n                            opts.initSelection = function (element, callback) {\n                                var data = [];\n                                $(splitVal(element.val(), opts.separator, opts.transformVal)).each(function () {\n                                    var obj = { id: this, text: this },\n                                        tags = opts.tags;\n                                    if ($.isFunction(tags)) tags=tags();\n                                    $(tags).each(function() { if (equal(this.id, obj.id)) { obj = this; return false; } });\n                                    data.push(obj);\n                                });\n\n                                callback(data);\n                            };\n                        }\n                    }\n                }\n            }\n            if (typeof(opts.query) !== \"function\") {\n                throw \"query function not defined for Select2 \" + opts.element.attr(\"id\");\n            }\n\n            if (opts.createSearchChoicePosition === 'top') {\n                opts.createSearchChoicePosition = function(list, item) { list.unshift(item); };\n            }\n            else if (opts.createSearchChoicePosition === 'bottom') {\n                opts.createSearchChoicePosition = function(list, item) { list.push(item); };\n            }\n            else if (typeof(opts.createSearchChoicePosition) !== \"function\")  {\n                throw \"invalid createSearchChoicePosition option must be 'top', 'bottom' or a custom function\";\n            }\n\n            return opts;\n        },\n\n        /**\n         * Monitor the original element for changes and update select2 accordingly\n         */\n        // abstract\n        monitorSource: function () {\n            var el = this.opts.element, observer, self = this;\n\n            el.on(\"change.select2\", this.bind(function (e) {\n                if (this.opts.element.data(\"select2-change-triggered\") !== true) {\n                    this.initSelection();\n                }\n            }));\n\n            this._sync = this.bind(function () {\n\n                // sync enabled state\n                var disabled = el.prop(\"disabled\");\n                if (disabled === undefined) disabled = false;\n                this.enable(!disabled);\n\n                var readonly = el.prop(\"readonly\");\n                if (readonly === undefined) readonly = false;\n                this.readonly(readonly);\n\n                if (this.container) {\n                    syncCssClasses(this.container, this.opts.element, this.opts.adaptContainerCssClass);\n                    this.container.addClass(evaluate(this.opts.containerCssClass, this.opts.element));\n                }\n\n                if (this.dropdown) {\n                    syncCssClasses(this.dropdown, this.opts.element, this.opts.adaptDropdownCssClass);\n                    this.dropdown.addClass(evaluate(this.opts.dropdownCssClass, this.opts.element));\n                }\n\n            });\n\n            // IE8-10 (IE9/10 won't fire propertyChange via attachEventListener)\n            if (el.length && el[0].attachEvent) {\n                el.each(function() {\n                    this.attachEvent(\"onpropertychange\", self._sync);\n                });\n            }\n\n            // safari, chrome, firefox, IE11\n            observer = window.MutationObserver || window.WebKitMutationObserver|| window.MozMutationObserver;\n            if (observer !== undefined) {\n                if (this.propertyObserver) { delete this.propertyObserver; this.propertyObserver = null; }\n                this.propertyObserver = new observer(function (mutations) {\n                    $.each(mutations, self._sync);\n                });\n                this.propertyObserver.observe(el.get(0), { attributes:true, subtree:false });\n            }\n        },\n\n        // abstract\n        triggerSelect: function(data) {\n            var evt = $.Event(\"select2-selecting\", { val: this.id(data), object: data, choice: data });\n            this.opts.element.trigger(evt);\n            return !evt.isDefaultPrevented();\n        },\n\n        /**\n         * Triggers the change event on the source element\n         */\n        // abstract\n        triggerChange: function (details) {\n\n            details = details || {};\n            details= $.extend({}, details, { type: \"change\", val: this.val() });\n            // prevents recursive triggering\n            this.opts.element.data(\"select2-change-triggered\", true);\n            this.opts.element.trigger(details);\n            this.opts.element.data(\"select2-change-triggered\", false);\n\n            // some validation frameworks ignore the change event and listen instead to keyup, click for selects\n            // so here we trigger the click event manually\n            this.opts.element.click();\n\n            // ValidationEngine ignores the change event and listens instead to blur\n            // so here we trigger the blur event manually if so desired\n            if (this.opts.blurOnChange)\n                this.opts.element.blur();\n        },\n\n        //abstract\n        isInterfaceEnabled: function()\n        {\n            return this.enabledInterface === true;\n        },\n\n        // abstract\n        enableInterface: function() {\n            var enabled = this._enabled && !this._readonly,\n                disabled = !enabled;\n\n            if (enabled === this.enabledInterface) return false;\n\n            this.container.toggleClass(\"select2-container-disabled\", disabled);\n            this.close();\n            this.enabledInterface = enabled;\n\n            return true;\n        },\n\n        // abstract\n        enable: function(enabled) {\n            if (enabled === undefined) enabled = true;\n            if (this._enabled === enabled) return;\n            this._enabled = enabled;\n\n            this.opts.element.prop(\"disabled\", !enabled);\n            this.enableInterface();\n        },\n\n        // abstract\n        disable: function() {\n            this.enable(false);\n        },\n\n        // abstract\n        readonly: function(enabled) {\n            if (enabled === undefined) enabled = false;\n            if (this._readonly === enabled) return;\n            this._readonly = enabled;\n\n            this.opts.element.prop(\"readonly\", enabled);\n            this.enableInterface();\n        },\n\n        // abstract\n        opened: function () {\n            return (this.container) ? this.container.hasClass(\"select2-dropdown-open\") : false;\n        },\n\n        // abstract\n        positionDropdown: function() {\n            var $dropdown = this.dropdown,\n                container = this.container,\n                offset = container.offset(),\n                height = container.outerHeight(false),\n                width = container.outerWidth(false),\n                dropHeight = $dropdown.outerHeight(false),\n                $window = $(window),\n                windowWidth = $window.width(),\n                windowHeight = $window.height(),\n                viewPortRight = $window.scrollLeft() + windowWidth,\n                viewportBottom = $window.scrollTop() + windowHeight,\n                dropTop = offset.top + height,\n                dropLeft = offset.left,\n                enoughRoomBelow = dropTop + dropHeight <= viewportBottom,\n                enoughRoomAbove = (offset.top - dropHeight) >= $window.scrollTop(),\n                dropWidth = $dropdown.outerWidth(false),\n                enoughRoomOnRight = function() {\n                    return dropLeft + dropWidth <= viewPortRight;\n                },\n                enoughRoomOnLeft = function() {\n                    return offset.left + viewPortRight + container.outerWidth(false)  > dropWidth;\n                },\n                aboveNow = $dropdown.hasClass(\"select2-drop-above\"),\n                bodyOffset,\n                above,\n                changeDirection,\n                css,\n                resultsListNode;\n\n            // always prefer the current above/below alignment, unless there is not enough room\n            if (aboveNow) {\n                above = true;\n                if (!enoughRoomAbove && enoughRoomBelow) {\n                    changeDirection = true;\n                    above = false;\n                }\n            } else {\n                above = false;\n                if (!enoughRoomBelow && enoughRoomAbove) {\n                    changeDirection = true;\n                    above = true;\n                }\n            }\n\n            //if we are changing direction we need to get positions when dropdown is hidden;\n            if (changeDirection) {\n                $dropdown.hide();\n                offset = this.container.offset();\n                height = this.container.outerHeight(false);\n                width = this.container.outerWidth(false);\n                dropHeight = $dropdown.outerHeight(false);\n                viewPortRight = $window.scrollLeft() + windowWidth;\n                viewportBottom = $window.scrollTop() + windowHeight;\n                dropTop = offset.top + height;\n                dropLeft = offset.left;\n                dropWidth = $dropdown.outerWidth(false);\n                $dropdown.show();\n\n                // fix so the cursor does not move to the left within the search-textbox in IE\n                this.focusSearch();\n            }\n\n            if (this.opts.dropdownAutoWidth) {\n                resultsListNode = $('.select2-results', $dropdown)[0];\n                $dropdown.addClass('select2-drop-auto-width');\n                $dropdown.css('width', '');\n                // Add scrollbar width to dropdown if vertical scrollbar is present\n                dropWidth = $dropdown.outerWidth(false) + (resultsListNode.scrollHeight === resultsListNode.clientHeight ? 0 : scrollBarDimensions.width);\n                dropWidth > width ? width = dropWidth : dropWidth = width;\n                dropHeight = $dropdown.outerHeight(false);\n            }\n            else {\n                this.container.removeClass('select2-drop-auto-width');\n            }\n\n            //console.log(\"below/ droptop:\", dropTop, \"dropHeight\", dropHeight, \"sum\", (dropTop+dropHeight)+\" viewport bottom\", viewportBottom, \"enough?\", enoughRoomBelow);\n            //console.log(\"above/ offset.top\", offset.top, \"dropHeight\", dropHeight, \"top\", (offset.top-dropHeight), \"scrollTop\", this.body.scrollTop(), \"enough?\", enoughRoomAbove);\n\n            // fix positioning when body has an offset and is not position: static\n            if (this.body.css('position') !== 'static') {\n                bodyOffset = this.body.offset();\n                dropTop -= bodyOffset.top;\n                dropLeft -= bodyOffset.left;\n            }\n\n            if (!enoughRoomOnRight() && enoughRoomOnLeft()) {\n                dropLeft = offset.left + this.container.outerWidth(false) - dropWidth;\n            }\n\n            css =  {\n                left: dropLeft,\n                width: width\n            };\n\n            if (above) {\n                this.container.addClass(\"select2-drop-above\");\n                $dropdown.addClass(\"select2-drop-above\");\n                dropHeight = $dropdown.outerHeight(false);\n                css.top = offset.top - dropHeight;\n                css.bottom = 'auto';\n            }\n            else {\n                css.top = dropTop;\n                css.bottom = 'auto';\n                this.container.removeClass(\"select2-drop-above\");\n                $dropdown.removeClass(\"select2-drop-above\");\n            }\n            css = $.extend(css, evaluate(this.opts.dropdownCss, this.opts.element));\n\n            $dropdown.css(css);\n        },\n\n        // abstract\n        shouldOpen: function() {\n            var event;\n\n            if (this.opened()) return false;\n\n            if (this._enabled === false || this._readonly === true) return false;\n\n            event = $.Event(\"select2-opening\");\n            this.opts.element.trigger(event);\n            return !event.isDefaultPrevented();\n        },\n\n        // abstract\n        clearDropdownAlignmentPreference: function() {\n            // clear the classes used to figure out the preference of where the dropdown should be opened\n            this.container.removeClass(\"select2-drop-above\");\n            this.dropdown.removeClass(\"select2-drop-above\");\n        },\n\n        /**\n         * Opens the dropdown\n         *\n         * @return {Boolean} whether or not dropdown was opened. This method will return false if, for example,\n         * the dropdown is already open, or if the 'open' event listener on the element called preventDefault().\n         */\n        // abstract\n        open: function () {\n\n            if (!this.shouldOpen()) return false;\n\n            this.opening();\n\n            // Only bind the document mousemove when the dropdown is visible\n            $document.on(\"mousemove.select2Event\", function (e) {\n                lastMousePosition.x = e.pageX;\n                lastMousePosition.y = e.pageY;\n            });\n\n            return true;\n        },\n\n        /**\n         * Performs the opening of the dropdown\n         */\n        // abstract\n        opening: function() {\n            var cid = this.containerEventName,\n                scroll = \"scroll.\" + cid,\n                resize = \"resize.\"+cid,\n                orient = \"orientationchange.\"+cid,\n                mask;\n\n            this.container.addClass(\"select2-dropdown-open\").addClass(\"select2-container-active\");\n\n            this.clearDropdownAlignmentPreference();\n\n            if(this.dropdown[0] !== this.body.children().last()[0]) {\n                this.dropdown.detach().appendTo(this.body);\n            }\n\n            // create the dropdown mask if doesn't already exist\n            mask = $(\"#select2-drop-mask\");\n            if (mask.length === 0) {\n                mask = $(document.createElement(\"div\"));\n                mask.attr(\"id\",\"select2-drop-mask\").attr(\"class\",\"select2-drop-mask\");\n                mask.hide();\n                mask.appendTo(this.body);\n                mask.on(\"mousedown touchstart click\", function (e) {\n                    // Prevent IE from generating a click event on the body\n                    reinsertElement(mask);\n\n                    var dropdown = $(\"#select2-drop\"), self;\n                    if (dropdown.length > 0) {\n                        self=dropdown.data(\"select2\");\n                        if (self.opts.selectOnBlur) {\n                            self.selectHighlighted({noFocus: true});\n                        }\n                        self.close();\n                        e.preventDefault();\n                        e.stopPropagation();\n                    }\n                });\n            }\n\n            // ensure the mask is always right before the dropdown\n            if (this.dropdown.prev()[0] !== mask[0]) {\n                this.dropdown.before(mask);\n            }\n\n            // move the global id to the correct dropdown\n            $(\"#select2-drop\").removeAttr(\"id\");\n            this.dropdown.attr(\"id\", \"select2-drop\");\n\n            // show the elements\n            mask.show();\n\n            this.positionDropdown();\n            this.dropdown.show();\n            this.positionDropdown();\n\n            this.dropdown.addClass(\"select2-drop-active\");\n\n            // attach listeners to events that can change the position of the container and thus require\n            // the position of the dropdown to be updated as well so it does not come unglued from the container\n            var that = this;\n            this.container.parents().add(window).each(function () {\n                $(this).on(resize+\" \"+scroll+\" \"+orient, function (e) {\n                    if (that.opened()) that.positionDropdown();\n                });\n            });\n\n\n        },\n\n        // abstract\n        close: function () {\n            if (!this.opened()) return;\n\n            var cid = this.containerEventName,\n                scroll = \"scroll.\" + cid,\n                resize = \"resize.\"+cid,\n                orient = \"orientationchange.\"+cid;\n\n            // unbind event listeners\n            this.container.parents().add(window).each(function () { $(this).off(scroll).off(resize).off(orient); });\n\n            this.clearDropdownAlignmentPreference();\n\n            $(\"#select2-drop-mask\").hide();\n            this.dropdown.removeAttr(\"id\"); // only the active dropdown has the select2-drop id\n            this.dropdown.hide();\n            this.container.removeClass(\"select2-dropdown-open\").removeClass(\"select2-container-active\");\n            this.results.empty();\n\n            // Now that the dropdown is closed, unbind the global document mousemove event\n            $document.off(\"mousemove.select2Event\");\n\n            this.clearSearch();\n            this.search.removeClass(\"select2-active\");\n\n            // Remove the aria active descendant for highlighted element\n            this.search.removeAttr(\"aria-activedescendant\");\n            this.opts.element.trigger($.Event(\"select2-close\"));\n        },\n\n        /**\n         * Opens control, sets input value, and updates results.\n         */\n        // abstract\n        externalSearch: function (term) {\n            this.open();\n            this.search.val(term);\n            this.updateResults(false);\n        },\n\n        // abstract\n        clearSearch: function () {\n\n        },\n\n        /**\n         * @return {Boolean} Whether or not search value was changed.\n         * @private\n         */\n        prefillNextSearchTerm: function () {\n            // initializes search's value with nextSearchTerm (if defined by user)\n            // ignore nextSearchTerm if the dropdown is opened by the user pressing a letter\n            if(this.search.val() !== \"\") {\n                return false;\n            }\n\n            var nextSearchTerm = this.opts.nextSearchTerm(this.data(), this.lastSearchTerm);\n            if(nextSearchTerm !== undefined){\n                this.search.val(nextSearchTerm);\n                this.search.select();\n                return true;\n            }\n\n            return false;\n        },\n\n        //abstract\n        getMaximumSelectionSize: function() {\n            return evaluate(this.opts.maximumSelectionSize, this.opts.element);\n        },\n\n        // abstract\n        ensureHighlightVisible: function () {\n            var results = this.results, children, index, child, hb, rb, y, more, topOffset;\n\n            index = this.highlight();\n\n            if (index < 0) return;\n\n            if (index == 0) {\n\n                // if the first element is highlighted scroll all the way to the top,\n                // that way any unselectable headers above it will also be scrolled\n                // into view\n\n                results.scrollTop(0);\n                return;\n            }\n\n            children = this.findHighlightableChoices().find('.select2-result-label');\n\n            child = $(children[index]);\n\n            topOffset = (child.offset() || {}).top || 0;\n\n            hb = topOffset + child.outerHeight(true);\n\n            // if this is the last child lets also make sure select2-more-results is visible\n            if (index === children.length - 1) {\n                more = results.find(\"li.select2-more-results\");\n                if (more.length > 0) {\n                    hb = more.offset().top + more.outerHeight(true);\n                }\n            }\n\n            rb = results.offset().top + results.outerHeight(false);\n            if (hb > rb) {\n                results.scrollTop(results.scrollTop() + (hb - rb));\n            }\n            y = topOffset - results.offset().top;\n\n            // make sure the top of the element is visible\n            if (y < 0 && child.css('display') != 'none' ) {\n                results.scrollTop(results.scrollTop() + y); // y is negative\n            }\n        },\n\n        // abstract\n        findHighlightableChoices: function() {\n            return this.results.find(\".select2-result-selectable:not(.select2-disabled):not(.select2-selected)\");\n        },\n\n        // abstract\n        moveHighlight: function (delta) {\n            var choices = this.findHighlightableChoices(),\n                index = this.highlight();\n\n            while (index > -1 && index < choices.length) {\n                index += delta;\n                var choice = $(choices[index]);\n                if (choice.hasClass(\"select2-result-selectable\") && !choice.hasClass(\"select2-disabled\") && !choice.hasClass(\"select2-selected\")) {\n                    this.highlight(index);\n                    break;\n                }\n            }\n        },\n\n        // abstract\n        highlight: function (index) {\n            var choices = this.findHighlightableChoices(),\n                choice,\n                data;\n\n            if (arguments.length === 0) {\n                return indexOf(choices.filter(\".select2-highlighted\")[0], choices.get());\n            }\n\n            if (index >= choices.length) index = choices.length - 1;\n            if (index < 0) index = 0;\n\n            this.removeHighlight();\n\n            choice = $(choices[index]);\n            choice.addClass(\"select2-highlighted\");\n\n            // ensure assistive technology can determine the active choice\n            this.search.attr(\"aria-activedescendant\", choice.find(\".select2-result-label\").attr(\"id\"));\n\n            this.ensureHighlightVisible();\n\n            this.liveRegion.text(choice.text());\n\n            data = choice.data(\"select2-data\");\n            if (data) {\n                this.opts.element.trigger({ type: \"select2-highlight\", val: this.id(data), choice: data });\n            }\n        },\n\n        removeHighlight: function() {\n            this.results.find(\".select2-highlighted\").removeClass(\"select2-highlighted\");\n        },\n\n        touchMoved: function() {\n            this._touchMoved = true;\n        },\n\n        clearTouchMoved: function() {\n          this._touchMoved = false;\n        },\n\n        // abstract\n        countSelectableResults: function() {\n            return this.findHighlightableChoices().length;\n        },\n\n        // abstract\n        highlightUnderEvent: function (event) {\n            var el = $(event.target).closest(\".select2-result-selectable\");\n            if (el.length > 0 && !el.is(\".select2-highlighted\")) {\n                var choices = this.findHighlightableChoices();\n                this.highlight(choices.index(el));\n            } else if (el.length == 0) {\n                // if we are over an unselectable item remove all highlights\n                this.removeHighlight();\n            }\n        },\n\n        // abstract\n        loadMoreIfNeeded: function () {\n            var results = this.results,\n                more = results.find(\"li.select2-more-results\"),\n                below, // pixels the element is below the scroll fold, below==0 is when the element is starting to be visible\n                page = this.resultsPage + 1,\n                self=this,\n                term=this.search.val(),\n                context=this.context;\n\n            if (more.length === 0) return;\n            below = more.offset().top - results.offset().top - results.height();\n\n            if (below <= this.opts.loadMorePadding) {\n                more.addClass(\"select2-active\");\n                this.opts.query({\n                        element: this.opts.element,\n                        term: term,\n                        page: page,\n                        context: context,\n                        matcher: this.opts.matcher,\n                        callback: this.bind(function (data) {\n\n                    // ignore a response if the select2 has been closed before it was received\n                    if (!self.opened()) return;\n\n\n                    self.opts.populateResults.call(this, results, data.results, {term: term, page: page, context:context});\n                    self.postprocessResults(data, false, false);\n\n                    if (data.more===true) {\n                        more.detach().appendTo(results).html(self.opts.escapeMarkup(evaluate(self.opts.formatLoadMore, self.opts.element, page+1)));\n                        window.setTimeout(function() { self.loadMoreIfNeeded(); }, 10);\n                    } else {\n                        more.remove();\n                    }\n                    self.positionDropdown();\n                    self.resultsPage = page;\n                    self.context = data.context;\n                    this.opts.element.trigger({ type: \"select2-loaded\", items: data });\n                })});\n            }\n        },\n\n        /**\n         * Default tokenizer function which does nothing\n         */\n        tokenize: function() {\n\n        },\n\n        /**\n         * @param initial whether or not this is the call to this method right after the dropdown has been opened\n         */\n        // abstract\n        updateResults: function (initial) {\n            var search = this.search,\n                results = this.results,\n                opts = this.opts,\n                data,\n                self = this,\n                input,\n                term = search.val(),\n                lastTerm = $.data(this.container, \"select2-last-term\"),\n                // sequence number used to drop out-of-order responses\n                queryNumber;\n\n            // prevent duplicate queries against the same term\n            if (initial !== true && lastTerm && equal(term, lastTerm)) return;\n\n            $.data(this.container, \"select2-last-term\", term);\n\n            // if the search is currently hidden we do not alter the results\n            if (initial !== true && (this.showSearchInput === false || !this.opened())) {\n                return;\n            }\n\n            function postRender() {\n                search.removeClass(\"select2-active\");\n                self.positionDropdown();\n                if (results.find('.select2-no-results,.select2-selection-limit,.select2-searching').length) {\n                    self.liveRegion.text(results.text());\n                }\n                else {\n                    self.liveRegion.text(self.opts.formatMatches(results.find('.select2-result-selectable:not(\".select2-selected\")').length));\n                }\n            }\n\n            function render(html) {\n                results.html(html);\n                postRender();\n            }\n\n            queryNumber = ++this.queryCount;\n\n            var maxSelSize = this.getMaximumSelectionSize();\n            if (maxSelSize >=1) {\n                data = this.data();\n                if ($.isArray(data) && data.length >= maxSelSize && checkFormatter(opts.formatSelectionTooBig, \"formatSelectionTooBig\")) {\n                    render(\"<li class='select2-selection-limit'>\" + evaluate(opts.formatSelectionTooBig, opts.element, maxSelSize) + \"</li>\");\n                    return;\n                }\n            }\n\n            if (search.val().length < opts.minimumInputLength) {\n                if (checkFormatter(opts.formatInputTooShort, \"formatInputTooShort\")) {\n                    render(\"<li class='select2-no-results'>\" + evaluate(opts.formatInputTooShort, opts.element, search.val(), opts.minimumInputLength) + \"</li>\");\n                } else {\n                    render(\"\");\n                }\n                if (initial && this.showSearch) this.showSearch(true);\n                return;\n            }\n\n            if (opts.maximumInputLength && search.val().length > opts.maximumInputLength) {\n                if (checkFormatter(opts.formatInputTooLong, \"formatInputTooLong\")) {\n                    render(\"<li class='select2-no-results'>\" + evaluate(opts.formatInputTooLong, opts.element, search.val(), opts.maximumInputLength) + \"</li>\");\n                } else {\n                    render(\"\");\n                }\n                return;\n            }\n\n            if (opts.formatSearching && this.findHighlightableChoices().length === 0) {\n                render(\"<li class='select2-searching'>\" + evaluate(opts.formatSearching, opts.element) + \"</li>\");\n            }\n\n            search.addClass(\"select2-active\");\n\n            this.removeHighlight();\n\n            // give the tokenizer a chance to pre-process the input\n            input = this.tokenize();\n            if (input != undefined && input != null) {\n                search.val(input);\n            }\n\n            this.resultsPage = 1;\n\n            opts.query({\n                element: opts.element,\n                    term: search.val(),\n                    page: this.resultsPage,\n                    context: null,\n                    matcher: opts.matcher,\n                    callback: this.bind(function (data) {\n                var def; // default choice\n\n                // ignore old responses\n                if (queryNumber != this.queryCount) {\n                  return;\n                }\n\n                // ignore a response if the select2 has been closed before it was received\n                if (!this.opened()) {\n                    this.search.removeClass(\"select2-active\");\n                    return;\n                }\n\n                // handle ajax error\n                if(data.hasError !== undefined && checkFormatter(opts.formatAjaxError, \"formatAjaxError\")) {\n                    render(\"<li class='select2-ajax-error'>\" + evaluate(opts.formatAjaxError, opts.element, data.jqXHR, data.textStatus, data.errorThrown) + \"</li>\");\n                    return;\n                }\n\n                // save context, if any\n                this.context = (data.context===undefined) ? null : data.context;\n                // create a default choice and prepend it to the list\n                if (this.opts.createSearchChoice && search.val() !== \"\") {\n                    def = this.opts.createSearchChoice.call(self, search.val(), data.results);\n                    if (def !== undefined && def !== null && self.id(def) !== undefined && self.id(def) !== null) {\n                        if ($(data.results).filter(\n                            function () {\n                                return equal(self.id(this), self.id(def));\n                            }).length === 0) {\n                            this.opts.createSearchChoicePosition(data.results, def);\n                        }\n                    }\n                }\n\n                if (data.results.length === 0 && checkFormatter(opts.formatNoMatches, \"formatNoMatches\")) {\n                    render(\"<li class='select2-no-results'>\" + evaluate(opts.formatNoMatches, opts.element, search.val()) + \"</li>\");\n                    if(this.showSearch){\n                        this.showSearch(search.val());\n                    }\n                    return;\n                }\n\n                results.empty();\n                self.opts.populateResults.call(this, results, data.results, {term: search.val(), page: this.resultsPage, context:null});\n\n                if (data.more === true && checkFormatter(opts.formatLoadMore, \"formatLoadMore\")) {\n                    results.append(\"<li class='select2-more-results'>\" + opts.escapeMarkup(evaluate(opts.formatLoadMore, opts.element, this.resultsPage)) + \"</li>\");\n                    window.setTimeout(function() { self.loadMoreIfNeeded(); }, 10);\n                }\n\n                this.postprocessResults(data, initial);\n\n                postRender();\n\n                this.opts.element.trigger({ type: \"select2-loaded\", items: data });\n            })});\n        },\n\n        // abstract\n        cancel: function () {\n            this.close();\n        },\n\n        // abstract\n        blur: function () {\n            // if selectOnBlur == true, select the currently highlighted option\n            if (this.opts.selectOnBlur)\n                this.selectHighlighted({noFocus: true});\n\n            this.close();\n            this.container.removeClass(\"select2-container-active\");\n            // synonymous to .is(':focus'), which is available in jquery >= 1.6\n            if (this.search[0] === document.activeElement) { this.search.blur(); }\n            this.clearSearch();\n            this.selection.find(\".select2-search-choice-focus\").removeClass(\"select2-search-choice-focus\");\n        },\n\n        // abstract\n        focusSearch: function () {\n            focus(this.search);\n        },\n\n        // abstract\n        selectHighlighted: function (options) {\n            if (this._touchMoved) {\n              this.clearTouchMoved();\n              return;\n            }\n            var index=this.highlight(),\n                highlighted=this.results.find(\".select2-highlighted\"),\n                data = highlighted.closest('.select2-result').data(\"select2-data\");\n\n            if (data) {\n                this.highlight(index);\n                this.onSelect(data, options);\n            } else if (options && options.noFocus) {\n                this.close();\n            }\n        },\n\n        // abstract\n        getPlaceholder: function () {\n            var placeholderOption;\n            return this.opts.element.attr(\"placeholder\") ||\n                this.opts.element.attr(\"data-placeholder\") || // jquery 1.4 compat\n                this.opts.element.data(\"placeholder\") ||\n                this.opts.placeholder ||\n                ((placeholderOption = this.getPlaceholderOption()) !== undefined ? placeholderOption.text() : undefined);\n        },\n\n        // abstract\n        getPlaceholderOption: function() {\n            if (this.select) {\n                var firstOption = this.select.children('option').first();\n                if (this.opts.placeholderOption !== undefined ) {\n                    //Determine the placeholder option based on the specified placeholderOption setting\n                    return (this.opts.placeholderOption === \"first\" && firstOption) ||\n                           (typeof this.opts.placeholderOption === \"function\" && this.opts.placeholderOption(this.select));\n                } else if ($.trim(firstOption.text()) === \"\" && firstOption.val() === \"\") {\n                    //No explicit placeholder option specified, use the first if it's blank\n                    return firstOption;\n                }\n            }\n        },\n\n        /**\n         * Get the desired width for the container element.  This is\n         * derived first from option `width` passed to select2, then\n         * the inline 'style' on the original element, and finally\n         * falls back to the jQuery calculated element width.\n         */\n        // abstract\n        initContainerWidth: function () {\n            function resolveContainerWidth() {\n                var style, attrs, matches, i, l, attr;\n\n                if (this.opts.width === \"off\") {\n                    return null;\n                } else if (this.opts.width === \"element\"){\n                    return this.opts.element.outerWidth(false) === 0 ? 'auto' : this.opts.element.outerWidth(false) + 'px';\n                } else if (this.opts.width === \"copy\" || this.opts.width === \"resolve\") {\n                    // check if there is inline style on the element that contains width\n                    style = this.opts.element.attr('style');\n                    if (typeof(style) === \"string\") {\n                        attrs = style.split(';');\n                        for (i = 0, l = attrs.length; i < l; i = i + 1) {\n                            attr = attrs[i].replace(/\\s/g, '');\n                            matches = attr.match(/^width:(([-+]?([0-9]*\\.)?[0-9]+)(px|em|ex|%|in|cm|mm|pt|pc))/i);\n                            if (matches !== null && matches.length >= 1)\n                                return matches[1];\n                        }\n                    }\n\n                    if (this.opts.width === \"resolve\") {\n                        // next check if css('width') can resolve a width that is percent based, this is sometimes possible\n                        // when attached to input type=hidden or elements hidden via css\n                        style = this.opts.element.css('width');\n                        if (style.indexOf(\"%\") > 0) return style;\n\n                        // finally, fallback on the calculated width of the element\n                        return (this.opts.element.outerWidth(false) === 0 ? 'auto' : this.opts.element.outerWidth(false) + 'px');\n                    }\n\n                    return null;\n                } else if ($.isFunction(this.opts.width)) {\n                    return this.opts.width();\n                } else {\n                    return this.opts.width;\n               }\n            };\n\n            var width = resolveContainerWidth.call(this);\n            if (width !== null) {\n                this.container.css(\"width\", width);\n            }\n        }\n    });\n\n    SingleSelect2 = clazz(AbstractSelect2, {\n\n        // single\n\n        createContainer: function () {\n            var container = $(document.createElement(\"div\")).attr({\n                \"class\": \"select2-container\"\n            }).html([\n                \"<a href='javascript:void(0)' class='select2-choice' tabindex='-1'>\",\n                \"   <span class='select2-chosen'>&#160;</span><abbr class='select2-search-choice-close'></abbr>\",\n                \"   <span class='select2-arrow' role='presentation'><b role='presentation'></b></span>\",\n                \"</a>\",\n                \"<label for='' class='select2-offscreen'></label>\",\n                \"<input class='select2-focusser select2-offscreen' type='text' aria-haspopup='true' role='button' />\",\n                \"<div class='select2-drop select2-display-none'>\",\n                \"   <div class='select2-search'>\",\n                \"       <label for='' class='select2-offscreen'></label>\",\n                \"       <input type='text' autocomplete='off' autocorrect='off' autocapitalize='off' spellcheck='false' class='select2-input' role='combobox' aria-expanded='true'\",\n                \"       aria-autocomplete='list' />\",\n                \"   </div>\",\n                \"   <ul class='select2-results' role='listbox'>\",\n                \"   </ul>\",\n                \"</div>\"].join(\"\"));\n            return container;\n        },\n\n        // single\n        enableInterface: function() {\n            if (this.parent.enableInterface.apply(this, arguments)) {\n                this.focusser.prop(\"disabled\", !this.isInterfaceEnabled());\n            }\n        },\n\n        // single\n        opening: function () {\n            var el, range, len;\n\n            if (this.opts.minimumResultsForSearch >= 0) {\n                this.showSearch(true);\n            }\n\n            this.parent.opening.apply(this, arguments);\n\n            if (this.showSearchInput !== false) {\n                // IE appends focusser.val() at the end of field :/ so we manually insert it at the beginning using a range\n                // all other browsers handle this just fine\n\n                this.search.val(this.focusser.val());\n            }\n            if (this.opts.shouldFocusInput(this)) {\n                this.search.focus();\n                // move the cursor to the end after focussing, otherwise it will be at the beginning and\n                // new text will appear *before* focusser.val()\n                el = this.search.get(0);\n                if (el.createTextRange) {\n                    range = el.createTextRange();\n                    range.collapse(false);\n                    range.select();\n                } else if (el.setSelectionRange) {\n                    len = this.search.val().length;\n                    el.setSelectionRange(len, len);\n                }\n            }\n\n            this.prefillNextSearchTerm();\n\n            this.focusser.prop(\"disabled\", true).val(\"\");\n            this.updateResults(true);\n            this.opts.element.trigger($.Event(\"select2-open\"));\n        },\n\n        // single\n        close: function () {\n            if (!this.opened()) return;\n            this.parent.close.apply(this, arguments);\n\n            this.focusser.prop(\"disabled\", false);\n\n            if (this.opts.shouldFocusInput(this)) {\n                this.focusser.focus();\n            }\n        },\n\n        // single\n        focus: function () {\n            if (this.opened()) {\n                this.close();\n            } else {\n                this.focusser.prop(\"disabled\", false);\n                if (this.opts.shouldFocusInput(this)) {\n                    this.focusser.focus();\n                }\n            }\n        },\n\n        // single\n        isFocused: function () {\n            return this.container.hasClass(\"select2-container-active\");\n        },\n\n        // single\n        cancel: function () {\n            this.parent.cancel.apply(this, arguments);\n            this.focusser.prop(\"disabled\", false);\n\n            if (this.opts.shouldFocusInput(this)) {\n                this.focusser.focus();\n            }\n        },\n\n        // single\n        destroy: function() {\n            $(\"label[for='\" + this.focusser.attr('id') + \"']\")\n                .attr('for', this.opts.element.attr(\"id\"));\n            this.parent.destroy.apply(this, arguments);\n\n            cleanupJQueryElements.call(this,\n                \"selection\",\n                \"focusser\"\n            );\n        },\n\n        // single\n        initContainer: function () {\n\n            var selection,\n                container = this.container,\n                dropdown = this.dropdown,\n                idSuffix = nextUid(),\n                elementLabel;\n\n            if (this.opts.minimumResultsForSearch < 0) {\n                this.showSearch(false);\n            } else {\n                this.showSearch(true);\n            }\n\n            this.selection = selection = container.find(\".select2-choice\");\n\n            this.focusser = container.find(\".select2-focusser\");\n\n            // add aria associations\n            selection.find(\".select2-chosen\").attr(\"id\", \"select2-chosen-\"+idSuffix);\n            this.focusser.attr(\"aria-labelledby\", \"select2-chosen-\"+idSuffix);\n            this.results.attr(\"id\", \"select2-results-\"+idSuffix);\n            this.search.attr(\"aria-owns\", \"select2-results-\"+idSuffix);\n\n            // rewrite labels from original element to focusser\n            this.focusser.attr(\"id\", \"s2id_autogen\"+idSuffix);\n\n            elementLabel = $(\"label[for='\" + this.opts.element.attr(\"id\") + \"']\");\n            this.opts.element.on('focus.select2', this.bind(function () { this.focus(); }));\n\n            this.focusser.prev()\n                .text(elementLabel.text())\n                .attr('for', this.focusser.attr('id'));\n\n            // Ensure the original element retains an accessible name\n            var originalTitle = this.opts.element.attr(\"title\");\n            this.opts.element.attr(\"title\", (originalTitle || elementLabel.text()));\n\n            this.focusser.attr(\"tabindex\", this.elementTabIndex);\n\n            // write label for search field using the label from the focusser element\n            this.search.attr(\"id\", this.focusser.attr('id') + '_search');\n\n            this.search.prev()\n                .text($(\"label[for='\" + this.focusser.attr('id') + \"']\").text())\n                .attr('for', this.search.attr('id'));\n\n            this.search.on(\"keydown\", this.bind(function (e) {\n                if (!this.isInterfaceEnabled()) return;\n\n                // filter 229 keyCodes (input method editor is processing key input)\n                if (229 == e.keyCode) return;\n\n                if (e.which === KEY.PAGE_UP || e.which === KEY.PAGE_DOWN) {\n                    // prevent the page from scrolling\n                    killEvent(e);\n                    return;\n                }\n\n                switch (e.which) {\n                    case KEY.UP:\n                    case KEY.DOWN:\n                        this.moveHighlight((e.which === KEY.UP) ? -1 : 1);\n                        killEvent(e);\n                        return;\n                    case KEY.ENTER:\n                        this.selectHighlighted();\n                        killEvent(e);\n                        return;\n                    case KEY.TAB:\n                        this.selectHighlighted({noFocus: true});\n                        return;\n                    case KEY.ESC:\n                        this.cancel(e);\n                        killEvent(e);\n                        return;\n                }\n            }));\n\n            this.search.on(\"blur\", this.bind(function(e) {\n                // a workaround for chrome to keep the search field focussed when the scroll bar is used to scroll the dropdown.\n                // without this the search field loses focus which is annoying\n                if (document.activeElement === this.body.get(0)) {\n                    window.setTimeout(this.bind(function() {\n                        if (this.opened() && this.results && this.results.length > 1) {\n                            this.search.focus();\n                        }\n                    }), 0);\n                }\n            }));\n\n            this.focusser.on(\"keydown\", this.bind(function (e) {\n                if (!this.isInterfaceEnabled()) return;\n\n                if (e.which === KEY.TAB || KEY.isControl(e) || KEY.isFunctionKey(e) || e.which === KEY.ESC) {\n                    return;\n                }\n\n                if (this.opts.openOnEnter === false && e.which === KEY.ENTER) {\n                    killEvent(e);\n                    return;\n                }\n\n                if (e.which == KEY.DOWN || e.which == KEY.UP\n                    || (e.which == KEY.ENTER && this.opts.openOnEnter)) {\n\n                    if (e.altKey || e.ctrlKey || e.shiftKey || e.metaKey) return;\n\n                    this.open();\n                    killEvent(e);\n                    return;\n                }\n\n                if (e.which == KEY.DELETE || e.which == KEY.BACKSPACE) {\n                    if (this.opts.allowClear) {\n                        this.clear();\n                    }\n                    killEvent(e);\n                    return;\n                }\n            }));\n\n\n            installKeyUpChangeEvent(this.focusser);\n            this.focusser.on(\"keyup-change input\", this.bind(function(e) {\n                if (this.opts.minimumResultsForSearch >= 0) {\n                    e.stopPropagation();\n                    if (this.opened()) return;\n                    this.open();\n                }\n            }));\n\n            selection.on(\"mousedown touchstart\", \"abbr\", this.bind(function (e) {\n                if (!this.isInterfaceEnabled()) {\n                    return;\n                }\n\n                this.clear();\n                killEventImmediately(e);\n                this.close();\n\n                if (this.selection) {\n                    this.selection.focus();\n                }\n            }));\n\n            selection.on(\"mousedown touchstart\", this.bind(function (e) {\n                // Prevent IE from generating a click event on the body\n                reinsertElement(selection);\n\n                if (!this.container.hasClass(\"select2-container-active\")) {\n                    this.opts.element.trigger($.Event(\"select2-focus\"));\n                }\n\n                if (this.opened()) {\n                    this.close();\n                } else if (this.isInterfaceEnabled()) {\n                    this.open();\n                }\n\n                killEvent(e);\n            }));\n\n            dropdown.on(\"mousedown touchstart\", this.bind(function() {\n                if (this.opts.shouldFocusInput(this)) {\n                    this.search.focus();\n                }\n            }));\n\n            selection.on(\"focus\", this.bind(function(e) {\n                killEvent(e);\n            }));\n\n            this.focusser.on(\"focus\", this.bind(function(){\n                if (!this.container.hasClass(\"select2-container-active\")) {\n                    this.opts.element.trigger($.Event(\"select2-focus\"));\n                }\n                this.container.addClass(\"select2-container-active\");\n            })).on(\"blur\", this.bind(function() {\n                if (!this.opened()) {\n                    this.container.removeClass(\"select2-container-active\");\n                    this.opts.element.trigger($.Event(\"select2-blur\"));\n                }\n            }));\n            this.search.on(\"focus\", this.bind(function(){\n                if (!this.container.hasClass(\"select2-container-active\")) {\n                    this.opts.element.trigger($.Event(\"select2-focus\"));\n                }\n                this.container.addClass(\"select2-container-active\");\n            }));\n\n            this.initContainerWidth();\n            this.opts.element.hide();\n            this.setPlaceholder();\n\n        },\n\n        // single\n        clear: function(triggerChange) {\n            var data=this.selection.data(\"select2-data\");\n            if (data) { // guard against queued quick consecutive clicks\n                var evt = $.Event(\"select2-clearing\");\n                this.opts.element.trigger(evt);\n                if (evt.isDefaultPrevented()) {\n                    return;\n                }\n                var placeholderOption = this.getPlaceholderOption();\n                this.opts.element.val(placeholderOption ? placeholderOption.val() : \"\");\n                this.selection.find(\".select2-chosen\").empty();\n                this.selection.removeData(\"select2-data\");\n                this.setPlaceholder();\n\n                if (triggerChange !== false){\n                    this.opts.element.trigger({ type: \"select2-removed\", val: this.id(data), choice: data });\n                    this.triggerChange({removed:data});\n                }\n            }\n        },\n\n        /**\n         * Sets selection based on source element's value\n         */\n        // single\n        initSelection: function () {\n            var selected;\n            if (this.isPlaceholderOptionSelected()) {\n                this.updateSelection(null);\n                this.close();\n                this.setPlaceholder();\n            } else {\n                var self = this;\n                this.opts.initSelection.call(null, this.opts.element, function(selected){\n                    if (selected !== undefined && selected !== null) {\n                        self.updateSelection(selected);\n                        self.close();\n                        self.setPlaceholder();\n                        self.lastSearchTerm = self.search.val();\n                    }\n                });\n            }\n        },\n\n        isPlaceholderOptionSelected: function() {\n            var placeholderOption;\n            if (this.getPlaceholder() === undefined) return false; // no placeholder specified so no option should be considered\n            return ((placeholderOption = this.getPlaceholderOption()) !== undefined && placeholderOption.prop(\"selected\"))\n                || (this.opts.element.val() === \"\")\n                || (this.opts.element.val() === undefined)\n                || (this.opts.element.val() === null);\n        },\n\n        // single\n        prepareOpts: function () {\n            var opts = this.parent.prepareOpts.apply(this, arguments),\n                self=this;\n\n            if (opts.element.get(0).tagName.toLowerCase() === \"select\") {\n                // install the selection initializer\n                opts.initSelection = function (element, callback) {\n                    var selected = element.find(\"option\").filter(function() { return this.selected && !this.disabled });\n                    // a single select box always has a value, no need to null check 'selected'\n                    callback(self.optionToData(selected));\n                };\n            } else if (\"data\" in opts) {\n                // install default initSelection when applied to hidden input and data is local\n                opts.initSelection = opts.initSelection || function (element, callback) {\n                    var id = element.val();\n                    //search in data by id, storing the actual matching item\n                    var match = null;\n                    opts.query({\n                        matcher: function(term, text, el){\n                            var is_match = equal(id, opts.id(el));\n                            if (is_match) {\n                                match = el;\n                            }\n                            return is_match;\n                        },\n                        callback: !$.isFunction(callback) ? $.noop : function() {\n                            callback(match);\n                        }\n                    });\n                };\n            }\n\n            return opts;\n        },\n\n        // single\n        getPlaceholder: function() {\n            // if a placeholder is specified on a single select without a valid placeholder option ignore it\n            if (this.select) {\n                if (this.getPlaceholderOption() === undefined) {\n                    return undefined;\n                }\n            }\n\n            return this.parent.getPlaceholder.apply(this, arguments);\n        },\n\n        // single\n        setPlaceholder: function () {\n            var placeholder = this.getPlaceholder();\n\n            if (this.isPlaceholderOptionSelected() && placeholder !== undefined) {\n\n                // check for a placeholder option if attached to a select\n                if (this.select && this.getPlaceholderOption() === undefined) return;\n\n                this.selection.find(\".select2-chosen\").html(this.opts.escapeMarkup(placeholder));\n\n                this.selection.addClass(\"select2-default\");\n\n                this.container.removeClass(\"select2-allowclear\");\n            }\n        },\n\n        // single\n        postprocessResults: function (data, initial, noHighlightUpdate) {\n            var selected = 0, self = this, showSearchInput = true;\n\n            // find the selected element in the result list\n\n            this.findHighlightableChoices().each2(function (i, elm) {\n                if (equal(self.id(elm.data(\"select2-data\")), self.opts.element.val())) {\n                    selected = i;\n                    return false;\n                }\n            });\n\n            // and highlight it\n            if (noHighlightUpdate !== false) {\n                if (initial === true && selected >= 0) {\n                    this.highlight(selected);\n                } else {\n                    this.highlight(0);\n                }\n            }\n\n            // hide the search box if this is the first we got the results and there are enough of them for search\n\n            if (initial === true) {\n                var min = this.opts.minimumResultsForSearch;\n                if (min >= 0) {\n                    this.showSearch(countResults(data.results) >= min);\n                }\n            }\n        },\n\n        // single\n        showSearch: function(showSearchInput) {\n            if (this.showSearchInput === showSearchInput) return;\n\n            this.showSearchInput = showSearchInput;\n\n            this.dropdown.find(\".select2-search\").toggleClass(\"select2-search-hidden\", !showSearchInput);\n            this.dropdown.find(\".select2-search\").toggleClass(\"select2-offscreen\", !showSearchInput);\n            //add \"select2-with-searchbox\" to the container if search box is shown\n            $(this.dropdown, this.container).toggleClass(\"select2-with-searchbox\", showSearchInput);\n        },\n\n        // single\n        onSelect: function (data, options) {\n\n            if (!this.triggerSelect(data)) { return; }\n\n            var old = this.opts.element.val(),\n                oldData = this.data();\n\n            this.opts.element.val(this.id(data));\n            this.updateSelection(data);\n\n            this.opts.element.trigger({ type: \"select2-selected\", val: this.id(data), choice: data });\n\n            this.lastSearchTerm = this.search.val();\n            this.close();\n\n            if ((!options || !options.noFocus) && this.opts.shouldFocusInput(this)) {\n                this.focusser.focus();\n            }\n\n            if (!equal(old, this.id(data))) {\n                this.triggerChange({ added: data, removed: oldData });\n            }\n        },\n\n        // single\n        updateSelection: function (data) {\n\n            var container=this.selection.find(\".select2-chosen\"), formatted, cssClass;\n\n            this.selection.data(\"select2-data\", data);\n\n            container.empty();\n            if (data !== null) {\n                formatted=this.opts.formatSelection(data, container, this.opts.escapeMarkup);\n            }\n            if (formatted !== undefined) {\n                container.append(formatted);\n            }\n            cssClass=this.opts.formatSelectionCssClass(data, container);\n            if (cssClass !== undefined) {\n                container.addClass(cssClass);\n            }\n\n            this.selection.removeClass(\"select2-default\");\n\n            if (this.opts.allowClear && this.getPlaceholder() !== undefined) {\n                this.container.addClass(\"select2-allowclear\");\n            }\n        },\n\n        // single\n        val: function () {\n            var val,\n                triggerChange = false,\n                data = null,\n                self = this,\n                oldData = this.data();\n\n            if (arguments.length === 0) {\n                return this.opts.element.val();\n            }\n\n            val = arguments[0];\n\n            if (arguments.length > 1) {\n                triggerChange = arguments[1];\n\n                if (this.opts.debug && console && console.warn) {\n                    console.warn(\n                        'Select2: The second option to `select2(\"val\")` is not supported in Select2 4.0.0. ' +\n                        'The `change` event will always be triggered in 4.0.0.'\n                    );\n                }\n            }\n\n            if (this.select) {\n                if (this.opts.debug && console && console.warn) {\n                    console.warn(\n                        'Select2: Setting the value on a <select> using `select2(\"val\")` is no longer supported in 4.0.0. ' +\n                        'You can use the `.val(newValue).trigger(\"change\")` method provided by jQuery instead.'\n                    );\n                }\n\n                this.select\n                    .val(val)\n                    .find(\"option\").filter(function() { return this.selected }).each2(function (i, elm) {\n                        data = self.optionToData(elm);\n                        return false;\n                    });\n                this.updateSelection(data);\n                this.setPlaceholder();\n                if (triggerChange) {\n                    this.triggerChange({added: data, removed:oldData});\n                }\n            } else {\n                // val is an id. !val is true for [undefined,null,'',0] - 0 is legal\n                if (!val && val !== 0) {\n                    this.clear(triggerChange);\n                    return;\n                }\n                if (this.opts.initSelection === undefined) {\n                    throw new Error(\"cannot call val() if initSelection() is not defined\");\n                }\n                this.opts.element.val(val);\n                this.opts.initSelection(this.opts.element, function(data){\n                    self.opts.element.val(!data ? \"\" : self.id(data));\n                    self.updateSelection(data);\n                    self.setPlaceholder();\n                    if (triggerChange) {\n                        self.triggerChange({added: data, removed:oldData});\n                    }\n                });\n            }\n        },\n\n        // single\n        clearSearch: function () {\n            this.search.val(\"\");\n            this.focusser.val(\"\");\n        },\n\n        // single\n        data: function(value) {\n            var data,\n                triggerChange = false;\n\n            if (arguments.length === 0) {\n                data = this.selection.data(\"select2-data\");\n                if (data == undefined) data = null;\n                return data;\n            } else {\n                if (this.opts.debug && console && console.warn) {\n                    console.warn(\n                        'Select2: The `select2(\"data\")` method can no longer set selected values in 4.0.0, ' +\n                        'consider using the `.val()` method instead.'\n                    );\n                }\n\n                if (arguments.length > 1) {\n                    triggerChange = arguments[1];\n                }\n                if (!value) {\n                    this.clear(triggerChange);\n                } else {\n                    data = this.data();\n                    this.opts.element.val(!value ? \"\" : this.id(value));\n                    this.updateSelection(value);\n                    if (triggerChange) {\n                        this.triggerChange({added: value, removed:data});\n                    }\n                }\n            }\n        }\n    });\n\n    MultiSelect2 = clazz(AbstractSelect2, {\n\n        // multi\n        createContainer: function () {\n            var container = $(document.createElement(\"div\")).attr({\n                \"class\": \"select2-container select2-container-multi\"\n            }).html([\n                \"<ul class='select2-choices'>\",\n                \"  <li class='select2-search-field'>\",\n                \"    <label for='' class='select2-offscreen'></label>\",\n                \"    <input type='text' autocomplete='off' autocorrect='off' autocapitalize='off' spellcheck='false' class='select2-input'>\",\n                \"  </li>\",\n                \"</ul>\",\n                \"<div class='select2-drop select2-drop-multi select2-display-none'>\",\n                \"   <ul class='select2-results'>\",\n                \"   </ul>\",\n                \"</div>\"].join(\"\"));\n            return container;\n        },\n\n        // multi\n        prepareOpts: function () {\n            var opts = this.parent.prepareOpts.apply(this, arguments),\n                self=this;\n\n            // TODO validate placeholder is a string if specified\n            if (opts.element.get(0).tagName.toLowerCase() === \"select\") {\n                // install the selection initializer\n                opts.initSelection = function (element, callback) {\n\n                    var data = [];\n\n                    element.find(\"option\").filter(function() { return this.selected && !this.disabled }).each2(function (i, elm) {\n                        data.push(self.optionToData(elm));\n                    });\n                    callback(data);\n                };\n            } else if (\"data\" in opts) {\n                // install default initSelection when applied to hidden input and data is local\n                opts.initSelection = opts.initSelection || function (element, callback) {\n                    var ids = splitVal(element.val(), opts.separator, opts.transformVal);\n                    //search in data by array of ids, storing matching items in a list\n                    var matches = [];\n                    opts.query({\n                        matcher: function(term, text, el){\n                            var is_match = $.grep(ids, function(id) {\n                                return equal(id, opts.id(el));\n                            }).length;\n                            if (is_match) {\n                                matches.push(el);\n                            }\n                            return is_match;\n                        },\n                        callback: !$.isFunction(callback) ? $.noop : function() {\n                            // reorder matches based on the order they appear in the ids array because right now\n                            // they are in the order in which they appear in data array\n                            var ordered = [];\n                            for (var i = 0; i < ids.length; i++) {\n                                var id = ids[i];\n                                for (var j = 0; j < matches.length; j++) {\n                                    var match = matches[j];\n                                    if (equal(id, opts.id(match))) {\n                                        ordered.push(match);\n                                        matches.splice(j, 1);\n                                        break;\n                                    }\n                                }\n                            }\n                            callback(ordered);\n                        }\n                    });\n                };\n            }\n\n            return opts;\n        },\n\n        // multi\n        selectChoice: function (choice) {\n\n            var selected = this.container.find(\".select2-search-choice-focus\");\n            if (selected.length && choice && choice[0] == selected[0]) {\n\n            } else {\n                if (selected.length) {\n                    this.opts.element.trigger(\"choice-deselected\", selected);\n                }\n                selected.removeClass(\"select2-search-choice-focus\");\n                if (choice && choice.length) {\n                    this.close();\n                    choice.addClass(\"select2-search-choice-focus\");\n                    this.opts.element.trigger(\"choice-selected\", choice);\n                }\n            }\n        },\n\n        // multi\n        destroy: function() {\n            $(\"label[for='\" + this.search.attr('id') + \"']\")\n                .attr('for', this.opts.element.attr(\"id\"));\n            this.parent.destroy.apply(this, arguments);\n\n            cleanupJQueryElements.call(this,\n                \"searchContainer\",\n                \"selection\"\n            );\n        },\n\n        // multi\n        initContainer: function () {\n\n            var selector = \".select2-choices\", selection;\n\n            this.searchContainer = this.container.find(\".select2-search-field\");\n            this.selection = selection = this.container.find(selector);\n\n            var _this = this;\n            this.selection.on(\"click\", \".select2-container:not(.select2-container-disabled) .select2-search-choice:not(.select2-locked)\", function (e) {\n                _this.search[0].focus();\n                _this.selectChoice($(this));\n            });\n\n            // rewrite labels from original element to focusser\n            this.search.attr(\"id\", \"s2id_autogen\"+nextUid());\n\n            this.search.prev()\n                .text($(\"label[for='\" + this.opts.element.attr(\"id\") + \"']\").text())\n                .attr('for', this.search.attr('id'));\n            this.opts.element.on('focus.select2', this.bind(function () { this.focus(); }));\n\n            this.search.on(\"input paste\", this.bind(function() {\n                if (this.search.attr('placeholder') && this.search.val().length == 0) return;\n                if (!this.isInterfaceEnabled()) return;\n                if (!this.opened()) {\n                    this.open();\n                }\n            }));\n\n            this.search.attr(\"tabindex\", this.elementTabIndex);\n\n            this.keydowns = 0;\n            this.search.on(\"keydown\", this.bind(function (e) {\n                if (!this.isInterfaceEnabled()) return;\n\n                ++this.keydowns;\n                var selected = selection.find(\".select2-search-choice-focus\");\n                var prev = selected.prev(\".select2-search-choice:not(.select2-locked)\");\n                var next = selected.next(\".select2-search-choice:not(.select2-locked)\");\n                var pos = getCursorInfo(this.search);\n\n                if (selected.length &&\n                    (e.which == KEY.LEFT || e.which == KEY.RIGHT || e.which == KEY.BACKSPACE || e.which == KEY.DELETE || e.which == KEY.ENTER)) {\n                    var selectedChoice = selected;\n                    if (e.which == KEY.LEFT && prev.length) {\n                        selectedChoice = prev;\n                    }\n                    else if (e.which == KEY.RIGHT) {\n                        selectedChoice = next.length ? next : null;\n                    }\n                    else if (e.which === KEY.BACKSPACE) {\n                        if (this.unselect(selected.first())) {\n                            this.search.width(10);\n                            selectedChoice = prev.length ? prev : next;\n                        }\n                    } else if (e.which == KEY.DELETE) {\n                        if (this.unselect(selected.first())) {\n                            this.search.width(10);\n                            selectedChoice = next.length ? next : null;\n                        }\n                    } else if (e.which == KEY.ENTER) {\n                        selectedChoice = null;\n                    }\n\n                    this.selectChoice(selectedChoice);\n                    killEvent(e);\n                    if (!selectedChoice || !selectedChoice.length) {\n                        this.open();\n                    }\n                    return;\n                } else if (((e.which === KEY.BACKSPACE && this.keydowns == 1)\n                    || e.which == KEY.LEFT) && (pos.offset == 0 && !pos.length)) {\n\n                    this.selectChoice(selection.find(\".select2-search-choice:not(.select2-locked)\").last());\n                    killEvent(e);\n                    return;\n                } else {\n                    this.selectChoice(null);\n                }\n\n                if (this.opened()) {\n                    switch (e.which) {\n                    case KEY.UP:\n                    case KEY.DOWN:\n                        this.moveHighlight((e.which === KEY.UP) ? -1 : 1);\n                        killEvent(e);\n                        return;\n                    case KEY.ENTER:\n                        this.selectHighlighted();\n                        killEvent(e);\n                        return;\n                    case KEY.TAB:\n                        this.selectHighlighted({noFocus:true});\n                        this.close();\n                        return;\n                    case KEY.ESC:\n                        this.cancel(e);\n                        killEvent(e);\n                        return;\n                    }\n                }\n\n                if (e.which === KEY.TAB || KEY.isControl(e) || KEY.isFunctionKey(e)\n                 || e.which === KEY.BACKSPACE || e.which === KEY.ESC) {\n                    return;\n                }\n\n                if (e.which === KEY.ENTER) {\n                    if (this.opts.openOnEnter === false) {\n                        return;\n                    } else if (e.altKey || e.ctrlKey || e.shiftKey || e.metaKey) {\n                        return;\n                    }\n                }\n\n                this.open();\n\n                if (e.which === KEY.PAGE_UP || e.which === KEY.PAGE_DOWN) {\n                    // prevent the page from scrolling\n                    killEvent(e);\n                }\n\n                if (e.which === KEY.ENTER) {\n                    // prevent form from being submitted\n                    killEvent(e);\n                }\n\n            }));\n\n            this.search.on(\"keyup\", this.bind(function (e) {\n                this.keydowns = 0;\n                this.resizeSearch();\n            })\n            );\n\n            this.search.on(\"blur\", this.bind(function(e) {\n                this.container.removeClass(\"select2-container-active\");\n                this.search.removeClass(\"select2-focused\");\n                this.selectChoice(null);\n                if (!this.opened()) this.clearSearch();\n                e.stopImmediatePropagation();\n                this.opts.element.trigger($.Event(\"select2-blur\"));\n            }));\n\n            this.container.on(\"click\", selector, this.bind(function (e) {\n                if (!this.isInterfaceEnabled()) return;\n                if ($(e.target).closest(\".select2-search-choice\").length > 0) {\n                    // clicked inside a select2 search choice, do not open\n                    return;\n                }\n                this.selectChoice(null);\n                this.clearPlaceholder();\n                if (!this.container.hasClass(\"select2-container-active\")) {\n                    this.opts.element.trigger($.Event(\"select2-focus\"));\n                }\n                this.open();\n                this.focusSearch();\n                e.preventDefault();\n            }));\n\n            this.container.on(\"focus\", selector, this.bind(function () {\n                if (!this.isInterfaceEnabled()) return;\n                if (!this.container.hasClass(\"select2-container-active\")) {\n                    this.opts.element.trigger($.Event(\"select2-focus\"));\n                }\n                this.container.addClass(\"select2-container-active\");\n                this.dropdown.addClass(\"select2-drop-active\");\n                this.clearPlaceholder();\n            }));\n\n            this.initContainerWidth();\n            this.opts.element.hide();\n\n            // set the placeholder if necessary\n            this.clearSearch();\n        },\n\n        // multi\n        enableInterface: function() {\n            if (this.parent.enableInterface.apply(this, arguments)) {\n                this.search.prop(\"disabled\", !this.isInterfaceEnabled());\n            }\n        },\n\n        // multi\n        initSelection: function () {\n            var data;\n            if (this.opts.element.val() === \"\" && this.opts.element.text() === \"\") {\n                this.updateSelection([]);\n                this.close();\n                // set the placeholder if necessary\n                this.clearSearch();\n            }\n            if (this.select || this.opts.element.val() !== \"\") {\n                var self = this;\n                this.opts.initSelection.call(null, this.opts.element, function(data){\n                    if (data !== undefined && data !== null) {\n                        self.updateSelection(data);\n                        self.close();\n                        // set the placeholder if necessary\n                        self.clearSearch();\n                    }\n                });\n            }\n        },\n\n        // multi\n        clearSearch: function () {\n            var placeholder = this.getPlaceholder(),\n                maxWidth = this.getMaxSearchWidth();\n\n            if (placeholder !== undefined  && this.getVal().length === 0 && this.search.hasClass(\"select2-focused\") === false) {\n                this.search.val(placeholder).addClass(\"select2-default\");\n                // stretch the search box to full width of the container so as much of the placeholder is visible as possible\n                // we could call this.resizeSearch(), but we do not because that requires a sizer and we do not want to create one so early because of a firefox bug, see #944\n                this.search.width(maxWidth > 0 ? maxWidth : this.container.css(\"width\"));\n            } else {\n                this.search.val(\"\").width(10);\n            }\n        },\n\n        // multi\n        clearPlaceholder: function () {\n            if (this.search.hasClass(\"select2-default\")) {\n                this.search.val(\"\").removeClass(\"select2-default\");\n            }\n        },\n\n        // multi\n        opening: function () {\n            this.clearPlaceholder(); // should be done before super so placeholder is not used to search\n            this.resizeSearch();\n\n            this.parent.opening.apply(this, arguments);\n\n            this.focusSearch();\n\n            this.prefillNextSearchTerm();\n            this.updateResults(true);\n\n            if (this.opts.shouldFocusInput(this)) {\n                this.search.focus();\n            }\n            this.opts.element.trigger($.Event(\"select2-open\"));\n        },\n\n        // multi\n        close: function () {\n            if (!this.opened()) return;\n            this.parent.close.apply(this, arguments);\n        },\n\n        // multi\n        focus: function () {\n            this.close();\n            this.search.focus();\n        },\n\n        // multi\n        isFocused: function () {\n            return this.search.hasClass(\"select2-focused\");\n        },\n\n        // multi\n        updateSelection: function (data) {\n            var ids = {}, filtered = [], self = this;\n\n            // filter out duplicates\n            $(data).each(function () {\n                if (!(self.id(this) in ids)) {\n                    ids[self.id(this)] = 0;\n                    filtered.push(this);\n                }\n            });\n\n            this.selection.find(\".select2-search-choice\").remove();\n            this.addSelectedChoice(filtered);\n            self.postprocessResults();\n        },\n\n        // multi\n        tokenize: function() {\n            var input = this.search.val();\n            input = this.opts.tokenizer.call(this, input, this.data(), this.bind(this.onSelect), this.opts);\n            if (input != null && input != undefined) {\n                this.search.val(input);\n                if (input.length > 0) {\n                    this.open();\n                }\n            }\n\n        },\n\n        // multi\n        onSelect: function (data, options) {\n\n            if (!this.triggerSelect(data) || data.text === \"\") { return; }\n\n            this.addSelectedChoice(data);\n\n            this.opts.element.trigger({ type: \"selected\", val: this.id(data), choice: data });\n\n            // keep track of the search's value before it gets cleared\n            this.lastSearchTerm = this.search.val();\n\n            this.clearSearch();\n            this.updateResults();\n\n            if (this.select || !this.opts.closeOnSelect) this.postprocessResults(data, false, this.opts.closeOnSelect===true);\n\n            if (this.opts.closeOnSelect) {\n                this.close();\n                this.search.width(10);\n            } else {\n                if (this.countSelectableResults()>0) {\n                    this.search.width(10);\n                    this.resizeSearch();\n                    if (this.getMaximumSelectionSize() > 0 && this.val().length >= this.getMaximumSelectionSize()) {\n                        // if we reached max selection size repaint the results so choices\n                        // are replaced with the max selection reached message\n                        this.updateResults(true);\n                    } else {\n                        // initializes search's value with nextSearchTerm and update search result\n                        if (this.prefillNextSearchTerm()) {\n                            this.updateResults();\n                        }\n                    }\n                    this.positionDropdown();\n                } else {\n                    // if nothing left to select close\n                    this.close();\n                    this.search.width(10);\n                }\n            }\n\n            // since its not possible to select an element that has already been\n            // added we do not need to check if this is a new element before firing change\n            this.triggerChange({ added: data });\n\n            if (!options || !options.noFocus)\n                this.focusSearch();\n        },\n\n        // multi\n        cancel: function () {\n            this.close();\n            this.focusSearch();\n        },\n\n        addSelectedChoice: function (data) {\n            var val = this.getVal(), self = this;\n            $(data).each(function () {\n                val.push(self.createChoice(this));\n            });\n            this.setVal(val);\n        },\n\n        createChoice: function (data) {\n            var enableChoice = !data.locked,\n                enabledItem = $(\n                    \"<li class='select2-search-choice'>\" +\n                    \"    <div></div>\" +\n                    \"    <a href='#' class='select2-search-choice-close' tabindex='-1'></a>\" +\n                    \"</li>\"),\n                disabledItem = $(\n                    \"<li class='select2-search-choice select2-locked'>\" +\n                    \"<div></div>\" +\n                    \"</li>\");\n            var choice = enableChoice ? enabledItem : disabledItem,\n                id = this.id(data),\n                formatted,\n                cssClass;\n\n            formatted=this.opts.formatSelection(data, choice.find(\"div\"), this.opts.escapeMarkup);\n            if (formatted != undefined) {\n                choice.find(\"div\").replaceWith($(\"<div></div>\").html(formatted));\n            }\n            cssClass=this.opts.formatSelectionCssClass(data, choice.find(\"div\"));\n            if (cssClass != undefined) {\n                choice.addClass(cssClass);\n            }\n\n            if(enableChoice){\n              choice.find(\".select2-search-choice-close\")\n                  .on(\"mousedown\", killEvent)\n                  .on(\"click dblclick\", this.bind(function (e) {\n                  if (!this.isInterfaceEnabled()) return;\n\n                  this.unselect($(e.target));\n                  this.selection.find(\".select2-search-choice-focus\").removeClass(\"select2-search-choice-focus\");\n                  killEvent(e);\n                  this.close();\n                  this.focusSearch();\n              })).on(\"focus\", this.bind(function () {\n                  if (!this.isInterfaceEnabled()) return;\n                  this.container.addClass(\"select2-container-active\");\n                  this.dropdown.addClass(\"select2-drop-active\");\n              }));\n            }\n\n            choice.data(\"select2-data\", data);\n            choice.insertBefore(this.searchContainer);\n\n            return id;\n        },\n\n        // multi\n        unselect: function (selected) {\n            var val = this.getVal(),\n                data,\n                index;\n            selected = selected.closest(\".select2-search-choice\");\n\n            if (selected.length === 0) {\n                throw \"Invalid argument: \" + selected + \". Must be .select2-search-choice\";\n            }\n\n            data = selected.data(\"select2-data\");\n\n            if (!data) {\n                // prevent a race condition when the 'x' is clicked really fast repeatedly the event can be queued\n                // and invoked on an element already removed\n                return;\n            }\n\n            var evt = $.Event(\"select2-removing\");\n            evt.val = this.id(data);\n            evt.choice = data;\n            this.opts.element.trigger(evt);\n\n            if (evt.isDefaultPrevented()) {\n                return false;\n            }\n\n            while((index = indexOf(this.id(data), val)) >= 0) {\n                val.splice(index, 1);\n                this.setVal(val);\n                if (this.select) this.postprocessResults();\n            }\n\n            selected.remove();\n\n            this.opts.element.trigger({ type: \"select2-removed\", val: this.id(data), choice: data });\n            this.triggerChange({ removed: data });\n\n            return true;\n        },\n\n        // multi\n        postprocessResults: function (data, initial, noHighlightUpdate) {\n            var val = this.getVal(),\n                choices = this.results.find(\".select2-result\"),\n                compound = this.results.find(\".select2-result-with-children\"),\n                self = this;\n\n            choices.each2(function (i, choice) {\n                var id = self.id(choice.data(\"select2-data\"));\n                if (indexOf(id, val) >= 0) {\n                    choice.addClass(\"select2-selected\");\n                    // mark all children of the selected parent as selected\n                    choice.find(\".select2-result-selectable\").addClass(\"select2-selected\");\n                }\n            });\n\n            compound.each2(function(i, choice) {\n                // hide an optgroup if it doesn't have any selectable children\n                if (!choice.is('.select2-result-selectable')\n                    && choice.find(\".select2-result-selectable:not(.select2-selected)\").length === 0) {\n                    choice.addClass(\"select2-selected\");\n                }\n            });\n\n            if (this.highlight() == -1 && noHighlightUpdate !== false && this.opts.closeOnSelect === true){\n                self.highlight(0);\n            }\n\n            //If all results are chosen render formatNoMatches\n            if(!this.opts.createSearchChoice && !choices.filter('.select2-result:not(.select2-selected)').length > 0){\n                if(!data || data && !data.more && this.results.find(\".select2-no-results\").length === 0) {\n                    if (checkFormatter(self.opts.formatNoMatches, \"formatNoMatches\")) {\n                        this.results.append(\"<li class='select2-no-results'>\" + evaluate(self.opts.formatNoMatches, self.opts.element, self.search.val()) + \"</li>\");\n                    }\n                }\n            }\n\n        },\n\n        // multi\n        getMaxSearchWidth: function() {\n            return this.selection.width() - getSideBorderPadding(this.search);\n        },\n\n        // multi\n        resizeSearch: function () {\n            var minimumWidth, left, maxWidth, containerLeft, searchWidth,\n                sideBorderPadding = getSideBorderPadding(this.search);\n\n            minimumWidth = measureTextWidth(this.search) + 10;\n\n            left = this.search.offset().left;\n\n            maxWidth = this.selection.width();\n            containerLeft = this.selection.offset().left;\n\n            searchWidth = maxWidth - (left - containerLeft) - sideBorderPadding;\n\n            if (searchWidth < minimumWidth) {\n                searchWidth = maxWidth - sideBorderPadding;\n            }\n\n            if (searchWidth < 40) {\n                searchWidth = maxWidth - sideBorderPadding;\n            }\n\n            if (searchWidth <= 0) {\n              searchWidth = minimumWidth;\n            }\n\n            this.search.width(Math.floor(searchWidth));\n        },\n\n        // multi\n        getVal: function () {\n            var val;\n            if (this.select) {\n                val = this.select.val();\n                return val === null ? [] : val;\n            } else {\n                val = this.opts.element.val();\n                return splitVal(val, this.opts.separator, this.opts.transformVal);\n            }\n        },\n\n        // multi\n        setVal: function (val) {\n            if (this.select) {\n                this.select.val(val);\n            } else {\n                var unique = [], valMap = {};\n                // filter out duplicates\n                $(val).each(function () {\n                    if (!(this in valMap)) {\n                        unique.push(this);\n                        valMap[this] = 0;\n                    }\n                });\n                this.opts.element.val(unique.length === 0 ? \"\" : unique.join(this.opts.separator));\n            }\n        },\n\n        // multi\n        buildChangeDetails: function (old, current) {\n            var current = current.slice(0),\n                old = old.slice(0);\n\n            // remove intersection from each array\n            for (var i = 0; i < current.length; i++) {\n                for (var j = 0; j < old.length; j++) {\n                    if (equal(this.opts.id(current[i]), this.opts.id(old[j]))) {\n                        current.splice(i, 1);\n                        i--;\n                        old.splice(j, 1);\n                        break;\n                    }\n                }\n            }\n\n            return {added: current, removed: old};\n        },\n\n\n        // multi\n        val: function (val, triggerChange) {\n            var oldData, self=this;\n\n            if (arguments.length === 0) {\n                return this.getVal();\n            }\n\n            oldData=this.data();\n            if (!oldData.length) oldData=[];\n\n            // val is an id. !val is true for [undefined,null,'',0] - 0 is legal\n            if (!val && val !== 0) {\n                this.opts.element.val(\"\");\n                this.updateSelection([]);\n                this.clearSearch();\n                if (triggerChange) {\n                    this.triggerChange({added: this.data(), removed: oldData});\n                }\n                return;\n            }\n\n            // val is a list of ids\n            this.setVal(val);\n\n            if (this.select) {\n                this.opts.initSelection(this.select, this.bind(this.updateSelection));\n                if (triggerChange) {\n                    this.triggerChange(this.buildChangeDetails(oldData, this.data()));\n                }\n            } else {\n                if (this.opts.initSelection === undefined) {\n                    throw new Error(\"val() cannot be called if initSelection() is not defined\");\n                }\n\n                this.opts.initSelection(this.opts.element, function(data){\n                    var ids=$.map(data, self.id);\n                    self.setVal(ids);\n                    self.updateSelection(data);\n                    self.clearSearch();\n                    if (triggerChange) {\n                        self.triggerChange(self.buildChangeDetails(oldData, self.data()));\n                    }\n                });\n            }\n            this.clearSearch();\n        },\n\n        // multi\n        onSortStart: function() {\n            if (this.select) {\n                throw new Error(\"Sorting of elements is not supported when attached to <select>. Attach to <input type='hidden'/> instead.\");\n            }\n\n            // collapse search field into 0 width so its container can be collapsed as well\n            this.search.width(0);\n            // hide the container\n            this.searchContainer.hide();\n        },\n\n        // multi\n        onSortEnd:function() {\n\n            var val=[], self=this;\n\n            // show search and move it to the end of the list\n            this.searchContainer.show();\n            // make sure the search container is the last item in the list\n            this.searchContainer.appendTo(this.searchContainer.parent());\n            // since we collapsed the width in dragStarted, we resize it here\n            this.resizeSearch();\n\n            // update selection\n            this.selection.find(\".select2-search-choice\").each(function() {\n                val.push(self.opts.id($(this).data(\"select2-data\")));\n            });\n            this.setVal(val);\n            this.triggerChange();\n        },\n\n        // multi\n        data: function(values, triggerChange) {\n            var self=this, ids, old;\n            if (arguments.length === 0) {\n                 return this.selection\n                     .children(\".select2-search-choice\")\n                     .map(function() { return $(this).data(\"select2-data\"); })\n                     .get();\n            } else {\n                old = this.data();\n                if (!values) { values = []; }\n                ids = $.map(values, function(e) { return self.opts.id(e); });\n                this.setVal(ids);\n                this.updateSelection(values);\n                this.clearSearch();\n                if (triggerChange) {\n                    this.triggerChange(this.buildChangeDetails(old, this.data()));\n                }\n            }\n        }\n    });\n\n    $.fn.select2 = function () {\n\n        var args = Array.prototype.slice.call(arguments, 0),\n            opts,\n            select2,\n            method, value, multiple,\n            allowedMethods = [\"val\", \"destroy\", \"opened\", \"open\", \"close\", \"focus\", \"isFocused\", \"container\", \"dropdown\", \"onSortStart\", \"onSortEnd\", \"enable\", \"disable\", \"readonly\", \"positionDropdown\", \"data\", \"search\"],\n            valueMethods = [\"opened\", \"isFocused\", \"container\", \"dropdown\"],\n            propertyMethods = [\"val\", \"data\"],\n            methodsMap = { search: \"externalSearch\" };\n\n        this.each(function () {\n            if (args.length === 0 || typeof(args[0]) === \"object\") {\n                opts = args.length === 0 ? {} : $.extend({}, args[0]);\n                opts.element = $(this);\n\n                if (opts.element.get(0).tagName.toLowerCase() === \"select\") {\n                    multiple = opts.element.prop(\"multiple\");\n                } else {\n                    multiple = opts.multiple || false;\n                    if (\"tags\" in opts) {opts.multiple = multiple = true;}\n                }\n\n                select2 = multiple ? new window.Select2[\"class\"].multi() : new window.Select2[\"class\"].single();\n                select2.init(opts);\n            } else if (typeof(args[0]) === \"string\") {\n\n                if (indexOf(args[0], allowedMethods) < 0) {\n                    throw \"Unknown method: \" + args[0];\n                }\n\n                value = undefined;\n                select2 = $(this).data(\"select2\");\n                if (select2 === undefined) return;\n\n                method=args[0];\n\n                if (method === \"container\") {\n                    value = select2.container;\n                } else if (method === \"dropdown\") {\n                    value = select2.dropdown;\n                } else {\n                    if (methodsMap[method]) method = methodsMap[method];\n\n                    value = select2[method].apply(select2, args.slice(1));\n                }\n                if (indexOf(args[0], valueMethods) >= 0\n                    || (indexOf(args[0], propertyMethods) >= 0 && args.length == 1)) {\n                    return false; // abort the iteration, ready to return first matched value\n                }\n            } else {\n                throw \"Invalid arguments to select2 plugin: \" + args;\n            }\n        });\n        return (value === undefined) ? this : value;\n    };\n\n    // plugin defaults, accessible to users\n    $.fn.select2.defaults = {\n        debug: false,\n        width: \"copy\",\n        loadMorePadding: 0,\n        closeOnSelect: true,\n        openOnEnter: true,\n        containerCss: {},\n        dropdownCss: {},\n        containerCssClass: \"\",\n        dropdownCssClass: \"\",\n        formatResult: function(result, container, query, escapeMarkup) {\n            var markup=[];\n            markMatch(this.text(result), query.term, markup, escapeMarkup);\n            return markup.join(\"\");\n        },\n        transformVal: function(val) {\n            return $.trim(val);\n        },\n        formatSelection: function (data, container, escapeMarkup) {\n            return data ? escapeMarkup(this.text(data)) : undefined;\n        },\n        sortResults: function (results, container, query) {\n            return results;\n        },\n        formatResultCssClass: function(data) {return data.css;},\n        formatSelectionCssClass: function(data, container) {return undefined;},\n        minimumResultsForSearch: 0,\n        minimumInputLength: 0,\n        maximumInputLength: null,\n        maximumSelectionSize: 0,\n        id: function (e) { return e == undefined ? null : e.id; },\n        text: function (e) {\n          if (e && this.data && this.data.text) {\n            if ($.isFunction(this.data.text)) {\n              return this.data.text(e);\n            } else {\n              return e[this.data.text];\n            }\n          } else {\n            return e.text;\n          }\n        },\n        matcher: function(term, text) {\n            return stripDiacritics(''+text).toUpperCase().indexOf(stripDiacritics(''+term).toUpperCase()) >= 0;\n        },\n        separator: \",\",\n        tokenSeparators: [],\n        tokenizer: defaultTokenizer,\n        escapeMarkup: defaultEscapeMarkup,\n        blurOnChange: false,\n        selectOnBlur: false,\n        adaptContainerCssClass: function(c) { return c; },\n        adaptDropdownCssClass: function(c) { return null; },\n        nextSearchTerm: function(selectedObject, currentSearchTerm) { return undefined; },\n        searchInputPlaceholder: '',\n        createSearchChoicePosition: 'top',\n        shouldFocusInput: function (instance) {\n            // Attempt to detect touch devices\n            var supportsTouchEvents = (('ontouchstart' in window) ||\n                                       (navigator.msMaxTouchPoints > 0));\n\n            // Only devices which support touch events should be special cased\n            if (!supportsTouchEvents) {\n                return true;\n            }\n\n            // Never focus the input if search is disabled\n            if (instance.opts.minimumResultsForSearch < 0) {\n                return false;\n            }\n\n            return true;\n        }\n    };\n\n    $.fn.select2.locales = [];\n\n    $.fn.select2.locales['en'] = {\n         formatMatches: function (matches) { if (matches === 1) { return \"One result is available, press enter to select it.\"; } return matches + \" results are available, use up and down arrow keys to navigate.\"; },\n         formatNoMatches: function () { return \"No matches found\"; },\n         formatAjaxError: function (jqXHR, textStatus, errorThrown) { return \"Loading failed\"; },\n         formatInputTooShort: function (input, min) { var n = min - input.length; return \"Please enter \" + n + \" or more character\" + (n == 1 ? \"\" : \"s\"); },\n         formatInputTooLong: function (input, max) { var n = input.length - max; return \"Please delete \" + n + \" character\" + (n == 1 ? \"\" : \"s\"); },\n         formatSelectionTooBig: function (limit) { return \"You can only select \" + limit + \" item\" + (limit == 1 ? \"\" : \"s\"); },\n         formatLoadMore: function (pageNumber) { return \"Loading more results\u2026\"; },\n         formatSearching: function () { return \"Searching\u2026\"; }\n    };\n\n    $.extend($.fn.select2.defaults, $.fn.select2.locales['en']);\n\n    $.fn.select2.ajaxDefaults = {\n        transport: $.ajax,\n        params: {\n            type: \"GET\",\n            cache: false,\n            dataType: \"json\"\n        }\n    };\n\n    // exports\n    window.Select2 = {\n        query: {\n            ajax: ajax,\n            local: local,\n            tags: tags\n        }, util: {\n            debounce: debounce,\n            markMatch: markMatch,\n            escapeMarkup: defaultEscapeMarkup,\n            stripDiacritics: stripDiacritics\n        }, \"class\": {\n            \"abstract\": AbstractSelect2,\n            \"single\": SingleSelect2,\n            \"multi\": MultiSelect2\n        }\n    };\n\n}(jQuery));\n", "/*!\n * clipboard.js v2.0.0\n * https://zenorocha.github.io/clipboard.js\n *\n * Licensed MIT \u00a9 Zeno Rocha\n */\n(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"ClipboardJS\"] = factory();\n\telse\n\t\troot[\"ClipboardJS\"] = factory();\n})(this, function() {\nreturn /******/ (function(modules) { // webpackBootstrap\n/******/ \t// The module cache\n/******/ \tvar installedModules = {};\n/******/\n/******/ \t// The require function\n/******/ \tfunction __webpack_require__(moduleId) {\n/******/\n/******/ \t\t// Check if module is in cache\n/******/ \t\tif(installedModules[moduleId]) {\n/******/ \t\t\treturn installedModules[moduleId].exports;\n/******/ \t\t}\n/******/ \t\t// Create a new module (and put it into the cache)\n/******/ \t\tvar module = installedModules[moduleId] = {\n/******/ \t\t\ti: moduleId,\n/******/ \t\t\tl: false,\n/******/ \t\t\texports: {}\n/******/ \t\t};\n/******/\n/******/ \t\t// Execute the module function\n/******/ \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n/******/\n/******/ \t\t// Flag the module as loaded\n/******/ \t\tmodule.l = true;\n/******/\n/******/ \t\t// Return the exports of the module\n/******/ \t\treturn module.exports;\n/******/ \t}\n/******/\n/******/\n/******/ \t// expose the modules object (__webpack_modules__)\n/******/ \t__webpack_require__.m = modules;\n/******/\n/******/ \t// expose the module cache\n/******/ \t__webpack_require__.c = installedModules;\n/******/\n/******/ \t// identity function for calling harmony imports with the correct context\n/******/ \t__webpack_require__.i = function(value) { return value; };\n/******/\n/******/ \t// define getter function for harmony exports\n/******/ \t__webpack_require__.d = function(exports, name, getter) {\n/******/ \t\tif(!__webpack_require__.o(exports, name)) {\n/******/ \t\t\tObject.defineProperty(exports, name, {\n/******/ \t\t\t\tconfigurable: false,\n/******/ \t\t\t\tenumerable: true,\n/******/ \t\t\t\tget: getter\n/******/ \t\t\t});\n/******/ \t\t}\n/******/ \t};\n/******/\n/******/ \t// getDefaultExport function for compatibility with non-harmony modules\n/******/ \t__webpack_require__.n = function(module) {\n/******/ \t\tvar getter = module && module.__esModule ?\n/******/ \t\t\tfunction getDefault() { return module['default']; } :\n/******/ \t\t\tfunction getModuleExports() { return module; };\n/******/ \t\t__webpack_require__.d(getter, 'a', getter);\n/******/ \t\treturn getter;\n/******/ \t};\n/******/\n/******/ \t// Object.prototype.hasOwnProperty.call\n/******/ \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n/******/\n/******/ \t// __webpack_public_path__\n/******/ \t__webpack_require__.p = \"\";\n/******/\n/******/ \t// Load entry module and return exports\n/******/ \treturn __webpack_require__(__webpack_require__.s = 3);\n/******/ })\n/************************************************************************/\n/******/ ([\n/* 0 */\n/***/ (function(module, exports, __webpack_require__) {\n\nvar __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;(function (global, factory) {\n    if (true) {\n        !(__WEBPACK_AMD_DEFINE_ARRAY__ = [module, __webpack_require__(7)], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),\n\t\t\t\t__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?\n\t\t\t\t(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),\n\t\t\t\t__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));\n    } else if (typeof exports !== \"undefined\") {\n        factory(module, require('select'));\n    } else {\n        var mod = {\n            exports: {}\n        };\n        factory(mod, global.select);\n        global.clipboardAction = mod.exports;\n    }\n})(this, function (module, _select) {\n    'use strict';\n\n    var _select2 = _interopRequireDefault(_select);\n\n    function _interopRequireDefault(obj) {\n        return obj && obj.__esModule ? obj : {\n            default: obj\n        };\n    }\n\n    var _typeof = typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\" ? function (obj) {\n        return typeof obj;\n    } : function (obj) {\n        return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj;\n    };\n\n    function _classCallCheck(instance, Constructor) {\n        if (!(instance instanceof Constructor)) {\n            throw new TypeError(\"Cannot call a class as a function\");\n        }\n    }\n\n    var _createClass = function () {\n        function defineProperties(target, props) {\n            for (var i = 0; i < props.length; i++) {\n                var descriptor = props[i];\n                descriptor.enumerable = descriptor.enumerable || false;\n                descriptor.configurable = true;\n                if (\"value\" in descriptor) descriptor.writable = true;\n                Object.defineProperty(target, descriptor.key, descriptor);\n            }\n        }\n\n        return function (Constructor, protoProps, staticProps) {\n            if (protoProps) defineProperties(Constructor.prototype, protoProps);\n            if (staticProps) defineProperties(Constructor, staticProps);\n            return Constructor;\n        };\n    }();\n\n    var ClipboardAction = function () {\n        /**\n         * @param {Object} options\n         */\n        function ClipboardAction(options) {\n            _classCallCheck(this, ClipboardAction);\n\n            this.resolveOptions(options);\n            this.initSelection();\n        }\n\n        /**\n         * Defines base properties passed from constructor.\n         * @param {Object} options\n         */\n\n\n        _createClass(ClipboardAction, [{\n            key: 'resolveOptions',\n            value: function resolveOptions() {\n                var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n\n                this.action = options.action;\n                this.container = options.container;\n                this.emitter = options.emitter;\n                this.target = options.target;\n                this.text = options.text;\n                this.trigger = options.trigger;\n\n                this.selectedText = '';\n            }\n        }, {\n            key: 'initSelection',\n            value: function initSelection() {\n                if (this.text) {\n                    this.selectFake();\n                } else if (this.target) {\n                    this.selectTarget();\n                }\n            }\n        }, {\n            key: 'selectFake',\n            value: function selectFake() {\n                var _this = this;\n\n                var isRTL = document.documentElement.getAttribute('dir') == 'rtl';\n\n                this.removeFake();\n\n                this.fakeHandlerCallback = function () {\n                    return _this.removeFake();\n                };\n                this.fakeHandler = this.container.addEventListener('click', this.fakeHandlerCallback) || true;\n\n                this.fakeElem = document.createElement('textarea');\n                // Prevent zooming on iOS\n                this.fakeElem.style.fontSize = '12pt';\n                // Reset box model\n                this.fakeElem.style.border = '0';\n                this.fakeElem.style.padding = '0';\n                this.fakeElem.style.margin = '0';\n                // Move element out of screen horizontally\n                this.fakeElem.style.position = 'absolute';\n                this.fakeElem.style[isRTL ? 'right' : 'left'] = '-9999px';\n                // Move element to the same position vertically\n                var yPosition = window.pageYOffset || document.documentElement.scrollTop;\n                this.fakeElem.style.top = yPosition + 'px';\n\n                this.fakeElem.setAttribute('readonly', '');\n                this.fakeElem.value = this.text;\n\n                this.container.appendChild(this.fakeElem);\n\n                this.selectedText = (0, _select2.default)(this.fakeElem);\n                this.copyText();\n            }\n        }, {\n            key: 'removeFake',\n            value: function removeFake() {\n                if (this.fakeHandler) {\n                    this.container.removeEventListener('click', this.fakeHandlerCallback);\n                    this.fakeHandler = null;\n                    this.fakeHandlerCallback = null;\n                }\n\n                if (this.fakeElem) {\n                    this.container.removeChild(this.fakeElem);\n                    this.fakeElem = null;\n                }\n            }\n        }, {\n            key: 'selectTarget',\n            value: function selectTarget() {\n                this.selectedText = (0, _select2.default)(this.target);\n                this.copyText();\n            }\n        }, {\n            key: 'copyText',\n            value: function copyText() {\n                var succeeded = void 0;\n\n                try {\n                    succeeded = document.execCommand(this.action);\n                } catch (err) {\n                    succeeded = false;\n                }\n\n                this.handleResult(succeeded);\n            }\n        }, {\n            key: 'handleResult',\n            value: function handleResult(succeeded) {\n                this.emitter.emit(succeeded ? 'success' : 'error', {\n                    action: this.action,\n                    text: this.selectedText,\n                    trigger: this.trigger,\n                    clearSelection: this.clearSelection.bind(this)\n                });\n            }\n        }, {\n            key: 'clearSelection',\n            value: function clearSelection() {\n                if (this.trigger) {\n                    this.trigger.focus();\n                }\n\n                window.getSelection().removeAllRanges();\n            }\n        }, {\n            key: 'destroy',\n            value: function destroy() {\n                this.removeFake();\n            }\n        }, {\n            key: 'action',\n            set: function set() {\n                var action = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'copy';\n\n                this._action = action;\n\n                if (this._action !== 'copy' && this._action !== 'cut') {\n                    throw new Error('Invalid \"action\" value, use either \"copy\" or \"cut\"');\n                }\n            },\n            get: function get() {\n                return this._action;\n            }\n        }, {\n            key: 'target',\n            set: function set(target) {\n                if (target !== undefined) {\n                    if (target && (typeof target === 'undefined' ? 'undefined' : _typeof(target)) === 'object' && target.nodeType === 1) {\n                        if (this.action === 'copy' && target.hasAttribute('disabled')) {\n                            throw new Error('Invalid \"target\" attribute. Please use \"readonly\" instead of \"disabled\" attribute');\n                        }\n\n                        if (this.action === 'cut' && (target.hasAttribute('readonly') || target.hasAttribute('disabled'))) {\n                            throw new Error('Invalid \"target\" attribute. You can\\'t cut text from elements with \"readonly\" or \"disabled\" attributes');\n                        }\n\n                        this._target = target;\n                    } else {\n                        throw new Error('Invalid \"target\" value, use a valid Element');\n                    }\n                }\n            },\n            get: function get() {\n                return this._target;\n            }\n        }]);\n\n        return ClipboardAction;\n    }();\n\n    module.exports = ClipboardAction;\n});\n\n/***/ }),\n/* 1 */\n/***/ (function(module, exports, __webpack_require__) {\n\nvar is = __webpack_require__(6);\nvar delegate = __webpack_require__(5);\n\n/**\n * Validates all params and calls the right\n * listener function based on its target type.\n *\n * @param {String|HTMLElement|HTMLCollection|NodeList} target\n * @param {String} type\n * @param {Function} callback\n * @return {Object}\n */\nfunction listen(target, type, callback) {\n    if (!target && !type && !callback) {\n        throw new Error('Missing required arguments');\n    }\n\n    if (!is.string(type)) {\n        throw new TypeError('Second argument must be a String');\n    }\n\n    if (!is.fn(callback)) {\n        throw new TypeError('Third argument must be a Function');\n    }\n\n    if (is.node(target)) {\n        return listenNode(target, type, callback);\n    }\n    else if (is.nodeList(target)) {\n        return listenNodeList(target, type, callback);\n    }\n    else if (is.string(target)) {\n        return listenSelector(target, type, callback);\n    }\n    else {\n        throw new TypeError('First argument must be a String, HTMLElement, HTMLCollection, or NodeList');\n    }\n}\n\n/**\n * Adds an event listener to a HTML element\n * and returns a remove listener function.\n *\n * @param {HTMLElement} node\n * @param {String} type\n * @param {Function} callback\n * @return {Object}\n */\nfunction listenNode(node, type, callback) {\n    node.addEventListener(type, callback);\n\n    return {\n        destroy: function() {\n            node.removeEventListener(type, callback);\n        }\n    }\n}\n\n/**\n * Add an event listener to a list of HTML elements\n * and returns a remove listener function.\n *\n * @param {NodeList|HTMLCollection} nodeList\n * @param {String} type\n * @param {Function} callback\n * @return {Object}\n */\nfunction listenNodeList(nodeList, type, callback) {\n    Array.prototype.forEach.call(nodeList, function(node) {\n        node.addEventListener(type, callback);\n    });\n\n    return {\n        destroy: function() {\n            Array.prototype.forEach.call(nodeList, function(node) {\n                node.removeEventListener(type, callback);\n            });\n        }\n    }\n}\n\n/**\n * Add an event listener to a selector\n * and returns a remove listener function.\n *\n * @param {String} selector\n * @param {String} type\n * @param {Function} callback\n * @return {Object}\n */\nfunction listenSelector(selector, type, callback) {\n    return delegate(document.body, selector, type, callback);\n}\n\nmodule.exports = listen;\n\n\n/***/ }),\n/* 2 */\n/***/ (function(module, exports) {\n\nfunction E () {\n  // Keep this empty so it's easier to inherit from\n  // (via https://github.com/lipsmack from https://github.com/scottcorgan/tiny-emitter/issues/3)\n}\n\nE.prototype = {\n  on: function (name, callback, ctx) {\n    var e = this.e || (this.e = {});\n\n    (e[name] || (e[name] = [])).push({\n      fn: callback,\n      ctx: ctx\n    });\n\n    return this;\n  },\n\n  once: function (name, callback, ctx) {\n    var self = this;\n    function listener () {\n      self.off(name, listener);\n      callback.apply(ctx, arguments);\n    };\n\n    listener._ = callback\n    return this.on(name, listener, ctx);\n  },\n\n  emit: function (name) {\n    var data = [].slice.call(arguments, 1);\n    var evtArr = ((this.e || (this.e = {}))[name] || []).slice();\n    var i = 0;\n    var len = evtArr.length;\n\n    for (i; i < len; i++) {\n      evtArr[i].fn.apply(evtArr[i].ctx, data);\n    }\n\n    return this;\n  },\n\n  off: function (name, callback) {\n    var e = this.e || (this.e = {});\n    var evts = e[name];\n    var liveEvents = [];\n\n    if (evts && callback) {\n      for (var i = 0, len = evts.length; i < len; i++) {\n        if (evts[i].fn !== callback && evts[i].fn._ !== callback)\n          liveEvents.push(evts[i]);\n      }\n    }\n\n    // Remove event from queue to prevent memory leak\n    // Suggested by https://github.com/lazd\n    // Ref: https://github.com/scottcorgan/tiny-emitter/commit/c6ebfaa9bc973b33d110a84a307742b7cf94c953#commitcomment-5024910\n\n    (liveEvents.length)\n      ? e[name] = liveEvents\n      : delete e[name];\n\n    return this;\n  }\n};\n\nmodule.exports = E;\n\n\n/***/ }),\n/* 3 */\n/***/ (function(module, exports, __webpack_require__) {\n\nvar __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;(function (global, factory) {\n    if (true) {\n        !(__WEBPACK_AMD_DEFINE_ARRAY__ = [module, __webpack_require__(0), __webpack_require__(2), __webpack_require__(1)], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),\n\t\t\t\t__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?\n\t\t\t\t(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),\n\t\t\t\t__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));\n    } else if (typeof exports !== \"undefined\") {\n        factory(module, require('./clipboard-action'), require('tiny-emitter'), require('good-listener'));\n    } else {\n        var mod = {\n            exports: {}\n        };\n        factory(mod, global.clipboardAction, global.tinyEmitter, global.goodListener);\n        global.clipboard = mod.exports;\n    }\n})(this, function (module, _clipboardAction, _tinyEmitter, _goodListener) {\n    'use strict';\n\n    var _clipboardAction2 = _interopRequireDefault(_clipboardAction);\n\n    var _tinyEmitter2 = _interopRequireDefault(_tinyEmitter);\n\n    var _goodListener2 = _interopRequireDefault(_goodListener);\n\n    function _interopRequireDefault(obj) {\n        return obj && obj.__esModule ? obj : {\n            default: obj\n        };\n    }\n\n    var _typeof = typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\" ? function (obj) {\n        return typeof obj;\n    } : function (obj) {\n        return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj;\n    };\n\n    function _classCallCheck(instance, Constructor) {\n        if (!(instance instanceof Constructor)) {\n            throw new TypeError(\"Cannot call a class as a function\");\n        }\n    }\n\n    var _createClass = function () {\n        function defineProperties(target, props) {\n            for (var i = 0; i < props.length; i++) {\n                var descriptor = props[i];\n                descriptor.enumerable = descriptor.enumerable || false;\n                descriptor.configurable = true;\n                if (\"value\" in descriptor) descriptor.writable = true;\n                Object.defineProperty(target, descriptor.key, descriptor);\n            }\n        }\n\n        return function (Constructor, protoProps, staticProps) {\n            if (protoProps) defineProperties(Constructor.prototype, protoProps);\n            if (staticProps) defineProperties(Constructor, staticProps);\n            return Constructor;\n        };\n    }();\n\n    function _possibleConstructorReturn(self, call) {\n        if (!self) {\n            throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");\n        }\n\n        return call && (typeof call === \"object\" || typeof call === \"function\") ? call : self;\n    }\n\n    function _inherits(subClass, superClass) {\n        if (typeof superClass !== \"function\" && superClass !== null) {\n            throw new TypeError(\"Super expression must either be null or a function, not \" + typeof superClass);\n        }\n\n        subClass.prototype = Object.create(superClass && superClass.prototype, {\n            constructor: {\n                value: subClass,\n                enumerable: false,\n                writable: true,\n                configurable: true\n            }\n        });\n        if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;\n    }\n\n    var Clipboard = function (_Emitter) {\n        _inherits(Clipboard, _Emitter);\n\n        /**\n         * @param {String|HTMLElement|HTMLCollection|NodeList} trigger\n         * @param {Object} options\n         */\n        function Clipboard(trigger, options) {\n            _classCallCheck(this, Clipboard);\n\n            var _this = _possibleConstructorReturn(this, (Clipboard.__proto__ || Object.getPrototypeOf(Clipboard)).call(this));\n\n            _this.resolveOptions(options);\n            _this.listenClick(trigger);\n            return _this;\n        }\n\n        /**\n         * Defines if attributes would be resolved using internal setter functions\n         * or custom functions that were passed in the constructor.\n         * @param {Object} options\n         */\n\n\n        _createClass(Clipboard, [{\n            key: 'resolveOptions',\n            value: function resolveOptions() {\n                var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n\n                this.action = typeof options.action === 'function' ? options.action : this.defaultAction;\n                this.target = typeof options.target === 'function' ? options.target : this.defaultTarget;\n                this.text = typeof options.text === 'function' ? options.text : this.defaultText;\n                this.container = _typeof(options.container) === 'object' ? options.container : document.body;\n            }\n        }, {\n            key: 'listenClick',\n            value: function listenClick(trigger) {\n                var _this2 = this;\n\n                this.listener = (0, _goodListener2.default)(trigger, 'click', function (e) {\n                    return _this2.onClick(e);\n                });\n            }\n        }, {\n            key: 'onClick',\n            value: function onClick(e) {\n                var trigger = e.delegateTarget || e.currentTarget;\n\n                if (this.clipboardAction) {\n                    this.clipboardAction = null;\n                }\n\n                this.clipboardAction = new _clipboardAction2.default({\n                    action: this.action(trigger),\n                    target: this.target(trigger),\n                    text: this.text(trigger),\n                    container: this.container,\n                    trigger: trigger,\n                    emitter: this\n                });\n            }\n        }, {\n            key: 'defaultAction',\n            value: function defaultAction(trigger) {\n                return getAttributeValue('action', trigger);\n            }\n        }, {\n            key: 'defaultTarget',\n            value: function defaultTarget(trigger) {\n                var selector = getAttributeValue('target', trigger);\n\n                if (selector) {\n                    return document.querySelector(selector);\n                }\n            }\n        }, {\n            key: 'defaultText',\n            value: function defaultText(trigger) {\n                return getAttributeValue('text', trigger);\n            }\n        }, {\n            key: 'destroy',\n            value: function destroy() {\n                this.listener.destroy();\n\n                if (this.clipboardAction) {\n                    this.clipboardAction.destroy();\n                    this.clipboardAction = null;\n                }\n            }\n        }], [{\n            key: 'isSupported',\n            value: function isSupported() {\n                var action = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ['copy', 'cut'];\n\n                var actions = typeof action === 'string' ? [action] : action;\n                var support = !!document.queryCommandSupported;\n\n                actions.forEach(function (action) {\n                    support = support && !!document.queryCommandSupported(action);\n                });\n\n                return support;\n            }\n        }]);\n\n        return Clipboard;\n    }(_tinyEmitter2.default);\n\n    /**\n     * Helper function to retrieve attribute value.\n     * @param {String} suffix\n     * @param {Element} element\n     */\n    function getAttributeValue(suffix, element) {\n        var attribute = 'data-clipboard-' + suffix;\n\n        if (!element.hasAttribute(attribute)) {\n            return;\n        }\n\n        return element.getAttribute(attribute);\n    }\n\n    module.exports = Clipboard;\n});\n\n/***/ }),\n/* 4 */\n/***/ (function(module, exports) {\n\nvar DOCUMENT_NODE_TYPE = 9;\n\n/**\n * A polyfill for Element.matches()\n */\nif (typeof Element !== 'undefined' && !Element.prototype.matches) {\n    var proto = Element.prototype;\n\n    proto.matches = proto.matchesSelector ||\n                    proto.mozMatchesSelector ||\n                    proto.msMatchesSelector ||\n                    proto.oMatchesSelector ||\n                    proto.webkitMatchesSelector;\n}\n\n/**\n * Finds the closest parent that matches a selector.\n *\n * @param {Element} element\n * @param {String} selector\n * @return {Function}\n */\nfunction closest (element, selector) {\n    while (element && element.nodeType !== DOCUMENT_NODE_TYPE) {\n        if (typeof element.matches === 'function' &&\n            element.matches(selector)) {\n          return element;\n        }\n        element = element.parentNode;\n    }\n}\n\nmodule.exports = closest;\n\n\n/***/ }),\n/* 5 */\n/***/ (function(module, exports, __webpack_require__) {\n\nvar closest = __webpack_require__(4);\n\n/**\n * Delegates event to a selector.\n *\n * @param {Element} element\n * @param {String} selector\n * @param {String} type\n * @param {Function} callback\n * @param {Boolean} useCapture\n * @return {Object}\n */\nfunction _delegate(element, selector, type, callback, useCapture) {\n    var listenerFn = listener.apply(this, arguments);\n\n    element.addEventListener(type, listenerFn, useCapture);\n\n    return {\n        destroy: function() {\n            element.removeEventListener(type, listenerFn, useCapture);\n        }\n    }\n}\n\n/**\n * Delegates event to a selector.\n *\n * @param {Element|String|Array} [elements]\n * @param {String} selector\n * @param {String} type\n * @param {Function} callback\n * @param {Boolean} useCapture\n * @return {Object}\n */\nfunction delegate(elements, selector, type, callback, useCapture) {\n    // Handle the regular Element usage\n    if (typeof elements.addEventListener === 'function') {\n        return _delegate.apply(null, arguments);\n    }\n\n    // Handle Element-less usage, it defaults to global delegation\n    if (typeof type === 'function') {\n        // Use `document` as the first parameter, then apply arguments\n        // This is a short way to .unshift `arguments` without running into deoptimizations\n        return _delegate.bind(null, document).apply(null, arguments);\n    }\n\n    // Handle Selector-based usage\n    if (typeof elements === 'string') {\n        elements = document.querySelectorAll(elements);\n    }\n\n    // Handle Array-like based usage\n    return Array.prototype.map.call(elements, function (element) {\n        return _delegate(element, selector, type, callback, useCapture);\n    });\n}\n\n/**\n * Finds closest match and invokes callback.\n *\n * @param {Element} element\n * @param {String} selector\n * @param {String} type\n * @param {Function} callback\n * @return {Function}\n */\nfunction listener(element, selector, type, callback) {\n    return function(e) {\n        e.delegateTarget = closest(e.target, selector);\n\n        if (e.delegateTarget) {\n            callback.call(element, e);\n        }\n    }\n}\n\nmodule.exports = delegate;\n\n\n/***/ }),\n/* 6 */\n/***/ (function(module, exports) {\n\n/**\n * Check if argument is a HTML element.\n *\n * @param {Object} value\n * @return {Boolean}\n */\nexports.node = function(value) {\n    return value !== undefined\n        && value instanceof HTMLElement\n        && value.nodeType === 1;\n};\n\n/**\n * Check if argument is a list of HTML elements.\n *\n * @param {Object} value\n * @return {Boolean}\n */\nexports.nodeList = function(value) {\n    var type = Object.prototype.toString.call(value);\n\n    return value !== undefined\n        && (type === '[object NodeList]' || type === '[object HTMLCollection]')\n        && ('length' in value)\n        && (value.length === 0 || exports.node(value[0]));\n};\n\n/**\n * Check if argument is a string.\n *\n * @param {Object} value\n * @return {Boolean}\n */\nexports.string = function(value) {\n    return typeof value === 'string'\n        || value instanceof String;\n};\n\n/**\n * Check if argument is a function.\n *\n * @param {Object} value\n * @return {Boolean}\n */\nexports.fn = function(value) {\n    var type = Object.prototype.toString.call(value);\n\n    return type === '[object Function]';\n};\n\n\n/***/ }),\n/* 7 */\n/***/ (function(module, exports) {\n\nfunction select(element) {\n    var selectedText;\n\n    if (element.nodeName === 'SELECT') {\n        element.focus();\n\n        selectedText = element.value;\n    }\n    else if (element.nodeName === 'INPUT' || element.nodeName === 'TEXTAREA') {\n        var isReadOnly = element.hasAttribute('readonly');\n\n        if (!isReadOnly) {\n            element.setAttribute('readonly', '');\n        }\n\n        element.select();\n        element.setSelectionRange(0, element.value.length);\n\n        if (!isReadOnly) {\n            element.removeAttribute('readonly');\n        }\n\n        selectedText = element.value;\n    }\n    else {\n        if (element.hasAttribute('contenteditable')) {\n            element.focus();\n        }\n\n        var selection = window.getSelection();\n        var range = document.createRange();\n\n        range.selectNodeContents(element);\n        selection.removeAllRanges();\n        selection.addRange(range);\n\n        selectedText = selection.toString();\n    }\n\n    return selectedText;\n}\n\nmodule.exports = select;\n\n\n/***/ })\n/******/ ]);\n});", "/** @preserve \njSignature v2 \"${buildDate}\" \"${commitID}\"\nCopyright (c) 2012 Willow Systems Corp http://willow-systems.com\nCopyright (c) 2010 Brinley Ang http://www.unbolt.net\nMIT License <http://www.opensource.org/licenses/mit-license.php> \n\n*/\n;(function() {\n\nvar apinamespace = 'jSignature'\n\n/**\nAllows one to delay certain eventual action by setting up a timer for it and allowing one to delay it\nby \"kick\"ing it. Sorta like \"kick the can down the road\"\n\n@public\n@class\n@param\n@returns {Type}\n*/\nvar KickTimerClass = function(time, callback) {\n    var timer;\n    this.kick = function() {\n        clearTimeout(timer);\n        timer = setTimeout(\n            callback\n            , time\n        );\n    }\n    this.clear = function() {\n        clearTimeout(timer);\n    }\n    return this;\n}\n\nvar PubSubClass = function(context){\n    'use strict'\n    /*  @preserve \n    -----------------------------------------------------------------------------------------------\n    JavaScript PubSub library\n    2012 (c) Willow Systems Corp (www.willow-systems.com)\n    based on Peter Higgins (dante@dojotoolkit.org)\n    Loosely based on Dojo publish/subscribe API, limited in scope. Rewritten blindly.\n    Original is (c) Dojo Foundation 2004-2010. Released under either AFL or new BSD, see:\n    http://dojofoundation.org/license for more information.\n    -----------------------------------------------------------------------------------------------\n    */\n    this.topics = {};\n    // here we choose what will be \"this\" for the called events.\n    // if context is defined, it's context. Else, 'this' is this instance of PubSub\n    this.context = context ? context : this;\n    /**\n     * Allows caller to emit an event and pass arguments to event listeners.\n     * @public\n     * @function\n     * @param topic {String} Name of the channel on which to voice this event\n     * @param **arguments Any number of arguments you want to pass to the listeners of this event.\n     */\n    this.publish = function(topic, arg1, arg2, etc) {\n        'use strict'\n        if (this.topics[topic]) {\n            var currentTopic = this.topics[topic]\n            , args = Array.prototype.slice.call(arguments, 1)\n            , toremove = []\n            , torun = []\n            , fn\n            , i, l\n            , pair;\n\n            for (i = 0, l = currentTopic.length; i < l; i++) {\n                pair = currentTopic[i]; // this is a [function, once_flag] array\n                fn = pair[0];\n                if (pair[1] /* 'run once' flag set */){\n                  pair[0] = function(){};\n                  toremove.push(i);\n                }\n                /* don't call the callback right now, it might decide to add or\n                 * remove subscribers which will wreak havoc on our index-based\n                 * iteration */\n                torun.push(fn);\n            }\n            for (i = 0, l = toremove.length; i < l; i++) {\n              currentTopic.splice(toremove[i], 1);\n            }\n            for (i = 0, l = torun.length; i < l; i++) {\n              torun[i].apply(this.context, args);\n            }\n        }\n    }\n    /**\n     * Allows listener code to subscribe to channel and be called when data is available \n     * @public\n     * @function\n     * @param topic {String} Name of the channel on which to voice this event\n     * @param callback {Function} Executable (function pointer) that will be ran when event is voiced on this channel.\n     * @param once {Boolean} (optional. False by default) Flag indicating if the function is to be triggered only once.\n     * @returns {Object} A token object that cen be used for unsubscribing.  \n     */\n    this.subscribe = function(topic, callback, once) {\n        'use strict'\n        if (!this.topics[topic]) {\n            this.topics[topic] = [[callback, once]];\n        } else {\n            this.topics[topic].push([callback,once]);\n        }\n        return {\n            \"topic\": topic,\n            \"callback\": callback\n        };\n    };\n    /**\n     * Allows listener code to unsubscribe from a channel \n     * @public\n     * @function\n     * @param token {Object} A token object that was returned by `subscribe` method \n     */\n    this.unsubscribe = function(token) {\n        if (this.topics[token.topic]) {\n            var currentTopic = this.topics[token.topic];\n            \n            for (var i = 0, l = currentTopic.length; i < l; i++) {\n                if (currentTopic[i] && currentTopic[i][0] === token.callback) {\n                    currentTopic.splice(i, 1);\n                }\n            }\n        }\n    }\n}\n\n/// Returns front, back and \"decor\" colors derived from element (as jQuery obj)\nfunction getColors($e){\n    var tmp\n    , undef\n    , frontcolor = $e.css('color')\n    , backcolor\n    , e = $e[0];\n    \n    var toOfDOM = false;\n    while(e && !backcolor && !toOfDOM){\n        try{\n            tmp = $(e).css('background-color');\n        } catch (ex) {\n            tmp = 'transparent';\n        }\n        if (tmp !== 'transparent' && tmp !== 'rgba(0, 0, 0, 0)'){\n            backcolor = tmp;\n        }\n        toOfDOM = e.body;\n        e = e.parentNode;\n    }\n\n    var rgbaregex = /rgb[a]*\\((\\d+),\\s*(\\d+),\\s*(\\d+)/ // modern browsers\n    , hexregex = /#([AaBbCcDdEeFf\\d]{2})([AaBbCcDdEeFf\\d]{2})([AaBbCcDdEeFf\\d]{2})/ // IE 8 and less.\n    , frontcolorcomponents;\n\n    // Decomposing Front color into R, G, B ints\n    tmp = undef;\n    tmp = frontcolor.match(rgbaregex);\n    if (tmp){\n        frontcolorcomponents = {'r':parseInt(tmp[1],10),'g':parseInt(tmp[2],10),'b':parseInt(tmp[3],10)};\n    } else {\n        tmp = frontcolor.match(hexregex);\n        if (tmp) {\n            frontcolorcomponents = {'r':parseInt(tmp[1],16),'g':parseInt(tmp[2],16),'b':parseInt(tmp[3],16)};\n        }\n    }\n//      if(!frontcolorcomponents){\n//          frontcolorcomponents = {'r':255,'g':255,'b':255}\n//      }\n\n    var backcolorcomponents\n    // Decomposing back color into R, G, B ints\n    if(!backcolor){\n        // HIghly unlikely since this means that no background styling was applied to any element from here to top of dom.\n        // we'll pick up back color from front color\n        if(frontcolorcomponents){\n            if (Math.max.apply(null, [frontcolorcomponents.r, frontcolorcomponents.g, frontcolorcomponents.b]) > 127){\n                backcolorcomponents = {'r':0,'g':0,'b':0};\n            } else {\n                backcolorcomponents = {'r':255,'g':255,'b':255};\n            }\n        } else {\n            // arg!!! front color is in format we don't understand (hsl, named colors)\n            // Let's just go with white background.\n            backcolorcomponents = {'r':255,'g':255,'b':255};\n        }\n    } else {\n        tmp = undef;\n        tmp = backcolor.match(rgbaregex);\n        if (tmp){\n            backcolorcomponents = {'r':parseInt(tmp[1],10),'g':parseInt(tmp[2],10),'b':parseInt(tmp[3],10)};\n        } else {\n            tmp = backcolor.match(hexregex);\n            if (tmp) {\n                backcolorcomponents = {'r':parseInt(tmp[1],16),'g':parseInt(tmp[2],16),'b':parseInt(tmp[3],16)};\n            }\n        }\n//          if(!backcolorcomponents){\n//              backcolorcomponents = {'r':0,'g':0,'b':0}\n//          }\n    }\n    \n    // Deriving Decor color\n    // THis is LAZY!!!! Better way would be to use HSL and adjust luminocity. However, that could be an overkill. \n    \n    var toRGBfn = function(o){return 'rgb(' + [o.r, o.g, o.b].join(', ') + ')'} \n    , decorcolorcomponents\n    , frontcolorbrightness\n    , adjusted;\n    \n    if (frontcolorcomponents && backcolorcomponents){\n        var backcolorbrightness = Math.max.apply(null, [frontcolorcomponents.r, frontcolorcomponents.g, frontcolorcomponents.b]);\n        \n        frontcolorbrightness = Math.max.apply(null, [backcolorcomponents.r, backcolorcomponents.g, backcolorcomponents.b]);\n        adjusted = Math.round(frontcolorbrightness + (-1 * (frontcolorbrightness - backcolorbrightness) * 0.75)); // \"dimming\" the difference between pen and back.\n        decorcolorcomponents = {'r':adjusted,'g':adjusted,'b':adjusted}; // always shade of gray\n    } else if (frontcolorcomponents) {\n        frontcolorbrightness = Math.max.apply(null, [frontcolorcomponents.r, frontcolorcomponents.g, frontcolorcomponents.b]);\n        var polarity = +1;\n        if (frontcolorbrightness > 127){\n            polarity = -1;\n        }\n        // shifting by 25% (64 points on RGB scale)\n        adjusted = Math.round(frontcolorbrightness + (polarity * 96)); // \"dimming\" the pen's color by 75% to get decor color.\n        decorcolorcomponents = {'r':adjusted,'g':adjusted,'b':adjusted}; // always shade of gray\n    } else {\n        decorcolorcomponents = {'r':191,'g':191,'b':191}; // always shade of gray\n    }\n\n    return {\n        'color': frontcolor\n        , 'background-color': backcolorcomponents? toRGBfn(backcolorcomponents) : backcolor\n        , 'decor-color': toRGBfn(decorcolorcomponents)\n    };\n}\n\nfunction Vector(x,y){\n    this.x = x;\n    this.y = y;\n    this.reverse = function(){\n        return new this.constructor( \n            this.x * -1\n            , this.y * -1\n        );\n    };\n    this._length = null;\n    this.getLength = function(){\n        if (!this._length){\n            this._length = Math.sqrt( Math.pow(this.x, 2) + Math.pow(this.y, 2) );\n        }\n        return this._length;\n    };\n    \n    var polarity = function (e){\n        return Math.round(e / Math.abs(e));\n    };\n    this.resizeTo = function(length){\n        // proportionally changes x,y such that the hypotenuse (vector length) is = new length\n        if (this.x === 0 && this.y === 0){\n            this._length = 0;\n        } else if (this.x === 0){\n            this._length = length;\n            this.y = length * polarity(this.y);\n        } else if(this.y === 0){\n            this._length = length;\n            this.x = length * polarity(this.x);\n        } else {\n            var proportion = Math.abs(this.y / this.x)\n                , x = Math.sqrt(Math.pow(length, 2) / (1 + Math.pow(proportion, 2)))\n                , y = proportion * x;\n            this._length = length;\n            this.x = x * polarity(this.x);\n            this.y = y * polarity(this.y);\n        }\n        return this;\n    };\n    \n    /**\n     * Calculates the angle between 'this' vector and another.\n     * @public\n     * @function\n     * @returns {Number} The angle between the two vectors as measured in PI. \n     */\n    this.angleTo = function(vectorB) {\n        var divisor = this.getLength() * vectorB.getLength();\n        if (divisor === 0) {\n            return 0;\n        } else {\n            // JavaScript floating point math is screwed up.\n            // because of it, the core of the formula can, on occasion, have values\n            // over 1.0 and below -1.0.\n            return Math.acos(\n                Math.min( \n                    Math.max( \n                        ( this.x * vectorB.x + this.y * vectorB.y ) / divisor\n                        , -1.0\n                    )\n                    , 1.0\n                )\n            ) / Math.PI;\n        }\n    };\n}\n\nfunction Point(x,y){\n    this.x = x;\n    this.y = y;\n    \n    this.getVectorToCoordinates = function (x, y) {\n        return new Vector(x - this.x, y - this.y);\n    };\n    this.getVectorFromCoordinates = function (x, y) {\n        return this.getVectorToCoordinates(x, y).reverse();\n    };\n    this.getVectorToPoint = function (point) {\n        return new Vector(point.x - this.x, point.y - this.y);\n    };\n    this.getVectorFromPoint = function (point) {\n        return this.getVectorToPoint(point).reverse();\n    };\n}\n\n/*\n * About data structure:\n * We don't store / deal with \"pictures\" this signature capture code captures \"vectors\"\n * \n * We don't store bitmaps. We store \"strokes\" as arrays of arrays. (Actually, arrays of objects containing arrays of coordinates.\n * \n * Stroke = mousedown + mousemoved * n (+ mouseup but we don't record that as that was the \"end / lack of movement\" indicator)\n * \n * Vectors = not classical vectors where numbers indicated shift relative last position. Our vectors are actually coordinates against top left of canvas.\n *          we could calc the classical vectors, but keeping the the actual coordinates allows us (through Math.max / min) \n *          to calc the size of resulting drawing very quickly. If we want classical vectors later, we can always get them in backend code.\n * \n * So, the data structure:\n * \n * var data = [\n *  { // stroke starts\n *      x : [101, 98, 57, 43] // x points\n *      , y : [1, 23, 65, 87] // y points\n *  } // stroke ends\n *  , { // stroke starts\n *      x : [55, 56, 57, 58] // x points\n *      , y : [101, 97, 54, 4] // y points\n *  } // stroke ends\n *  , { // stroke consisting of just a dot\n *      x : [53] // x points\n *      , y : [151] // y points\n *  } // stroke ends\n * ]\n * \n * we don't care or store stroke width (it's canvas-size-relative), color, shadow values. These can be added / changed on whim post-capture.\n * \n */\nfunction DataEngine(storageObject, context, startStrokeFn, addToStrokeFn, endStrokeFn){\n    this.data = storageObject; // we expect this to be an instance of Array\n    this.context = context;\n\n    if (storageObject.length){\n        // we have data to render\n        var numofstrokes = storageObject.length\n        , stroke\n        , numofpoints;\n        \n        for (var i = 0; i < numofstrokes; i++){\n            stroke = storageObject[i];\n            numofpoints = stroke.x.length;\n            startStrokeFn.call(context, stroke);\n            for(var j = 1; j < numofpoints; j++){\n                addToStrokeFn.call(context, stroke, j);\n            }\n            endStrokeFn.call(context, stroke);\n        }\n    }\n\n    this.changed = function(){};\n    \n    this.startStrokeFn = startStrokeFn;\n    this.addToStrokeFn = addToStrokeFn;\n    this.endStrokeFn = endStrokeFn;\n\n    this.inStroke = false;\n    \n    this._lastPoint = null;\n    this._stroke = null;\n    this.startStroke = function(point){\n        if(point && typeof(point.x) == \"number\" && typeof(point.y) == \"number\"){\n            this._stroke = {'x':[point.x], 'y':[point.y]};\n            this.data.push(this._stroke);\n            this._lastPoint = point;\n            this.inStroke = true;\n            // 'this' does not work same inside setTimeout(\n            var stroke = this._stroke \n            , fn = this.startStrokeFn\n            , context = this.context;\n            setTimeout(\n                // some IE's don't support passing args per setTimeout API. Have to create closure every time instead.\n                function() {fn.call(context, stroke)}\n                , 3\n            );\n            return point;\n        } else {\n            return null;\n        }\n    };\n    // that \"5\" at the very end of this if is important to explain.\n    // we do NOT render links between two captured points (in the middle of the stroke) if the distance is shorter than that number.\n    // not only do we NOT render it, we also do NOT capture (add) these intermediate points to storage.\n    // when clustering of these is too tight, it produces noise on the line, which, because of smoothing, makes lines too curvy.\n    // maybe, later, we can expose this as a configurable setting of some sort.\n    this.addToStroke = function(point){\n        if (this.inStroke && \n            typeof(point.x) === \"number\" && \n            typeof(point.y) === \"number\" &&\n            // calculates absolute shift in diagonal pixels away from original point\n            (Math.abs(point.x - this._lastPoint.x) + Math.abs(point.y - this._lastPoint.y)) > 4\n        ){\n            var positionInStroke = this._stroke.x.length;\n            this._stroke.x.push(point.x);\n            this._stroke.y.push(point.y);\n            this._lastPoint = point;\n            \n            var stroke = this._stroke\n            , fn = this.addToStrokeFn\n            , context = this.context;\n            setTimeout(\n                // some IE's don't support passing args per setTimeout API. Have to create closure every time instead.\n                function() {fn.call(context, stroke, positionInStroke)}\n                , 3\n            );\n            return point;\n        } else {\n            return null;\n        }\n    };\n    this.endStroke = function(){\n        var c = this.inStroke;\n        this.inStroke = false;\n        this._lastPoint = null;\n        if (c){\n            var stroke = this._stroke\n            , fn = this.endStrokeFn // 'this' does not work same inside setTimeout(\n            , context = this.context\n            , changedfn = this.changed;\n            setTimeout(\n                // some IE's don't support passing args per setTimeout API. Have to create closure every time instead.\n                function(){\n                    fn.call(context, stroke);\n                    changedfn.call(context);\n                }\n                , 3\n            );\n            return true;\n        } else {\n            return null;\n        }\n    };\n}\n\nvar basicDot = function(ctx, x, y, size){\n    var fillStyle = ctx.fillStyle;\n    ctx.fillStyle = ctx.strokeStyle;\n    ctx.fillRect(x + size / -2 , y + size / -2, size, size);\n    ctx.fillStyle = fillStyle;\n}\n, basicLine = function(ctx, startx, starty, endx, endy){\n    ctx.beginPath();\n    ctx.moveTo(startx, starty);\n    ctx.lineTo(endx, endy);\n    ctx.closePath();\n    ctx.stroke();\n}\n, basicCurve = function(ctx, startx, starty, endx, endy, cp1x, cp1y, cp2x, cp2y){\n    ctx.beginPath();\n    ctx.moveTo(startx, starty);\n    ctx.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, endx, endy);\n    ctx.closePath();\n    ctx.stroke();\n}\n, strokeStartCallback = function(stroke) {\n    // this = jSignatureClass instance\n    basicDot(this.canvasContext, stroke.x[0], stroke.y[0], this.settings.lineWidth);\n}\n, strokeAddCallback = function(stroke, positionInStroke){\n    // this = jSignatureClass instance\n\n    // Because we are funky this way, here we draw TWO curves.\n    // 1. POSSIBLY \"this line\" - spanning from point right before us, to this latest point.\n    // 2. POSSIBLY \"prior curve\" - spanning from \"latest point\" to the one before it.\n    \n    // Why you ask?\n    // long lines (ones with many pixels between them) do not look good when they are part of a large curvy stroke.\n    // You know, the jaggedy crocodile spine instead of a pretty, smooth curve. Yuck!\n    // We want to approximate pretty curves in-place of those ugly lines.\n    // To approximate a very nice curve we need to know the direction of line before and after.\n    // Hence, on long lines we actually wait for another point beyond it to come back from\n    // mousemoved before we draw this curve.\n    \n    // So for \"prior curve\" to be calc'ed we need 4 points \n    //  A, B, C, D (we are on D now, A is 3 points in the past.)\n    // and 3 lines:\n    //  pre-line (from points A to B), \n    //  this line (from points B to C), (we call it \"this\" because if it was not yet, it's the only one we can draw for sure.) \n    //  post-line (from points C to D) (even through D point is 'current' we don't know how we can draw it yet)\n    //\n    // Well, actually, we don't need to *know* the point A, just the vector A->B\n    var Cpoint = new Point(stroke.x[positionInStroke-1], stroke.y[positionInStroke-1])\n        , Dpoint = new Point(stroke.x[positionInStroke], stroke.y[positionInStroke])\n        , CDvector = Cpoint.getVectorToPoint(Dpoint);\n        \n    // Again, we have a chance here to draw TWO things:\n    //  BC Curve (only if it's long, because if it was short, it was drawn by previous callback) and \n    //  CD Line (only if it's short)\n    \n    // So, let's start with BC curve.\n    // if there is only 2 points in stroke array, we don't have \"history\" long enough to have point B, let alone point A.\n    // Falling through to drawing line CD is proper, as that's the only line we have points for.\n    if(positionInStroke > 1) {\n        // we are here when there are at least 3 points in stroke array.\n        var Bpoint = new Point(stroke.x[positionInStroke-2], stroke.y[positionInStroke-2])\n        , BCvector = Bpoint.getVectorToPoint(Cpoint)\n        , ABvector;\n        if(BCvector.getLength() > this.lineCurveThreshold){\n            // Yey! Pretty curves, here we come!\n            if(positionInStroke > 2) {\n                // we are here when at least 4 points in stroke array.\n                ABvector = (new Point(stroke.x[positionInStroke-3], stroke.y[positionInStroke-3])).getVectorToPoint(Bpoint);\n            } else {\n                ABvector = new Vector(0,0);\n            }\n\n            var minlenfraction = 0.05\n            , maxlen = BCvector.getLength() * 0.35\n            , ABCangle = BCvector.angleTo(ABvector.reverse())\n            , BCDangle = CDvector.angleTo(BCvector.reverse())\n            , BCP1vector = new Vector(ABvector.x + BCvector.x, ABvector.y + BCvector.y).resizeTo(\n                Math.max(minlenfraction, ABCangle) * maxlen\n            )\n            , CCP2vector = (new Vector(BCvector.x + CDvector.x, BCvector.y + CDvector.y)).reverse().resizeTo(\n                Math.max(minlenfraction, BCDangle) * maxlen\n            );\n            \n            basicCurve(\n                this.canvasContext\n                , Bpoint.x\n                , Bpoint.y\n                , Cpoint.x\n                , Cpoint.y\n                , Bpoint.x + BCP1vector.x\n                , Bpoint.y + BCP1vector.y\n                , Cpoint.x + CCP2vector.x\n                , Cpoint.y + CCP2vector.y\n            );\n        }\n    }\n    if(CDvector.getLength() <= this.lineCurveThreshold){\n        basicLine(\n            this.canvasContext\n            , Cpoint.x\n            , Cpoint.y\n            , Dpoint.x\n            , Dpoint.y\n        );\n    }\n}\n, strokeEndCallback = function(stroke){\n    // this = jSignatureClass instance\n\n    // Here we tidy up things left unfinished in last strokeAddCallback run.\n\n    // What's POTENTIALLY left unfinished there is the curve between the last points\n    // in the stroke, if the len of that line is more than lineCurveThreshold\n    // If the last line was shorter than lineCurveThreshold, it was drawn there, and there\n    // is nothing for us here to do.\n    // We can also be called when there is only one point in the stroke (meaning, the \n    // stroke was just a dot), in which case, again, there is nothing for us to do.\n                \n    // So for \"this curve\" to be calc'ed we need 3 points \n    //  A, B, C\n    // and 2 lines:\n    //  pre-line (from points A to B), \n    //  this line (from points B to C) \n    // Well, actually, we don't need to *know* the point A, just the vector A->B\n    // so, we really need points B, C and AB vector.\n    var positionInStroke = stroke.x.length - 1;\n    \n    if (positionInStroke > 0){\n        // there are at least 2 points in the stroke.we are in business.\n        var Cpoint = new Point(stroke.x[positionInStroke], stroke.y[positionInStroke])\n            , Bpoint = new Point(stroke.x[positionInStroke-1], stroke.y[positionInStroke-1])\n            , BCvector = Bpoint.getVectorToPoint(Cpoint)\n            , ABvector;\n        if (BCvector.getLength() > this.lineCurveThreshold){\n            // yep. This one was left undrawn in prior callback. Have to draw it now.\n            if (positionInStroke > 1){\n                // we have at least 3 elems in stroke\n                ABvector = (new Point(stroke.x[positionInStroke-2], stroke.y[positionInStroke-2])).getVectorToPoint(Bpoint);\n                var BCP1vector = new Vector(ABvector.x + BCvector.x, ABvector.y + BCvector.y).resizeTo(BCvector.getLength() / 2);\n                basicCurve(\n                    this.canvasContext\n                    , Bpoint.x\n                    , Bpoint.y\n                    , Cpoint.x\n                    , Cpoint.y\n                    , Bpoint.x + BCP1vector.x\n                    , Bpoint.y + BCP1vector.y\n                    , Cpoint.x\n                    , Cpoint.y\n                );\n            } else {\n                // Since there is no AB leg, there is no curve to draw. This line is still \"long\" but no curve.\n                basicLine(\n                    this.canvasContext\n                    , Bpoint.x\n                    , Bpoint.y\n                    , Cpoint.x\n                    , Cpoint.y\n                );\n            }\n        }\n    }\n}\n\n\n/*\nvar getDataStats = function(){\n    var strokecnt = strokes.length\n        , stroke\n        , pointid\n        , pointcnt\n        , x, y\n        , maxX = Number.NEGATIVE_INFINITY\n        , maxY = Number.NEGATIVE_INFINITY\n        , minX = Number.POSITIVE_INFINITY\n        , minY = Number.POSITIVE_INFINITY\n    for(strokeid = 0; strokeid < strokecnt; strokeid++){\n        stroke = strokes[strokeid]\n        pointcnt = stroke.length\n        for(pointid = 0; pointid < pointcnt; pointid++){\n            x = stroke.x[pointid]\n            y = stroke.y[pointid]\n            if (x > maxX){\n                maxX = x\n            } else if (x < minX) {\n                minX = x\n            }\n            if (y > maxY){\n                maxY = y\n            } else if (y < minY) {\n                minY = y\n            }\n        }\n    }\n    return {'maxX': maxX, 'minX': minX, 'maxY': maxY, 'minY': minY}\n}\n*/\n\nfunction conditionallyLinkCanvasResizeToWindowResize(jSignatureInstance, settingsWidth, apinamespace, globalEvents){\n    'use strict'\n    if ( settingsWidth === 'ratio' || settingsWidth.split('')[settingsWidth.length - 1] === '%' ) {\n        \n        this.eventTokens[apinamespace + '.parentresized'] = globalEvents.subscribe(\n            apinamespace + '.parentresized'\n            , (function(eventTokens, $parent, originalParentWidth, sizeRatio){\n                'use strict'\n\n                return function(){\n                    'use strict'\n\n                    var w = $parent.width();\n                    if (w !== originalParentWidth) {\n                    \n                        // UNsubscribing this particular instance of signature pad only.\n                        // there is a separate `eventTokens` per each instance of signature pad \n                        for (var key in eventTokens){\n                            if (eventTokens.hasOwnProperty(key)) {\n                                globalEvents.unsubscribe(eventTokens[key]);\n                                delete eventTokens[key];\n                            }\n                        }\n\n                        var settings = jSignatureInstance.settings;\n                        jSignatureInstance.$parent.children().remove();\n                        for (var key in jSignatureInstance){\n                            if (jSignatureInstance.hasOwnProperty(key)) {\n                                delete jSignatureInstance[key];\n                            }\n                        }\n                        \n                        // scale data to new signature pad size\n                        settings.data = (function(data, scale){\n                            var newData = [];\n                            var o, i, l, j, m, stroke;\n                            for ( i = 0, l = data.length; i < l; i++) {\n                                stroke = data[i];\n                                \n                                o = {'x':[],'y':[]};\n                                \n                                for ( j = 0, m = stroke.x.length; j < m; j++) {\n                                    o.x.push(stroke.x[j] * scale);\n                                    o.y.push(stroke.y[j] * scale);\n                                }\n                            \n                                newData.push(o);\n                            }\n                            return newData;\n                        })(\n                            settings.data\n                            , w * 1.0 / originalParentWidth\n                        )\n                        \n                        $parent[apinamespace](settings);\n                    }\n                }\n            })(\n                this.eventTokens\n                , this.$parent\n                , this.$parent.width()\n                , this.canvas.width * 1.0 / this.canvas.height\n            )\n        )\n    }\n};\n\n\nfunction jSignatureClass(parent, options, instanceExtensions) {\n\n    var $parent = this.$parent = $(parent)\n    , eventTokens = this.eventTokens = {}\n    , events = this.events = new PubSubClass(this)\n    , globalEvents = $.fn[apinamespace]('globalEvents')\n    , settings = {\n        'width' : 'ratio'\n        ,'height' : 'ratio'\n        ,'sizeRatio': 4 // only used when height = 'ratio'\n        ,'color' : '#000'\n        ,'background-color': '#fff'\n        ,'decor-color': '#eee'\n        ,'show-stroke': true\n        ,'lineWidth' : 0\n        ,'minFatFingerCompensation' : -10\n        ,'showUndoButton': false\n        ,'readOnly': false\n        ,'data': []\n    };\n    \n    $.extend(settings, getColors($parent));\n    if (options) {\n        $.extend(settings, options);\n    }\n    this.settings = settings;\n\n    for (var extensionName in instanceExtensions){\n        if (instanceExtensions.hasOwnProperty(extensionName)) {\n            instanceExtensions[extensionName].call(this, extensionName);\n        }\n    }\n\n    this.events.publish(apinamespace+'.initializing');\n\n    // these, when enabled, will hover above the sig area. Hence we append them to DOM before canvas.\n    this.$controlbarUpper = (function(){\n        var controlbarstyle = 'padding:0 !important; margin:0 !important;'+\n            'width: 100% !important; height: 0 !important; -ms-touch-action: none; touch-action: none;'+\n            'margin-top:-1em !important; margin-bottom:1em !important;';\n        return $('<div style=\"'+controlbarstyle+'\"></div>').appendTo($parent);\n    })();\n\n    this.isCanvasEmulator = false; // will be flipped by initializer when needed.\n    var canvas = this.canvas = this.initializeCanvas(settings)\n    , $canvas = $(canvas);\n\n    this.$controlbarLower = (function(){\n        var controlbarstyle = 'padding:0 !important; margin:0 !important;'+\n            'width: 100% !important; height: 0 !important; -ms-touch-action: none; touch-action: none;'+\n            'margin-top:-1.5em !important; margin-bottom:1.5em !important; position: relative;';\n        return $('<div style=\"'+controlbarstyle+'\"></div>').appendTo($parent);\n    })();\n\n    this.canvasContext = canvas.getContext(\"2d\");\n\n    // Most of our exposed API will be looking for this:\n    $canvas.data(apinamespace + '.this', this);\n\n    settings.lineWidth = (function(defaultLineWidth, canvasWidth){\n        if (!defaultLineWidth){\n            return Math.max(\n                Math.round(canvasWidth / 400) /*+1 pixel for every extra 300px of width.*/\n                , 2 /* minimum line width */\n            );\n        } else {\n            return defaultLineWidth;\n        }\n    })(settings.lineWidth, canvas.width);\n\n    this.lineCurveThreshold = settings.lineWidth * 3;\n\n    // Add custom class if defined\n    if(settings.cssclass && $.trim(settings.cssclass) != \"\") {\n        $canvas.addClass(settings.cssclass);\n    }\n\n    // used for shifting the drawing point up on touch devices, so one can see the drawing above the finger.\n    this.fatFingerCompensation = 0;\n\n    var movementHandlers = (function(jSignatureInstance) {\n\n        //================================\n        // mouse down, move, up handlers:\n\n        // shifts - adjustment values in viewport pixels drived from position of canvas on the page\n        var shiftX\n        , shiftY\n        , setStartValues = function(){\n            var tos = $(jSignatureInstance.canvas).offset()\n            shiftX = tos.left * -1\n            shiftY = tos.top * -1\n        }\n        , getPointFromEvent = function(e) {\n            var firstEvent = (e.changedTouches && e.changedTouches.length > 0 ? e.changedTouches[0] : e);\n            // All devices i tried report correct coordinates in pageX,Y\n            // Android Chrome 2.3.x, 3.1, 3.2., Opera Mobile,  safari iOS 4.x,\n            // Windows: Chrome, FF, IE9, Safari\n            // None of that scroll shift calc vs screenXY other sigs do is needed.\n            // ... oh, yeah, the \"fatFinger..\" is for tablets so that people see what they draw.\n            return new Point(\n                Math.round(firstEvent.pageX + shiftX)\n                , Math.round(firstEvent.pageY + shiftY) + jSignatureInstance.fatFingerCompensation\n            );\n        }\n        , timer = new KickTimerClass(\n            750\n            , function() { jSignatureInstance.dataEngine.endStroke(); }\n        );\n\n        this.drawEndHandler = function(e) {\n            if (!jSignatureInstance.settings.readOnly) {\n                try { e.preventDefault(); } catch (ex) {}\n                timer.clear();\n                jSignatureInstance.dataEngine.endStroke();\n            }\n        };\n        this.drawStartHandler = function(e) {\n            if (!jSignatureInstance.settings.readOnly) {\n                e.preventDefault();\n                // for performance we cache the offsets\n                // we recalc these only at the beginning the stroke         \n                setStartValues();\n                jSignatureInstance.dataEngine.startStroke( getPointFromEvent(e) );\n                timer.kick();\n            }\n        };\n        this.drawMoveHandler = function(e) {\n            if (!jSignatureInstance.settings.readOnly) {\n                e.preventDefault();\n                if (!jSignatureInstance.dataEngine.inStroke){\n                    return;\n                } \n                jSignatureInstance.dataEngine.addToStroke( getPointFromEvent(e) );\n                timer.kick();\n            }\n        };\n\n        return this;\n\n    }).call( {}, this )\n\n    //\n    //================================\n\n    ;(function(drawEndHandler, drawStartHandler, drawMoveHandler) {\n        var canvas = this.canvas\n        , $canvas = $(canvas)\n        , undef;\n        if (this.isCanvasEmulator){\n            $canvas.bind('mousemove.'+apinamespace, drawMoveHandler);\n            $canvas.bind('mouseup.'+apinamespace, drawEndHandler);\n            $canvas.bind('mousedown.'+apinamespace, drawStartHandler);\n        } else {\n            canvas.addEventListener('touchstart', function(e) {\n                canvas.onmousedown = canvas.onmouseup = canvas.onmousemove = undef;\n\n                this.fatFingerCompensation = (\n                    settings.minFatFingerCompensation && \n                    settings.lineWidth * -3 > settings.minFatFingerCompensation\n                ) ? settings.lineWidth * -3 : settings.minFatFingerCompensation;\n\n                drawStartHandler(e);\n\n                canvas.addEventListener('touchend', drawEndHandler);\n                canvas.addEventListener('touchstart', drawStartHandler);\n                canvas.addEventListener('touchmove', drawMoveHandler);\n            });\n            canvas.addEventListener('mousedown', function(e) {\n                canvas.ontouchstart = canvas.ontouchend = canvas.ontouchmove = undef;\n\n                drawStartHandler(e);\n\n                canvas.addEventListener('mousedown', drawStartHandler);\n                canvas.addEventListener('mouseup', drawEndHandler);\n                canvas.addEventListener('mousemove', drawMoveHandler);\n            });\n            if (window.navigator.msPointerEnabled) {\n                canvas.onmspointerdown = drawStartHandler;\n                canvas.onmspointerup = drawEndHandler;\n                canvas.onmspointermove = drawMoveHandler;\n            }\n        }\n    }).call( \n        this\n        , movementHandlers.drawEndHandler\n        , movementHandlers.drawStartHandler\n        , movementHandlers.drawMoveHandler\n    )\n\n    //=========================================\n    // various event handlers\n\n    // on mouseout + mouseup canvas did not know that mouseUP fired. Continued to draw despite mouse UP.\n    // it is bettr than\n    // $canvas.bind('mouseout', drawEndHandler)\n    // because we don't want to break the stroke where user accidentally gets ouside and wants to get back in quickly.\n    eventTokens[apinamespace + '.windowmouseup'] = globalEvents.subscribe(\n        apinamespace + '.windowmouseup'\n        , movementHandlers.drawEndHandler\n    );\n\n    this.events.publish(apinamespace+'.attachingEventHandlers');\n\n    // If we have proportional width, we sign up to events broadcasting \"window resized\" and checking if\n    // parent's width changed. If so, we (1) extract settings + data from current signature pad,\n    // (2) remove signature pad from parent, and (3) reinit new signature pad at new size with same settings, (rescaled) data.\n    conditionallyLinkCanvasResizeToWindowResize.call(\n        this\n        , this\n        , settings.width.toString(10)\n        , apinamespace, globalEvents\n    );\n    \n    // end of event handlers.\n    // ===============================\n\n    this.resetCanvas(settings.data);\n\n    // resetCanvas renders the data on the screen and fires ONE \"change\" event\n    // if there is data. If you have controls that rely on \"change\" firing\n    // attach them to something that runs before this.resetCanvas, like\n    // apinamespace+'.attachingEventHandlers' that fires a bit higher.\n    this.events.publish(apinamespace+'.initialized');\n\n    return this;\n} // end of initBase\n\n//=========================================================================\n// jSignatureClass's methods and supporting fn's\n\njSignatureClass.prototype.resetCanvas = function(data, dontClear){\n    var canvas = this.canvas\n    , settings = this.settings\n    , ctx = this.canvasContext\n    , isCanvasEmulator = this.isCanvasEmulator\n    , cw = canvas.width\n    , ch = canvas.height;\n    \n    // preparing colors, drawing area\n    if (!dontClear){\n        ctx.clearRect(0, 0, cw + 30, ch + 30);\n    }\n\n    ctx.shadowColor = ctx.fillStyle = settings['background-color']\n    if (isCanvasEmulator){\n        // FLashCanvas fills with Black by default, covering up the parent div's background\n        // hence we refill \n        ctx.fillRect(0,0,cw + 30, ch + 30);\n    }\n\n    ctx.lineWidth = Math.ceil(parseInt(settings.lineWidth, 10));\n    ctx.lineCap = ctx.lineJoin = \"round\";\n    \n    // signature line\n    if (null != settings['decor-color'] && settings['show-stroke']) {\n        ctx.strokeStyle = settings['decor-color'];\n        ctx.shadowOffsetX = 0;\n        ctx.shadowOffsetY = 0;\n        var lineoffset = Math.round( ch / 5 );\n        basicLine(ctx, lineoffset * 1.5, ch - lineoffset, cw - (lineoffset * 1.5), ch - lineoffset);\n    }\n    ctx.strokeStyle = settings.color;\n\n    if (!isCanvasEmulator){\n        ctx.shadowColor = ctx.strokeStyle;\n        ctx.shadowOffsetX = ctx.lineWidth * 0.5;\n        ctx.shadowOffsetY = ctx.lineWidth * -0.6;\n        ctx.shadowBlur = 0;\n    }\n    \n    // setting up new dataEngine\n\n    if (!data) { data = []; }\n    \n    var dataEngine = this.dataEngine = new DataEngine(\n        data\n        , this\n        , strokeStartCallback\n        , strokeAddCallback\n        , strokeEndCallback\n    );\n\n    settings.data = data; // onwindowresize handler uses it, i think.\n    $(canvas).data(apinamespace+'.data', data)\n        .data(apinamespace+'.settings', settings);\n\n    // we fire \"change\" event on every change in data.\n    // setting this up:\n    dataEngine.changed = (function(target, events, apinamespace) {\n        'use strict'\n        return function() {\n            events.publish(apinamespace+'.change');\n            target.trigger('change');\n        }\n    })(this.$parent, this.events, apinamespace);\n    // let's trigger change on all data reloads\n    dataEngine.changed();\n\n    // import filters will be passing this back as indication of \"we rendered\"\n    return true;\n};\n\nfunction initializeCanvasEmulator(canvas){\n    if (canvas.getContext){\n        return false;\n    } else {\n        // for cases when jSignature, FlashCanvas is inserted\n        // from one window into another (child iframe)\n        // 'window' and 'FlashCanvas' may be stuck behind\n        // in that other parent window.\n        // we need to find it\n        var window = canvas.ownerDocument.parentWindow;\n        var FC = window.FlashCanvas ?\n            canvas.ownerDocument.parentWindow.FlashCanvas :\n            (\n                typeof FlashCanvas === \"undefined\" ?\n                undefined :\n                FlashCanvas\n            );\n\n        if (FC) {\n            canvas = FC.initElement(canvas);\n            \n            var zoom = 1;\n            // FlashCanvas uses flash which has this annoying habit of NOT scaling with page zoom. \n            // It matches pixel-to-pixel to screen instead.\n            // Since we are targeting ONLY IE 7, 8 with FlashCanvas, we will test the zoom only the IE8, IE7 way\n            if (window && window.screen && window.screen.deviceXDPI && window.screen.logicalXDPI){\n                zoom = window.screen.deviceXDPI * 1.0 / window.screen.logicalXDPI;\n            }\n            if (zoom !== 1){\n                try {\n                    // We effectively abuse the brokenness of FlashCanvas and force the flash rendering surface to\n                    // occupy larger pixel dimensions than the wrapping, scaled up DIV and Canvas elems.\n                    $(canvas).children('object').get(0).resize(Math.ceil(canvas.width * zoom), Math.ceil(canvas.height * zoom));\n                    // And by applying \"scale\" transformation we can talk \"browser pixels\" to FlashCanvas\n                    // and have it translate the \"browser pixels\" to \"screen pixels\"\n                    canvas.getContext('2d').scale(zoom, zoom);\n                    // Note to self: don't reuse Canvas element. Repeated \"scale\" are cumulative.\n                } catch (ex) {}\n            }\n            return true;\n        } else {\n            throw new Error(\"Canvas element does not support 2d context. jSignature cannot proceed.\");\n        }\n    }\n\n}\n\njSignatureClass.prototype.initializeCanvas = function(settings) {\n    // ===========\n    // Init + Sizing code\n\n    var canvas = document.createElement('canvas')\n    , $canvas = $(canvas);\n\n    // We cannot work with circular dependency\n    if (settings.width === settings.height && settings.height === 'ratio') {\n        settings.width = '100%';\n    }\n\n    $canvas.css({\n        'margin': 0,\n        'padding': 0,\n        'border': 'none',\n        'height': settings.height === 'ratio' || !settings.height ? 1 : settings.height.toString(10),\n        'width': settings.width === 'ratio' || !settings.width ? 1 : settings.width.toString(10),\n        '-ms-touch-action': 'none',\n        'touch-action': 'none',\n        'background-color': settings['background-color'],\n    });\n\n    $canvas.appendTo(this.$parent);\n\n    // we could not do this until canvas is rendered (appended to DOM)\n    if (settings.height === 'ratio') {\n        $canvas.css(\n            'height'\n            , Math.round( $canvas.width() / settings.sizeRatio )\n        );\n    } else if (settings.width === 'ratio') {\n        $canvas.css(\n            'width'\n            , Math.round( $canvas.height() * settings.sizeRatio )\n        );\n    }\n\n    $canvas.addClass(apinamespace);\n\n    // canvas's drawing area resolution is independent from canvas's size.\n    // pixels are just scaled up or down when internal resolution does not\n    // match external size. So...\n\n    canvas.width = $canvas.width();\n    canvas.height = $canvas.height();\n    \n    // Special case Sizing code\n\n    this.isCanvasEmulator = initializeCanvasEmulator(canvas);\n\n    // End of Sizing Code\n    // ===========\n\n    // normally select preventer would be short, but\n    // Canvas emulator on IE does NOT provide value for Event. Hence this convoluted line.\n    canvas.onselectstart = function(e){if(e && e.preventDefault){e.preventDefault()}; if(e && e.stopPropagation){e.stopPropagation()}; return false;};\n\n    return canvas;\n}\n\n\nvar GlobalJSignatureObjectInitializer = function(window){\n\n    var globalEvents = new PubSubClass();\n    \n    // common \"window resized\" event listener.\n    // jSignature instances will subscribe to this chanel.\n    // to resize themselves when needed.\n    ;(function(globalEvents, apinamespace, $, window){\n        'use strict'\n\n        var resizetimer\n        , runner = function(){\n            globalEvents.publish(\n                apinamespace + '.parentresized'\n            )\n        };\n\n        // jSignature knows how to resize its content when its parent is resized\n        // window resize is the only way we can catch resize events though...\n        $(window).bind('resize.'+apinamespace, function(){\n            if (resizetimer) {\n                clearTimeout(resizetimer);\n            }\n            resizetimer = setTimeout( \n                runner\n                , 500\n            );\n        })\n        // when mouse exists canvas element and \"up\"s outside, we cannot catch it with\n        // callbacks attached to canvas. This catches it outside.\n        .bind('mouseup.'+apinamespace, function(e){\n            globalEvents.publish(\n                apinamespace + '.windowmouseup'\n            )\n        });\n\n    })(globalEvents, apinamespace, $, window)\n\n    var jSignatureInstanceExtensions = {\n        /*\n        'exampleExtension':function(extensionName){\n            // we are called very early in instance's life.\n            // right after the settings are resolved and \n            // jSignatureInstance.events is created \n            // and right before first (\"jSignature.initializing\") event is called.\n            // You don't really need to manupilate \n            // jSignatureInstance directly, just attach\n            // a bunch of events to jSignatureInstance.events\n            // (look at the source of jSignatureClass to see when these fire)\n            // and your special pieces of code will attach by themselves.\n\n            // this function runs every time a new instance is set up.\n            // this means every var you create will live only for one instance\n            // unless you attach it to something outside, like \"window.\"\n            // and pick it up later from there.\n\n            // when globalEvents' events fire, 'this' is globalEvents object\n            // when jSignatureInstance's events fire, 'this' is jSignatureInstance\n\n            // Here,\n            // this = is new jSignatureClass's instance.\n\n            // The way you COULD approch setting this up is:\n            // if you have multistep set up, attach event to \"jSignature.initializing\"\n            // that attaches other events to be fired further lower the init stream.\n            // Or, if you know for sure you rely on only one jSignatureInstance's event,\n            // just attach to it directly\n\n            this.events.subscribe(\n                // name of the event\n                apinamespace + '.initializing'\n                // event handlers, can pass args too, but in majority of cases,\n                // 'this' which is jSignatureClass object instance pointer is enough to get by.\n                , function(){\n                    if (this.settings.hasOwnProperty('non-existent setting category?')) {\n                        console.log(extensionName + ' is here')\n                    }\n                }\n            )\n        }\n        */\n    };\n\n    var exportplugins = {\n        'default':function(data){return this.toDataURL()}\n        , 'native':function(data){return data}\n        , 'image':function(data){\n            /*this = canvas elem */\n            var imagestring = this.toDataURL();\n            \n            if (typeof imagestring === 'string' && \n                imagestring.length > 4 && \n                imagestring.slice(0,5) === 'data:' &&\n                imagestring.indexOf(',') !== -1){\n                \n                var splitterpos = imagestring.indexOf(',');\n\n                return [\n                    imagestring.slice(5, splitterpos)\n                    , imagestring.substr(splitterpos + 1)\n                ];\n            }\n            return [];\n        }\n    };\n\n    // will be part of \"importplugins\"\n    function _renderImageOnCanvas( data, formattype, rerendercallable ) {\n        'use strict'\n        // #1. Do NOT rely on this. No worky on IE \n        //   (url max len + lack of base64 decoder + possibly other issues)\n        // #2. This does NOT affect what is captured as \"signature\" as far as vector data is \n        // concerned. This is treated same as \"signature line\" - i.e. completely ignored\n        // the only time you see imported image data exported is if you export as image.\n\n        // we do NOT call rerendercallable here (unlike in other import plugins)\n        // because importing image does absolutely nothing to the underlying vector data storage\n        // This could be a way to \"import\" old signatures stored as images\n        // This could also be a way to import extra decor into signature area.\n        \n        var img = new Image()\n        // this = Canvas DOM elem. Not jQuery object. Not Canvas's parent div.\n        , c = this;\n\n        img.onload = function () {\n            var ctx = c.getContext(\"2d\");\n            var oldShadowColor = ctx.shadowColor;\n            ctx.shadowColor = \"transparent\";\n            ctx.drawImage( \n                img, 0, 0\n                , ( img.width < c.width) ? img.width : c.width\n                , ( img.height < c.height) ? img.height : c.height\n            );\n            ctx.shadowColor = oldShadowColor;\n        };\n\n        img.src = 'data:' + formattype + ',' + data;\n    }\n\n    var importplugins = {\n        'native':function(data, formattype, rerendercallable){\n            // we expect data as Array of objects of arrays here - whatever 'default' EXPORT plugin spits out.\n            // returning Truthy to indicate we are good, all updated.\n            rerendercallable( data );\n        }\n        , 'image': _renderImageOnCanvas\n        , 'image/png;base64': _renderImageOnCanvas\n        , 'image/jpeg;base64': _renderImageOnCanvas\n        , 'image/jpg;base64': _renderImageOnCanvas\n    };\n\n    function _clearDrawingArea( data, dontClear ) {\n        this.find('canvas.'+apinamespace)\n            .add(this.filter('canvas.'+apinamespace))\n            .data(apinamespace+'.this').resetCanvas( data, dontClear );\n        return this;\n    }\n\n    function _setDrawingData( data, formattype ) {\n        var undef;\n\n        if (formattype === undef && typeof data === 'string' && data.substr(0,5) === 'data:') {\n            formattype = data.slice(5).split(',')[0];\n            // 5 chars of \"data:\" + mimetype len + 1 \",\" char = all skipped.\n            data = data.slice(6 + formattype.length);\n            if (formattype === data) {\n                return;\n            }\n        }\n\n        var $canvas = this.find('canvas.'+apinamespace).add(this.filter('canvas.'+apinamespace));\n\n        if (!importplugins.hasOwnProperty(formattype)) {\n            throw new Error(apinamespace + \" is unable to find import plugin with for format '\"+ String(formattype) +\"'\");\n        } else if ($canvas.length !== 0) {\n            importplugins[formattype].call(\n                $canvas[0]\n                , data\n                , formattype\n                , (function(jSignatureInstance){ \n                    return function(){ return jSignatureInstance.resetCanvas.apply(jSignatureInstance, arguments) }\n                })($canvas.data(apinamespace+'.this'))\n            );\n        }\n\n        return this;\n    }\n\n    var elementIsOrphan = function(e){\n        var topOfDOM = false;\n        e = e.parentNode;\n        while (e && !topOfDOM){\n            topOfDOM = e.body;\n            e = e.parentNode;\n        }\n        return !topOfDOM;\n    }\n\n    //These are exposed as methods under $obj.jSignature('methodname', *args)\n    var plugins = {'export':exportplugins, 'import':importplugins, 'instance': jSignatureInstanceExtensions}\n    , methods = {\n        'init' : function( options ) {\n            return this.each( function() {\n                if (!elementIsOrphan(this)) {\n                    new jSignatureClass(this, options, jSignatureInstanceExtensions);\n                }\n            })\n        }\n        , 'getSettings' : function() {\n            return this.find('canvas.'+apinamespace)\n                .add(this.filter('canvas.'+apinamespace))\n                .data(apinamespace+'.this').settings;\n        }\n        , 'isModified' : function() {\n            return this.find('canvas.'+apinamespace)\n                .add(this.filter('canvas.'+apinamespace))\n                .data(apinamespace+'.this')\n                .dataEngine\n                ._stroke !== null;\n        }\n        , 'updateSetting' : function(param, val, forFuture) {\n            var $canvas = this.find('canvas.'+apinamespace)\n                            .add(this.filter('canvas.'+apinamespace))\n                            .data(apinamespace+'.this');\n            $canvas.settings[param] = val;\n            $canvas.resetCanvas(( forFuture ? null : $canvas.settings.data ), true);\n            return $canvas.settings[param];\n        }\n        // around since v1\n        , 'clear' : _clearDrawingArea\n        // was mistakenly introduced instead of 'clear' in v2\n        , 'reset' : _clearDrawingArea\n        , 'addPlugin' : function(pluginType, pluginName, callable){\n            if (plugins.hasOwnProperty(pluginType)){\n                plugins[pluginType][pluginName] = callable;\n            }\n            return this;\n        }\n        , 'listPlugins' : function(pluginType){\n            var answer = [];\n            if (plugins.hasOwnProperty(pluginType)){\n                var o = plugins[pluginType];\n                for (var k in o){\n                    if (o.hasOwnProperty(k)){\n                        answer.push(k);\n                    }\n                }\n            }\n            return answer;\n        }\n        , 'getData' : function( formattype ) {\n            var undef, $canvas=this.find('canvas.'+apinamespace).add(this.filter('canvas.'+apinamespace));\n            if (formattype === undef) {\n                formattype = 'default';\n            }\n            if ($canvas.length !== 0 && exportplugins.hasOwnProperty(formattype)){              \n                return exportplugins[formattype].call(\n                    $canvas.get(0) // canvas dom elem\n                    , $canvas.data(apinamespace+'.data') // raw signature data as array of objects of arrays\n                    , $canvas.data(apinamespace+'.settings')\n                );\n            }\n        }\n        // around since v1. Took only one arg - data-url-formatted string with (likely png of) signature image\n        , 'importData' : _setDrawingData\n        // was mistakenly introduced instead of 'importData' in v2\n        , 'setData' : _setDrawingData\n        // this is one and same instance for all jSignature.\n        , 'globalEvents' : function(){return globalEvents}\n        , 'disable' : function() {\n            this.find(\"input\").attr(\"disabled\", 1);\n            this.find('canvas.'+apinamespace)\n                .addClass(\"disabled\")\n                .data(apinamespace+'.this')\n                .settings\n                .readOnly=true;\n        }\n        , 'enable' : function() {\n            this.find(\"input\").removeAttr(\"disabled\");\n            this.find('canvas.'+apinamespace)\n                .removeClass(\"disabled\")\n                .data(apinamespace+'.this')\n                .settings\n                .readOnly=false;\n        }\n        // there will be a separate one for each jSignature instance.\n        , 'events' : function() {\n            return this.find('canvas.'+apinamespace)\n                    .add(this.filter('canvas.'+apinamespace))\n                    .data(apinamespace+'.this').events;\n        }\n    } // end of methods declaration.\n    \n    $.fn[apinamespace] = function(method) {\n        'use strict'\n        if ( !method || typeof method === 'object' ) {\n            return methods.init.apply( this, arguments );\n        } else if ( typeof method === 'string' && methods[method] ) {\n            return methods[method].apply( this, Array.prototype.slice.call( arguments, 1 ));\n        } else {\n            $.error( 'Method ' +  String(method) + ' does not exist on jQuery.' + apinamespace );\n        }\n    }\n\n} // end of GlobalJSignatureObjectInitializer\n\nGlobalJSignatureObjectInitializer(window)\n\n})();\n", "/*\nCopyright (c) 2013, Fabien Meghazi\n\nReleased under the MIT license\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal in\nthe Software without restriction, including without limitation the rights to use,\ncopy, modify, merge, publish, distribute, sublicense, and/or sell copies of the\nSoftware, and to permit persons to whom the Software is furnished to do so,\nsubject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\nFOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\nCOPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN\nAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n*/\n\n// TODO: trim support\n// TODO: line number -> https://bugzilla.mozilla.org/show_bug.cgi?id=618650\n// TODO: templates orverwritten could be called by t-call=\"__super__\" ?\n// TODO: t-set + t-value + children node == scoped variable ?\nvar QWeb2 = {\n    expressions_cache: { },\n    RESERVED_WORDS: 'true,false,NaN,null,undefined,debugger,console,window,in,instanceof,new,function,return,this,typeof,eval,void,Math,RegExp,Array,Object,Date'.split(','),\n    ACTIONS_PRECEDENCE: 'foreach,if,elif,else,call,set,tag,out,esc,raw,js,debug,log'.split(','),\n    WORD_REPLACEMENT: {\n        'and': '&&',\n        'or': '||',\n        'gt': '>',\n        'gte': '>=',\n        'lt': '<',\n        'lte': '<='\n    },\n    VOID_ELEMENTS: 'area,base,br,col,embed,hr,img,input,keygen,link,menuitem,meta,param,source,track,wbr'.split(','),\n    tools: {\n        exception: function(message, context) {\n            context = context || {};\n            var prefix = 'QWeb2';\n            if (context.template) {\n                prefix += \" - template['\" + context.template + \"']\";\n            }\n            throw new Error(prefix + \": \" + message);\n        },\n        warning : function(message) {\n            if (typeof(window) !== 'undefined' && window.console) {\n                window.console.warn(message);\n            }\n        },\n        trim: function(s, mode) {\n            switch (mode) {\n                case \"left\":\n                    return s.replace(/^\\s*/, \"\");\n                case \"right\":\n                    return s.replace(/\\s*$/, \"\");\n                default:\n                    return s.replace(/^\\s*|\\s*$/g, \"\");\n            }\n        },\n        js_escape: function(s, noquotes) {\n            return (noquotes ? '' : \"'\") + s.replace(/\\r?\\n/g, \"\\\\n\").replace(/'/g, \"\\\\'\") + (noquotes ? '' : \"'\");\n        },\n        html_escape: function(s) {\n            if (s == null) {\n                return '';\n            }\n            return _.escape(s);\n        },\n        markup(s) {\n            return new _Markup(s);\n        },\n        gen_attribute: function(o) {\n            if (o !== null && o !== undefined) {\n                if (o.constructor === Array) {\n                    if (o[1] !== null && o[1] !== undefined) {\n                        return this.format_attribute(o[0], o[1]);\n                    }\n                } else if (typeof o === 'object') {\n                    var r = '';\n                    for (var k in o) {\n                        if (o.hasOwnProperty(k)) {\n                            r += this.gen_attribute([k, o[k]]);\n                        }\n                    }\n                    return r;\n                }\n            }\n            return '';\n        },\n        format_attribute: function(name, value) {\n            // we want to ensure `value` is *not* a `Markup`, because markup-safe\n            // strings are not necessarily attributes-safe.\n            const attrvalue = value == null ? '' : this.html_escape(String(value));\n            return ` ${name}=\"${attrvalue}\"`;\n        },\n        extend: function(dst, src, exclude) {\n            for (var p in src) {\n                if (src.hasOwnProperty(p) && !(exclude && this.arrayIndexOf(exclude, p) !== -1)) {\n                    dst[p] = src[p];\n                }\n            }\n            return dst;\n        },\n        arrayIndexOf : function(array, item) {\n            for (var i = 0, ilen = array.length; i < ilen; i++) {\n                if (array[i] === item) {\n                    return i;\n                }\n            }\n            return -1;\n        },\n        get_element_sibling: function(node, dom_attr) {\n            // This helper keeps support for IE8 which does not\n            // implement DOMNode.(previous|next)ElementSibling\n            var sibling = node[dom_attr];\n            while (sibling && sibling.nodeType !== 1) {\n                sibling = sibling[dom_attr];\n            }\n            return sibling;\n        },\n        xml_node_to_string : function(node, childs_only) {\n            if (childs_only) {\n                var childs = node.childNodes, r = [];\n                for (var i = 0, ilen = childs.length; i < ilen; i++) {\n                    r.push(this.xml_node_to_string(childs[i]));\n                }\n                return r.join('');\n            } else {\n                // avoid XMLSerializer with text node for IE\n                if (node.nodeType == 3) {\n                    return node.data;\n                }\n                if (typeof XMLSerializer !== 'undefined') {\n                    return (new XMLSerializer()).serializeToString(node);\n                } else {\n                    switch(node.nodeType) {\n                    case 1: return node.outerHTML;\n                    case 4: return '<![CDATA[' + node.data + ']]>';\n                    case 8: return '<!-- ' + node.data + '-->';\n                    }\n                    throw new Error('Unknown node type ' + node.nodeType);\n                }\n            }\n        },\n        call: function(context, template, old_dict, _import, callback) {\n            var new_dict = this.extend({}, old_dict);\n            new_dict['__caller__'] = old_dict['__template__'];\n            if (callback) {\n                new_dict[0] = this.markup(callback(context, new_dict));\n            }\n            return this.markup(context.engine._render(template, new_dict));\n        },\n        foreach: function(context, enu, as, old_dict, callback) {\n            if (enu != null) {\n                var index, jlen, cur;\n                var new_dict = this.extend({}, old_dict);\n                new_dict[as + \"_all\"] = enu;\n                var as_value = as + \"_value\",\n                    as_index = as + \"_index\",\n                    as_first = as + \"_first\",\n                    as_last = as + \"_last\",\n                    as_parity = as + \"_parity\";\n                if (enu instanceof Array) {\n                    var size = enu.length;\n                    new_dict[as + \"_size\"] = size;\n                    for (index = 0, jlen = enu.length; index < jlen; index++) {\n                        cur = enu[index];\n                        new_dict[as_value] = cur;\n                        new_dict[as_index] = index;\n                        new_dict[as_first] = index === 0;\n                        new_dict[as_last] = index + 1 === size;\n                        new_dict[as_parity] = (index % 2 == 1 ? 'odd' : 'even');\n                        if (cur && cur.constructor === Object) {\n                            this.extend(new_dict, cur);\n                        }\n                        new_dict[as] = cur;\n                        callback(context, new_dict);\n                    }\n                } else if (enu.constructor == Number) {\n                    var _enu = [];\n                    for (var i = 0; i < enu; i++) {\n                        _enu.push(i);\n                    }\n                    this.foreach(context, _enu, as, old_dict, callback);\n                } else {\n                    index = 0;\n                    for (var k in enu) {\n                        if (enu.hasOwnProperty(k)) {\n                            cur = enu[k];\n                            new_dict[as_value] = cur;\n                            new_dict[as_index] = index;\n                            new_dict[as_first] = index === 0;\n                            new_dict[as_parity] = (index % 2 == 1 ? 'odd' : 'even');\n                            new_dict[as] = k;\n                            callback(context, new_dict);\n                            index += 1;\n                        }\n                      }\n                }\n\n                _.each(Object.keys(old_dict), function(z) {\n                    old_dict[z] = new_dict[z];\n                });\n            } else {\n                this.exception(\"No enumerator given to foreach\", context);\n            }\n        }\n    }\n};\n\nQWeb2.Engine = (function() {\n    function Engine() {\n        // TODO: handle prefix at template level : t-prefix=\"x\", don't forget to lowercase it\n        this.prefix = 't';\n        this.debug = false;\n        this.templates_resources = []; // TODO: implement this.reload()\n        this.templates = {};\n        this.compiled_templates = {};\n        this.extend_templates = {};\n        this.default_dict = {};\n        this.tools = QWeb2.tools;\n        this.jQuery = window.jQuery;\n        this.reserved_words = QWeb2.RESERVED_WORDS.slice(0);\n        this.actions_precedence = QWeb2.ACTIONS_PRECEDENCE.slice(0);\n        this.void_elements = QWeb2.VOID_ELEMENTS.slice(0);\n        this.word_replacement = QWeb2.tools.extend({}, QWeb2.WORD_REPLACEMENT);\n        this.preprocess_node = null;\n        for (var i = 0; i < arguments.length; i++) {\n            this.add_template(arguments[i]);\n        }\n    }\n\n    QWeb2.tools.extend(Engine.prototype, {\n        /**\n         * Add a template to the engine\n         *\n         * @param {String|Document} template Template as string or url or DOM Document\n         * @param {Function} [callback] Called when the template is loaded, force async request\n         */\n        add_template : function(template, callback) {\n            var self = this;\n            this.templates_resources.push(template);\n            if (template.constructor === String) {\n                return this.load_xml(template, function (err, xDoc) {\n                    if (err) {\n                        if (callback) {\n                            return callback(err);\n                        } else {\n                            throw err;\n                        }\n                    }\n                    self.add_template(xDoc, callback);\n                });\n            }\n            template = this.preprocess(template);\n            var ec = (template.documentElement && template.documentElement.childNodes) || template.childNodes || [];\n            for (var i = 0; i < ec.length; i++) {\n                var node = ec[i];\n                if (node.nodeType === 1) {\n                    var name = node.getAttribute(this.prefix + '-name');\n                    var extend = node.getAttribute(this.prefix + '-extend');\n                    if (name && extend) {\n                        // Clone template and extend it\n                        if (!this.templates[extend]) {\n                            return this.tools.exception(\"Can't clone undefined template \" + extend);\n                        }\n                        this.templates[name] = this.templates[extend].cloneNode(true);\n                        this.extend_templates[name] = (this.extend_templates[extend] || []).slice();\n                        extend = name;\n                        name = undefined;\n                    }\n                    if (name) {\n                        this.templates[name] = node;\n                        this.compiled_templates[name] = null;\n                    } else if (extend) {\n                        delete(this.compiled_templates[extend]);\n                        if (this.extend_templates[extend]) {\n                            this.extend_templates[extend].push(node);\n                        } else {\n                            this.extend_templates[extend] = [node];\n                        }\n                    }\n                }\n            }\n            if (callback) {\n                callback(null, template);\n            }\n            return true;\n        },\n        preprocess: function(doc) {\n            /**\n             * Preprocess a template's document at load time.\n             * This method is mostly used for template sanitization but could\n             * also be overloaded for extended features such as translations, ...\n             * Throws an exception if a template is invalid.\n             *\n             * @param {Document} doc Document containg the loaded templates\n             * @return {Document} Returns the pre-processed/sanitized template\n             */\n            var self = this;\n            var childs = (doc.documentElement && doc.documentElement.childNodes) || doc.childNodes || [];\n\n            // Check for load errors\n            for (var i = 0; i < childs.length; i++) {\n                var node = childs[i];\n                if (node.nodeType === 1 && node.nodeName == 'parsererror') {\n                    return this.tools.exception(node.innerText);\n                }\n            }\n\n            // Sanitize t-elif and t-else directives\n            var tbranch = doc.querySelectorAll('[t-elif], [t-else]');\n            for (var i = 0, ilen = tbranch.length; i < ilen; i++) {\n                var node = tbranch[i];\n                var prev_elem = self.tools.get_element_sibling(node, 'previousSibling');\n                var pattr = function(name) { return prev_elem.getAttribute(name); }\n                var nattr = function(name) { return +!!node.getAttribute(name); }\n                if (prev_elem && (pattr('t-if') || pattr('t-elif'))) {\n                    if (pattr('t-foreach')) {\n                        return self.tools.exception(\"Error: t-if cannot stay at the same level as t-foreach when using t-elif or t-else\");\n                    }\n                    if (['t-if', 't-elif', 't-else'].map(nattr).reduce(function(a, b) { return a + b; }) > 1) {\n                        return self.tools.exception(\"Error: only one conditional branching directive is allowed per node\");\n                    }\n                    // All text nodes between branch nodes are removed\n                    var text_node;\n                    while ((text_node = node.previousSibling) !== prev_elem) {\n                        if (text_node.nodeType !== 8 && self.tools.trim(text_node.nodeValue)) {\n                            return self.tools.exception(\"Error: text is not allowed between branching directives\");\n                        }\n                        // IE <= 11.0 doesn't support ChildNode.remove\n                        text_node.parentNode.removeChild(text_node);\n                    }\n                } else {\n                    return self.tools.exception(\"Error: t-elif and t-else directives must be preceded by a t-if or t-elif directive\");\n                }\n            }\n\n            return doc;\n        },\n        load_xml : function(s, callback) {\n            var self = this;\n            var async = !!callback;\n            s = this.tools.trim(s);\n            if (s.charAt(0) === '<') {\n                var tpl = this.load_xml_string(s);\n                if (callback) {\n                    callback(null, tpl);\n                }\n                return tpl;\n            } else {\n                var req = this.get_xhr();\n                if (this.debug) {\n                    s += '?debug=' + (new Date()).getTime(); // TODO fme: do it properly in case there's already url parameters\n                }\n                req.open('GET', s, async);\n                if (async) {\n                    req.addEventListener(\"load\", function() {\n                        // 0, not being a valid HTTP status code, is used by browsers\n                        // to indicate success for a non-http xhr response\n                        // (for example, using the file:// protocol)\n                        // https://developer.mozilla.org/fr/docs/Web/API/XMLHttpRequest\n                        // https://bugzilla.mozilla.org/show_bug.cgi?id=331610\n                        if (req.status == 200 || req.status == 0) {\n                            callback(null, self._parse_from_request(req));\n                        } else {\n                            callback(new Error(\"Can't load template \" + s + \", http status \" + req.status));\n                        }\n                    });\n                }\n                req.send(null);\n                if (!async) {\n                    return this._parse_from_request(req);\n                }\n            }\n        },\n        _parse_from_request: function(req) {\n            var xDoc = req.responseXML;\n            if (xDoc) {\n                if (!xDoc.documentElement) {\n                    throw new Error(\"QWeb2: This xml document has no root document : \" + xDoc.responseText);\n                }\n                if (xDoc.documentElement.nodeName == \"parsererror\") {\n                    throw new Error(\"QWeb2: Could not parse document :\" + xDoc.documentElement.childNodes[0].nodeValue);\n                }\n                return xDoc;\n            } else {\n                return this.load_xml_string(req.responseText);\n            }\n        },\n        load_xml_string : function(s) {\n            if (window.DOMParser) {\n                var dp = new DOMParser();\n                var r = dp.parseFromString(s, \"text/xml\");\n                if (r.body && r.body.firstChild && r.body.firstChild.nodeName == 'parsererror') {\n                    throw new Error(\"QWeb2: Could not parse document :\" + r.body.innerText);\n                }\n                return r;\n            }\n            var xDoc;\n            try {\n                xDoc = new ActiveXObject(\"MSXML2.DOMDocument\");\n            } catch (e) {\n                throw new Error(\"Could not find a DOM Parser: \" + e.message);\n            }\n            xDoc.async = false;\n            xDoc.preserveWhiteSpace = true;\n            xDoc.loadXML(s);\n            return xDoc;\n        },\n        has_template : function(template) {\n            return !!this.templates[template];\n        },\n        get_xhr : function() {\n            if (window.XMLHttpRequest) {\n                return new window.XMLHttpRequest();\n            }\n            try {\n                return new ActiveXObject('MSXML2.XMLHTTP.3.0');\n            } catch (e) {\n                throw new Error(\"Could not get XHR\");\n            }\n        },\n        compile : function(node) {\n            var e = new QWeb2.Element(this, node);\n            var template = node.getAttribute(this.prefix + '-name');\n            return  \"   /* 'this' refers to Qweb2.Engine instance */\\n\" +\n                    \"   var context = { engine : this, template : \" + (this.tools.js_escape(template)) + \" };\\n\" +\n                    \"   dict = dict || {};\\n\" +\n                    \"   dict['__template__'] = '\" + template + \"';\\n\" +\n                    \"   var r = [];\\n\" +\n                    \"   /* START TEMPLATE */\" +\n                    (this.debug ? \"\" : \" try {\\n\") +\n                    (e.compile()) + \"\\n\" +\n                    \"   /* END OF TEMPLATE */\" +\n                    (this.debug ? \"\" : \" } catch(error) {\\n\" +\n                    \"       if (console && console.exception) console.exception(error);\\n\" +\n                    \"       context.engine.tools.exception('Runtime Error: ' + error, context);\\n\") +\n                    (this.debug ? \"\" : \"   }\\n\") +\n                    \"   return r.join('');\";\n        },\n        render : function(template, dict) {\n            dict = dict || {};\n            QWeb2.tools.extend(dict, this.default_dict);\n            /*if (this.debug && window['console'] !== undefined) {\n                console.time(\"QWeb render template \" + template);\n            }*/\n            var r = this._render(template, dict);\n            /*if (this.debug && window['console'] !== undefined) {\n                console.timeEnd(\"QWeb render template \" + template);\n            }*/\n            return r;\n        },\n        _render : function(template, dict) {\n            if (this.compiled_templates[template]) {\n                return this.compiled_templates[template].apply(this, [dict || {}]);\n            } else if (this.templates[template]) {\n                var ext;\n                if (ext = this.extend_templates[template]) {\n                    var extend_node;\n                    while (extend_node = ext.shift()) {\n                        this.extend(template, extend_node);\n                    }\n                }\n                var code = this.compile(this.templates[template]), tcompiled;\n                try {\n                    tcompiled = new Function(['dict'], code);\n                } catch (error) {\n                    if (this.debug && window.console) {\n                        console.log(code);\n                    }\n                    this.tools.exception(\"Error evaluating template: \" + error, { template: template });\n                }\n                if (!tcompiled) {\n                    this.tools.exception(\"Error evaluating template: (IE?)\" + error, { template: template });\n                }\n                this.compiled_templates[template] = tcompiled;\n                return this.render(template, dict);\n            } else {\n                return this.tools.exception(\"Template '\" + template + \"' not found\");\n            }\n        },\n        extend : function(template, extend_node) {\n            var jQuery = this.jQuery;\n            if (!jQuery) {\n                return this.tools.exception(\"Can't extend template \" + template + \" without jQuery\");\n            }\n            var template_dest = this.templates[template];\n            for (var i = 0, ilen = extend_node.childNodes.length; i < ilen; i++) {\n                var child = extend_node.childNodes[i];\n                if (child.nodeType === 1) {\n                    var jquery = child.getAttribute(this.prefix + '-jquery'),\n                        operation = child.getAttribute(this.prefix + '-operation'),\n                        target,\n                        error_msg = \"Error while extending template '\" + template;\n                    if (jquery) {\n                        target = jQuery(jquery, template_dest);\n                        if (!target.length && window.console) {\n                            console.error(\"Can't find '\" + jquery + \"' when extending template \" + template);\n                        }\n                    } else {\n                        this.tools.exception(error_msg + \"No expression given\");\n                    }\n                    error_msg += \"' (expression='\" + jquery + \"') : \";\n                    if (operation) {\n                        var allowed_operations = \"append,prepend,before,after,replace,inner,attributes\".split(',');\n                        if (this.tools.arrayIndexOf(allowed_operations, operation) == -1) {\n                            this.tools.exception(error_msg + \"Invalid operation : '\" + operation + \"'\");\n                        }\n                        operation = {'replace' : 'replaceWith', 'inner' : 'html'}[operation] || operation;\n                        if (operation === 'attributes') {\n                            jQuery('attribute', child).each(function () {\n                                var attrib = jQuery(this);\n                                target.attr(attrib.attr('name'), attrib.text() || attrib.attr('value'));\n                            });\n                        } else {\n                            target[operation](child.cloneNode(true).childNodes);\n                        }\n                    } else {\n                        try {\n                            var f = new Function(['$', 'document'], this.tools.xml_node_to_string(child, true));\n                        } catch(error) {\n                            return this.tools.exception(\"Parse \" + error_msg + error);\n                        }\n                        try {\n                            f.apply(target, [jQuery, template_dest.ownerDocument]);\n                        } catch(error) {\n                            return this.tools.exception(\"Runtime \" + error_msg + error);\n                        }\n                    }\n                }\n            }\n        }\n    });\n    return Engine;\n})();\n\nQWeb2.Element = (function() {\n    function Element(engine, node) {\n        this.engine = engine;\n        this.node = node;\n        this.tag = node.tagName;\n        this.actions = {tag: this.tag};\n        this.actions_done = [];\n        this.attributes = {};\n        this.children = [];\n        this._top = [];\n        this._bottom = [];\n        this._indent = 1;\n        this.process_children = true;\n        this.is_void_element = ~QWeb2.tools.arrayIndexOf(this.engine.void_elements, this.tag);\n        var childs = this.node.childNodes;\n        if (childs) {\n            for (var i = 0, ilen = childs.length; i < ilen; i++) {\n                this.children.push(new QWeb2.Element(this.engine, childs[i]));\n            }\n        }\n        var attrs = this.node.attributes;\n        if (attrs) {\n            for (var j = 0, jlen = attrs.length; j < jlen; j++) {\n                var attr = attrs[j];\n                var name = attr.name;\n                var m = name.match(new RegExp(\"^\" + this.engine.prefix + \"-(.+)\"));\n                if (m) {\n                    name = m[1];\n                    if (name === 'name') {\n                        continue;\n                    }\n                    if (name.match(/^attf?(-.*)?/)) {\n                        this.attributes[m[0]] = attr.value;\n                    } else {\n                        this.actions[name] = attr.value;\n                    }\n                } else {\n                    this.attributes[name] = attr.value;\n                }\n            }\n        }\n        if (this.engine.preprocess_node) {\n            this.engine.preprocess_node.call(this);\n        }\n    }\n\n    QWeb2.tools.extend(Element.prototype, {\n        compile : function() {\n            var r = [],\n                instring = false,\n                lines = this._compile().split('\\n');\n            for (var i = 0, ilen = lines.length; i < ilen; i++) {\n                var m, line = lines[i];\n                if (m = line.match(/^(\\s*)\\/\\/@string=(.*)/)) {\n                    if (instring) {\n                        if (this.engine.debug) {\n                            // Split string lines in indented r.push arguments\n                            r.push((m[2].indexOf(\"\\\\n\") != -1 ? \"',\\n\\t\" + m[1] + \"'\" : '') + m[2]);\n                        } else {\n                            r.push(m[2]);\n                        }\n                    } else {\n                        r.push(m[1] + \"r.push('\" + m[2]);\n                        instring = true;\n                    }\n                } else {\n                    if (instring) {\n                        r.push(\"');\\n\");\n                    }\n                    instring = false;\n                    r.push(line + '\\n');\n                }\n            }\n            return r.join('');\n        },\n        _compile : function() {\n            switch (this.node.nodeType) {\n                case 3:\n                case 4:\n                    this.top_string(this.node.data);\n                break;\n                case 1:\n                    this.compile_element();\n            }\n            var r = this._top.join('');\n            if (this.process_children) {\n                for (var i = 0, ilen = this.children.length; i < ilen; i++) {\n                    var child = this.children[i];\n                    child._indent = this._indent;\n                    r += child._compile();\n                }\n            }\n            r += this._bottom.join('');\n            return r;\n        },\n        format_expression : function(e) {\n            /* Naive format expression builder. Replace reserved words and variables to dict[variable]\n             * Does not handle spaces before dot yet, and causes problems for anonymous functions. Use t-js=\"\" for that */\n             if (QWeb2.expressions_cache[e]) {\n              return QWeb2.expressions_cache[e];\n            }\n            var chars = e.split(''),\n                instring = '',\n                invar = '',\n                invar_pos = 0,\n                r = '';\n            chars.push(' ');\n            for (var i = 0, ilen = chars.length; i < ilen; i++) {\n                var c = chars[i];\n                if (instring.length) {\n                    if (c === instring && chars[i - 1] !== \"\\\\\") {\n                        instring = '';\n                    }\n                } else if (c === '\"' || c === \"'\") {\n                    instring = c;\n                } else if (c.match(/[a-zA-Z_\\$]/) && !invar.length) {\n                    invar = c;\n                    invar_pos = i;\n                    continue;\n                } else if (c.match(/\\W/) && invar.length) {\n                    // TODO: Should check for possible spaces before dot\n                    if (chars[invar_pos - 1] !== '.' && QWeb2.tools.arrayIndexOf(this.engine.reserved_words, invar) < 0) {\n                        invar = this.engine.word_replacement[invar] || (\"dict['\" + invar + \"']\");\n                    }\n                    r += invar;\n                    invar = '';\n                } else if (invar.length) {\n                    invar += c;\n                    continue;\n                }\n                r += c;\n            }\n            r = r.slice(0, -1);\n            QWeb2.expressions_cache[e] = r;\n            return r;\n        },\n        format_str: function (e) {\n            if (e == '0') {\n                return 'dict[0]';\n            }\n            return this.format_expression(e);\n        },\n        string_interpolation : function(s) {\n            var _this = this;\n            if (!s) {\n              return \"''\";\n            }\n            function append_literal(s) {\n                s && r.push(_this.engine.tools.js_escape(s));\n            }\n\n            var re = /#{(.+?)}|{{(.+?)}}/g, start = 0, r = [], m;\n            while (m = re.exec(s)) {\n                // extract literal string between previous and current match\n                append_literal(s.slice(start, re.lastIndex - m[0].length));\n                // extract matched expression\n                r.push('(' + this.format_str(m[2] || m[1]) + ')');\n                // update position of new matching\n                start = re.lastIndex;\n            }\n            // remaining text after last expression\n            append_literal(s.slice(start));\n\n            return r.join(' + ');\n        },\n        indent : function() {\n            return this._indent++;\n        },\n        dedent : function() {\n            if (this._indent !== 0) {\n                return this._indent--;\n            }\n        },\n        get_indent : function() {\n            return new Array(this._indent + 1).join(\"\\t\");\n        },\n        top : function(s) {\n            return this._top.push(this.get_indent() + s + '\\n');\n        },\n        top_string : function(s) {\n            return this._top.push(this.get_indent() + \"//@string=\" + this.engine.tools.js_escape(s, true) + '\\n');\n        },\n        bottom : function(s) {\n            return this._bottom.unshift(this.get_indent() + s + '\\n');\n        },\n        bottom_string : function(s) {\n            return this._bottom.unshift(this.get_indent() + \"//@string=\" + this.engine.tools.js_escape(s, true) + '\\n');\n        },\n        compile_element : function() {\n            for (var i = 0, ilen = this.engine.actions_precedence.length; i < ilen; i++) {\n                var a = this.engine.actions_precedence[i];\n                if (a in this.actions) {\n                    var value = this.actions[a];\n                    var key = 'compile_action_' + a;\n                    if (this[key]) {\n                        this[key](value);\n                    } else if (this.engine[key]) {\n                        this.engine[key].call(this, value);\n                    } else {\n                        this.engine.tools.exception(\"No handler method for action '\" + a + \"'\");\n                    }\n                }\n            }\n        },\n        compile_action_tag : function() {\n            if (this.tag.toLowerCase() !== this.engine.prefix) {\n                this.top_string(\"<\" + this.tag);\n                for (var a in this.attributes) {\n                    var v = this.attributes[a];\n                    var d = a.split('-');\n                    if (d[0] === this.engine.prefix && d.length > 1) {\n                        if (d.length === 2) {\n                            this.top(\"r.push(context.engine.tools.gen_attribute(\" + (this.format_expression(v)) + \"));\");\n                        } else {\n                            this.top(\"r.push(context.engine.tools.gen_attribute(['\" + d.slice(2).join('-') + \"', (\" +\n                                (d[1] === 'att' ? this.format_expression(v) : this.string_interpolation(v)) + \")]));\");\n                        }\n                    } else {\n                        this.top_string(this.engine.tools.gen_attribute([a, v]));\n                    }\n                }\n\n                if (this.actions.opentag === 'true' || (!this.children.length && this.is_void_element)) {\n                    // We do not enforce empty content on void elements\n                    // because QWeb rendering is not necessarily html.\n                    this.top_string(\"/>\");\n                } else {\n                    this.top_string(\">\");\n                    this.bottom_string(\"</\" + this.tag + \">\");\n                }\n            }\n        },\n        compile_action_if : function(value) {\n            this.top(\"if (\" + (this.format_expression(value)) + \") {\");\n            this.bottom(\"}\");\n            this.indent();\n        },\n        compile_action_elif : function(value) {\n            this.top(\"else if (\" + (this.format_expression(value)) + \") {\");\n            this.bottom(\"}\");\n            this.indent();\n        },\n        compile_action_else : function(value) {\n            this.top(\"else {\");\n            this.bottom(\"}\");\n            this.indent();\n        },\n        compile_action_foreach : function(value) {\n            var as = this.actions['as'] || value.replace(/[^a-zA-Z0-9]/g, '_');\n            //TODO: exception if t-as not valid\n            this.top(\"context.engine.tools.foreach(context, \" + (this.format_expression(value)) + \", \" + (this.engine.tools.js_escape(as)) + \", dict, function(context, dict) {\");\n            this.bottom(\"});\");\n            this.indent();\n        },\n        compile_action_call : function(value) {\n            if (this.children.length === 0) {\n                return this.top(\"r.push(context.engine.tools.call(context, \" + (this.string_interpolation(value)) + \", dict));\");\n            } else {\n                this.top(\"r.push(context.engine.tools.call(context, \" + (this.string_interpolation(value)) + \", dict, null, function(context, dict) {\");\n                this.bottom(\"}));\");\n                this.indent();\n                this.top(\"var r = [];\");\n                return this.bottom(\"return context.engine.tools.markup(r.join(''));\");\n            }\n        },\n        compile_action_set : function(value) {\n            var variable = this.format_expression(value);\n            if (this.actions['value']) {\n                if (this.children.length) {\n                    this.engine.tools.warning(\"@set with @value plus node chidren found. Children are ignored.\");\n                }\n                this.top(variable + \" = (\" + (this.format_expression(this.actions['value'])) + \");\");\n                this.process_children = false;\n            } else {\n                if (this.children.length === 0) {\n                    this.top(variable + \" = '';\");\n                } else if (this.children.length === 1 && this.children[0].node.nodeType === 3) {\n                    this.top(variable + \" = \" + (this.engine.tools.js_escape(this.children[0].node.data)) + \";\");\n                    this.process_children = false;\n                } else {\n                    this.top(variable + \" = (function(dict) {\");\n                    this.bottom(\"})(dict);\");\n                    this.indent();\n                    this.top(\"var r = [];\");\n                    this.bottom(\"return context.engine.tools.markup(r.join(''));\");\n                }\n            }\n        },\n        compile_action_esc : function(value) {\n            return this.compile_action_out(value);\n        },\n        compile_action_out(value) {\n            this.top(\"var t = \" + this.format_str(value) + \";\");\n            this.top(\"if (t != null) r.push(context.engine.tools.html_escape(t));\");\n            this.top(\"else {\");\n            this.bottom(\"}\");\n            this.indent();\n        },\n        compile_action_raw : function(value) {\n            let e = this.node;\n            while (e.parentElement && !e.getAttribute('t-name')) {\n                e = e.parentElement;\n            }\n            console.warn(\n                \"Found deprecated directive '@t-raw=\\\"%s\\\"' in \"\n              + \"template '%s'. Replace by @t-out, and explicitely wrap content in \"\n              + \"utils.Markup if necessary.\", value, e.getAttribute('t-name'));\n            this.top(\"var t = \" + this.format_str(value) + \";\");\n            this.top(\"if (t != null) r.push(t);\");\n            this.top(\"else {\");\n            this.bottom(\"}\");\n            this.indent();\n        },\n        compile_action_js : function(value) {\n            this.top(\"(function(\" + value + \") {\");\n            this.bottom(\"})(dict);\");\n            this.indent();\n            var lines = this.engine.tools.xml_node_to_string(this.node, true).split(/\\r?\\n/);\n            for (var i = 0, ilen = lines.length; i < ilen; i++) {\n                this.top(lines[i]);\n            }\n            this.process_children = false;\n        },\n        compile_action_debug : function(value) {\n            this.top(\"debugger;\");\n        },\n        compile_action_log : function(value) {\n            this.top(\"console.log(\" + this.format_expression(value) + \");\");\n        }\n    });\n    return Element;\n})();\n", "odoo.define('web.autocomplete.extensions', function () {\n'use strict';\n\n/**\n * The jquery autocomplete library extensions and fixes should be done here to\n * avoid patching in place.\n */\n\n// jquery autocomplete tweak to allow html and classnames\nvar proto = $.ui.autocomplete.prototype;\nvar initSource = proto._initSource;\n\nfunction filter( array, term ) {\n    var matcher = new RegExp( $.ui.autocomplete.escapeRegex(term), \"i\" );\n    return $.grep( array, function (value_) {\n        return matcher.test( $( \"<div>\" ).html( value_.label || value_.value || value_ ).text() );\n    });\n}\n\n$.extend(proto, {\n    _initSource: function () {\n        if ( this.options.html && $.isArray(this.options.source) ) {\n            this.source = function (request, response) {\n                response( filter( this.options.source, request.term ) );\n            };\n        } else {\n            initSource.call( this );\n        }\n    },\n    _renderItem: function (ul, item) {\n        return $( \"<li></li>\" )\n            .data( \"item.autocomplete\", item )\n            .append( $( \"<a></a>\" )[ this.options.html ? \"html\" : \"text\" ]( item.label ) )\n            .appendTo( ul )\n            .addClass(item.classname);\n    },\n});\n});\n", "odoo.define('web.bootstrap.extensions', function () {\n'use strict';\n\n/**\n * The bootstrap library extensions and fixes should be done here to avoid\n * patching in place.\n */\n\n/**\n * Review Bootstrap Sanitization: leave it enabled by default but extend it to\n * accept more common tag names like tables and buttons, and common attributes\n * such as style or data-. If a specific tooltip or popover must accept custom\n * tags or attributes, they must be supplied through the whitelist BS\n * parameter explicitely.\n *\n * We cannot disable sanitization because bootstrap uses tooltip/popover\n * DOM attributes in an \"unsafe\" way.\n */\nvar bsSanitizeWhiteList = $.fn.tooltip.Constructor.Default.whiteList;\n\nbsSanitizeWhiteList['*'].push('title', 'style', /^data-[\\w-]+/);\n\nbsSanitizeWhiteList.header = [];\nbsSanitizeWhiteList.main = [];\nbsSanitizeWhiteList.footer = [];\n\nbsSanitizeWhiteList.caption = [];\nbsSanitizeWhiteList.col = ['span'];\nbsSanitizeWhiteList.colgroup = ['span'];\nbsSanitizeWhiteList.table = [];\nbsSanitizeWhiteList.thead = [];\nbsSanitizeWhiteList.tbody = [];\nbsSanitizeWhiteList.tfooter = [];\nbsSanitizeWhiteList.tr = [];\nbsSanitizeWhiteList.th = ['colspan', 'rowspan'];\nbsSanitizeWhiteList.td = ['colspan', 'rowspan'];\n\nbsSanitizeWhiteList.address = [];\nbsSanitizeWhiteList.article = [];\nbsSanitizeWhiteList.aside = [];\nbsSanitizeWhiteList.blockquote = [];\nbsSanitizeWhiteList.section = [];\n\nbsSanitizeWhiteList.button = ['type'];\nbsSanitizeWhiteList.del = [];\n\n/**\n * Returns an extended version of bootstrap default whitelist for sanitization,\n * i.e. a version where, for each key, the original value is concatened with the\n * received version's value and where the received version's extra key/values\n * are added.\n *\n * Note: the returned version\n *\n * @param {Object} extensions\n * @returns {Object} /!\\ the returned whitelist is made from a *shallow* copy of\n *      the default whitelist, extended with given whitelist.\n */\nfunction makeExtendedSanitizeWhiteList(extensions) {\n    var whiteList = _.clone($.fn.tooltip.Constructor.Default.whiteList);\n    Object.keys(extensions).forEach(key => {\n        whiteList[key] = (whiteList[key] || []).concat(extensions[key]);\n    });\n    return whiteList;\n}\n\n/* Bootstrap tooltip defaults overwrite */\n$.fn.tooltip.Constructor.Default.placement = 'auto';\n$.fn.tooltip.Constructor.Default.fallbackPlacement = ['bottom', 'right', 'left', 'top'];\n$.fn.tooltip.Constructor.Default.html = true;\n$.fn.tooltip.Constructor.Default.trigger = 'hover';\n$.fn.tooltip.Constructor.Default.container = 'body';\n$.fn.tooltip.Constructor.Default.boundary = 'window';\n$.fn.tooltip.Constructor.Default.delay = { show: 1000, hide: 0 };\n\nvar bootstrapShowFunction = $.fn.tooltip.Constructor.prototype.show;\n$.fn.tooltip.Constructor.prototype.show = function () {\n    // Overwrite bootstrap tooltip method to prevent showing 2 tooltip at the\n    // same time\n    $('.tooltip').remove();\n    const errorsToIgnore = [\"Please use show on visible elements\"];\n    try {\n        return bootstrapShowFunction.call(this);\n    } catch (error) {\n        if (errorsToIgnore.includes(error.message)) {\n            return 0;\n        }\n        throw error;\n    }\n};\n\n/* Bootstrap scrollspy fix for non-body to spy */\n\nconst bootstrapSpyRefreshFunction = $.fn.scrollspy.Constructor.prototype.refresh;\n$.fn.scrollspy.Constructor.prototype.refresh = function () {\n    bootstrapSpyRefreshFunction.apply(this, arguments);\n    if (this._scrollElement === window || this._config.method !== 'offset') {\n        return;\n    }\n    const baseScrollTop = this._getScrollTop();\n    for (let i = 0; i < this._offsets.length; i++) {\n        this._offsets[i] += baseScrollTop;\n    }\n};\n\n/**\n * In some cases, we need to keep the first element of navbars selected.\n */\nconst bootstrapSpyProcessFunction = $.fn.scrollspy.Constructor.prototype._process;\n$.fn.scrollspy.Constructor.prototype._process = function () {\n    bootstrapSpyProcessFunction.apply(this, arguments);\n    if (this._activeTarget === null && this._config.alwaysKeepFirstActive) {\n        this._activate(this._targets[0]);\n    }\n};\n\n/* Bootstrap modal scrollbar compensation on non-body */\nconst bsSetScrollbarFunction = $.fn.modal.Constructor.prototype._setScrollbar;\n$.fn.modal.Constructor.prototype._setScrollbar = function () {\n    const $scrollable = $().getScrollingElement();\n    if (document.body.contains($scrollable[0])) {\n        $scrollable.compensateScrollbar(true);\n    }\n    return bsSetScrollbarFunction.apply(this, arguments);\n};\nconst bsResetScrollbarFunction = $.fn.modal.Constructor.prototype._resetScrollbar;\n$.fn.modal.Constructor.prototype._resetScrollbar = function () {\n    const $scrollable = $().getScrollingElement();\n    if (document.body.contains($scrollable[0])) {\n        $scrollable.compensateScrollbar(false);\n    }\n    return bsResetScrollbarFunction.apply(this, arguments);\n};\n\nreturn {\n    makeExtendedSanitizeWhiteList: makeExtendedSanitizeWhiteList,\n};\n});\n", "/*\n(The MIT License)\n\nCopyright (c) 2014-2017 Douglas Christopher Wilson\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n */\n\n/**\n * Stripped down to only parsing/decoding.\n */\nodoo.define('web.contentdisposition', function () {\n'use strict';\n\n/**\n * RegExp to match percent encoding escape.\n * @private\n */\nvar HEX_ESCAPE_REPLACE_REGEXP = /%([0-9A-Fa-f]{2})/g;\n\n/**\n * RegExp to match non-latin1 characters.\n * @private\n */\nvar NON_LATIN1_REGEXP = /[^\\x20-\\x7e\\xa0-\\xff]/g;\n\n/**\n * RegExp to match quoted-pair in RFC 2616\n *\n * quoted-pair = \"\\\" CHAR\n * CHAR        = <any US-ASCII character (octets 0 - 127)>\n * @private\n */\nvar QESC_REGEXP = /\\\\([\\u0000-\\u007f])/g;\n\n/**\n * RegExp for various RFC 2616 grammar\n *\n * parameter     = token \"=\" ( token | quoted-string )\n * token         = 1*<any CHAR except CTLs or separators>\n * separators    = \"(\" | \")\" | \"<\" | \">\" | \"@\"\n *               | \",\" | \";\" | \":\" | \"\\\" | <\">\n *               | \"/\" | \"[\" | \"]\" | \"?\" | \"=\"\n *               | \"{\" | \"}\" | SP | HT\n * quoted-string = ( <\"> *(qdtext | quoted-pair ) <\"> )\n * qdtext        = <any TEXT except <\">>\n * quoted-pair   = \"\\\" CHAR\n * CHAR          = <any US-ASCII character (octets 0 - 127)>\n * TEXT          = <any OCTET except CTLs, but including LWS>\n * LWS           = [CRLF] 1*( SP | HT )\n * CRLF          = CR LF\n * CR            = <US-ASCII CR, carriage return (13)>\n * LF            = <US-ASCII LF, linefeed (10)>\n * SP            = <US-ASCII SP, space (32)>\n * HT            = <US-ASCII HT, horizontal-tab (9)>\n * CTL           = <any US-ASCII control character (octets 0 - 31) and DEL (127)>\n * OCTET         = <any 8-bit sequence of data>\n * @private\n */\nvar PARAM_REGEXP = /;[\\x09\\x20]*([!#$%&'*+.0-9A-Z^_`a-z|~-]+)[\\x09\\x20]*=[\\x09\\x20]*(\"(?:[\\x20!\\x23-\\x5b\\x5d-\\x7e\\x80-\\xff]|\\\\[\\x20-\\x7e])*\"|[!#$%&'*+.0-9A-Z^_`a-z|~-]+)[\\x09\\x20]*/g;\n\n/**\n * RegExp for various RFC 5987 grammar\n *\n * ext-value     = charset  \"'\" [ language ] \"'\" value-chars\n * charset       = \"UTF-8\" / \"ISO-8859-1\" / mime-charset\n * mime-charset  = 1*mime-charsetc\n * mime-charsetc = ALPHA / DIGIT\n *               / \"!\" / \"#\" / \"$\" / \"%\" / \"&\"\n *               / \"+\" / \"-\" / \"^\" / \"_\" / \"`\"\n *               / \"{\" / \"}\" / \"~\"\n * language      = ( 2*3ALPHA [ extlang ] )\n *               / 4ALPHA\n *               / 5*8ALPHA\n * extlang       = *3( \"-\" 3ALPHA )\n * value-chars   = *( pct-encoded / attr-char )\n * pct-encoded   = \"%\" HEXDIG HEXDIG\n * attr-char     = ALPHA / DIGIT\n *               / \"!\" / \"#\" / \"$\" / \"&\" / \"+\" / \"-\" / \".\"\n *               / \"^\" / \"_\" / \"`\" / \"|\" / \"~\"\n * @private\n */\nvar EXT_VALUE_REGEXP = /^([A-Za-z0-9!#$%&+\\-^_`{}~]+)'(?:[A-Za-z]{2,3}(?:-[A-Za-z]{3}){0,3}|[A-Za-z]{4,8}|)'((?:%[0-9A-Fa-f]{2}|[A-Za-z0-9!#$&+.^_`|~-])+)$/;\n\n/**\n * RegExp for various RFC 6266 grammar\n *\n * disposition-type = \"inline\" | \"attachment\" | disp-ext-type\n * disp-ext-type    = token\n * disposition-parm = filename-parm | disp-ext-parm\n * filename-parm    = \"filename\" \"=\" value\n *                  | \"filename*\" \"=\" ext-value\n * disp-ext-parm    = token \"=\" value\n *                  | ext-token \"=\" ext-value\n * ext-token        = <the characters in token, followed by \"*\">\n * @private\n */\nvar DISPOSITION_TYPE_REGEXP = /^([!#$%&'*+.0-9A-Z^_`a-z|~-]+)[\\x09\\x20]*(?:$|;)/;\n\n/**\n * Decode a RFC 6987 field value (gracefully).\n *\n * @param {string} str\n * @return {string}\n * @private\n */\nfunction decodefield(str) {\n    var match = EXT_VALUE_REGEXP.exec(str);\n\n    if (!match) {\n        throw new TypeError('invalid extended field value')\n    }\n\n    var charset = match[1].toLowerCase();\n    var encoded = match[2];\n\n    switch (charset) {\n    case 'iso-8859-1':\n        return encoded.replace(HEX_ESCAPE_REPLACE_REGEXP, pdecode).replace(NON_LATIN1_REGEXP, '?');\n    case 'utf-8':\n        return decodeURIComponent(encoded);\n    default:\n        throw new TypeError('unsupported charset in extended field')\n    }\n}\n\n/**\n * Parse Content-Disposition header string.\n *\n * @param {string} string\n * @return {ContentDisposition}\n * @public\n */\nfunction parse(string) {\n    if (!string || typeof string !== 'string') {\n        throw new TypeError('argument string is required')\n    }\n\n    var match = DISPOSITION_TYPE_REGEXP.exec(string);\n\n    if (!match) {\n        throw new TypeError('invalid type format')\n    }\n\n    // normalize type\n    var index = match[0].length;\n    var type = match[1].toLowerCase();\n\n    var key;\n    var names = [];\n    var params = {};\n    var value;\n\n    // calculate index to start at\n    index = PARAM_REGEXP.lastIndex = match[0].substr(-1) === ';' ? index - 1 : index;\n\n    // match parameters\n    while ((match = PARAM_REGEXP.exec(string))) {\n        if (match.index !== index) {\n            throw new TypeError('invalid parameter format')\n        }\n\n        index += match[0].length;\n        key = match[1].toLowerCase();\n        value = match[2];\n\n        if (names.indexOf(key) !== -1) {\n            throw new TypeError('invalid duplicate parameter')\n        }\n\n        names.push(key);\n\n        if (key.indexOf('*') + 1 === key.length) {\n            // decode extended value\n            key = key.slice(0, -1);\n            value = decodefield(value);\n\n            // overwrite existing value\n            params[key] = value;\n            continue\n        }\n\n        if (typeof params[key] === 'string') {\n            continue\n        }\n\n        if (value[0] === '\"') {\n            // remove quotes and escapes\n            value = value\n                    .substr(1, value.length - 2)\n                    .replace(QESC_REGEXP, '$1')\n        }\n\n        params[key] = value\n    }\n\n    if (index !== -1 && index !== string.length) {\n        throw new TypeError('invalid parameter format')\n    }\n\n    return new ContentDisposition(type, params)\n}\n\n/**\n * Percent decode a single character.\n *\n * @param {string} str\n * @param {string} hex\n * @return {string}\n * @private\n */\nfunction pdecode(str, hex) {\n    return String.fromCharCode(parseInt(hex, 16))\n}\n\n/**\n * Class for parsed Content-Disposition header for v8 optimization\n *\n * @public\n * @param {string} type\n * @param {object} parameters\n * @constructor\n */\nfunction ContentDisposition(type, parameters) {\n    this.type = type;\n    this.parameters = parameters\n}\n\nreturn {\n    parse: parse,\n};\n});\n", "/*\nMIT License\n\nCopyright (c) 2016 dandavis\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n */\n\n/**\n * download.js v4.2, by dandavis; 2008-2018. [MIT] see http://danml.com/download.html for tests/usage\n *\n * @param {Blob | File | String} data\n * @param {String} [filename]\n * @param {String} [mimetype]\n */\nodoo.define('web.download', function () {\nreturn function download(data, filename, mimetype) {\n    var self = window, // this script is only for browsers anyway...\n            defaultMime = \"application/octet-stream\", // this default mime also triggers iframe downloads\n            mimeType = mimetype || defaultMime, payload = data,\n            url = !filename && !mimetype && payload,\n            anchor = document.createElement(\"a\"),\n            toString = function (a) {return String(a);},\n            myBlob = (self.Blob || self.MozBlob || self.WebKitBlob || toString),\n            fileName = filename || \"download\", blob, reader;\n    myBlob = myBlob.call ? myBlob.bind(self) : Blob;\n\n    if (String(this) === \"true\") { //reverse arguments, allowing download.bind(true, \"text/xml\", \"export.xml\") to act as a callback\n        payload = [payload, mimeType];\n        mimeType = payload[0];\n        payload = payload[1];\n    }\n\n    if (url && url.length < 2048) { // if no filename and no mime, assume a url was passed as the only argument\n        fileName = url.split(\"/\").pop().split(\"?\")[0];\n        anchor.href = url; // assign href prop to temp anchor\n        if (anchor.href.indexOf(url) !== -1) { // if the browser determines that it's a potentially valid url path:\n            var ajax = new XMLHttpRequest();\n            ajax.open(\"GET\", url, true);\n            ajax.responseType = 'blob';\n            ajax.onload = function (e) {\n                download(e.target.response, fileName, defaultMime);\n            };\n            setTimeout(function () { ajax.send();}, 0); // allows setting custom ajax headers using the return:\n            return ajax;\n        }\n    }\n\n    //go ahead and download dataURLs right away\n    if (/^data:[\\w+\\-]+\\/[\\w+\\-]+[,;]/.test(payload)) {\n\n        if (payload.length > (1024 * 1024 * 1.999) && myBlob !== toString) {\n            payload = dataUrlToBlob(payload);\n            mimeType = payload.type || defaultMime;\n        } else {\n            return navigator.msSaveBlob ?  // IE10 can't do a[download], only Blobs:\n                    navigator.msSaveBlob(dataUrlToBlob(payload), fileName) : saver(payload); // everyone else can save dataURLs un-processed\n        }\n\n    }\n\n    blob = payload instanceof myBlob ? payload : new myBlob([payload], {type: mimeType});\n\n\n    function dataUrlToBlob(strUrl) {\n        var parts = strUrl.split(/[:;,]/), type = parts[1],\n                decoder = parts[2] === \"base64\" ? atob : decodeURIComponent,\n                binData = decoder(parts.pop()), mx = binData.length,\n                i = 0, uiArr = new Uint8Array(mx);\n\n        for (i; i < mx; ++i) uiArr[i] = binData.charCodeAt(i);\n\n        return new myBlob([uiArr], {type: type});\n    }\n\n    function saver(url, winMode) {\n        if ('download' in anchor) { //html5 A[download]\n            anchor.href = url;\n            anchor.setAttribute(\"download\", fileName);\n            anchor.className = \"download-js-link\";\n            anchor.innerHTML = \"downloading...\";\n            anchor.style.display = \"none\";\n            document.body.appendChild(anchor);\n            setTimeout(function () {\n                anchor.click();\n                document.body.removeChild(anchor);\n                if (winMode === true) {setTimeout(function () { self.URL.revokeObjectURL(anchor.href);}, 250);}\n            }, 66);\n            return true;\n        }\n\n        // handle non-a[download] safari as best we can:\n        if (/(Version)\\/(\\d+)\\.(\\d+)(?:\\.(\\d+))?.*Safari\\//.test(navigator.userAgent)) {\n            url = url.replace(/^data:([\\w\\/\\-+]+)/, defaultMime);\n            if (!window.open(url)) { // popup blocked, offer direct download:\n                if (confirm(\"Displaying New Document\\n\\nUse Save As... to download, then click back to return to this page.\")) { location.href = url; }\n            }\n            return true;\n        }\n\n        //do iframe dataURL download (old ch+FF):\n        var f = document.createElement(\"iframe\");\n        document.body.appendChild(f);\n\n        if (!winMode) { // force a mime that will download:\n            url = \"data:\" + url.replace(/^data:([\\w\\/\\-+]+)/, defaultMime);\n        }\n        f.src = url;\n        setTimeout(function () { document.body.removeChild(f); }, 333);\n    }\n\n    if (navigator.msSaveBlob) { // IE10+ : (has Blob, but not a[download] or URL)\n        return navigator.msSaveBlob(blob, fileName);\n    }\n\n    if (self.URL) { // simple fast and modern way using Blob and URL:\n        saver(self.URL.createObjectURL(blob), true);\n    } else {\n        // handle non-Blob()+non-URL browsers:\n        if (typeof blob === \"string\" || blob.constructor === toString) {\n            try {\n                return saver(\"data:\" + mimeType + \";base64,\" + self.btoa(blob));\n            } catch (y) {\n                return saver(\"data:\" + mimeType + \",\" + encodeURIComponent(blob));\n            }\n        }\n\n        // Blob but not URL support:\n        reader = new FileReader();\n        reader.onload = function () {\n            saver(this.result);\n        };\n        reader.readAsDataURL(blob);\n    }\n    return true;\n};\n});\n", "odoo.define('/web/static/src/js/libs/fullcalendar.js', function () {\n    \"use strict\";\n\n    function createYearCalendarView(FullCalendar) {\n        const {\n            Calendar,\n            createElement,\n            EventApi,\n            memoizeRendering,\n            View,\n        } = FullCalendar;\n\n        class YearView extends View {\n            constructor() {\n                super(...arguments);\n                this.months = null;\n                this.renderSubCalendarsMem = memoizeRendering(\n                    this.renderSubCalendars, this.unrenderSubCalendars);\n                this.events = [];\n            }\n\n            //----------------------------------------------------------------------\n            // Getters\n            //----------------------------------------------------------------------\n\n            get currentDate() {\n                return this.context.calendar.state.currentDate;\n            }\n\n            //----------------------------------------------------------------------\n            // Public\n            //----------------------------------------------------------------------\n\n            /**\n             * @override\n             */\n            destroy() {\n                this.renderSubCalendarsMem.unrender();\n                super.destroy();\n            }\n            /**\n             * Removes the selection on sub calendar.\n             * Selections on sub calendars are not propagated to this view so\n             * this view cannot manage them.\n             */\n            unselect() {\n                for (const { calendar } of this.months) {\n                    calendar.unselect();\n                }\n            }\n            /**\n             * @override\n             */\n            render() {\n                this.renderSubCalendarsMem(this.context);\n                super.render(...arguments);\n            }\n            /**\n             * Renders the main layout (the 4x3 month grid)\n             */\n            renderSubCalendars() {\n                this.el.classList.add('fc-scroller');\n                if (!this.context.options.selectable) {\n                    this.el.classList.add('fc-readonly-year-view');\n                }\n                this.months = [];\n                const currentMonthNumber = (new Date()).getMonth();\n                let currentMonthEl = undefined;\n                for (let monthNumber = 0; monthNumber < 12; monthNumber++) {\n                    const monthDate = new Date(this.currentDate.getFullYear(), monthNumber);\n                    const monthShortName = moment(monthDate).format('MMM').toLowerCase();\n                    const container = createElement('div', { class: 'fc-month-container' });\n                    this.el.appendChild(container);\n                    const el = createElement('div', {\n                        class: `fc-month fc-month-${monthShortName}`,\n                    });\n                    container.appendChild(el);\n                    const calendar = this._createMonthCalendar(el, monthDate);\n                    this.months.push({ el, calendar });\n                    calendar.render();\n                    if (monthNumber === currentMonthNumber) {\n                        currentMonthEl = el;\n                    }\n                }\n\n                if (currentMonthEl !== undefined) {\n                    currentMonthEl.scrollIntoView();\n                }\n            }\n            /**\n             * Removes the main layout (the 4x3 month grid).\n             * Called when view is switched/destroyed.\n             */\n            unrenderSubCalendars() {\n                for (const { el, calendar } of this.months) {\n                    calendar.destroy();\n                    el.remove();\n                }\n            }\n            /**\n             * Renders events in sub calendars.\n             * Called every time event source changed (when changing the date,\n             *   when changing filters, adding/removing filters).\n             */\n            renderEvents() {\n                // `renderDates` also renders events so if it's called just before\n                // then do not execute this as it will do a re-render.\n                if (this.datesRendered) {\n                    this.datesRendered = false;\n                    return;\n                }\n                this.events = this._computeEvents();\n                for (const { calendar } of this.months) {\n                    calendar.refetchEvents();\n                }\n                this._setCursorOnEventDates();\n            }\n            /**\n             * Renders dates and events in sub calendars.\n             * Called when the year of the date changed to render a new\n             * 4*3 grid of month calendar based on the new year.\n             */\n            renderDates() {\n                this.events = this._computeEvents();\n                for (const [monthNumber, { calendar }] of Object.entries(this.months)) {\n                    const monthDate = new Date(this.currentDate.getFullYear(), monthNumber);\n                    calendar.gotoDate(monthDate);\n                }\n                this._setCursorOnEventDates();\n                this.datesRendered = true;\n            }\n\n            //----------------------------------------------------------------------\n            // Private\n            //----------------------------------------------------------------------\n\n            /**\n             * @private\n             */\n            _computeEvents() {\n                const calendar = this.context.calendar;\n                return calendar.getEvents().map(event => {\n                    const endUTC = calendar.dateEnv.toDate(event._instance.range.end);\n                    const end = new Date(event._instance.range.end);\n                    if (endUTC.getHours() > 0 || endUTC.getMinutes() > 0 ||\n                        endUTC.getSeconds() > 0 || endUTC.getMilliseconds() > 0) {\n                        end.setDate(end.getDate() + 1);\n                    }\n                    // clone event data to not trigger rerendering and issues\n                    const instance = Object.assign({}, event._instance, {\n                        range: { start: new Date(event._instance.range.start), end },\n                    });\n                    const def = Object.assign({}, event._def, {\n                        rendering: 'background',\n                        allDay: true,\n                    });\n                    return new EventApi(this.context.calendar, def, instance);\n                });\n            }\n            /**\n             * Create a month calendar for the date `monthDate` and mount it on container.\n             *\n             * @private\n             * @param {HTMLElement} container\n             * @param {Date} monthDate\n             */\n            _createMonthCalendar(container, monthDate) {\n                return new Calendar(container, Object.assign({}, this.context.options, {\n                    defaultDate: monthDate,\n                    defaultView: 'dayGridMonth',\n                    header: { left: false, center: 'title', right: false },\n                    titleFormat: { month: 'short', year: 'numeric' },\n                    height: 0,\n                    contentHeight: 0,\n                    showNonCurrentDates: false,\n                    views: {\n                        dayGridMonth: {\n                            columnHeaderText: (date) => moment(date).format(\"ddd\")[0],\n                        },\n                    },\n                    selectMinDistance: 5, // needed to not trigger select when click\n                    dateClick: this._onYearDateClick.bind(this),\n                    datesRender: undefined,\n                    events: (info, successCB) => {\n                        successCB(this.events);\n                    },\n                    windowResize: undefined,\n                }));\n            }\n            /**\n             * Sets fc-has-event class on every dates that have at least one event.\n             *\n             * @private\n             */\n            _setCursorOnEventDates() {\n                for (const el of this.el.querySelectorAll('.fc-has-event')) {\n                    el.classList.remove('fc-has-event');\n                }\n                for (const event of Object.values(this.events)) {\n                    let currentDate = moment(event.start);\n                    while (currentDate.isBefore(event.end, 'day')) {\n                        const formattedDate = currentDate.format('YYYY-MM-DD');\n                        const el = this.el.querySelector(`.fc-day-top[data-date=\"${formattedDate}\"]`);\n                        if (el) {\n                            el.classList.add('fc-has-event');\n                        }\n                        currentDate.add(1, 'days');\n                    }\n                }\n            }\n\n            //----------------------------------------------------------------------\n            // Handlers\n            //----------------------------------------------------------------------\n\n            /**\n             * @private\n             * @param {*} info\n             */\n            _onYearDateClick(info) {\n                const calendar = this.context.calendar;\n                const events = this.events\n                    .filter(event => {\n                        const start = moment(event.start);\n                        const end = moment(event.end);\n                        const inclusivity = start.isSame(end, 'day') ? '[]' : '[)';\n                        return moment(info.date).isBetween(start, end, 'day', inclusivity);\n                    })\n                    .map(event => {\n                        return Object.assign({}, event._def, event._instance.range);\n                    });\n                const yearDateInfo = Object.assign({}, info, {\n                    view: this,\n                    monthView: info.view,\n                    events,\n                    selectable: this.context.options.selectable,\n                });\n                calendar.publiclyTrigger('yearDateClick', [yearDateInfo]);\n            }\n        }\n\n        return FullCalendar.createPlugin({\n            views: {\n                dayGridYear: {\n                    class: YearView,\n                    duration: { years: 1 },\n                    defaults: {\n                        fixedWeekCount: true,\n                    },\n                },\n            },\n        });\n    }\n\n    return {\n        createYearCalendarView,\n    };\n});\n", "odoo.define('web.jquery.extensions', function () {\n'use strict';\n\n/**\n * The jquery library extensions and fixes should be done here to avoid patching\n * in place.\n */\n\n// jQuery selectors extensions\n$.extend($.expr[':'], {\n    containsLike: function (element, index, matches){\n        return element.innerHTML.toUpperCase().indexOf(matches[3].toUpperCase()) >= 0;\n    },\n    containsTextLike: function (element, index, matches){\n        return element.innerText.toUpperCase().indexOf(matches[3].toUpperCase()) >= 0;\n    },\n    containsExact: function (element, index, matches){\n        return $.trim(element.innerHTML) === matches[3];\n    },\n    containsExactText: function (element, index, matches) {\n        return element.innerText.trim() === matches[3].trim();\n    },\n    /**\n     * Note all escaped characters need to be double escaped inside of the\n     * expression, so \"\\(\" needs to be \"\\\\(\"\n     */\n    containsRegex: function (element, index, matches){\n        var regreg =  /^\\/((?:\\\\\\/|[^\\/])+)\\/([mig]{0,3})$/,\n        reg = regreg.exec(matches[3]);\n        return reg ? new RegExp(reg[1], reg[2]).test($.trim(element.innerHTML)) : false;\n    },\n    propChecked: function (element, index, matches) {\n        return $(element).prop(\"checked\") === true;\n    },\n    propSelected: function (element, index, matches) {\n        return $(element).prop(\"selected\") === true;\n    },\n    propValue: function (element, index, matches) {\n        return $(element).prop(\"value\") === matches[3];\n    },\n    propValueContains: function (element, index, matches) {\n        return $(element).prop(\"value\") && $(element).prop(\"value\").indexOf(matches[3]) !== -1;\n    },\n    hasData: function (element) {\n        return !!_.toArray(element.dataset).length;\n    },\n    data: function (element, index, matches) {\n        return $(element).data(matches[3]);\n    },\n    hasVisibility: function (element, index, matches) {\n        var $element = $(element);\n        if ($(element).css('visibility') === 'hidden') {\n            return false;\n        }\n        var $parent = $element.parent();\n        if (!$parent.length || $element.is('html')) {\n            return true;\n        }\n        return $parent.is(':hasVisibility');\n    },\n    hasOpacity: function (element, index, matches) {\n        var $element = $(element);\n        if (parseFloat($(element).css('opacity')) <= 0.01) {\n            return false;\n        }\n        var $parent = $element.parent();\n        if (!$parent.length || $element.is('html')) {\n            return true;\n        }\n        return $parent.is(':hasOpacity');\n    },\n});\n\n// jQuery functions extensions\n$.fn.extend({\n    /**\n     * Returns all the attributes of a DOM element (first one in the jQuery\n     * set).\n     *\n     * @returns {Object} attribute name -> attribute value\n     */\n    getAttributes: function () {\n        var o = {};\n        if (this.length) {\n            var attrs = this[0].attributes;\n            for (var i = 0, l = attrs.length ; i < l ; i++) {\n                var attr = attrs.item(i);\n                o[attr.name] = attr.value;\n            }\n        }\n        return o;\n    },\n    /**\n     * Makes DOM elements bounce the way Odoo decided it.\n     *\n     * @param {string} [extraClass]\n     */\n    odooBounce: function (extraClass) {\n        for (const el of this) {\n            el.classList.add('o_catch_attention', extraClass);\n            setTimeout(() => el.classList.remove('o_catch_attention', extraClass), 400);\n        }\n        return this;\n    },\n    /**\n     * Allows to bind events to a handler just as the standard `$.on` function\n     * but binds the handler so that it is executed before any already-attached\n     * handler for the same events.\n     *\n     * @see jQuery.on\n     */\n    prependEvent: function (events, selector, data, handler) {\n        this.on.apply(this, arguments);\n\n        events = events.split(' ');\n        return this.each(function () {\n            var el = this;\n            _.each(events, function (evNameNamespaced) {\n                var evName = evNameNamespaced.split('.')[0];\n                var handler = $._data(el, 'events')[evName].pop();\n                $._data(el, 'events')[evName].unshift(handler);\n            });\n        });\n    },\n    /**\n     * @todo Should really be converted to no jQuery and probably even removed\n     * from jQuery utilities in master\n     * @return {jQuery}\n     */\n    closestScrollable() {\n        const document = this.length ? this[0].ownerDocument : window.document;\n\n        let $el = this;\n        while ($el[0] !== document.scrollingElement) {\n            if (!$el.length || $el[0] instanceof Document) {\n                // Ensure that $().closestScrollable() -> $() and handle the\n                // case of elements not attached to the DOM.\n                // Also, .parent() used to loop through ancestors can\n                // theoretically reach the document if nothing up to the HTML\n                // included is not scrollable.\n                return $();\n            }\n            if ($el.isScrollable()) {\n                return $el;\n            }\n            $el = $el.parent();\n        }\n        return $el;\n    },\n    /**\n     * Adapt the given css property by adding the size of a scrollbar if any.\n     * Limitation: only works if the given css property is not already used as\n     * inline style for another reason.\n     *\n     * @param {boolean} [add=true]\n     * @param {boolean} [isScrollElement=true]\n     * @param {string} [cssProperty='padding-right']\n     */\n    compensateScrollbar(add = true, isScrollElement = true, cssProperty = 'padding-right') {\n        for (const el of this) {\n            // Compensate scrollbar\n            const scrollableEl = isScrollElement ? el : $(el).parent().closestScrollable()[0];\n            const isRTL = scrollableEl.matches(\".o_rtl\");\n            if (isRTL) {\n                cssProperty = cssProperty.replace(\"right\", \"left\");\n            }\n            el.style.removeProperty(cssProperty);\n            if (!add) {\n                return;\n            }\n            const style = window.getComputedStyle(el);\n            const borderLeftWidth = parseInt(style.borderLeftWidth.replace('px', ''));\n            const borderRightWidth = parseInt(style.borderRightWidth.replace('px', ''));\n            const bordersWidth = borderLeftWidth + borderRightWidth;\n            const newValue = parseInt(style[cssProperty]) + scrollableEl.offsetWidth - scrollableEl.clientWidth - bordersWidth;\n            el.style.setProperty(cssProperty, `${newValue}px`, 'important');\n        }\n    },\n    /**\n     * @returns {jQuery}\n     */\n    getScrollingElement(document = window.document) {\n        const $baseScrollingElement = $(document.scrollingElement);\n        if ($baseScrollingElement.isScrollable()\n                && $baseScrollingElement.hasScrollableContent()) {\n            return $baseScrollingElement;\n        }\n        const bodyHeight = $(document.body).height();\n        for (const el of document.body.children) {\n            // Search for a body child which is at least as tall as the body\n            // and which has the ability to scroll if enough content in it. If\n            // found, suppose this is the top scrolling element.\n            if (bodyHeight - el.scrollHeight > 1.5) {\n                continue;\n            }\n            const $el = $(el);\n            if ($el.isScrollable()) {\n                return $el;\n            }\n        }\n        return $baseScrollingElement;\n    },\n    /**\n     * @return {boolean}\n     */\n    hasScrollableContent() {\n        return this[0].scrollHeight > this[0].clientHeight;\n    },\n    /**\n     * @returns {boolean}\n     */\n    isScrollable() {\n        if (!this.length) {\n            return false;\n        }\n        const overflow = this.css('overflow-y');\n        const el = this[0];\n        return overflow === 'auto' || overflow === 'scroll'\n            || (overflow === 'visible' && el === el.ownerDocument.scrollingElement);\n    },\n});\n\n// jQuery functions monkey-patching\n\n// Some magic to ensure scrolltop and animate on html/body animate the top level\n// scrollable element even if not html or body.\nconst originalScrollTop = $.fn.scrollTop;\n$.fn.scrollTop = function (value) {\n    if (value !== undefined && this.filter('html, body').length) {\n        // The caller wants to scroll a set of elements including html and/or\n        // body to a specific point -> do that but make sure to add the real\n        // top level element to that set of elements if any different is found.\n        originalScrollTop.apply(this.not('html, body').add($().getScrollingElement()), arguments);\n        return this;\n    } else if (value === undefined && this.eq(0).is('html, body')) {\n        // The caller wants to get the scroll point of a set of elements, jQuery\n        // will return the scroll point of the first one, if it is html or body\n        // return the scroll point of the real top level element.\n        return originalScrollTop.apply($().getScrollingElement(), arguments);\n    }\n    return originalScrollTop.apply(this, arguments);\n};\nconst originalAnimate = $.fn.animate;\n$.fn.animate = function (properties, ...rest) {\n    const props = Object.assign({}, properties);\n    if ('scrollTop' in props && this.filter('html, body').length) {\n        // The caller wants to scroll a set of elements including html and/or\n        // body to a specific point -> do that but make sure to add the real\n        // top level element to that set of elements if any different is found.\n        originalAnimate.call(this.not('html, body').add($().getScrollingElement()), {'scrollTop': props['scrollTop']}, ...rest);\n        delete props['scrollTop'];\n    }\n    if (!Object.keys(props).length) {\n        return this;\n    }\n    return originalAnimate.call(this, props, ...rest);\n};\n});\n", "/**\n * This file aim to contains the update/fix we have to do on moment.js localizations.\n * By using updateLocale and/or defineLocale here, we avoid adding change in the official\n * moment.js files, which could lead to conflict when updating the library.\n */\n\n odoo.define('web.moment.extensions', function () {\n    'use strict';\n    const locale = moment.locale();\n    moment.updateLocale('ca', {\n        preparse: function (string) {\n            return string.replace(/\\b(?:d\u2019|de )(gener|febrer|mar\u00e7|abril|maig|juny|juliol|agost|setembre|octubre|novembre|desembre)/g, '$1');\n        }\n    });\n    if(locale !== 'ca'){\n        moment.locale(locale);\n    }\n});\n", "/**\n * The _throttle in underscore has the feature to cancel the throttled function\n * only starting version 1.9.0\n * @todo remove this in master and update underscorejs to 1.9.1\n */\n\n// Returns a function, that, when invoked, will only be triggered at most once\n// during a given window of time. Normally, the throttled function will run\n// as much as it can, without ever going more than once per `wait` duration;\n// but if you'd like to disable the execution on the leading edge, pass\n// `{leading: false}`. To disable execution on the trailing edge, ditto.\n\n_.cancellableThrottleRemoveMeSoon = function (func, wait, options) {\n    var timeout, context, args, result;\n    var previous = 0;\n    if (!options) options = {};\n\n    var later = function () {\n        previous = options.leading === false ? 0 : _.now();\n        timeout = null;\n        result = func.apply(context, args);\n        if (!timeout) context = args = null;\n    };\n\n    var throttled = function () {\n        var now = _.now();\n        if (!previous && options.leading === false) previous = now;\n        var remaining = wait - (now - previous);\n        context = this;\n        args = arguments;\n        if (remaining <= 0 || remaining > wait) {\n            if (timeout) {\n                clearTimeout(timeout);\n                timeout = null;\n            }\n            previous = now;\n            result = func.apply(context, args);\n            if (!timeout) context = args = null;\n        } else if (!timeout && options.trailing !== false) {\n            timeout = setTimeout(later, remaining);\n        }\n        return result;\n    };\n\n    throttled.cancel = function () {\n        clearTimeout(timeout);\n        previous = 0;\n        timeout = context = args = null;\n    };\n\n    return throttled;\n};\n", "/** @odoo-module **/\n\nimport config from 'web.config';\n\n/**\n * Until we have our own implementation of the /web/static/lib/pdfjs/web/viewer.{html,js,css}\n * (currently based on Firefox), this method allows us to hide the buttons that we do not want:\n * * \"Open File\"\n * * \"View Bookmark\"\n * * \"Print\" (Hidden on mobile device like Android, iOS, ...)\n * * \"Download\" (Hidden on mobile device like Android, iOS, ...)\n *\n * @link https://mozilla.github.io/pdf.js/getting_started/\n *\n * @param {Element} rootElement\n */\nexport function hidePDFJSButtons(rootElement) {\n    const cssStyle = document.createElement(\"style\");\n    cssStyle.rel = \"stylesheet\";\n    cssStyle.innerHTML = `button#secondaryOpenFile.secondaryToolbarButton, button#openFile.toolbarButton,\na#secondaryViewBookmark.secondaryToolbarButton, a#viewBookmark.toolbarButton {\ndisplay: none !important;\n}`;\n    if (config.device.isMobileDevice) {\n        cssStyle.innerHTML = `${cssStyle.innerHTML}\nbutton#secondaryDownload.secondaryToolbarButton, button#download.toolbarButton,\nbutton#secondaryPrint.secondaryToolbarButton, button#print.toolbarButton{\ndisplay: none !important;\n}`;\n    }\n    const iframe = rootElement.tagName === 'IFRAME' ? rootElement : rootElement.querySelector('iframe');\n    if (iframe) {\n        if (!iframe.dataset.hideButtons) {\n            iframe.dataset.hideButtons = 'true';\n            iframe.addEventListener('load', event => {\n                if (iframe.contentDocument && iframe.contentDocument.head) {\n                    iframe.contentDocument.head.appendChild(cssStyle);\n                }\n            });\n        }\n    } else {\n        console.warn('No IFRAME found');\n    }\n}\n\n/*\n* List of changes made in the library\n* There is no changes to pdf.js in this section, but only a note about changes that has been done in /web/static/lib/pdfjs/.\n*\n* In the module account_invoice_extract, the the code need to react to the 'pagerendered' event triggered by\n* pdf.js. However in recent version of pdf.js, event are not visible outside of the library, except if the \n* 'eventBusDispatchToDOM' has been set to true.\n*\n* We tried to set this option from outside of the library but without success, as our pdf viewer is in an iframe.\n* There is no state of the iframe in which we can add an event listener to set the option.\n* pdf.js has an event used to signal when we can set settings, called 'webviewerloaded'.\n* This event is triggered in an EventListener attached to the 'DOMContentLoaded' event.\n* So, to list options we had, we could:\n* a) add an eventListener to the iframe document or window to react to 'webviewerloaded'. This doesn't work as \n*    document and windows are not the definitive ones and won't catche the event later.\n* b) add an eventListener to the iframe to react to 'DOMContentLoaded', which doens't work too as our listener will be called\n*    after the pdf.js one.\n*\n* Finally the option was choosed to modify the default value of this option directly in pdf.js as no hook worked in the\n* 'account_invoice_extract' module.\n*/\n", "/** @odoo-module **/\nPopper.Defaults.modifiers.preventOverflow.priority = ['right', 'left', 'bottom', 'top'];\n", "odoo.define('web.zoomodoo', function (require) {\n'use strict';\n\n/**\n    This code has been more that widely inspired by easyZoom library.\n\n    Copyright 2013 Matt Hinchliffe\n\n    Permission is hereby granted, free of charge, to any person obtaining\n    a copy of this software and associated documentation files (the\n    \"Software\"), to deal in the Software without restriction, including\n    without limitation the rights to use, copy, modify, merge, publish,\n    distribute, sublicense, and/or sell copies of the Software, and to\n    permit persons to whom the Software is furnished to do so, subject to\n    the following conditions:\n\n    The above copyright notice and this permission notice shall be\n    included in all copies or substantial portions of the Software.\n**/\n\nvar dw, dh, rw, rh, lx, ly;\n\nvar defaults = {\n\n    // Attribute to retrieve the zoom image URL from.\n    linkTag: 'a',\n    linkAttribute: 'data-zoom-image',\n\n    // event to trigger zoom\n    event: 'click', //or mouseenter\n\n    // Timer before trigger zoom\n    timer: 0,\n\n    // Prevent clicks on the zoom image link.\n    preventClicks: true,\n\n    // disable on mobile\n    disabledOnMobile: true,\n\n    // Callback function to execute before the flyout is displayed.\n    beforeShow: $.noop,\n\n    // Callback function to execute before the flyout is removed.\n    beforeHide: $.noop,\n\n    // Callback function to execute when the flyout is displayed.\n    onShow: $.noop,\n\n    // Callback function to execute when the flyout is removed.\n    onHide: $.noop,\n\n    // Callback function to execute when the cursor is moved while over the image.\n    onMove: $.noop,\n\n    // Callback function to execute when the flyout is attached to the target.\n    beforeAttach: $.noop\n\n};\n\n/**\n * ZoomOdoo\n * @constructor\n * @param {Object} target\n * @param {Object} options (Optional)\n */\nfunction ZoomOdoo(target, options) {\n    this.$target = $(target);\n    this.opts = $.extend({}, defaults, options, this.$target.data());\n\n    if (this.isOpen === undefined) {\n        this._init();\n    }\n}\n\n/**\n * Init\n * @private\n */\nZoomOdoo.prototype._init = function () {\n    if (window.outerWidth > 467 || !this.opts.disabledOnMobile) {\n        this.$link  = this.$target.find(this.opts.linkTag).length && this.$target.find(this.opts.linkTag) || this.$target;\n        this.$image  = this.$target.find('img').length && this.$target.find('img') || this.$target;\n        this.$flyout = $('<div class=\"zoomodoo-flyout\" />');\n\n        var $attach = this.$target;\n        if (this.opts.attach !== undefined && this.$target.closest(this.opts.attach).length) {\n            $attach = this.$target.closest(this.opts.attach);\n        }\n        $attach.parent().on('mousemove.zoomodoo touchmove.zoomodoo', $.proxy(this._onMove, this));\n        $attach.parent().on('mouseleave.zoomodoo touchend.zoomodoo', $.proxy(this._onLeave, this));\n        this.$target.on(this.opts.event + '.zoomodoo touchstart.zoomodoo', $.proxy(this._onEnter, this));\n\n        if (this.opts.preventClicks) {\n            this.$target.on('click.zoomodoo', function (e) { e.preventDefault(); });\n        } else {\n            var self = this;\n            this.$target.on('click.zoomodoo', function () { self.hide(); self.$target.unbind(); });\n        }\n    }\n};\n\n/**\n * Show\n * @param {MouseEvent|TouchEvent} e\n * @param {Boolean} testMouseOver (Optional)\n */\nZoomOdoo.prototype.show = function (e, testMouseOver) {\n    var w1, h1, w2, h2;\n    var self = this;\n\n    if (this.opts.beforeShow.call(this) === false) return;\n\n    if (!this.isReady) {\n        return this._loadImage(this.$link.attr(this.opts.linkAttribute), function () {\n            if (self.isMouseOver || !testMouseOver) {\n                self.show(e);\n            }\n        });\n    }\n\n    var $attach = this.$target;\n    if (this.opts.attach !== undefined && this.$target.closest(this.opts.attach).length) {\n        $attach = this.$target.closest(this.opts.attach);\n    }\n\n    // Prevents having multiple zoom flyouts\n    $attach.parent().find('.zoomodoo-flyout').remove();\n    this.$flyout.removeAttr('style');\n    $attach.parent().append(this.$flyout);\n\n    if (this.opts.attachToTarget) {\n        this.opts.beforeAttach.call(this);\n\n        // Be sure that the flyout is at top 0, left 0 to ensure correct computation\n        // e.g. employees kanban on dashboard\n        this.$flyout.css('position', 'fixed');\n        var flyoutOffset = this.$flyout.offset();\n        if (flyoutOffset.left > 0) {\n            var flyoutLeft = parseFloat(this.$flyout.css('left').replace('px',''));\n            this.$flyout.css('left', flyoutLeft - flyoutOffset.left + 'px');\n        }\n        if (flyoutOffset.top > 0) {\n            var flyoutTop = parseFloat(this.$flyout.css('top').replace('px',''));\n            this.$flyout.css('top', flyoutTop - flyoutOffset.top + 'px');\n        }\n\n        if(this.$zoom.height() < this.$flyout.height()) {\n             this.$flyout.css('height', this.$zoom.height() + 'px');\n        }\n        if(this.$zoom.width() < this.$flyout.width()) {\n             this.$flyout.css('width', this.$zoom.width() + 'px');\n        }\n\n        var offset = this.$target.offset();\n        var left = offset.left - this.$flyout.width();\n        var top = offset.top;\n\n        // Position the zoom on the right side of the target\n        // if there's not enough room on the left\n        if(left < 0) {\n            if(offset.left < ($(document).width() / 2)) {\n                left = offset.left + this.$target.width();\n            } else {\n                left = 0;\n            }\n        }\n\n        // Prevents the flyout to overflow \n        if(left + this.$flyout.width() > $(document).width()) {\n            this.$flyout.css('width',  $(document).width() - left + 'px');\n        } else if(left === 0) { // Limit the max width if displayed on the left\n            this.$flyout.css('width', offset.left + 'px');\n        }\n\n        // Prevents the zoom to be displayed outside the current viewport\n        if((top + this.$flyout.height()) > $(document).height()) {\n            top = $(document).height() - this.$flyout.height();\n        }\n\n        this.$flyout.css('transform', 'translate3d(' + left + 'px, ' + top + 'px, 0px)');\n    } else {\n        // Computing flyout max-width depending to the available space on the right to avoid overflow-x issues\n        // e.g. width too high so a right zoomed element is not visible (need to scroll on x axis)\n        var rightAvailableSpace = document.body.clientWidth - this.$flyout[0].getBoundingClientRect().left;\n        this.$flyout.css('max-width', rightAvailableSpace);\n    }\n\n    w1 = this.$target[0].offsetWidth;\n    h1 = this.$target[0].offsetHeight;\n\n    w2 = this.$flyout.width();\n    h2 = this.$flyout.height();\n\n    dw = this.$zoom.width() - w2;\n    dh = this.$zoom.height() - h2;\n\n    // For the case where the zoom image is actually smaller than\n    // the flyout.\n    if (dw < 0) dw = 0;\n    if (dh < 0) dh = 0;\n\n    rw = dw / w1;\n    rh = dh / h1;\n\n    this.isOpen = true;\n\n    this.opts.onShow.call(this);\n\n    if (e) {\n        this._move(e);\n    }\n};\n\n/**\n * On enter\n * @private\n * @param {Event} e\n */\nZoomOdoo.prototype._onEnter = function (e) {\n    var self = this;\n    var touches = e.originalEvent.touches;\n    e.preventDefault();\n    this.isMouseOver = true;\n\n    setTimeout(function () {\n        if (self.isMouseOver && (!touches || touches.length === 1)) {\n            self.show(e, true);\n        }\n      }, this.opts.timer);\n\n};\n\n/**\n * On move\n * @private\n * @param {Event} e\n */\nZoomOdoo.prototype._onMove = function (e) {\n    if (!this.isOpen) return;\n\n    e.preventDefault();\n    this._move(e);\n};\n\n/**\n * On leave\n * @private\n */\nZoomOdoo.prototype._onLeave = function () {\n    this.isMouseOver = false;\n    if (this.isOpen) {\n        this.hide();\n    }\n};\n\n/**\n * On load\n * @private\n * @param {Event} e\n */\nZoomOdoo.prototype._onLoad = function (e) {\n    // IE may fire a load event even on error so test the image dimensions\n    if (!e.currentTarget.width) return;\n\n    this.isReady = true;\n\n    this.$flyout.html(this.$zoom);\n\n    if (e.data.call) {\n        e.data();\n    }\n};\n\n/**\n * Load image\n * @private\n * @param {String} href\n * @param {Function} callback\n */\nZoomOdoo.prototype._loadImage = function (href, callback) {\n    var zoom = new Image();\n\n    this.$zoom = $(zoom).on('load', callback, $.proxy(this._onLoad, this));\n\n    zoom.style.position = 'absolute';\n    zoom.src = href;\n};\n\n/**\n * Move\n * @private\n * @param {Event} e\n */\nZoomOdoo.prototype._move = function (e) {\n    if (e.type.indexOf('touch') === 0) {\n        var touchlist = e.touches || e.originalEvent.touches;\n        lx = touchlist[0].pageX;\n        ly = touchlist[0].pageY;\n    } else {\n        lx = e.pageX || lx;\n        ly = e.pageY || ly;\n    }\n\n    var offset  = this.$target.offset();\n    var pt = ly - offset.top;\n    var pl = lx - offset.left;\n    var xt = Math.ceil(pt * rh);\n    var xl = Math.ceil(pl * rw);\n\n    // Close if outside\n    if (!this.opts.attachToTarget && (xl < 0 || xt < 0 || xl > dw || xt > dh || lx > (offset.left + this.$target.outerWidth()))) {\n        this.hide();\n    } else {\n        var top = xt * -1;\n        var left = xl * -1;\n\n        this.$zoom.css({\n            top: top,\n            left: left\n        });\n\n        this.opts.onMove.call(this, top, left);\n    }\n\n};\n\n/**\n * Hide\n */\nZoomOdoo.prototype.hide = function () {\n    if (!this.isOpen) return;\n    if (this.opts.beforeHide.call(this) === false) return;\n\n    this.$flyout.detach();\n    this.isOpen = false;\n\n    this.opts.onHide.call(this);\n};\n\n// jQuery plugin wrapper\n$.fn.zoomOdoo = function (options) {\n    return this.each(function () {\n        var api = $.data(this, 'zoomOdoo');\n\n        if (!api) {\n            $.data(this, 'zoomOdoo', new ZoomOdoo(this, options));\n        } else if (api.isOpen === undefined) {\n            api._init();\n        }\n    });\n};\n});\n", "function _renderImageOnCanvas( data, formattype, rerendercallable ) {\n    'use strict'\n    // #1. Do NOT rely on this. No worky on IE \n    //   (url max len + lack of base64 decoder + possibly other issues)\n    // #2. This does NOT affect what is captured as \"signature\" as far as vector data is \n    // concerned. This is treated same as \"signature line\" - i.e. completely ignored\n    // the only time you see imported image data exported is if you export as image.\n\n    // we do NOT call rerendercallable here (unlike in other import plugins)\n    // because importing image does absolutely nothing to the underlying vector data storage\n    // This could be a way to \"import\" old signatures stored as images\n    // This could also be a way to import extra decor into signature area.\n\n    // Odoo override: \n    // If a signature is saved in mobile resolution, when the user tries to sign a document in desktop, the size that is shown is the mobile size, which is strange for the user.\n    // This modifies the library method that adds the image to the canvas, resizing the image to the canvas size, keeping the image ratio and showing it centered.\n    \n    var img = new Image()\n    // this = Canvas DOM elem. Not jQuery object. Not Canvas's parent div.\n    , c = this;\n\n    img.onload = function () {\n        var ctx = c.getContext(\"2d\");\n        var oldShadowColor = ctx.shadowColor;\n        ctx.shadowColor = \"transparent\";\n\n        var ratio = ((img.width / img.height) > (c.width / c.height)) ? c.width / img.width : c.height / img.height;\n\n        ctx.drawImage( \n            img,\n            (c.width / 2) - (img.width * ratio / 2),\n            (c.height / 2) - (img.height * ratio / 2)\n            , img.width * ratio\n            , img.height * ratio\n        );\n        ctx.shadowColor = oldShadowColor;\n    };\n\n    img.src = 'data:' + formattype + ',' + data;\n}\n\n// Override\n// Supported image types\n[\n    'image',\n    'image/png;base64',\n    'image/jpeg;base64',\n    'image/jpg;base64',\n].forEach(imageType => $.fn.jSignature(\"addPlugin\", \"import\", imageType, _renderImageOnCanvas));\n", "odoo.define('web.AbstractService', function (require) {\n\"use strict\";\n\nvar Class = require('web.Class');\nconst { serviceRegistry } = require(\"web.core\");\nvar Mixins = require('web.mixins');\nvar ServicesMixin = require('web.ServicesMixin');\n\nvar AbstractService = Class.extend(Mixins.EventDispatcherMixin, ServicesMixin, {\n    dependencies: [],\n    init: function (env) {\n        Mixins.EventDispatcherMixin.init.call(this, arguments);\n        this.env = env;\n    },\n    /**\n     * @abstract\n     */\n    start: function () {},\n    /**\n     * Directly calls the requested service, instead of triggering a\n     * 'call_service' event up, which wouldn't work as services have no parent\n     *\n     * @param {OdooEvent} ev\n     */\n    _trigger_up: function (ev) {\n        Mixins.EventDispatcherMixin._trigger_up.apply(this, arguments);\n        if (ev.is_stopped()) {\n            return;\n        }\n        const payload = ev.data;\n        if (ev.name === 'call_service') {\n            let args = payload.args || [];\n            if (payload.service === 'ajax' && payload.method === 'rpc') {\n                // ajax service uses an extra 'target' argument for rpc\n                args = args.concat(ev.target);\n            }\n            const service = this.env.services[payload.service];\n            const result = service[payload.method].apply(service, args);\n            payload.callback(result);\n        } else if (ev.name === 'do_action') {\n            this.env.bus.trigger('do-action', payload);\n        }\n    },\n\n    //--------------------------------------------------------------------------\n    // Static\n    //--------------------------------------------------------------------------\n\n    /**\n     * Deploy services in the env (specializations of AbstractService registered\n     * into the serviceRegistry).\n     *\n     * @static\n     * @param {Object} env\n     */\n    deployServices(env) {\n        const UndeployedServices = Object.assign({}, serviceRegistry.map);\n        function _deployServices() {\n            let done = false;\n            while (!done) {\n                // find a service with no missing dependency\n                const serviceName = Object.keys(UndeployedServices).find(serviceName => {\n                    const Service = UndeployedServices[serviceName];\n                    return Service.prototype.dependencies.every(depName => {\n                        return env.services[depName];\n                    });\n                });\n                if (serviceName) {\n                    const Service = UndeployedServices[serviceName];\n                    const service = new Service(env);\n                    env.services[serviceName] = service;\n                    delete UndeployedServices[serviceName];\n                    service.start();\n                } else {\n                    done = true;\n                }\n            }\n        }\n        serviceRegistry.onAdd((serviceName, Service) => {\n            if (serviceName in env.services || serviceName in UndeployedServices) {\n                throw new Error(`Service ${serviceName} is already loaded.`);\n            }\n            UndeployedServices[serviceName] = Service;\n            _deployServices();\n        });\n        _deployServices();\n    }\n});\n\nreturn AbstractService;\n});\n", "odoo.define('web.AbstractStorageService', function (require) {\n'use strict';\n\n/**\n * This module defines an abstraction for services that write into Storage\n * objects (e.g. localStorage or sessionStorage).\n */\n\nvar AbstractService = require('web.AbstractService');\n\nvar AbstractStorageService = AbstractService.extend({\n    // the 'storage' attribute must be set by actual StorageServices extending\n    // this abstraction\n    storage: null,\n\n    /**\n     * @override\n     */\n    destroy: function () {\n        // storage can be permanent or transient, destroy transient ones\n        if ((this.storage || {}).destroy) {\n            this.storage.destroy();\n        }\n        this._super.apply(this, arguments);\n    },\n\n    //--------------------------------------------------------------------------\n    // Public\n    //--------------------------------------------------------------------------\n\n    /**\n     * Removes all data from the storage\n     */\n    clear: function() {\n        this.storage.clear();\n    },\n    /**\n     * Returns the value associated with a given key in the storage\n     *\n     * @param {string} key\n     * @returns {string}\n     */\n    getItem: function(key, defaultValue) {\n        var val = this.storage.getItem(key);\n        return val ? JSON.parse(val) : defaultValue;\n    },\n    /**\n     * @param {integer} index\n     * @return {string}\n     */\n    key: function (index) {\n        return this.storage.key(index);\n    },\n    /**\n     * @return {integer}\n     */\n    length: function () {\n        return this.storage.length;\n    },\n    /**\n     * Removes the given key from the storage\n     *\n     * @param {string} key\n     */\n    removeItem: function(key) {\n        this.storage.removeItem(key);\n    },\n    /**\n     * Sets the value of a given key in the storage\n     *\n     * @param {string} key\n     * @param {string} value\n     */\n    setItem: function(key, value) {\n        this.storage.setItem(key, JSON.stringify(value));\n    },\n    /**\n     * Add an handler on storage event\n     *\n     */\n    onStorage: function () {\n        this.storage.on.apply(this.storage, [\"storage\"].concat(Array.prototype.slice.call(arguments)));\n    },\n});\n\nreturn AbstractStorageService;\n\n});\n", "odoo.define('web.ajax', function (require) {\n\"use strict\";\n\nvar config = require('web.config');\nvar concurrency = require('web.concurrency');\nvar core = require('web.core');\nconst {Markup} = require('web.utils');\nvar time = require('web.time');\nvar download = require('web.download');\nvar contentdisposition = require('web.contentdisposition');\nconst { session } = require('@web/session');\n\nvar _t = core._t;\n\n// Create the final object containing all the functions first to allow monkey\n// patching them correctly if ever needed.\nvar ajax = {};\n\nfunction _genericJsonRpc (fct_name, params, settings, fct) {\n    var shadow = settings.shadow || false;\n    delete settings.shadow;\n    var data = {\n        jsonrpc: \"2.0\",\n        method: fct_name,\n        params: params,\n        id: Math.floor(Math.random() * 1000 * 1000 * 1000)\n    };\n\n    if (!shadow) {\n        core.bus.trigger('rpc_request', data.id);\n    }\n\n    var xhr = fct(data);\n    var result = xhr.then(function(result) {\n        core.bus.trigger('rpc:result', data, result);\n        if (result.error !== undefined) {\n            if (result.error.data.arguments[0] !== \"bus.Bus not available in test mode\") {\n                console.debug(\n                    \"Server application error\\n\",\n                    \"Error code:\", result.error.code, \"\\n\",\n                    \"Error message:\", result.error.message, \"\\n\",\n                    \"Error data message:\\n\", result.error.data.message, \"\\n\",\n                    \"Error data debug:\\n\", result.error.data.debug\n                );\n            }\n            return Promise.reject({type: \"server\", error: result.error});\n        } else {\n            return result.result;\n        }\n    }, function() {\n        //console.error(\"JsonRPC communication error\", _.toArray(arguments));\n        var reason = {\n            type: 'communication',\n            error: arguments[0],\n            textStatus: arguments[1],\n            errorThrown: arguments[2],\n        };\n        return Promise.reject(reason);\n    });\n\n    var rejection;\n    var promise = new Promise(function (resolve, reject) {\n        rejection = reject;\n\n        result.then(function (result) {\n            if (!shadow) {\n                core.bus.trigger('rpc_response', data.id);\n            }\n            resolve(result);\n        }, function (reason) {\n            var type = reason.type;\n            var error = reason.error;\n            var textStatus = reason.textStatus;\n            var errorThrown = reason.errorThrown;\n            if (type === \"server\") {\n                if (!shadow) {\n                    core.bus.trigger('rpc_response', data.id);\n                }\n                if (error.code === 100) {\n                    core.bus.trigger('invalidate_session');\n                }\n                reject({message: error, event: $.Event()});\n            } else {\n                if (!shadow) {\n                    core.bus.trigger('rpc_response_failed', data.id);\n                }\n                var nerror = {\n                    code: -32098,\n                    message: \"XmlHttpRequestError \" + errorThrown,\n                    data: {\n                        type: \"xhr\"+textStatus,\n                        debug: error.responseText,\n                        objects: [error, errorThrown],\n                        arguments: [reason || textStatus]\n                    },\n                };\n                reject({message: nerror, event: $.Event()});\n            }\n        });\n    });\n\n    // FIXME: jsonp?\n    promise.abort = function () {\n        rejection({\n            message: \"XmlHttpRequestError abort\",\n            event: $.Event('abort')\n        });\n\n        if (!shadow) {\n            core.bus.trigger('rpc_response');\n        }\n\n        if (xhr.abort) {\n            xhr.abort();\n        }\n    };\n    promise.guardedCatch(function (reason) { // Allow promise user to disable rpc_error call in case of failure\n        setTimeout(function () {\n            // we want to execute this handler after all others (hence\n            // setTimeout) to let the other handlers prevent the event\n            if (!reason.event.isDefaultPrevented()) {\n                core.bus.trigger('rpc_error', reason.message, reason.event);\n            }\n        }, 0);\n    });\n    return promise;\n};\n\nfunction jsonRpc(url, fct_name, params, settings) {\n    settings = settings || {};\n    return _genericJsonRpc(fct_name, params, settings, function(data) {\n        return $.ajax(url, _.extend({}, settings, {\n            url: url,\n            dataType: 'json',\n            type: 'POST',\n            data: JSON.stringify(data, time.date_to_utc),\n            contentType: 'application/json'\n        }));\n    });\n}\n\n// helper function to make a rpc with a function name hardcoded to 'call'\nfunction rpc(url, params, settings) {\n    return jsonRpc(url, 'call', params, settings);\n}\n\n\n/**\n * Load css asynchronously: fetch it from the url parameter and add a link tag\n * to <head>.\n * If the url has already been requested and loaded, the promise will resolve\n * immediately.\n *\n * @param {String} url of the css to be fetched\n * @returns {Promise} resolved when the css has been loaded.\n */\nvar loadCSS = (function () {\n    var urlDefs = {};\n\n    return function loadCSS(url) {\n        if (url in urlDefs) {\n            // nothing to do here\n        } else if ($('link[href=\"' + url + '\"]').length) {\n            // the link is already in the DOM, the promise can be resolved\n            urlDefs[url] = Promise.resolve();\n        } else {\n            var $link = $('<link>', {\n                'href': url,\n                'rel': 'stylesheet',\n                'type': 'text/css'\n            });\n            urlDefs[url] = new Promise(function (resolve, reject) {\n                $link.on('load', function () {\n                    resolve();\n                }).on('error', function () {\n                    reject(new Error(\"Couldn't load css dependency: \" + $link[0].href));\n                });\n            });\n            $('head').append($link);\n        }\n        return urlDefs[url];\n    };\n})();\n\nvar loadJS = (function () {\n    var dependenciesPromise = {};\n\n    var load = function loadJS(url) {\n        // Check the DOM to see if a script with the specified url is already there\n        var alreadyRequired = ($('script[src=\"' + url + '\"]').length > 0);\n\n        // If loadJS was already called with the same URL, it will have a registered promise indicating if\n        // the script has been fully loaded. If not, the promise has to be initialized.\n        // This is initialized as already resolved if the script was already there without the need of loadJS.\n        if (url in dependenciesPromise) {\n            return dependenciesPromise[url];\n        }\n        var scriptLoadedPromise = new Promise(function (resolve, reject) {\n            if (alreadyRequired) {\n                resolve();\n            } else {\n                // Get the script associated promise and returns it after initializing the script if needed. The\n                // promise is marked to be resolved on script load and rejected on script error.\n                var script = document.createElement('script');\n                script.type = 'text/javascript';\n                script.src = url;\n                script.onload = script.onreadystatechange = function() {\n                    if ((script.readyState && script.readyState !== \"loaded\" && script.readyState !== \"complete\") || script.onload_done) {\n                        return;\n                    }\n                    script.onload_done = true;\n                    resolve(url);\n                };\n                script.onerror = function () {\n                    console.error(\"Error loading file\", script.src);\n                    reject(url);\n                };\n                var head = document.head || document.getElementsByTagName('head')[0];\n                head.appendChild(script);\n            }\n        });\n\n        dependenciesPromise[url] = scriptLoadedPromise;\n        return scriptLoadedPromise;\n    };\n\n    return load;\n})();\n\n\n/**\n * Cooperative file download implementation, for ajaxy APIs.\n *\n * @param {Object} options\n * @param {String} [options.url] used to dynamically create a form\n * @param {Object} [options.data] data to add to the form submission. If can be used without a form, in which case a form is created from scratch. Otherwise, added to form data\n * @param {HTMLFormElement} [options.form] the form to submit in order to fetch the file\n * @param {Function} [options.success] callback in case of download success\n * @param {Function} [options.error] callback in case of request error, provided with the error body\n * @param {Function} [options.complete] called after both ``success`` and ``error`` callbacks have executed\n * @returns {boolean} a false value means that a popup window was blocked. This\n *   mean that we probably need to inform the user that something needs to be\n *   changed to make it work.\n */\nfunction get_file(options) {\n    var xhr = new XMLHttpRequest();\n\n    var data;\n    if (options.form) {\n        xhr.open(options.form.method, options.form.action);\n        data = new FormData(options.form);\n    } else {\n        xhr.open('POST', options.url);\n        data = new FormData();\n        _.each(options.data || {}, function (v, k) {\n            data.append(k, v);\n        });\n    }\n    if (core.csrf_token) {\n        data.append('csrf_token', core.csrf_token);\n    }\n    // IE11 wants this after xhr.open or it throws\n    xhr.responseType = 'blob';\n\n    // onreadystatechange[readyState = 4]\n    // => onload (success) | onerror (error) | onabort\n    // => onloadend\n    xhr.onload = function () {\n        var mimetype = xhr.response.type;\n        if (xhr.status === 200 && mimetype !== 'text/html') {\n            // replace because apparently we send some C-D headers with a trailing \";\"\n            // todo: maybe a lack of CD[attachment] should be interpreted as an error case?\n            var header = (xhr.getResponseHeader('Content-Disposition') || '').replace(/;$/, '');\n            var filename = header ? contentdisposition.parse(header).parameters.filename : null;\n\n            download(xhr.response, filename, mimetype);\n            // not sure download is going to be sync so this may be called\n            // before the file is actually fetched (?)\n            if (options.success) { options.success(); }\n            return true;\n        }\n\n        if (!options.error) {\n            return true;\n        }\n        var decoder = new FileReader();\n        decoder.onload = function () {\n            var contents = decoder.result;\n\n            var err;\n            var doc = new DOMParser().parseFromString(contents, 'text/html');\n            var nodes = doc.body.children.length === 0 ? doc.body.childNodes : doc.body.children;\n            try { // Case of a serialized Odoo Exception: It is Json Parsable\n                var node = nodes[1] || nodes[0];\n                err = JSON.parse(node.textContent);\n            } catch (e) { // Arbitrary uncaught python side exception\n                err = {\n                    message: nodes.length > 1 ? nodes[1].textContent : '',\n                    data: {\n                        name: String(xhr.status),\n                        title: nodes.length > 0 ? nodes[0].textContent : '',\n                    }\n                };\n            }\n            options.error(err);\n        };\n        decoder.readAsText(xhr.response);\n    };\n    xhr.onerror = function () {\n        if (options.error) {\n            options.error({\n                message: _t(\"Something happened while trying to contact the server, check that the server is online and that you still have a working network connection.\"),\n                data: { title: _t(\"Could not connect to the server\") }\n            });\n        }\n    };\n    if (options.complete) {\n        xhr.onloadend = function () { options.complete(); };\n    }\n\n    xhr.send(data);\n    return true;\n}\n\nfunction post (controller_url, data) {\n    var postData = new FormData();\n\n    $.each(data, function(i,val) {\n        postData.append(i, val);\n    });\n    if (core.csrf_token) {\n        postData.append('csrf_token', core.csrf_token);\n    }\n\n    return new Promise(function (resolve, reject) {\n        $.ajax(controller_url, {\n            data: postData,\n            processData: false,\n            contentType: false,\n            type: 'POST'\n        }).then(resolve).fail(reject);\n    });\n}\n\n/**\n * Loads an XML file according to the given URL and adds its associated qweb\n * templates to the given qweb engine. The function can also be used to get\n * the promise which indicates when all the calls to the function are finished.\n *\n * Note: \"all the calls\" = the calls that happened before the current no-args\n * one + the calls that will happen after but when the previous ones are not\n * finished yet.\n *\n * @param {string} [url] - an URL where to find qweb templates\n * @param {QWeb} [qweb] - the engine to which the templates need to be added\n * @returns {Promise}\n *          If no argument is given to the function, the promise's state\n *          indicates if \"all the calls\" are finished (see main description).\n *          Otherwise, it indicates when the templates associated to the given\n *          url have been loaded.\n */\nvar loadXML = (function () {\n    // Some \"static\" variables associated to the loadXML function\n    var isLoading = false;\n    var loadingsData = [];\n    var seenURLs = [];\n\n    return function (url, qweb) {\n        function _load() {\n            isLoading = true;\n            if (loadingsData.length) {\n                // There is something to load, load it, resolve the associated\n                // promise then start loading the next one\n                var loadingData = loadingsData[0];\n                loadingData.qweb.add_template(loadingData.url, function () {\n                    // Remove from array only now so that multiple calls to\n                    // loadXML with the same URL returns the right promise\n                    loadingsData.shift();\n                    loadingData.resolve();\n                    _load();\n                });\n            } else {\n                // There is nothing to load anymore, so resolve the\n                // \"all the calls\" promise\n                isLoading = false;\n            }\n        }\n\n        // If no argument, simply returns the promise which indicates when\n        // \"all the calls\" are finished\n        if (!url || !qweb) {\n            return Promise.resolve();\n        }\n\n        // If the given URL has already been seen, do nothing but returning the\n        // associated promise\n        if (_.contains(seenURLs, url)) {\n            var oldLoadingData = _.findWhere(loadingsData, {url: url});\n            return oldLoadingData ? oldLoadingData.def : Promise.resolve();\n        }\n        seenURLs.push(url);\n\n\n        // Add the information about the new data to load: the url, the qweb\n        // engine and the associated promise\n        var newLoadingData = {\n            url: url,\n            qweb: qweb,\n        };\n        newLoadingData.def = new Promise(function (resolve, reject) {\n            newLoadingData.resolve = resolve;\n            newLoadingData.reject = reject;\n        });\n        loadingsData.push(newLoadingData);\n\n        // If not already started, start the loading loop (reinitialize the\n        // \"all the calls\" promise to an unresolved state)\n        if (!isLoading) {\n            _load();\n        }\n\n        // Return the promise associated to the new given URL\n        return newLoadingData.def;\n    };\n})();\n\n/**\n * Loads a template file according to the given xmlId.\n *\n * @param {string} [xmlId] - the template xmlId\n * @param {Object} [context]\n *        additionnal rpc context to be merged with the default one\n * @param {string} [tplRoute='/web/dataset/call_kw/']\n * @returns {Deferred} resolved with an object\n *          cssLibs: list of css files\n *          cssContents: list of style tag contents\n *          jsLibs: list of JS files\n *          jsContents: list of script tag contents\n */\nvar loadAsset = (function () {\n    var cache = {};\n\n    var load = function loadAsset(xmlId, context, tplRoute = '/web/dataset/call_kw/') {\n        if (cache[xmlId]) {\n            return cache[xmlId];\n        }\n        context = _.extend({}, session.user_context, context);\n        const params = {\n            args: [xmlId, {\n                debug: config.isDebug()\n            }],\n            kwargs: {\n                context: context,\n            },\n        };\n        if (tplRoute === '/web/dataset/call_kw/') {\n            Object.assign(params, {\n                model: 'ir.ui.view',\n                method: 'render_public_asset',\n            });\n        }\n        cache[xmlId] = rpc(tplRoute, params).then(function (xml) {\n            var $xml = $(xml);\n            return {\n                cssLibs: $xml.filter('link[href]:not([type=\"image/x-icon\"])').map(function () {\n                    return $(this).attr('href');\n                }).get(),\n                cssContents: $xml.filter('style').map(function () {\n                    return Markup($(this).html());\n                }).get(),\n                jsLibs: $xml.filter('script[src]').map(function () {\n                    return $(this).attr('src');\n                }).get(),\n                jsContents: $xml.filter('script:not([src])').map(function () {\n                    return Markup($(this).html());\n                }).get(),\n            };\n        }).guardedCatch(reason => {\n            reason.event.preventDefault();\n            throw `Unable to render the required templates for the assets to load: ${reason.message.message}`;\n        });\n        return cache[xmlId];\n    };\n\n    return load;\n})();\n\n/**\n * Loads the given js/css libraries and asset bundles. Note that no library or\n * asset will be loaded if it was already done before.\n *\n * @param {Object} libs\n * @param {Array<string|string[]>} [libs.assetLibs=[]]\n *      The list of assets to load. Each list item may be a string (the xmlID\n *      of the asset to load) or a list of strings. The first level is loaded\n *      sequentially (so use this if the order matters) while the assets in\n *      inner lists are loaded in parallel (use this for efficiency but only\n *      if the order does not matter, should rarely be the case for assets).\n * @param {string[]} [libs.cssLibs=[]]\n *      The list of CSS files to load. They will all be loaded in parallel but\n *      put in the DOM in the given order (only the order in the DOM is used\n *      to determine priority of CSS rules, not loaded time).\n * @param {Array<string|string[]>} [libs.jsLibs=[]]\n *      The list of JS files to load. Each list item may be a string (the URL\n *      of the file to load) or a list of strings. The first level is loaded\n *      sequentially (so use this if the order matters) while the files in inner\n *      lists are loaded in parallel (use this for efficiency but only\n *      if the order does not matter).\n * @param {string[]} [libs.cssContents=[]]\n *      List of inline styles to add after loading the CSS files.\n * @param {string[]} [libs.jsContents=[]]\n *      List of inline scripts to add after loading the JS files.\n * @param {Object} [context]\n *        additionnal rpc context to be merged with the default one\n * @param {string} [tplRoute]\n *      Custom route to use for template rendering of the potential assets\n *      to load (see libs.assetLibs).\n *\n * @returns {Promise}\n */\nfunction loadLibs(libs, context, tplRoute) {\n    var mutex = new concurrency.Mutex();\n    mutex.exec(function () {\n        var defs = [];\n        var cssLibs = [libs.cssLibs || []];  // Force loading in parallel\n        defs.push(_loadArray(cssLibs, ajax.loadCSS).then(function () {\n            if (libs.cssContents && libs.cssContents.length) {\n                $('head').append($('<style/>', {\n                    html: libs.cssContents.join('\\n'),\n                }));\n            }\n        }));\n        defs.push(_loadArray(libs.jsLibs || [], ajax.loadJS).then(function () {\n            if (libs.jsContents && libs.jsContents.length) {\n                $('head').append($('<script/>', {\n                    html: libs.jsContents.join('\\n'),\n                }));\n            }\n        }));\n        return Promise.all(defs);\n    });\n    mutex.exec(function () {\n        return _loadArray(libs.assetLibs || [], function (xmlID) {\n            return ajax.loadAsset(xmlID, context, tplRoute).then(function (asset) {\n                return ajax.loadLibs(asset);\n            });\n        });\n    });\n\n    function _loadArray(array, loadCallback) {\n        var _mutex = new concurrency.Mutex();\n        array.forEach(function (urlData) {\n            _mutex.exec(function () {\n                if (typeof urlData === 'string') {\n                    return loadCallback(urlData);\n                }\n                return Promise.all(urlData.map(loadCallback));\n            });\n        });\n        return _mutex.getUnlockedDef();\n    }\n\n    return mutex.getUnlockedDef();\n}\n\n_.extend(ajax, {\n    jsonRpc: jsonRpc,\n    rpc: rpc,\n    loadCSS: loadCSS,\n    loadJS: loadJS,\n    loadXML: loadXML,\n    loadAsset: loadAsset,\n    loadLibs: loadLibs,\n    get_file: get_file,\n    post: post,\n});\n\nreturn ajax;\n\n});\n", "odoo.define('web.BrowserDetection', function (require) {\n    \"use strict\";\n    var Class = require('web.Class');\n    const { isMacOS, isBrowserChrome } = require('@web/core/browser/feature_detection');\n\n    var BrowserDetection = Class.extend({\n        init: function () {\n\n        },\n        isOsMac: isMacOS,\n        isBrowserChrome,\n    });\n    return BrowserDetection;\n});\n\n", "odoo.define('web.Bus', function (require) {\n\"use strict\";\n\nvar Class = require('web.Class');\nvar mixins = require('web.mixins');\n\n/**\n * Event Bus used to bind events scoped in the current instance\n *\n * @class Bus\n */\nreturn Class.extend(mixins.EventDispatcherMixin, {\n    init: function (parent) {\n        mixins.EventDispatcherMixin.init.call(this);\n        this.setParent(parent);\n    },\n});\n\n});\n", "odoo.define('web.custom_hooks', function (require) {\n    \"use strict\";\n\n    const { Component } = owl;\n    const { useEffect } = require(\"@web/core/utils/hooks\");\n\n    /**\n     * Focus a given selector as soon as it appears in the DOM and if it was not\n     * displayed before. If the selected target is an input|textarea, set the selection\n     * at the end.\n     * @param {Object} [params]\n     * @param {string} [params.selector='autofocus'] default: select the first element\n     *                 with an `autofocus` attribute.\n     * @returns {Function} function that forces the focus on the next update if visible.\n     */\n    function useAutofocus(params = {}) {\n        const comp = Component.current;\n        // Prevent autofocus in mobile\n        if (comp.env.device.isMobileDevice) {\n            return () => {};\n        }\n        const selector = params.selector || '[autofocus]';\n        let forceFocusCount = 0;\n        useEffect(function autofocus(target) {\n            if (target) {\n                target.focus();\n                if ([\"INPUT\", \"TEXTAREA\"].includes(target.tagName)) {\n                    const inputEl = target;\n                    inputEl.selectionStart = inputEl.selectionEnd = inputEl.value.length;\n                }\n            }\n        }, () => [comp.el.querySelector(selector), forceFocusCount]);\n\n        return function focusOnUpdate() {\n            forceFocusCount++; // force the effect to rerun on next patch\n        };\n    }\n\n    /**\n     * The useListener hook offers an alternative to Owl's classical event\n     * registration mechanism (with attribute 't-on-eventName' in xml). It is\n     * especially useful for abstract components, meant to be extended by\n     * specific ones. If those abstract components need to define event handlers,\n     * but don't have any template (because the template completely depends on\n     * specific cases), then using the 't-on' mechanism isn't adequate, as the\n     * handlers would be lost by the template override. In this case, using this\n     * hook instead is more convenient.\n     *\n     * Example: navigation event handling in AbstractField\n     *\n     * Usage: like all Owl hooks, this function has to be called in the\n     * constructor of an Owl component:\n     *\n     *   useListener('click', () => { console.log('clicked'); });\n     *\n     * An optional native query selector can be specified as second argument for\n     * event delegation. In this case, the handler is only called if the event\n     * is triggered on an element matching the given selector.\n     *\n     *   useListener('click', 'button', () => { console.log('clicked'); });\n     *\n     * Note: components that alter the event's target (e.g. Portal) are not\n     * expected to behave as expected with event delegation.\n     *\n     * @param {string} eventName the name of the event\n     * @param {string} [querySelector] a JS native selector for event delegation\n     * @param {function} handler the event handler (will be bound to the component)\n     * @param {Object} [addEventListenerOptions] to be passed to addEventListener as options.\n     *    Useful for listening in the capture phase\n     */\n    function useListener(eventName, querySelector, handler, addEventListenerOptions) {\n        if (typeof arguments[1] !== 'string') {\n            querySelector = null;\n            handler = arguments[1];\n            addEventListenerOptions = arguments[2];\n        }\n        if (typeof handler !== 'function') {\n            throw new Error('The handler must be a function');\n        }\n\n        const comp = Component.current;\n        let boundHandler;\n        if (querySelector) {\n            boundHandler = function (ev) {\n                let el = ev.target;\n                let target;\n                while (el && !target) {\n                    if (el.matches(querySelector)) {\n                        target = el;\n                    } else if (el === comp.el) {\n                        el = null;\n                    } else {\n                        el = el.parentElement;\n                    }\n                }\n                if (el) {\n                    handler.call(comp, ev);\n                }\n            };\n        } else {\n            boundHandler = handler.bind(comp);\n        }\n        useEffect(() => {\n            comp.el.addEventListener(eventName, boundHandler, addEventListenerOptions);\n            return () => {\n                comp.el.removeEventListener(eventName, boundHandler, addEventListenerOptions);\n            };\n        }, () => []);\n    }\n\n    return {\n        useAutofocus,\n        useListener,\n    };\n});\n", "odoo.define('web.Class', function () {\n\"use strict\";\n/**\n * Improved John Resig's inheritance, based on:\n *\n * Simple JavaScript Inheritance\n * By John Resig http://ejohn.org/\n * MIT Licensed.\n *\n * Adds \"include()\"\n *\n * Defines The Class object. That object can be used to define and inherit classes using\n * the extend() method.\n *\n * Example::\n *\n *     var Person = Class.extend({\n *      init: function(isDancing){\n *         this.dancing = isDancing;\n *       },\n *       dance: function(){\n *         return this.dancing;\n *       }\n *     });\n *\n * The init() method act as a constructor. This class can be instanced this way::\n *\n *     var person = new Person(true);\n *     person.dance();\n *\n *     The Person class can also be extended again:\n *\n *     var Ninja = Person.extend({\n *       init: function(){\n *         this._super( false );\n *       },\n *       dance: function(){\n *         // Call the inherited version of dance()\n *         return this._super();\n *       },\n *       swingSword: function(){\n *         return true;\n *       }\n *     });\n *\n * When extending a class, each re-defined method can use this._super() to call the previous\n * implementation of that method.\n *\n * @class Class\n */\nfunction OdooClass(){}\n\nvar initializing = false;\n// eslint-disable-next-line no-undef\nvar fnTest = /xyz/.test(function(){xyz();}) ? /\\b_super\\b/ : /.*/;\n\n/**\n * Subclass an existing class\n *\n * @param {Object} prop class-level properties (class attributes and instance methods) to set on the new class\n */\nOdooClass.extend = function() {\n    var _super = this.prototype;\n    // Support mixins arguments\n    var args = _.toArray(arguments);\n    args.unshift({});\n    var prop = _.extend.apply(_,args);\n\n    // Instantiate a web class (but only create the instance,\n    // don't run the init constructor)\n    initializing = true;\n    var This = this;\n    var prototype = new This();\n    initializing = false;\n\n    // Copy the properties over onto the new prototype\n    _.each(prop, function(val, name) {\n        // Check if we're overwriting an existing function\n        prototype[name] = typeof prop[name] == \"function\" &&\n                          fnTest.test(prop[name]) ?\n                (function(name, fn) {\n                    return function() {\n                        var tmp = this._super;\n\n                        // Add a new ._super() method that is the same\n                        // method but on the super-class\n                        this._super = _super[name];\n\n                        // The method only need to be bound temporarily, so\n                        // we remove it when we're done executing\n                        var ret = fn.apply(this, arguments);\n                        this._super = tmp;\n\n                        return ret;\n                    };\n                })(name, prop[name]) :\n                prop[name];\n    });\n\n    // The dummy class constructor\n    function Class() {\n        if(this.constructor !== OdooClass){\n            throw new Error(\"You can only instanciate objects with the 'new' operator\");\n        }\n        // All construction is actually done in the init method\n        this._super = null;\n        if (!initializing && this.init) {\n            var ret = this.init.apply(this, arguments);\n            if (ret) { return ret; }\n        }\n        return this;\n    }\n    Class.include = function (properties) {\n        _.each(properties, function(val, name) {\n            if (typeof properties[name] !== 'function'\n                    || !fnTest.test(properties[name])) {\n                prototype[name] = properties[name];\n            } else if (typeof prototype[name] === 'function'\n                       && prototype.hasOwnProperty(name)) {\n                prototype[name] = (function (name, fn, previous) {\n                    return function () {\n                        var tmp = this._super;\n                        this._super = previous;\n                        var ret = fn.apply(this, arguments);\n                        this._super = tmp;\n                        return ret;\n                    };\n                })(name, properties[name], prototype[name]);\n            } else if (typeof _super[name] === 'function') {\n                prototype[name] = (function (name, fn) {\n                    return function () {\n                        var tmp = this._super;\n                        this._super = _super[name];\n                        var ret = fn.apply(this, arguments);\n                        this._super = tmp;\n                        return ret;\n                    };\n                })(name, properties[name]);\n            }\n        });\n    };\n\n    // Populate our constructed prototype object\n    Class.prototype = prototype;\n\n    // Enforce the constructor to be what we expect\n    Class.constructor = Class;\n\n    // And make this class extendable\n    Class.extend = this.extend;\n\n    return Class;\n};\n\nreturn OdooClass;\n});\n", "odoo.define(\"web.collections\", function (require) {\n    \"use strict\";\n\n    var Class = require(\"web.Class\");\n\n    /**\n     * Allows to build a tree representation of a data.\n     */\n    var Tree = Class.extend({\n        /**\n         * @constructor\n         * @param {*} data - the data associated to the root node\n         */\n        init: function (data) {\n            this._data = data;\n            this._children = [];\n        },\n\n        //----------------------------------------------------------------------\n        // Public\n        //----------------------------------------------------------------------\n\n        /**\n         * Returns the root's associated data.\n         *\n         * @returns {*}\n         */\n        getData: function () {\n            return this._data;\n        },\n        /**\n         * Adds a child tree.\n         *\n         * @param {Tree} tree\n         */\n        addChild: function (tree) {\n            this._children.push(tree);\n        },\n    });\n\n    return {\n        Tree: Tree,\n    };\n});\n", "odoo.define('web.concurrency', function (require) {\n\"use strict\";\n\n/**\n * Concurrency Utils\n *\n * This file contains a short collection of useful helpers designed to help with\n * everything concurrency related in Odoo.\n *\n * The basic concurrency primitives in Odoo JS are the callback, and the\n * promises.  Promises (promise) are more composable, so we usually use them\n * whenever possible.  We use the jQuery implementation.\n *\n * Those functions are really nothing special, but are simply the result of how\n * we solved some concurrency issues, when we noticed that a pattern emerged.\n */\n\nvar Class = require('web.Class');\n\nreturn {\n    /**\n     * Returns a promise resolved after 'wait' milliseconds\n     *\n     * @param {int} [wait=0] the delay in ms\n     * @return {Promise}\n     */\n    delay: function (wait) {\n        return new Promise(function (resolve) {\n            setTimeout(resolve, wait);\n        });\n    },\n    /**\n     * The DropMisordered abstraction is useful for situations where you have\n     * a sequence of operations that you want to do, but if one of them\n     * completes after a subsequent operation, then its result is obsolete and\n     * should be ignored.\n     *\n     * Note that is is kind of similar to the DropPrevious abstraction, but\n     * subtly different.  The DropMisordered operations will all resolves if\n     * they complete in the correct order.\n     */\n    DropMisordered: Class.extend({\n        /**\n         * @constructor\n         *\n         * @param {boolean} [failMisordered=false] whether mis-ordered responses\n         *   should be failed or just ignored\n         */\n        init: function (failMisordered) {\n            // local sequence number, for requests sent\n            this.lsn = 0;\n            // remote sequence number, seqnum of last received request\n            this.rsn = -1;\n            this.failMisordered = failMisordered || false;\n        },\n        /**\n         * Adds a promise (usually an async request) to the sequencer\n         *\n         * @param {Promise} promise to ensure add\n         * @returns {Promise}\n         */\n        add: function (promise) {\n            var self = this;\n            var seq = this.lsn++;\n            var res = new Promise(function (resolve, reject) {\n                promise.then(function (result) {\n                    if (seq > self.rsn) {\n                        self.rsn = seq;\n                        resolve(result);\n                    } else if (self.failMisordered) {\n                        reject();\n                    }\n                }).guardedCatch(function (result) {\n                    reject(result);\n                });\n            });\n            return res;\n        },\n    }),\n    /**\n     * The DropPrevious abstraction is useful when you have a sequence of\n     * operations that you want to execute, but you only care of the result of\n     * the last operation.\n     *\n     * For example, let us say that we have a _fetch method on a widget which\n     * fetches data.  We want to rerender the widget after.  We could do this::\n     *\n     *      this._fetch().then(function (result) {\n     *          self.state = result;\n     *          self.render();\n     *      });\n     *\n     * Now, we have at least two problems:\n     *\n     * - if this code is called twice and the second _fetch completes before the\n     *   first, the end state will be the result of the first _fetch, which is\n     *   not what we expect\n     * - in any cases, the user interface will rerender twice, which is bad.\n     *\n     * Now, if we have a DropPrevious::\n     *\n     *      this.dropPrevious = new DropPrevious();\n     *\n     * Then we can wrap the _fetch in a DropPrevious and have the expected\n     * result::\n     *\n     *      this.dropPrevious\n     *          .add(this._fetch())\n     *          .then(function (result) {\n     *              self.state = result;\n     *              self.render();\n     *          });\n     */\n    DropPrevious: Class.extend({\n        /**\n         * Registers a new promise and rejects the previous one\n         *\n         * @param {Promise} promise the new promise\n         * @returns {Promise}\n         */\n        add: function (promise) {\n            if (this.currentDef) {\n                this.currentDef.reject();\n            }\n            var rejection;\n            var res = new Promise(function (resolve, reject) {\n                rejection = reject;\n                promise.then(resolve).catch(function (reason) {\n                    reject(reason);\n                });\n            });\n\n            this.currentDef = res;\n            this.currentDef.reject = rejection;\n            return res;\n        }\n    }),\n    /**\n     * A (Odoo) mutex is a primitive for serializing computations.  This is\n     * useful to avoid a situation where two computations modify some shared\n     * state and cause some corrupted state.\n     *\n     * Imagine that we have a function to fetch some data _load(), which returns\n     * a promise which resolves to something useful. Now, we have some code\n     * looking like this::\n     *\n     *      return this._load().then(function (result) {\n     *          this.state = result;\n     *      });\n     *\n     * If this code is run twice, but the second execution ends before the\n     * first, then the final state will be the result of the first call to\n     * _load.  However, if we have a mutex::\n     *\n     *      this.mutex = new Mutex();\n     *\n     * and if we wrap the calls to _load in a mutex::\n     *\n     *      return this.mutex.exec(function() {\n     *          return this._load().then(function (result) {\n     *              this.state = result;\n     *          });\n     *      });\n     *\n     * Then, it is guaranteed that the final state will be the result of the\n     * second execution.\n     *\n     * A Mutex has to be a class, and not a function, because we have to keep\n     * track of some internal state.\n     */\n    Mutex: Class.extend({\n        init: function () {\n            this.lock = Promise.resolve();\n            this.queueSize = 0;\n            this.unlockedProm = undefined;\n            this._unlock = undefined;\n        },\n        /**\n         * Add a computation to the queue, it will be executed as soon as the\n         * previous computations are completed.\n         *\n         * @param {function} action a function which may return a Promise\n         * @returns {Promise}\n         */\n        exec: function (action) {\n            var self = this;\n            var currentLock = this.lock;\n            var result;\n            this.queueSize++;\n            this.unlockedProm = this.unlockedProm || new Promise(function (resolve) {\n                self._unlock = resolve;\n            });\n            this.lock = new Promise(function (unlockCurrent) {\n                currentLock.then(function () {\n                    result = action();\n                    var always = function (returnedResult) {\n                        unlockCurrent();\n                        self.queueSize--;\n                        if (self.queueSize === 0) {\n                            self.unlockedProm = undefined;\n                            self._unlock();\n                        }\n                        return returnedResult;\n                    };\n                    Promise.resolve(result).then(always).guardedCatch(always);\n                });\n            });\n            return this.lock.then(function () {\n                return result;\n            });\n        },\n        /**\n         * @returns {Promise} resolved as soon as the Mutex is unlocked\n         *   (directly if it is currently idle)\n         */\n        getUnlockedDef: function () {\n            return this.unlockedProm || Promise.resolve();\n        },\n    }),\n    /**\n     * A MutexedDropPrevious is a primitive for serializing computations while\n     * skipping the ones that where executed between a current one and before\n     * the execution of a new one. This is useful to avoid useless RPCs.\n     *\n     * You can read the Mutex description to understand its role ; for the\n     * DropPrevious part of this abstraction, imagine the following situation:\n     * you have a code that call the server with a fixed argument and a list of\n     * operations that only grows after each call and you only care about the\n     * RPC result (the server code doesn't do anything). If this code is called\n     * three times (A B C) and C is executed before B has started, it's useless\n     * to make an extra RPC (B) if you know that it won't have an impact and you\n     * won't use its result.\n     *\n     * Note that the promise returned by the exec call won't be resolved if\n     * exec is called before the first exec call resolution ; only the promise\n     * returned by the last exec call will be resolved (the other are rejected);\n     *\n     * A MutexedDropPrevious has to be a class, and not a function, because we\n     * have to keep track of some internal state. The exec function takes as\n     * argument an action (and not a promise as DropPrevious for example)\n     * because it's the MutexedDropPrevious role to trigger the RPC call that\n     * returns a promise when it's time.\n     */\n    MutexedDropPrevious: Class.extend({\n        init: function () {\n            this.locked = false;\n            this.currentProm = null;\n            this.pendingAction = null;\n            this.pendingProm = null;\n        },\n        /**\n         * @param {function} action a function which may return a promise\n         * @returns {Promise}\n         */\n        exec: function (action) {\n            var self = this;\n            var resolution;\n            var rejection;\n            if (this.locked) {\n                this.pendingAction = action;\n                var oldPendingDef = this.pendingProm;\n\n                this.pendingProm = new Promise(function (resolve, reject) {\n                    resolution = resolve;\n                    rejection = reject;\n                    if (oldPendingDef) {\n                        oldPendingDef.reject();\n                    }\n                    self.currentProm.reject();\n                });\n                this.pendingProm.resolve = resolution;\n                this.pendingProm.reject = rejection;\n                return this.pendingProm;\n            } else {\n                this.locked = true;\n                this.currentProm = new Promise(function (resolve, reject) {\n                    resolution = resolve;\n                    rejection = reject;\n                    function unlock() {\n                        self.locked = false;\n                        if (self.pendingAction) {\n                            var action = self.pendingAction;\n                            var prom = self.pendingProm;\n                            self.pendingAction = null;\n                            self.pendingProm = null;\n                            self.exec(action)\n                                .then(prom.resolve)\n                                .guardedCatch(prom.reject);\n                        }\n                    }\n                    Promise.resolve(action())\n                        .then(function (result) {\n                            resolve(result);\n                            unlock();\n                        })\n                        .guardedCatch(function (reason) {\n                            reject(reason);\n                            unlock();\n                        });\n                });\n                this.currentProm.resolve = resolution;\n                this.currentProm.reject = rejection;\n                return this.currentProm;\n            }\n        }\n    }),\n    /**\n     * Rejects a promise as soon as a reference promise is either resolved or\n     * rejected\n     *\n     * @param {Promise} [target_def] the promise to potentially reject\n     * @param {Promise} [reference_def] the reference target\n     * @returns {Promise}\n     */\n    rejectAfter: function (target_def, reference_def) {\n        return new Promise(function (resolve, reject) {\n            target_def.then(resolve).guardedCatch(reject);\n            reference_def.then(reject).guardedCatch(reject);\n        });\n    }\n};\n\n});\n", "odoo.define('web.Dialog', function (require) {\n\"use strict\";\n\nvar core = require('web.core');\nvar dom = require('web.dom');\nvar Widget = require('web.Widget');\nconst OwlDialog = require('web.OwlDialog');\n\nvar QWeb = core.qweb;\nvar _t = core._t;\n\n/**\n * A useful class to handle dialogs.\n * Attributes:\n *\n * ``$footer``\n *   A jQuery element targeting a dom part where buttons can be added. It\n *   always exists during the lifecycle of the dialog.\n **/\nvar Dialog = Widget.extend({\n    tagName: 'main',\n    xmlDependencies: ['/web/static/src/legacy/xml/dialog.xml'],\n    custom_events: _.extend({}, Widget.prototype.custom_events, {\n        focus_control_button: '_onFocusControlButton',\n        close_dialog: '_onCloseDialog',\n    }),\n    events: _.extend({}, Widget.prototype.events, {\n        'keydown .modal-footer button': '_onFooterButtonKeyDown',\n    }),\n    /**\n     * @param {Widget} parent\n     * @param {Object} [options]\n     * @param {string} [options.title=Odoo]\n     * @param {string} [options.subtitle]\n     * @param {string} [options.size=large] - 'extra-large', 'large', 'medium'\n     *        or 'small'\n     * @param {boolean} [options.fullscreen=false] - whether or not the dialog\n     *        should be open in fullscreen mode (the main usecase is mobile)\n     * @param {string} [options.dialogClass] - class to add to the modal-body\n     * @param {jQuery} [options.$content]\n     *        Element which will be the $el, replace the .modal-body and get the\n     *        modal-body class\n     * @param {Object[]} [options.buttons]\n     *        List of button descriptions. Note: if no buttons, a \"ok\" primary\n     *        button is added to allow closing the dialog\n     * @param {string} [options.buttons[].text]\n     * @param {string} [options.buttons[].classes]\n     *        Default to 'btn-primary' if only one button, 'btn-secondary'\n     *        otherwise\n     * @param {boolean} [options.buttons[].close=false]\n     * @param {function} [options.buttons[].click]\n     * @param {boolean} [options.buttons[].disabled]\n     * @param {boolean} [options.technical=true]\n     *        If set to false, the modal will have the standard frontend style\n     *        (use this for non-editor frontend features)\n     * @param {jQueryElement} [options.$parentNode]\n     *        Element in which dialog will be appended, by default it will be\n     *        in the body\n     * @param {boolean|string} [options.backdrop='static']\n     *        The kind of modal backdrop to use (see BS documentation)\n     * @param {boolean} [options.renderHeader=true]\n     *        Whether or not the dialog should be rendered with header\n     * @param {boolean} [options.renderFooter=true]\n     *        Whether or not the dialog should be rendered with footer\n     * @param {function} [options.onForceClose]\n     *        Callback that triggers when the modal is closed by other means than with the buttons\n     *        e.g. pressing ESC\n     */\n    init: function (parent, options) {\n        var self = this;\n        this._super(parent);\n        this._opened = new Promise(function (resolve) {\n            self._openedResolver = resolve;\n        });\n        if (this.on_attach_callback) {\n            this._opened = this.opened(this.on_attach_callback);\n        }\n        options = _.defaults(options || {}, {\n            title: _t('Odoo'), subtitle: '',\n            size: 'large',\n            fullscreen: false,\n            dialogClass: '',\n            $content: false,\n            buttons: [{text: _t(\"Ok\"), close: true}],\n            technical: true,\n            $parentNode: false || $(document.body.querySelector(\".o_dialog_container\")),\n            backdrop: 'static',\n            renderHeader: true,\n            renderFooter: true,\n            onForceClose: false,\n        });\n\n        this.$content = options.$content;\n        this.title = options.title;\n        this.subtitle = options.subtitle;\n        this.fullscreen = options.fullscreen;\n        this.dialogClass = options.dialogClass;\n        this.size = options.size;\n        this.buttons = options.buttons;\n        this.technical = options.technical;\n        this.$parentNode = options.$parentNode;\n        this.backdrop = options.backdrop;\n        this.renderHeader = options.renderHeader;\n        this.renderFooter = options.renderFooter;\n        this.onForceClose = options.onForceClose;\n\n        core.bus.on('close_dialogs', this, this.destroy.bind(this));\n    },\n    /**\n     * Wait for XML dependencies and instantiate the modal structure (except\n     * modal-body).\n     *\n     * @override\n     */\n    willStart: function () {\n        var self = this;\n        return this._super.apply(this, arguments).then(function () {\n            // Render modal once xml dependencies are loaded\n            self.$modal = $(QWeb.render('Dialog', {\n                fullscreen: self.fullscreen,\n                title: self.title,\n                subtitle: self.subtitle,\n                technical: self.technical,\n                renderHeader: self.renderHeader,\n                renderFooter: self.renderFooter,\n            }));\n            switch (self.size) {\n                case 'extra-large':\n                    self.$modal.find('.modal-dialog').addClass('modal-xl');\n                    break;\n                case 'large':\n                    self.$modal.find('.modal-dialog').addClass('modal-lg');\n                    break;\n                case 'small':\n                    self.$modal.find('.modal-dialog').addClass('modal-sm');\n                    break;\n            }\n            if (self.renderFooter) {\n                self.$footer = self.$modal.find(\".modal-footer\");\n                self.set_buttons(self.buttons);\n            }\n            self.$modal.on('hidden.bs.modal', _.bind(self.destroy, self));\n        });\n    },\n    /**\n     * @override\n     */\n    renderElement: function () {\n        this._super();\n        // Note: ideally, the $el which is created/set here should use the\n        // 'main' tag, we cannot enforce this as it would require to re-create\n        // the whole element.\n        if (this.$content) {\n            this.setElement(this.$content);\n        }\n        this.$el.addClass('modal-body ' + this.dialogClass);\n    },\n    //--------------------------------------------------------------------------\n    // Public\n    //--------------------------------------------------------------------------\n    /**\n     * @param {Object[]} buttons - @see init\n     */\n    set_buttons: function (buttons) {\n        this._setButtonsTo(this.$footer, buttons);\n    },\n\n    set_title: function (title, subtitle) {\n        this.title = title || \"\";\n        if (subtitle !== undefined) {\n            this.subtitle = subtitle || \"\";\n        }\n\n        var $title = this.$modal.find('.modal-title').first();\n        var $subtitle = $title.find('.o_subtitle').detach();\n        $title.html(this.title);\n        $subtitle.html(this.subtitle).appendTo($title);\n\n        return this;\n    },\n\n    opened: function (handler) {\n        return (handler)? this._opened.then(handler) : this._opened;\n    },\n\n    /**\n     * Show a dialog\n     *\n     * @param {Object} options\n     * @param {boolean} options.shouldFocusButtons  if true, put the focus on\n     * the first button primary when the dialog opens\n     */\n    open: function (options) {\n        $('.tooltip').remove(); // remove open tooltip if any to prevent them staying when modal is opened\n\n        var self = this;\n        this.appendTo($('<div/>')).then(function () {\n            if (self.isDestroyed()) {\n                return;\n            }\n            self.$modal.find(\".modal-body\").replaceWith(self.$el);\n            self.$modal.attr('open', true);\n            if (self.$parentNode) {\n                self.$modal.appendTo(self.$parentNode);\n            }\n            self.$modal.modal({\n                show: true,\n                backdrop: self.backdrop,\n                keyboard: false,\n            });\n            self._openedResolver();\n            if (options && options.shouldFocusButtons) {\n                self._onFocusControlButton();\n            }\n\n            // Notifies OwlDialog to adjust focus/active properties on owl dialogs\n            OwlDialog.display(self);\n\n            // Notifies new webclient to adjust UI active element\n            core.bus.trigger(\"legacy_dialog_opened\", self);\n        });\n\n        return self;\n    },\n\n    close: function () {\n        this.destroy();\n    },\n\n    /**\n     * Close and destroy the dialog.\n     *\n     * @param {Object} [options]\n     * @param {Object} [options.infos] if provided and `silent` is unset, the\n     *   `on_close` handler will pass this information related to closing this\n     *   information.\n     * @param {boolean} [options.silent=false] if set, do not call the\n     *   `on_close` handler.\n     */\n    destroy: function (options) {\n        // Need to trigger before real destroy but if 'closed' handler destroys\n        // the widget again, we want to avoid infinite recursion\n        if (!this.__closed) {\n            this.__closed = true;\n            this.trigger('closed', options);\n        }\n\n        if (this.isDestroyed()) {\n            return;\n        }\n\n        // Notifies OwlDialog to adjust focus/active properties on owl dialogs.\n        // Only has to be done if the dialog has been opened (has an el).\n        if (this.el) {\n            OwlDialog.hide(this);\n\n            // Notifies new webclient to adjust UI active element\n            core.bus.trigger(\"legacy_dialog_destroyed\", this);\n        }\n\n        // Triggers the onForceClose event if the callback is defined\n        if (this.onForceClose) {\n            this.onForceClose();\n        }\n        var isFocusSet = this._focusOnClose();\n\n        this._super();\n\n        $('.tooltip').remove(); //remove open tooltip if any to prevent them staying when modal has disappeared\n        if (this.$modal) {\n            if (this.on_detach_callback) {\n                this.on_detach_callback();\n            }\n            this.$modal.modal('hide');\n            this.$modal.remove();\n        }\n\n        const modals = $('.modal[role=\"dialog\"]').filter(':visible').filter(this._isBlocking);\n        if (modals.length) {\n            if (!isFocusSet) {\n                modals.last().focus();\n            }\n            // Keep class modal-open (deleted by bootstrap hide fnct) on body to allow scrolling inside the modal\n            $('body').addClass('modal-open');\n        }\n    },\n    /**\n     * adds the keydown behavior to the dialogs after external files modifies\n     * its DOM.\n     */\n    rebindButtonBehavior: function () {\n        this.$footer.on('keydown', this._onFooterButtonKeyDown);\n    },\n    //--------------------------------------------------------------------------\n    // Private\n    //--------------------------------------------------------------------------\n    /**\n     * Manages the focus when the dialog closes. The default behavior is to set the focus on the top-most opened popup.\n     * The goal of this function is to be overridden by all children of the dialog class.\n     *\n     * @returns: boolean  should return true if the focus has already been set else false.\n     */\n    _focusOnClose: function() {\n        return false;\n    },\n    /**\n     * Render and set the given buttons into a target element\n     *\n     * @private\n     * @param {jQueryElement} $target The destination of the rendered buttons\n     * @param {Array} buttons The array of buttons to render\n     */\n    _setButtonsTo($target, buttons) {\n        var self = this;\n        $target.empty();\n        _.each(buttons, function (buttonData) {\n            var $button = dom.renderButton({\n                attrs: {\n                    class: buttonData.classes || (buttons.length > 1 ? 'btn-secondary' : 'btn-primary'),\n                    disabled: buttonData.disabled,\n                },\n                icon: buttonData.icon,\n                text: buttonData.text,\n            });\n            $button.on('click', function (e) {\n                var def;\n                if (buttonData.click) {\n                    def = buttonData.click.call(self, e);\n                }\n                if (buttonData.close) {\n                    self.onForceClose = false;\n                    Promise.resolve(def).then(self.close.bind(self));\n                }\n            });\n            if (self.technical) {\n                $target.append($button);\n            } else {\n                $target.prepend($button);\n            }\n        });\n    },\n    /**\n     * Returns false for non-\"blocking\" dialogs.\n     * This is intended to be overridden by subclasses.\n     *\n     * @private\n     * @param {int} index\n     * @param {element} el The element of a dialog.\n     * @returns {boolean}\n     */\n    _isBlocking(index, el) {\n        return true;\n    },\n\n    //--------------------------------------------------------------------------\n    // Handlers\n    //--------------------------------------------------------------------------\n    /**\n     * @private\n     */\n    _onCloseDialog: function (ev) {\n        ev.stopPropagation();\n        this.close();\n    },\n    /**\n     * Moves the focus to the first button primary in the footer of the dialog\n     *\n     * @private\n     * @param {odooEvent} e\n     */\n    _onFocusControlButton: function (e) {\n        if (this.$footer) {\n            if (e) {\n                e.stopPropagation();\n            }\n            this.$footer.find('.btn-primary:visible:first()').focus();\n        }\n    },\n    /**\n     * Manages the TAB key on the buttons. If you the focus is on a primary\n     * button and the users tries to tab to go to the next button, display\n     * a tooltip\n     *\n     * @param {jQueryEvent} e\n     * @private\n     */\n    _onFooterButtonKeyDown: function (e) {\n        switch(e.which) {\n            case $.ui.keyCode.TAB:\n                if (!e.shiftKey && e.target.classList.contains(\"btn-primary\")) {\n                    e.preventDefault();\n                    var $primaryButton = $(e.target);\n                    $primaryButton.tooltip({\n                        delay: {show: 200, hide:0},\n                        title: function(){\n                            return QWeb.render('FormButton.tooltip',{title:$primaryButton.text().toUpperCase()});\n                        },\n                        trigger: 'manual',\n                    });\n                    $primaryButton.tooltip('show');\n                }\n                break;\n        }\n    }\n});\n\n// static method to open simple alert dialog\nDialog.alert = function (owner, message, options) {\n    var buttons = [{\n        text: _t(\"Ok\"),\n        close: true,\n        click: options && options.confirm_callback,\n    }];\n    return new Dialog(owner, _.extend({\n        size: 'medium',\n        buttons: buttons,\n        $content: $('<main/>', {\n            role: 'alert',\n            text: message,\n        }),\n        title: _t(\"Alert\"),\n        onForceClose: options && (options.onForceClose || options.confirm_callback),\n    }, options)).open({shouldFocusButtons:true});\n};\n\n// static method to open simple confirm dialog\nDialog.confirm = function (owner, message, options) {\n    /**\n     * Creates an improved callback from the given callback value at the given\n     * key from the parent function's options parameter. This is improved to:\n     *\n     * - Prevent calling given callbacks once one has been called.\n     *\n     * - Re-allow calling callbacks once a previous callback call's returned\n     *   Promise is rejected.\n     */\n    let isBlocked = false;\n    function makeCallback(key) {\n        const callback = options && options[key];\n        return function () {\n            if (isBlocked) {\n                // Do not (re)call any callback and return a rejected Promise\n                // to prevent closing the Dialog.\n                return Promise.reject();\n            }\n            isBlocked = true;\n            const callbackRes = callback && callback.apply(this, arguments);\n            Promise.resolve(callbackRes).guardedCatch(() => {\n                isBlocked = false;\n            });\n            return callbackRes;\n        };\n    }\n    var buttons = [\n        {\n            text: _t(\"Ok\"),\n            classes: 'btn-primary',\n            close: true,\n            click: makeCallback('confirm_callback'),\n        },\n        {\n            text: _t(\"Cancel\"),\n            close: true,\n            click: makeCallback('cancel_callback'),\n        }\n    ];\n    return new Dialog(owner, _.extend({\n        size: 'medium',\n        buttons: buttons,\n        $content: $('<main/>', {\n            role: 'alert',\n            text: message,\n        }),\n        title: _t(\"Confirmation\"),\n        onForceClose: options && (options.onForceClose || options.cancel_callback),\n    }, options)).open({shouldFocusButtons:true});\n};\n\n/**\n * Static method to open double confirmation dialog.\n *\n * @param {Widget} owner\n * @param {string} message\n * @param {Object} [options] @see Dialog.init @see Dialog.confirm\n * @param {string} [options.securityLevel=\"warning\"] - bootstrap color\n * @param {string} [options.securityMessage=\"I am sure about this\"]\n * @returns {Dialog} (open() is automatically called)\n */\nDialog.safeConfirm = function (owner, message, options) {\n    var $checkbox = dom.renderCheckbox({\n        text: options && options.securityMessage || _t(\"I am sure about this.\"),\n    }).addClass('mb0');\n    var $securityCheck = $('<div/>', {\n        class: 'alert alert-' + (options && options.securityLevel || 'warning') + ' mt8 mb0',\n    }).prepend($checkbox);\n    var $content;\n    if (options && options.$content) {\n        $content = options.$content;\n        delete options.$content;\n    } else {\n        $content = $('<div>', {\n            text: message,\n        });\n    }\n    $content = $('<main/>', {role: 'alert'}).append($content, $securityCheck);\n\n    var buttons = [\n        {\n            text: _t(\"Ok\"),\n            classes: 'btn-primary o_safe_confirm_button',\n            close: true,\n            click: options && options.confirm_callback,\n            disabled: true,\n        },\n        {\n            text: _t(\"Cancel\"),\n            close: true,\n            click: options && options.cancel_callback\n        }\n    ];\n    var dialog = new Dialog(owner, _.extend({\n        size: 'medium',\n        buttons: buttons,\n        $content: $content,\n        title: _t(\"Confirmation\"),\n        onForceClose: options && (options.onForceClose || options.cancel_callback),\n    }, options));\n    dialog.opened(function () {\n        var $button = dialog.$footer.find('.o_safe_confirm_button');\n        $securityCheck.on('click', 'input[type=\"checkbox\"]', function (ev) {\n            $button.prop('disabled', !$(ev.currentTarget).prop('checked'));\n        });\n    });\n    return dialog.open();\n};\n\nreturn Dialog;\n\n});\n", "odoo.define('web.OwlDialog', function (require) {\n    \"use strict\";\n\n    const { Component, hooks, misc } = owl;\n    const { Portal } = misc;\n    const { useRef } = hooks;\n    const SIZE_CLASSES = {\n        'extra-large': 'modal-xl',\n        'large': 'modal-lg',\n        'small': 'modal-sm',\n    };\n\n    /**\n     * Dialog (owl version)\n     *\n     * Represents a bootstrap-styled dialog handled with pure JS. Its implementation\n     * is roughly the same as the legacy dialog, the only exception being the buttons.\n     * @extends Component\n     **/\n    class Dialog extends Component {\n        /**\n         * @param {Object} [props]\n         * @param {(boolean|string)} [props.backdrop='static'] The kind of modal backdrop\n         *      to use (see Bootstrap documentation).\n         * @param {string} [props.contentClass] Class to add to the dialog\n         * @param {boolean} [props.fullscreen=false] Whether the dialog should be\n         *      open in fullscreen mode (the main usecase is mobile).\n         * @param {boolean} [props.renderFooter=true] Whether the dialog footer\n         *      should be rendered.\n         * @param {boolean} [props.renderHeader=true] Whether the dialog header\n         *      should be rendered.\n         * @param {string} [props.size='large'] 'extra-large', 'large', 'medium'\n         *      or 'small'.\n         * @param {string} [props.stopClicks=true] whether the dialog should stop\n         *      the clicks propagation outside of itself.\n         * @param {string} [props.subtitle='']\n         * @param {string} [props.title='Odoo']\n         * @param {boolean} [props.technical=true] If set to false, the modal will have\n         *      the standard frontend style (use this for non-editor frontend features).\n         */\n        constructor() {\n            super(...arguments);\n\n            this.modalRef = useRef('modal');\n            this.footerRef = useRef('modal-footer');\n        }\n\n        mounted() {\n            this.constructor.display(this);\n\n            this.env.bus.on('close_dialogs', this, this._close);\n\n            if (this.props.renderFooter) {\n                // Set up main button : will first look for an element with the\n                // 'btn-primary' class, then a 'btn' class, then the first button\n                // element.\n                let mainButton = this.footerRef.el.querySelector('.btn.btn-primary');\n                if (!mainButton) {\n                    mainButton = this.footerRef.el.querySelector('.btn');\n                }\n                if (!mainButton) {\n                    mainButton = this.footerRef.el.querySelector('button');\n                }\n                if (mainButton) {\n                    this.mainButton = mainButton;\n                    this.mainButton.addEventListener('keydown', this._onMainButtonKeydown.bind(this));\n                    this.mainButton.focus();\n                }\n            }\n\n            this._removeTooltips();\n\n            // Notifies new webclient to adjust UI active element\n            this.env.bus.trigger(\"owl_dialog_mounted\", this);\n        }\n\n        willUnmount() {\n            // Notifies new webclient to adjust UI active element\n            this.env.bus.trigger(\"owl_dialog_willunmount\", this);\n\n            this.env.bus.off('close_dialogs', this, this._close);\n\n            this._removeTooltips();\n\n            this.constructor.hide(this);\n        }\n\n        //--------------------------------------------------------------------------\n        // Getters\n        //--------------------------------------------------------------------------\n\n        /**\n         * @returns {string}\n         */\n        get size() {\n            return SIZE_CLASSES[this.props.size];\n        }\n\n        //--------------------------------------------------------------------------\n        // Private\n        //--------------------------------------------------------------------------\n\n        /**\n         * Send an event signaling that the dialog must be closed.\n         * @private\n         */\n        _close() {\n            this.trigger('dialog-closed');\n        }\n\n        /**\n         * Remove any existing tooltip present in the DOM.\n         * @private\n         */\n        _removeTooltips() {\n            for (const tooltip of document.querySelectorAll('.tooltip')) {\n                tooltip.remove(); // remove open tooltip if any to prevent them staying when modal is opened\n            }\n        }\n\n        //--------------------------------------------------------------------------\n        // Handlers\n        //--------------------------------------------------------------------------\n\n        /**\n         * @private\n         * @param {MouseEvent} ev\n         */\n        _onBackdropClick(ev) {\n            if (!this.props.backdrop || ev.target !== ev.currentTarget) {\n                return;\n            }\n            if (this.props.backdrop === 'static') {\n                if (this.mainButton) {\n                    this.mainButton.focus();\n                }\n            } else {\n                this._close();\n            }\n        }\n\n        /**\n         * @private\n         * @param {MouseEvent} ev\n         */\n        _onClick(ev) {\n            if (this.props.stopClicks) {\n                ev.stopPropagation();\n            }\n        }\n\n        /**\n         * @private\n         */\n        _onFocus() {\n            if (this.mainButton) {\n                this.mainButton.focus();\n            }\n        }\n\n        /**\n         * Manage the TAB key on the main button. If the focus is on a primary\n         * button and the user tries to tab to go to the next button : a tooltip\n         * will be displayed.\n         * @private\n         * @param {KeyboardEvent} ev\n         */\n        _onMainButtonKeydown(ev) {\n            if (ev.key === 'Tab' && !ev.shiftKey) {\n                ev.preventDefault();\n                $(this.mainButton)\n                    .tooltip({\n                        delay: { show: 200, hide: 0 },\n                        title: () => this.env.qweb.renderToString('web.DialogButton.tooltip', {\n                            title: this.mainButton.innerText.toUpperCase(),\n                        }),\n                        trigger: 'manual',\n                    })\n                    .tooltip('show');\n            }\n        }\n\n        //--------------------------------------------------------------------------\n        // Static\n        //--------------------------------------------------------------------------\n\n        /**\n         * Push the given dialog at the end of the displayed list then set it as\n         * active and all the others as passive.\n         * @param {(LegacyDialog|OwlDialog|LegacyAdaptedDialog)} dialog\n         */\n        static display(dialog) {\n            const activeDialog = this.displayed[this.displayed.length - 1];\n            if (activeDialog) {\n                // Deactivate previous dialog\n                const activeDialogEl = activeDialog.modalRef ?\n                    // Owl dialog | LegacyAdaptedDialog\n                    activeDialog.modalRef.el :\n                    // Legacy dialog\n                    activeDialog.$modal[0];\n                activeDialogEl.classList.add('o_inactive_modal');\n                activeDialogEl.removeAttribute(\"tabindex\");\n            }\n            // Push dialog\n            this.displayed.push(dialog);\n            // Update body class\n            document.body.classList.add('modal-open');\n        }\n\n        /**\n         * Set the given displayed dialog as passive and the last added displayed dialog\n         * as active, then remove it from the displayed list.\n         * @param {(LegacyDialog|OwlDialog|LegacyAdaptedDialog)} dialog\n         */\n        static hide(dialog) {\n            // Remove given dialog from the list\n            this.displayed.splice(this.displayed.indexOf(dialog), 1);\n            // Activate last dialog and update body class\n            const lastDialog = this.displayed[this.displayed.length - 1];\n            if (lastDialog) {\n                lastDialog.el.focus();\n                const modalEl = lastDialog.modalRef ?\n                    // Owl dialog | LegacyAdaptedDialog\n                    lastDialog.modalRef.el :\n                    // Legacy dialog\n                    lastDialog.$modal[0];\n                modalEl.classList.remove('o_inactive_modal');\n                modalEl.setAttribute(\"tabindex\", \"-1\");\n            } else {\n                document.body.classList.remove('modal-open');\n            }\n        }\n    }\n\n    Dialog.displayed = [];\n\n    Dialog.components = { Portal };\n    Dialog.defaultProps = {\n        backdrop: 'static',\n        renderFooter: true,\n        renderHeader: true,\n        size: 'large',\n        stopClicks: true,\n        technical: true,\n        title: \"Odoo\",\n    };\n    Dialog.props = {\n        backdrop: { validate: b => ['static', true, false].includes(b) },\n        contentClass: { type: String, optional: 1 },\n        fullscreen: { type: Boolean, optional: 1 },\n        renderFooter: Boolean,\n        renderHeader: Boolean,\n        size: { validate: s => ['extra-large', 'large', 'medium', 'small'].includes(s) },\n        stopClicks: Boolean,\n        subtitle: { type: String, optional: 1 },\n        technical: Boolean,\n        title: String,\n    };\n    Dialog.template = 'web.OwlDialog';\n\n    return Dialog;\n});\n", "odoo.define('web.Popover', function (require) {\n    'use strict';\n\n    const { Component, hooks, misc, QWeb } = owl;\n    const { Portal } = misc;\n    const { useRef, useState } = hooks;\n\n    /**\n     * Popover\n     *\n     * Represents a bootstrap-style popover handled with pure JS. The popover\n     * will be visually bound to its `target` using an arrow-like '::before'\n     * CSS pseudo-element.\n     * @extends Component\n     **/\n    class Popover extends Component {\n        /**\n         * @param {Object} props\n         * @param {String} [props.position='bottom']\n         * @param {String} [props.title]\n         */\n        constructor() {\n            super(...arguments);\n            this.popoverRef = useRef('popover');\n            this.orderedPositions = ['top', 'bottom', 'left', 'right'];\n            this.state = useState({\n                displayed: false,\n            });\n\n            this._onClickDocument = this._onClickDocument.bind(this);\n            this._onScrollDocument = this._onScrollDocument.bind(this);\n            this._onResizeWindow = this._onResizeWindow.bind(this);\n\n            this._onScrollDocument = _.throttle(this._onScrollDocument, 50);\n            this._onResizeWindow = _.debounce(this._onResizeWindow, 250);\n\n            /**\n             * Those events are only necessary if the popover is currently open,\n             * so we decided for performance reasons to avoid binding them while\n             * it is closed. This allows to have many popover instantiated while\n             * keeping the count of global handlers low.\n             */\n            this._hasGlobalEventListeners = false;\n        }\n\n        mounted() {\n            this._compute();\n        }\n\n        patched() {\n            this._compute();\n        }\n\n        willUnmount() {\n            if (this._hasGlobalEventListeners) {\n                this._removeGlobalEventListeners();\n            }\n        }\n\n        //----------------------------------------------------------------------\n        // Private\n        //----------------------------------------------------------------------\n\n        /**\n         * @private\n         */\n        _addGlobalEventListeners() {\n            /**\n             * Use capture for the following events to ensure no other part of\n             * the code can stop its propagation from reaching here.\n             */\n            document.addEventListener('click', this._onClickDocument, {\n                capture: true,\n            });\n            document.addEventListener('scroll', this._onScrollDocument, {\n                capture: true,\n            });\n            window.addEventListener('resize', this._onResizeWindow);\n            this._hasGlobalEventListeners = true;\n        }\n\n        _close() {\n            this.state.displayed = false;\n            this.trigger('o-popover-closed');\n        }\n\n        /**\n         * Computes the popover according to its props. This method will try to position the\n         * popover as requested (according to the `position` props). If the requested position\n         * does not fit the viewport, other positions will be tried in a clockwise order starting\n         * a the requested position (e.g. starting from left: top, right, bottom). If no position\n         * is found that fits the viewport, 'bottom' is used.\n         *\n         * @private\n         */\n        _compute() {\n            if (!this._hasGlobalEventListeners && this.state.displayed) {\n                this._addGlobalEventListeners();\n            }\n            if (this._hasGlobalEventListeners && !this.state.displayed) {\n                this._removeGlobalEventListeners();\n            }\n            if (!this.state.displayed) {\n                return;\n            }\n\n            // copy the default ordered position to avoid updating them in place\n            const possiblePositions = [...this.orderedPositions];\n            const positionIndex = possiblePositions.indexOf(\n                this.props.position\n            );\n\n            const positioningData = this.constructor.computePositioningData(\n                this.popoverRef.el,\n                this.el\n            );\n\n            // check if the requested position fits the viewport; if not,\n            // try all other positions and find one that does\n            const position = possiblePositions\n                .slice(positionIndex)\n                .concat(possiblePositions.slice(0, positionIndex))\n                .map((pos) => positioningData[pos])\n                .find((pos) => {\n                    this.popoverRef.el.style.top = `${pos.top}px`;\n                    this.popoverRef.el.style.left = `${pos.left}px`;\n                    const rect = this.popoverRef.el.getBoundingClientRect();\n                    const html = document.documentElement;\n                    return (\n                        rect.top >= 0 &&\n                        rect.left >= 0 &&\n                        rect.bottom <= (window.innerHeight || html.clientHeight) &&\n                        rect.right <= (window.innerWidth || html.clientWidth)\n                    );\n                });\n\n            // remove all existing positioning classes\n            possiblePositions.forEach((pos) => {\n                this.popoverRef.el.classList.remove(`o_popover--${pos}`);\n            });\n\n            if (position) {\n                // apply the preferred found position that fits the viewport\n                this.popoverRef.el.classList.add(`o_popover--${position.name}`);\n            } else {\n                // use the given `position` props because no position fits\n                this.popoverRef.el.style.top = `${positioningData[this.props.position].top}px`;\n                this.popoverRef.el.style.left = `${positioningData[this.props.position].left}px`;\n                this.popoverRef.el.classList.add(`o_popover--${this.props.position}`);\n            }\n        }\n\n        /**\n         * @private\n         */\n        _removeGlobalEventListeners() {\n            document.removeEventListener('click', this._onClickDocument, true);\n            document.removeEventListener('scroll', this._onScrollDocument, true);\n            window.removeEventListener('resize', this._onResizeWindow);\n            this._hasGlobalEventListeners = false;\n        }\n\n        //----------------------------------------------------------------------\n        // Handlers\n        //----------------------------------------------------------------------\n\n        /**\n         * Toggles the popover depending on its current state.\n         *\n         * @private\n         * @param {MouseEvent} ev\n         */\n        _onClick(ev) {\n            this.state.displayed = !this.state.displayed;\n            if (this.state.displayed) {\n                this.trigger('o-popover-opened');\n            } else {\n                this.trigger('o-popover-closed');\n            }\n        }\n\n        /**\n         * A click outside the popover will dismiss the current popover.\n         *\n         * @private\n         * @param {MouseEvent} ev\n         */\n        _onClickDocument(ev) {\n            // Handled by `_onClick`.\n            if (this.el.contains(ev.target)) {\n                return;\n            }\n            // Ignore click inside the popover.\n            if (this.popoverRef.el && this.popoverRef.el.contains(ev.target)) {\n                return;\n            }\n            this._close();\n        }\n\n        /**\n         * @private\n         * @param {Event} ev\n         */\n        _onPopoverClose(ev) {\n            this._close();\n        }\n\n        /**\n         * Popover must recompute its position when children content changes.\n         *\n         * @private\n         * @param {Event} ev\n         */\n        _onPopoverCompute(ev) {\n            this._compute();\n        }\n\n        /**\n         * A resize event will need to 'reposition' the popover close to its\n         * target.\n         *\n         * @private\n         * @param {Event} ev\n         */\n        _onResizeWindow(ev) {\n            if (this.__owl__.status === 5 /* destroyed */) {\n                return;\n            }\n            this._compute();\n        }\n\n        /**\n         * A scroll event will need to 'reposition' the popover close to its\n         * target.\n         *\n         * @private\n         * @param {Event} ev\n         */\n        _onScrollDocument(ev) {\n            if (this.__owl__.status === 5 /* destroyed */) {\n                return;\n            }\n            this._compute();\n        }\n\n        //----------------------------------------------------------------------\n        // Static\n        //----------------------------------------------------------------------\n\n        /**\n         * Compute the expected positioning coordinates for each possible\n         * positioning based on the target and popover sizes.\n         * In particular the popover must not overflow the viewport in any\n         * direction, it should actually stay at `margin` distance from the\n         * border to look good.\n         *\n         * @static\n         * @param {HTMLElement} popoverElement The popover element\n         * @param {HTMLElement} targetElement The target element, to which\n         *  the popover will be visually 'bound'\n         * @param {integer} [margin=16] Minimal accepted margin from the border\n         *  of the viewport.\n         * @returns {Object}\n         */\n        static computePositioningData(popoverElement, targetElement, margin = 16) {\n            // set target position, possible position\n            const boundingRectangle = targetElement.getBoundingClientRect();\n            const targetTop = boundingRectangle.top;\n            const targetLeft = boundingRectangle.left;\n            const targetHeight = targetElement.offsetHeight;\n            const targetWidth = targetElement.offsetWidth;\n            const popoverHeight = popoverElement.offsetHeight;\n            const popoverWidth = popoverElement.offsetWidth;\n            const windowWidth = window.innerWidth || document.documentElement.clientWidth;\n            const windowHeight = window.innerHeight || document.documentElement.clientHeight;\n            const leftOffsetForVertical = Math.max(\n                margin,\n                Math.min(\n                    Math.round(targetLeft - (popoverWidth - targetWidth) / 2),\n                    windowWidth - popoverWidth - margin,\n                ),\n            );\n            const topOffsetForHorizontal = Math.max(\n                margin,\n                Math.min(\n                    Math.round(targetTop - (popoverHeight - targetHeight) / 2),\n                    windowHeight - popoverHeight - margin,\n                ),\n            );\n            return {\n                top: {\n                    name: 'top',\n                    top: Math.round(targetTop - popoverHeight),\n                    left: leftOffsetForVertical,\n                },\n                right: {\n                    name: 'right',\n                    top: topOffsetForHorizontal,\n                    left: Math.round(targetLeft + targetWidth),\n                },\n                bottom: {\n                    name: 'bottom',\n                    top: Math.round(targetTop + targetHeight),\n                    left: leftOffsetForVertical,\n                },\n                left: {\n                    name: 'left',\n                    top: topOffsetForHorizontal,\n                    left: Math.round(targetLeft - popoverWidth),\n                },\n            };\n        }\n\n    }\n\n    Popover.components = { Portal };\n    Popover.template = 'Popover';\n    Popover.defaultProps = {\n        position: 'bottom',\n    };\n    Popover.props = {\n        popoverClass: {\n            type: String,\n            optional: true,\n        },\n        position: {\n            type: String,\n            validate: (p) => ['top', 'bottom', 'left', 'right'].includes(p),\n        },\n        title: { type: String, optional: true },\n        titleAttribute: { type: String, optional: true },\n    };\n\n    QWeb.registerComponent('Popover', Popover);\n\n    return Popover;\n});\n", "odoo.define('web.dom_ready', function (require) {\n'use strict';\n\n    return new Promise(function (resolve, reject) {\n        $(resolve);\n    });\n});\n//==============================================================================\n\nodoo.define('web.dom', function (require) {\n\"use strict\";\n\n/**\n * DOM Utility helpers\n *\n * We collect in this file some helpers to help integrate various DOM\n * functionalities with the odoo framework.  A common theme in these functions\n * is the use of the main core.bus, which helps the framework react when\n * something happens in the DOM.\n */\n\nvar concurrency = require('web.concurrency');\nvar config = require('web.config');\nvar core = require('web.core');\nvar _t = core._t;\n\n/**\n * Private function to notify that something has been attached in the DOM\n * @param {htmlString or Element or Array or jQuery} [content] the content that\n * has been attached in the DOM\n * @params {Array} [callbacks] array of {widget: w, callback_args: args} such\n * that on_attach_callback() will be called on each w with arguments args\n */\nfunction _notify(content, callbacks) {\n    callbacks.forEach(function (c) {\n        if (c.widget && c.widget.on_attach_callback) {\n            c.widget.on_attach_callback(c.callback_args);\n        }\n    });\n    core.bus.trigger('DOM_updated', content);\n}\n\nvar dom = {\n    DEBOUNCE: 400,\n\n    /**\n     * Appends content in a jQuery object and optionnally triggers an event\n     *\n     * @param {jQuery} [$target] the node where content will be appended\n     * @param {htmlString or Element or Array or jQuery} [content] DOM element,\n     *   array of elements, HTML string or jQuery object to append to $target\n     * @param {Boolean} [options.in_DOM] true if $target is in the DOM\n     * @param {Array} [options.callbacks] array of objects describing the\n     *   callbacks to perform (see _notify for a complete description)\n     */\n    append: function ($target, content, options) {\n        $target.append(content);\n        if (options && options.in_DOM) {\n            _notify(content, options.callbacks);\n        }\n    },\n    /**\n     * Detects if 2 elements are colliding.\n     *\n     * @param {Element} el1\n     * @param {Element} el2\n     * @returns {boolean}\n     */\n     areColliding(el1, el2) {\n        const el1Rect = el1.getBoundingClientRect();\n        const el2Rect = el2.getBoundingClientRect();\n        return el1Rect.bottom > el2Rect.top\n            && el1Rect.top < el2Rect.bottom\n            && el1Rect.right > el2Rect.left\n            && el1Rect.left < el2Rect.right;\n    },\n    /**\n     * Autoresize a $textarea node, by recomputing its height when necessary\n     * @param {number} [options.min_height] by default, 50.\n     * @param {Widget} [options.parent] if set, autoresize will listen to some\n     *   extra events to decide when to resize itself.  This is useful for\n     *   widgets that are not in the dom when the autoresize is declared.\n     */\n    autoresize: function ($textarea, options) {\n        if ($textarea.data(\"auto_resize\")) {\n            return;\n        }\n\n        var $fixedTextarea;\n        var minHeight;\n\n        function resize() {\n            $fixedTextarea.insertAfter($textarea);\n            var heightOffset = 0;\n            var style = window.getComputedStyle($textarea[0], null);\n            if (style.boxSizing === 'border-box') {\n                var paddingHeight = parseFloat(style.paddingTop) + parseFloat(style.paddingBottom);\n                var borderHeight = parseFloat(style.borderTopWidth) + parseFloat(style.borderBottomWidth);\n                heightOffset = borderHeight + paddingHeight;\n            }\n            $fixedTextarea.width($textarea.width());\n            $fixedTextarea.val($textarea.val());\n            var height = $fixedTextarea[0].scrollHeight;\n            $textarea.css({height: Math.max(height + heightOffset, minHeight)});\n        }\n\n        function removeVerticalResize() {\n            // We already compute the correct height:\n            // we don't want the user to resize it vertically.\n            // On Chrome this needs to be called after the DOM is ready.\n            var style = window.getComputedStyle($textarea[0], null);\n            if (style.resize === 'vertical') {\n                $textarea[0].style.resize = 'none';\n            } else if (style.resize === 'both') {\n                $textarea[0].style.resize = 'horizontal';\n            }\n        }\n\n        options = options || {};\n        minHeight = 'min_height' in options ? options.min_height : 50;\n\n        $fixedTextarea = $('<textarea disabled>', {\n            class: $textarea[0].className,\n        });\n\n        var direction = _t.database.parameters.direction === 'rtl' ? 'right' : 'left';\n        $fixedTextarea.css({\n            position: 'absolute',\n            opacity: 0,\n            height: 10,\n            borderTopWidth: 0,\n            borderBottomWidth: 0,\n            padding: 0,\n            overflow: 'hidden',\n            top: -10000,\n        }).css(direction, -10000);\n        $fixedTextarea.data(\"auto_resize\", true);\n\n        // The following line is necessary to prevent the scrollbar to appear\n        // on the textarea on Firefox when adding a new line if the current line\n        // has just enough characters to completely fill the line.\n        // This fix should be fine since we compute the height depending on the\n        // content, there should never be an overflow.\n        // TODO ideally understand why and fix this another way if possible.\n        $textarea.css({'overflow-y': 'hidden'});\n\n        resize();\n        removeVerticalResize();\n        $textarea.data(\"auto_resize\", true);\n\n        $textarea.on('input focus change', resize);\n        if (options.parent) {\n            core.bus.on('DOM_updated', options.parent, function () {\n                resize();\n                removeVerticalResize();\n            });\n        }\n    },\n    /**\n     * @return {HTMLElement|null}\n     */\n    closestScrollable(el) {\n        return $(el).closestScrollable()[0] || null;\n    },\n    /**\n     * @param {HTMLElement} el\n     * @see $.compensateScrollbar\n     */\n    compensateScrollbar(el, ...rest) {\n        $(el).compensateScrollbar(...rest);\n    },\n    /**\n     * jQuery find function behavior is::\n     *\n     *      $('A').find('A B') <=> $('A A B')\n     *\n     * The searches behavior to find options' DOM needs to be::\n     *\n     *      $('A').find('A B') <=> $('A B')\n     *\n     * This is what this function does.\n     *\n     * @param {jQuery} $from - the jQuery element(s) from which to search\n     * @param {string} selector - the CSS selector to match\n     * @param {boolean} [addBack=false] - whether or not the $from element\n     *                                  should be considered in the results\n     * @returns {jQuery}\n     */\n    cssFind: function ($from, selector, addBack) {\n        var $results;\n\n        // No way to correctly parse a complex jQuery selector but having no\n        // spaces should be a good-enough condition to use a simple find\n        var multiParts = selector.indexOf(' ') >= 0;\n        if (multiParts) {\n            $results = $from.find('*').filter(selector);\n        } else {\n            $results = $from.find(selector);\n        }\n\n        if (addBack && $from.is(selector)) {\n            $results = $results.add($from);\n        }\n\n        return $results;\n    },\n    /**\n     * Detaches widgets from the DOM and performs their on_detach_callback()\n     *\n     * @param {Array} [to_detach] array of {widget: w, callback_args: args} such\n     *   that w.$el will be detached and w.on_detach_callback(args) will be\n     *   called\n     * @param {jQuery} [options.$to_detach] if given, detached instead of\n     *   widgets' $el\n     * @return {jQuery} the detached elements\n     */\n    detach: function (to_detach, options) {\n        to_detach.forEach( function (d) {\n            if (d.widget.on_detach_callback) {\n                d.widget.on_detach_callback(d.callback_args);\n            }\n        });\n        var $to_detach = options && options.$to_detach;\n        if (!$to_detach) {\n            $to_detach = $(to_detach.map(function (d) {\n                return d.widget.el;\n            }));\n        }\n        return $to_detach.detach();\n    },\n    /**\n     * Returns the selection range of an input or textarea\n     *\n     * @param {Object} node DOM item input or texteara\n     * @returns {Object} range\n     */\n    getSelectionRange: function (node) {\n        return {\n            start: node.selectionStart,\n            end: node.selectionEnd,\n        };\n    },\n    /**\n     * Returns the distance between a DOM element and the top-left corner of the\n     * window\n     *\n     * @param {Object} e DOM element (input or texteara)\n     * @return {Object} the left and top distances in pixels\n     */\n    getPosition: function (e) {\n        var position = {left: 0, top: 0};\n        while (e) {\n            position.left += e.offsetLeft;\n            position.top += e.offsetTop;\n            e = e.offsetParent;\n        }\n        return position;\n    },\n    /**\n     * @returns {HTMLElement}\n     */\n    getScrollingElement() {\n        return $().getScrollingElement()[0];\n    },\n    /**\n     * @param {HTMLElement} el\n     * @returns {boolean}\n     */\n    hasScrollableContent(el) {\n        return $(el).hasScrollableContent();\n    },\n    /**\n     * @param {HTMLElement} el\n     * @returns {boolean}\n     */\n    isScrollable(el) {\n        return $(el).isScrollable();\n    },\n    /**\n     * Protects a function which is to be used as a handler by preventing its\n     * execution for the duration of a previous call to it (including async\n     * parts of that call).\n     *\n     * Limitation: as the handler is ignored during async actions,\n     * the 'preventDefault' or 'stopPropagation' calls it may want to do\n     * will be ignored too. Using the 'preventDefault' and 'stopPropagation'\n     * arguments solves that problem.\n     *\n     * @param {function} fct\n     *      The function which is to be used as a handler. If a promise\n     *      is returned, it is used to determine when the handler's action is\n     *      finished. Otherwise, the return is used as jQuery uses it.\n     * @param {function|boolean} preventDefault\n     * @param {function|boolean} stopPropagation\n     */\n    makeAsyncHandler: function (fct, preventDefault, stopPropagation) {\n        var pending = false;\n        function _isLocked() {\n            return pending;\n        }\n        function _lock() {\n            pending = true;\n        }\n        function _unlock() {\n            pending = false;\n        }\n        return function (ev) {\n            if (preventDefault === true || preventDefault && preventDefault()) {\n                ev.preventDefault();\n            }\n            if (stopPropagation === true || stopPropagation && stopPropagation()) {\n                ev.stopPropagation();\n            }\n\n            if (_isLocked()) {\n                // If a previous call to this handler is still pending, ignore\n                // the new call.\n                return;\n            }\n\n            _lock();\n            var result = fct.apply(this, arguments);\n            Promise.resolve(result).then(_unlock).guardedCatch(_unlock);\n            return result;\n        };\n    },\n    /**\n     * Creates a debounced version of a function to be used as a button click\n     * handler. Also improves the handler to disable the button for the time of\n     * the debounce and/or the time of the async actions it performs.\n     *\n     * Limitation: if two handlers are put on the same button, the button will\n     * become enabled again once any handler's action finishes (multiple click\n     * handlers should however not be binded to the same button).\n     *\n     * @param {function} fct\n     *      The function which is to be used as a button click handler. If a\n     *      promise is returned, it is used to determine when the button can be\n     *      re-enabled. Otherwise, the return is used as jQuery uses it.\n     */\n    makeButtonHandler: function (fct) {\n        // Fallback: if the final handler is not binded to a button, at least\n        // make it an async handler (also handles the case where some events\n        // might ignore the disabled state of the button).\n        fct = dom.makeAsyncHandler(fct);\n\n        return function (ev) {\n            var result = fct.apply(this, arguments);\n\n            var $button = $(ev.target).closest('.btn');\n            if (!$button.length) {\n                return result;\n            }\n\n            // Disable the button for the duration of the handler's action\n            // or at least for the duration of the click debounce. This makes\n            // a 'real' debounce creation useless. Also, during the debouncing\n            // part, the button is disabled without any visual effect.\n            $button.addClass('o_debounce_disabled');\n            Promise.resolve(dom.DEBOUNCE && concurrency.delay(dom.DEBOUNCE)).then(function () {\n                $button.removeClass('o_debounce_disabled');\n                const restore = dom.addButtonLoadingEffect($button[0]);\n                return Promise.resolve(result).then(restore).guardedCatch(restore);\n            });\n\n            return result;\n        };\n    },\n    /**\n     * Gives the button a loading effect by disabling it and adding a `fa`\n     * spinner icon.\n     * The existing button `fa` icons will be hidden through css.\n     *\n     * @param {HTMLElement} btn - the button to disable/load\n     * @return {function} a callback function that will restore the button\n     *         initial state\n     */\n    addButtonLoadingEffect: function (btn) {\n        const $btn = $(btn);\n        $btn.addClass('o_website_btn_loading disabled');\n        $btn.prop('disabled', true);\n        const $loader = $('<span/>', {\n            class: 'fa fa-refresh fa-spin mr-2',\n        });\n        $btn.prepend($loader);\n        return () => {\n             $btn.removeClass('o_website_btn_loading disabled');\n             $btn.prop('disabled', false);\n             $loader.remove();\n        };\n    },\n    /**\n     * Prepends content in a jQuery object and optionnally triggers an event\n     *\n     * @param {jQuery} [$target] the node where content will be prepended\n     * @param {htmlString or Element or Array or jQuery} [content] DOM element,\n     *   array of elements, HTML string or jQuery object to prepend to $target\n     * @param {Boolean} [options.in_DOM] true if $target is in the DOM\n     * @param {Array} [options.callbacks] array of objects describing the\n     *   callbacks to perform (see _notify for a complete description)\n     */\n    prepend: function ($target, content, options) {\n        $target.prepend(content);\n        if (options && options.in_DOM) {\n            _notify(content, options.callbacks);\n        }\n    },\n    /**\n     * Renders a button with standard odoo template. This does not use any xml\n     * template to avoid forcing the frontend part to lazy load a xml file for\n     * each widget which might want to create a simple button.\n     *\n     * @param {Object} options\n     * @param {Object} [options.attrs] - Attributes to put on the button element\n     * @param {string} [options.attrs.type='button']\n     * @param {string} [options.attrs.class='btn-secondary']\n     *        Note: automatically completed with \"btn btn-X\"\n     *        (@see options.size for the value of X)\n     * @param {string} [options.size] - @see options.attrs.class\n     * @param {string} [options.icon]\n     *        The specific fa icon class (for example \"fa-home\") or an URL for\n     *        an image to use as icon.\n     * @param {string} [options.text] - the button's text\n     * @returns {jQuery}\n     */\n    renderButton: function (options) {\n        var jQueryParams = _.extend({\n            type: 'button',\n        }, options.attrs || {});\n\n        var extraClasses = jQueryParams.class;\n        if (extraClasses) {\n            // If we got extra classes, check if old oe_highlight/oe_link\n            // classes are given and switch them to the right classes (those\n            // classes have no style associated to them anymore).\n            // TODO ideally this should be dropped at some point.\n            extraClasses = extraClasses.replace(/\\boe_highlight\\b/g, 'btn-primary')\n                                       .replace(/\\boe_link\\b/g, 'btn-link');\n        }\n\n        jQueryParams.class = 'btn';\n        if (options.size) {\n            jQueryParams.class += (' btn-' + options.size);\n        }\n        jQueryParams.class += (' ' + (extraClasses || 'btn-secondary'));\n\n        var $button = $('<button/>', jQueryParams);\n\n        if (options.icon) {\n            if (options.icon.substr(0, 3) === 'fa-') {\n                $button.append($('<i/>', {\n                    class: 'fa fa-fw o_button_icon ' + options.icon,\n                }));\n            } else {\n                $button.append($('<img/>', {\n                    src: options.icon,\n                }));\n            }\n        }\n        if (options.text) {\n            $button.append($('<span/>', {\n                text: options.text,\n            }));\n        }\n\n        return $button;\n    },\n    /**\n     * Renders a checkbox with standard odoo/BS template. This does not use any\n     * xml template to avoid forcing the frontend part to lazy load a xml file\n     * for each widget which might want to create a simple checkbox.\n     *\n     * @param {Object} [options]\n     * @param {Object} [options.prop]\n     *        Allows to set the input properties (disabled and checked states).\n     * @param {string} [options.text]\n     *        The checkbox's associated text. If none is given then a simple\n     *        checkbox is rendered.\n     * @returns {jQuery}\n     */\n    renderCheckbox: function (options) {\n        var id = _.uniqueId('checkbox-');\n        var $container = $('<div/>', {\n            class: 'custom-control custom-checkbox',\n        });\n        var $input = $('<input/>', {\n            type: 'checkbox',\n            id: id,\n            class: 'custom-control-input',\n        });\n        var $label = $('<label/>', {\n            for: id,\n            class: 'custom-control-label',\n            text: options && options.text || '',\n        });\n        if (!options || !options.text) {\n            $label.html('&#8203;'); // BS checkboxes need some label content (so\n                                // add a zero-width space when there is no text)\n        }\n        if (options && options.prop) {\n            $input.prop(options.prop);\n        }\n        if (options && options.role) {\n            $input.attr('role', options.role);\n        }\n        return $container.append($input, $label);\n    },\n    /**\n     * Sets the selection range of a given input or textarea\n     *\n     * @param {Object} node DOM element (input or textarea)\n     * @param {integer} range.start\n     * @param {integer} range.end\n     */\n    setSelectionRange: function (node, range) {\n        if (node.setSelectionRange){\n            node.setSelectionRange(range.start, range.end);\n        } else if (node.createTextRange){\n            node.createTextRange()\n                .collapse(true)\n                .moveEnd('character', range.start)\n                .moveStart('character', range.end)\n                .select();\n        }\n    },\n    /**\n     * Computes the size by which a scrolling point should be decreased so that\n     * the top fixed elements of the page appear above that scrolling point.\n     *\n     * @returns {number}\n     */\n    scrollFixedOffset() {\n        let size = 0;\n        for (const el of $('.o_top_fixed_element')) {\n            size += $(el).outerHeight();\n        }\n        return size;\n    },\n    /**\n     * @param {HTMLElement|string} el - the element to scroll to. If \"el\" is a\n     *      string, it must be a valid selector of an element in the DOM or\n     *      '#top' or '#bottom'. If it is an HTML element, it must be present\n     *      in the DOM.\n     *      Limitation: if the element is using a fixed position, this\n     *      function cannot work except if is the header (el is then either a\n     *      string set to '#top' or an HTML element with the \"top\" id) or the\n     *      footer (el is then a string set to '#bottom' or an HTML element\n     *      with the \"bottom\" id) for which exceptions have been made.\n     * @param {number} [options] - same as animate of jQuery\n     * @param {number} [options.extraOffset=0]\n     *      extra offset to add on top of the automatic one (the automatic one\n     *      being computed based on fixed header sizes)\n     * @param {number} [options.forcedOffset]\n     *      offset used instead of the automatic one (extraOffset will be\n     *      ignored too)\n     * @param {JQuery} [options.$scrollable] the $element to scroll\n     * @return {Promise}\n     */\n    scrollTo(el, options = {}) {\n        if (!el) {\n            throw new Error(\"The scrollTo function was called without any given element\");\n        }\n        const $el = $(el);\n        if (typeof(el) === 'string' && $el[0]) {\n            el = $el[0];\n        }\n        const isTopOrBottomHidden = (el === '#top' || el === '#bottom');\n        const $topLevelScrollable = $().getScrollingElement();\n        const $scrollable = isTopOrBottomHidden ? $topLevelScrollable : (options.$scrollable || $el.parent().closestScrollable());\n        const isTopScroll = $scrollable.is($topLevelScrollable);\n        // If $scrollable and $el are not in the same document, we can safely\n        // assume $el is in an $iframe. We retrieve it by filtering the list of\n        // iframes in $scrollable to keep only the one that contains $el.\n        const isInOneDocument = isTopOrBottomHidden || $scrollable[0].ownerDocument === $el[0].ownerDocument;\n        const $iframe = !isInOneDocument && $scrollable.find('iframe').filter((i, node) => $(node).contents().has($el));\n\n        function _computeScrollTop() {\n            if (el === '#top' || el.id === 'top') {\n                return 0;\n            }\n            if (el === '#bottom' || el.id === 'bottom') {\n                return $scrollable[0].scrollHeight - $scrollable[0].clientHeight;\n            }\n\n            let offsetTop = $el.offset().top;\n            if (el.classList.contains('d-none')) {\n                el.classList.remove('d-none');\n                offsetTop = $el.offset().top;\n                el.classList.add('d-none');\n            }\n            const isDocScrollingEl = $scrollable.is(el.ownerDocument.scrollingElement);\n            let elPosition = offsetTop\n                - ($scrollable.offset().top - (isDocScrollingEl ? 0 : $scrollable[0].scrollTop));\n            if (!isInOneDocument && $iframe.length) {\n                elPosition += $iframe.offset().top;\n            }\n            let offset = options.forcedOffset;\n            if (offset === undefined) {\n                offset = (isTopScroll ? dom.scrollFixedOffset() : 0) + (options.extraOffset || 0);\n            }\n            return Math.max(0, elPosition - offset);\n        }\n\n        const originalScrollTop = _computeScrollTop();\n\n        return new Promise(resolve => {\n            const clonedOptions = Object.assign({}, options);\n\n            // During the animation, detect any change needed for the scroll\n            // offset. If any occurs, stop the animation and continuing it to\n            // the new scroll point for the remaining time.\n            // Note: limitation, the animation won't be as fluid as possible if\n            // the easing mode is different of 'linear'.\n            clonedOptions.progress = function (a, b, remainingMs) {\n                if (options.progress) {\n                    options.progress.apply(this, ...arguments);\n                }\n                const newScrollTop = _computeScrollTop();\n                if (Math.abs(newScrollTop - originalScrollTop) <= 1.0\n                        && (isTopOrBottomHidden || !(el.classList.contains('o_transitioning')))) {\n                    return;\n                }\n                $scrollable.stop();\n                dom.scrollTo(el, Object.assign({}, options, {\n                    duration: remainingMs,\n                    easing: 'linear',\n                })).then(() => resolve());\n            };\n\n            // Detect the end of the animation to be able to indicate it to\n            // the caller via the returned Promise.\n            clonedOptions.complete = function () {\n                if (options.complete) {\n                    options.complete.apply(this, ...arguments);\n                }\n                resolve();\n            };\n\n            $scrollable.animate({scrollTop: originalScrollTop}, clonedOptions);\n        });\n    },\n};\nreturn dom;\n});\n", "odoo.define('web.local_storage', function (require) {\n'use strict';\n\nvar RamStorage = require('web.RamStorage');\nvar mixins = require('web.mixins');\n\n// use a fake localStorage in RAM if the native localStorage is unavailable\n// (e.g. private browsing in Safari)\nvar storage;\nvar localStorage = window.localStorage;\ntry {\n    var uid = new Date();\n    localStorage.setItem(uid, uid);\n    localStorage.removeItem(uid);\n\n    /*\n     * We create an intermediate object in order to triggered the storage on\n     * this object. the localStorage. This simplifies testing and usage as \n     * starages are commutable in services without change. Also, objects\n     * that use storage do not have to know that events go through window,\n     * it's not up to them to handle these cases.\n     */\n    storage = (function () {\n        var storage = Object.create(_.extend({\n                getItem: localStorage.getItem.bind(localStorage),\n                setItem: localStorage.setItem.bind(localStorage),\n                removeItem: localStorage.removeItem.bind(localStorage),\n                clear: localStorage.clear.bind(localStorage),\n            },\n            mixins.EventDispatcherMixin\n        ));\n        storage.init();\n        $(window).on('storage', function (e) {\n            var key = e.originalEvent.key;\n            var newValue = e.originalEvent.newValue;\n            try {\n                JSON.parse(newValue);\n                storage.trigger('storage', {\n                    key: key,\n                    newValue: newValue,\n                });\n            } catch (error) {}\n        });\n        return storage;\n    })();\n\n} catch (exception) {\n\tconsole.warn('Fail to load localStorage');\n    storage = new RamStorage();\n}\n\nreturn storage;\n\n});\n", "odoo.define('web.mixins', function (require) {\n\"use strict\";\n\nvar Class = require('web.Class');\nvar utils = require('web.utils');\n\n/**\n * Mixin to structure objects' life-cycles folowing a parent-children\n * relationship. Each object can a have a parent and multiple children.\n * When an object is destroyed, all its children are destroyed too releasing\n * any resource they could have reserved before.\n *\n * @name ParentedMixin\n * @mixin\n */\nvar ParentedMixin = {\n    __parentedMixin : true,\n    init: function () {\n        this.__parentedDestroyed = false;\n        this.__parentedChildren = [];\n        this.__parentedParent = null;\n    },\n    /**\n     * Set the parent of the current object. When calling this method, the\n     * parent will also be informed and will return the current object\n     * when its getChildren() method is called. If the current object did\n     * already have a parent, it is unregistered before, which means the\n     * previous parent will not return the current object anymore when its\n     * getChildren() method is called.\n     */\n    setParent : function (parent) {\n        if (this.getParent()) {\n            if (this.getParent().__parentedMixin) {\n                this.getParent().__parentedChildren = _.without(this\n                        .getParent().getChildren(), this);\n            }\n        }\n        this.__parentedParent = parent;\n        if (parent && parent.__parentedMixin) {\n            parent.__parentedChildren.push(this);\n        }\n    },\n    /**\n     * Return the current parent of the object (or null).\n     */\n    getParent : function () {\n        return this.__parentedParent;\n    },\n    /**\n     * Return a list of the children of the current object.\n     */\n    getChildren : function () {\n        return _.clone(this.__parentedChildren);\n    },\n    /**\n     * Returns true if destroy() was called on the current object.\n     */\n    isDestroyed : function () {\n        return this.__parentedDestroyed;\n    },\n    /**\n     * Utility method to only execute asynchronous actions if the current\n     * object has not been destroyed.\n     *\n     * @param {Promise} promise The promise representing the asynchronous\n     *                             action.\n     * @param {bool} [shouldReject=false] If true, the returned promise will be\n     *                              rejected with no arguments if the current\n     *                              object is destroyed. If false, the\n     *                              returned promise will never be resolved\n     *                              or rejected.\n     * @returns {Promise} A promise that will mirror the given promise if\n     *                       everything goes fine but will either be rejected\n     *                       with no arguments or never resolved if the\n     *                       current object is destroyed.\n     */\n    alive: function (promise, shouldReject) {\n        var self = this;\n\n        return new Promise(function (resolve, reject) {\n            promise.then(function (result) {\n                if (!self.isDestroyed()) {\n                    resolve(result);\n                } else if (shouldReject) {\n                    reject();\n                }\n            }).guardedCatch(function (reason) {\n                if (!self.isDestroyed()) {\n                    reject(reason);\n                } else if (shouldReject) {\n                    reject();\n                }\n            });\n        });\n    },\n    /**\n     * Inform the object it should destroy itself, releasing any\n     * resource it could have reserved.\n     */\n    destroy : function () {\n        this.getChildren().forEach(function (child) {\n            child.destroy();\n        });\n        this.setParent(undefined);\n        this.__parentedDestroyed = true;\n    },\n    /**\n     * Find the closest ancestor matching predicate\n     */\n    findAncestor: function (predicate) {\n        var ancestor = this;\n        while (ancestor && !(predicate(ancestor)) && ancestor.getParent) {\n            ancestor = ancestor.getParent();\n        }\n        return ancestor;\n    },\n};\n\nfunction OdooEvent(target, name, data) {\n    this.target = target;\n    this.name = name;\n    this.data = Object.create(null);\n    _.extend(this.data, data);\n    this.stopped = false;\n}\n\nOdooEvent.prototype.stopPropagation = function () {\n    this.stopped = true;\n};\n\nOdooEvent.prototype.is_stopped = function () {\n    return this.stopped;\n};\n\n/**\n * Backbone's events. Do not ever use it directly, use EventDispatcherMixin instead.\n *\n * This class just handle the dispatching of events, it is not meant to be extended,\n * nor used directly. All integration with parenting and automatic unregistration of\n * events is done in EventDispatcherMixin.\n *\n * Copyright notice for the following Class:\n *\n * (c) 2010-2012 Jeremy Ashkenas, DocumentCloud Inc.\n * Backbone may be freely distributed under the MIT license.\n * For all details and documentation:\n * http://backbonejs.org\n *\n */\nvar Events = Class.extend({\n    on : function (events, callback, context) {\n        var ev;\n        events = events.split(/\\s+/);\n        var calls = this._callbacks || (this._callbacks = {});\n        while ((ev = events.shift())) {\n            var list = calls[ev] || (calls[ev] = {});\n            var tail = list.tail || (list.tail = list.next = {});\n            tail.callback = callback;\n            tail.context = context;\n            list.tail = tail.next = {};\n        }\n        return this;\n    },\n\n    off : function (events, callback, context) {\n        var ev, calls, node;\n        if (!events) {\n            delete this._callbacks;\n        } else if ((calls = this._callbacks)) {\n            events = events.split(/\\s+/);\n            while ((ev = events.shift())) {\n                node = calls[ev];\n                delete calls[ev];\n                if (!callback || !node)\n                    continue;\n                while ((node = node.next) && node.next) {\n                    if (node.callback === callback\n                            && (!context || node.context === context))\n                        continue;\n                    this.on(ev, node.callback, node.context);\n                }\n            }\n        }\n        return this;\n    },\n\n    callbackList: function () {\n        var lst = [];\n        _.each(this._callbacks || {}, function (el, eventName) {\n            var node = el;\n            while ((node = node.next) && node.next) {\n                lst.push([eventName, node.callback, node.context]);\n            }\n        });\n        return lst;\n    },\n\n    trigger : function (events) {\n        var event, node, calls, tail, args, all, rest;\n        if (!(calls = this._callbacks))\n            return this;\n        all = calls.all;\n        (events = events.split(/\\s+/)).push(null);\n        // Save references to the current heads & tails.\n        while ((event = events.shift())) {\n            if (all)\n                events.push({\n                    next : all.next,\n                    tail : all.tail,\n                    event : event\n                });\n            if (!(node = calls[event]))\n                continue;\n            events.push({\n                next : node.next,\n                tail : node.tail\n            });\n        }\n        rest = Array.prototype.slice.call(arguments, 1);\n        while ((node = events.pop())) {\n            tail = node.tail;\n            args = node.event ? [ node.event ].concat(rest) : rest;\n            while ((node = node.next) !== tail) {\n                node.callback.apply(node.context || this, args);\n            }\n        }\n        return this;\n    }\n});\n\n/**\n * Mixin containing an event system. Events are also registered by specifying the target object\n * (the object which will receive the event when it is raised). Both the event-emitting object\n * and the target object store or reference to each other. This is used to correctly remove all\n * reference to the event handler when any of the object is destroyed (when the destroy() method\n * from ParentedMixin is called). Removing those references is necessary to avoid memory leak\n * and phantom events (events which are raised and sent to a previously destroyed object).\n *\n * @name EventDispatcherMixin\n * @mixin\n */\nvar EventDispatcherMixin = _.extend({}, ParentedMixin, {\n    __eventDispatcherMixin: true,\n    custom_events: {},\n    init: function () {\n        ParentedMixin.init.call(this);\n        this.__edispatcherEvents = new Events();\n        this.__edispatcherRegisteredEvents = [];\n        this._delegateCustomEvents();\n    },\n    /**\n     * Proxies a method of the object, in order to keep the right ``this`` on\n     * method invocations.\n     *\n     * This method is similar to ``Function.prototype.bind`` or ``_.bind``, and\n     * even more so to ``jQuery.proxy`` with a fundamental difference: its\n     * resolution of the method being called is lazy, meaning it will use the\n     * method as it is when the proxy is called, not when the proxy is created.\n     *\n     * Other methods will fix the bound method to what it is when creating the\n     * binding/proxy, which is fine in most javascript code but problematic in\n     * OpenERP Web where developers may want to replace existing callbacks with\n     * theirs.\n     *\n     * The semantics of this precisely replace closing over the method call.\n     *\n     * @param {String|Function} method function or name of the method to invoke\n     * @returns {Function} proxied method\n     */\n    proxy: function (method) {\n        var self = this;\n        return function () {\n            var fn = (typeof method === 'string') ? self[method] : method;\n            if (fn === void 0) {\n                throw new Error(\"Couldn't find method '\" + method + \"' in widget \" + self);\n            }\n            return fn.apply(self, arguments);\n        };\n    },\n    _delegateCustomEvents: function () {\n        if (_.isEmpty(this.custom_events)) { return; }\n        for (var key in this.custom_events) {\n            if (!this.custom_events.hasOwnProperty(key)) { continue; }\n\n            var method = this.proxy(this.custom_events[key]);\n            this.on(key, this, method);\n        }\n    },\n    on: function (events, dest, func) {\n        var self = this;\n        if (typeof func !== \"function\") {\n            throw new Error(\"Event handler must be a function.\");\n        }\n        events = events.split(/\\s+/);\n        _.each(events, function (eventName) {\n            self.__edispatcherEvents.on(eventName, func, dest);\n            if (dest && dest.__eventDispatcherMixin) {\n                dest.__edispatcherRegisteredEvents.push({name: eventName, func: func, source: self});\n            }\n        });\n        return this;\n    },\n    off: function (events, dest, func) {\n        var self = this;\n        events = events.split(/\\s+/);\n        _.each(events, function (eventName) {\n            self.__edispatcherEvents.off(eventName, func, dest);\n            if (dest && dest.__eventDispatcherMixin) {\n                dest.__edispatcherRegisteredEvents = _.filter(dest.__edispatcherRegisteredEvents, function (el) {\n                    return !(el.name === eventName && el.func === func && el.source === self);\n                });\n            }\n        });\n        return this;\n    },\n    once: function (events, dest, func) {\n        // similar to this.on(), but func is executed only once\n        var self = this;\n        if (typeof func !== \"function\") {\n            throw new Error(\"Event handler must be a function.\");\n        }\n        self.on(events, dest, function what() {\n            func.apply(this, arguments);\n            self.off(events, dest, what);\n        });\n    },\n    trigger: function () {\n        this.__edispatcherEvents.trigger.apply(this.__edispatcherEvents, arguments);\n        return this;\n    },\n    trigger_up: function (name, info) {\n        var event = new OdooEvent(this, name, info);\n        //console.info('event: ', name, info);\n        this._trigger_up(event);\n        return event;\n    },\n    _trigger_up: function (event) {\n        var parent;\n        this.__edispatcherEvents.trigger(event.name, event);\n        if (!event.is_stopped() && (parent = this.getParent())) {\n            parent._trigger_up(event);\n        }\n    },\n    destroy: function () {\n        var self = this;\n        _.each(this.__edispatcherRegisteredEvents, function (event) {\n            event.source.__edispatcherEvents.off(event.name, event.func, self);\n        });\n        this.__edispatcherRegisteredEvents = [];\n        _.each(this.__edispatcherEvents.callbackList(), function (cal) {\n            this.off(cal[0], cal[2], cal[1]);\n        }, this);\n        this.__edispatcherEvents.off();\n        ParentedMixin.destroy.call(this);\n    }\n});\n\n/**\n * @name PropertiesMixin\n * @mixin\n */\nvar PropertiesMixin = _.extend({}, EventDispatcherMixin, {\n    init: function () {\n        EventDispatcherMixin.init.call(this);\n        this.__getterSetterInternalMap = {};\n    },\n    set: function (arg1, arg2, arg3) {\n        var map;\n        var options;\n        if (typeof arg1 === \"string\") {\n            map = {};\n            map[arg1] = arg2;\n            options = arg3 || {};\n        } else {\n            map = arg1;\n            options = arg2 || {};\n        }\n        var self = this;\n        var changed = false;\n        _.each(map, function (val, key) {\n            var tmp = self.__getterSetterInternalMap[key];\n            if (tmp === val)\n                return;\n            // seriously, why are you doing this? it is obviously a stupid design.\n            // the properties mixin should not be concerned with handling fields details.\n            // this also has the side effect of introducing a dependency on utils.  Todo:\n            // remove this, or move it elsewhere.  Also, learn OO programming.\n            if (key === 'value' && self.field && self.field.type === 'float' && tmp && val){\n                var digits = self.field.digits;\n                if (_.isArray(digits)) {\n                    if (utils.float_is_zero(tmp - val, digits[1])) {\n                        return;\n                    }\n                }\n            }\n            changed = true;\n            self.__getterSetterInternalMap[key] = val;\n            if (! options.silent)\n                self.trigger(\"change:\" + key, self, {\n                    oldValue: tmp,\n                    newValue: val\n                });\n        });\n        if (changed)\n            self.trigger(\"change\", self);\n    },\n    get: function (key) {\n        return this.__getterSetterInternalMap[key];\n    }\n});\n\nreturn {\n    ParentedMixin: ParentedMixin,\n    EventDispatcherMixin: EventDispatcherMixin,\n    PropertiesMixin: PropertiesMixin,\n};\n\n});\n", "odoo.define('web.QWeb', function (require) {\n\"use strict\";\n\nvar translation = require('web.translation');\n\nvar _t = translation._t;\n\n/**\n * @param {boolean} debug\n * @param {Object} default_dict\n * @param {boolean} [enableTranslation=true] if true (this is the default),\n *   the rendering will translate all strings that are not marked with\n *   t-translation=off.  This is useful for the kanban view, which uses a\n *   template which is already translated by the server\n */\nfunction QWeb(debug, default_dict, enableTranslation) {\n    if (enableTranslation === undefined) {\n        enableTranslation = true;\n    }\n    var qweb = new QWeb2.Engine();\n    qweb.default_dict = _.extend({}, default_dict || {}, {\n        '_' : _,\n        'JSON': JSON,\n        '_t' : translation._t,\n        '__debug__': debug,\n        'moment': function(date) { return new moment(date); },\n        'csrf_token': odoo.csrf_token,\n    });\n    qweb.debug = debug;\n    qweb.preprocess_node = enableTranslation ? preprocess_node : function () {};\n    return qweb;\n}\n\nfunction preprocess_node() {\n    // Note that 'this' is the Qweb Node\n    switch (this.node.nodeType) {\n        case Node.TEXT_NODE:\n        case Node.CDATA_SECTION_NODE:\n            // Text and CDATAs\n            var translation = this.node.parentNode.attributes['t-translation'];\n            if (translation && translation.value === 'off') {\n                return;\n            }\n            var match = /^(\\s*)([\\s\\S]+?)(\\s*)$/.exec(this.node.data);\n            if (match) {\n                this.node.data = match[1] + _t(match[2]) + match[3];\n            }\n            break;\n        case Node.ELEMENT_NODE:\n            // Element\n            var attr, attrs = ['label', 'title', 'alt', 'placeholder', 'aria-label'];\n            while ((attr = attrs.pop())) {\n                if (this.attributes[attr]) {\n                    this.attributes[attr] = _t(this.attributes[attr]);\n                }\n            }\n    }\n}\n\nreturn QWeb;\n\n});\n", "odoo.define('web.RamStorage', function (require) {\n'use strict';\n\n/**\n * This module defines an alternative of the Storage objects (localStorage,\n * sessionStorage), stored in RAM. It is used when those native Storage objects\n * are unavailable (e.g. in private browsing on Safari).\n */\n\nvar Class = require('web.Class');\nvar mixins = require('web.mixins');\n\n\nvar RamStorage = Class.extend(mixins.EventDispatcherMixin, {\n    /**\n     * @constructor\n     */\n    init: function () {\n        mixins.EventDispatcherMixin.init.call(this);\n        if (!this.storage) {\n            this.clear();\n        }\n    },\n\n    //--------------------------------------------------------------------------\n    // Public\n    //--------------------------------------------------------------------------\n\n    /**\n     * Removes all data from the storage\n     */\n    clear: function () {\n        this.storage = Object.create(null);\n        this.length = 0;\n    },\n    /**\n     * Returns the value associated with a given key in the storage\n     *\n     * @param {string} key\n     * @returns {string}\n     */\n    getItem: function (key) {\n        return this.storage[key];\n    },\n    /**\n     * @param {integer} index\n     * @return {string}\n     */\n    key: function (index) {\n        return _.keys(this.storage)[index];\n    },\n    /**\n     * Removes the given key from the storage\n     *\n     * @param {string} key\n     */\n    removeItem: function (key) {\n        if (key in this.storage) {\n            this.length--;\n        }\n        delete this.storage[key];\n        this.trigger('storage', {key: key, newValue: null});\n    },\n    /**\n     * Adds a given key-value pair to the storage, or update the value of the\n     * given key if it already exists\n     *\n     * @param {string} key\n     * @param {string} value\n     */\n    setItem: function (key, value) {\n        if (!(key in this.storage)) {\n            this.length++;\n        }\n        this.storage[key] = value;\n        this.trigger('storage', {key: key, newValue: value});\n    },\n});\n\nreturn RamStorage;\n\n});\n", "odoo.define(\"web.Registry\", function (require) {\n    \"use strict\";\n\n    const { sortBy } = require(\"web.utils\");\n\n    /**\n     * The registry is really pretty much only a mapping from some keys to some\n     * values. The Registry class only add a few simple methods around that to make\n     * it nicer and slightly safer.\n     *\n     * Note that registries have a fundamental problem: the value that you try to\n     * get in a registry might not have been added yet, so of course, you need to\n     * make sure that your dependencies are solid.  For this reason, it is a good\n     * practice to avoid using the registry if you can simply import what you need\n     * with the 'require' statement.\n     *\n     * However, on the flip side, sometimes you cannot just simply import something\n     * because we would have a dependency cycle.  In that case, registries might\n     * help.\n     */\n    class Registry {\n        /**\n         * @function predicate\n         * @param {any} value\n         * @returns {boolean}\n         */\n        /**\n         * @param {Object} [mapping] the initial data in the registry\n         * @param {predicate} [predicate=(() => true)] predicate that each\n         *      added value must pass to be registered.\n         */\n        constructor(mapping, predicate = () => true) {\n            this.map = Object.create(mapping || null);\n            this._scoreMapping = Object.create(null);\n            this._sortedKeys = null;\n            this.listeners = []; // listening callbacks on newly added items.\n            this.predicate = predicate;\n        }\n\n        //--------------------------------------------------------------------------\n        // Public\n        //--------------------------------------------------------------------------\n\n        /**\n         * Add a key (and a value) to the registry.\n         * Notify the listeners on newly added item in the registry.\n         * @param {string} key\n         * @param {any} value\n         * @param {number} [score] if given, this value will be used to order keys\n         * @returns {Registry} can be used to chain add calls.\n         */\n        add(key, value, score) {\n            if (!this.predicate(value)) {\n                throw new Error(`Value of key \"${key}\" does not pass the addition predicate.`);\n            }\n            this._scoreMapping[key] = score === undefined ? key : score;\n            this._sortedKeys = null;\n            this.map[key] = value;\n            for (const callback of this.listeners) {\n                callback(key, value);\n            }\n            return this;\n        }\n\n        /**\n         * Check if the registry contains the key\n         * @param {string} key\n         * @returns {boolean}\n         */\n        contains(key) {\n            return key in this.map;\n        }\n\n        /**\n         * Returns the content of the registry (an object mapping keys to values)\n         * @returns {Object}\n         */\n        entries() {\n            const entries = {};\n            const keys = this.keys();\n            for (const key of keys) {\n                entries[key] = this.map[key];\n            }\n            return entries;\n        }\n\n        /**\n         * Returns the value associated to the given key.\n         * @param {string} key\n         * @returns {any}\n         */\n        get(key) {\n            return this.map[key];\n        }\n\n        /**\n         * Tries a number of keys, and returns the first object matching one of\n         * the keys.\n         * @param {string[]} keys a sequence of keys to fetch the object for\n         * @returns {any} the first result found matching an object\n         */\n        getAny(keys) {\n            for (const key of keys) {\n                if (key in this.map) {\n                    return this.map[key];\n                }\n            }\n            return null;\n        }\n\n        /**\n         * Return the list of keys in map object.\n         *\n         * The registry guarantees that the keys have a consistent order, defined by\n         * the 'score' value when the item has been added.\n         * @returns {string[]}\n         */\n        keys() {\n            if (!this._sortedKeys) {\n                const keys = [];\n                for (const key in this.map) {\n                    keys.push(key);\n                }\n                this._sortedKeys = sortBy(keys,\n                    key => this._scoreMapping[key] || 0\n                );\n            }\n            return this._sortedKeys;\n        }\n\n        /**\n         * @function onAddCallback\n         * @param {string} key\n         * @param {any} value\n         */\n        /**\n         * Register a callback to execute when items are added to the registry.\n         * @param {onAddCallback} callback function with parameters (key, value).\n         */\n        onAdd(callback) {\n            this.listeners.push(callback);\n        }\n\n        /**\n         * Return the list of values in map object\n         * @returns {string[]}\n         */\n        values() {\n            return this.keys().map((key) => this.map[key]);\n        }\n    }\n\n    return Registry;\n});\n", "odoo.define('web.rpc', function (require) {\n\"use strict\";\n\nvar ajax = require('web.ajax');\n\nconst rpc = {\n    /**\n     * Perform a RPC.  Please note that this is not the preferred way to do a\n     * rpc if you are in the context of a widget.  In that case, you should use\n     * the this._rpc method.\n     *\n     * @param {Object} params @see buildQuery for a description\n     * @param {Object} options\n     * @returns {Promise<any>}\n     */\n    query: function (params, options) {\n        var query = rpc.buildQuery(params);\n        return ajax.rpc(query.route, query.params, options);\n    },\n    /**\n     * @param {Object} options\n     * @param {any[]} [options.args]\n     * @param {Object} [options.context]\n     * @param {any[]} [options.domain]\n     * @param {string[]} [options.fields]\n     * @param {string[]} [options.groupBy]\n     * @param {Object} [options.kwargs]\n     * @param {integer|false} [options.limit]\n     * @param {string} [options.method]\n     * @param {string} [options.model]\n     * @param {integer} [options.offset]\n     * @param {string[]} [options.orderBy]\n     * @param {Object} [options.params]\n     * @param {string} [options.route]\n     * @returns {Object} with 2 keys: route and params\n     */\n    buildQuery: function (options) {\n        var route;\n        var params = options.params || {};\n        var orderBy;\n        if (options.route) {\n            route = options.route;\n        } else if (options.model && options.method) {\n            route = '/web/dataset/call_kw/' + options.model + '/' + options.method;\n        }\n        if (options.method) {\n            params.args = options.args || [];\n            params.model = options.model;\n            params.method = options.method;\n            params.kwargs = _.extend(params.kwargs || {}, options.kwargs);\n            params.kwargs.context = options.context || params.context || params.kwargs.context;\n        }\n\n        if (options.method === 'read_group' || options.method === 'web_read_group') {\n            if (!(params.args && params.args[0] !== undefined)) {\n                params.kwargs.domain = options.domain || params.domain || params.kwargs.domain || [];\n            }\n            if (!(params.args && params.args[1] !== undefined)) {\n                params.kwargs.fields = options.fields || params.fields || params.kwargs.fields || [];\n            }\n            if (!(params.args && params.args[2] !== undefined)) {\n                params.kwargs.groupby = options.groupBy || params.groupBy || params.kwargs.groupby || [];\n            }\n            params.kwargs.offset = options.offset || params.offset || params.kwargs.offset;\n            params.kwargs.limit = options.limit || params.limit || params.kwargs.limit;\n            // In kwargs, we look for \"orderby\" rather than \"orderBy\" (note the absence of capital B),\n            // since the Python argument to the actual function is \"orderby\".\n            orderBy = options.orderBy || params.orderBy || params.kwargs.orderby;\n            params.kwargs.orderby = orderBy ? rpc._serializeSort(orderBy) : orderBy;\n            params.kwargs.lazy = 'lazy' in options ? options.lazy : params.lazy;\n\n            if (options.method === 'web_read_group') {\n                params.kwargs.expand = options.expand || params.expand || params.kwargs.expand;\n                params.kwargs.expand_limit = options.expand_limit || params.expand_limit || params.kwargs.expand_limit;\n                var expandOrderBy = options.expand_orderby || params.expand_orderby || params.kwargs.expand_orderby;\n                params.kwargs.expand_orderby = expandOrderBy ? rpc._serializeSort(expandOrderBy) : expandOrderBy;\n            }\n        }\n\n        if (options.method === 'search_read') {\n            // call the model method\n            params.kwargs.domain = options.domain || params.domain || params.kwargs.domain;\n            params.kwargs.fields = options.fields || params.fields || params.kwargs.fields;\n            params.kwargs.offset = options.offset || params.offset || params.kwargs.offset;\n            params.kwargs.limit = options.limit || params.limit || params.kwargs.limit;\n            // In kwargs, we look for \"order\" rather than \"orderBy\" since the Python\n            // argument to the actual function is \"order\".\n            orderBy = options.orderBy || params.orderBy || params.kwargs.order;\n            params.kwargs.order = orderBy ? rpc._serializeSort(orderBy) : orderBy;\n        }\n\n        if (options.route === '/web/dataset/search_read') {\n            // specifically call the controller\n            params.model = options.model || params.model;\n            params.domain = options.domain || params.domain;\n            params.fields = options.fields || params.fields;\n            params.limit = options.limit || params.limit;\n            params.offset = options.offset || params.offset;\n            orderBy = options.orderBy || params.orderBy;\n            params.sort = orderBy ? rpc._serializeSort(orderBy) : orderBy;\n            params.context = options.context || params.context || {};\n        }\n\n        return {\n            route: route,\n            params: JSON.parse(JSON.stringify(params)),\n        };\n    },\n    /**\n     * Helper method, generates a string to describe a ordered by sequence for\n     * SQL.\n     *\n     * For example, [{name: 'foo'}, {name: 'bar', asc: false}] will\n     * be converted into 'foo ASC, bar DESC'\n     *\n     * @param {Object[]} orderBy list of objects {name:..., [asc: ...]}\n     * @returns {string}\n     */\n    _serializeSort: function (orderBy) {\n        return _.map(orderBy, function (order) {\n            return order.name + (order.asc !== false ? ' ASC' : ' DESC');\n        }).join(', ');\n    },\n};\n\nreturn rpc;\n\n});\n", "odoo.define('web.ServiceProviderMixin', function (require) {\n\"use strict\";\n\nvar core = require('web.core');\n\n// ServiceProviderMixin is deprecated. It is only used by the ProjectTimesheet\n// app. As soon as it no longer uses it, we can remove it.\nvar ServiceProviderMixin = {\n    services: {}, // dict containing deployed service instances\n    UndeployedServices: {}, // dict containing classes of undeployed services\n    /**\n     * @override\n     */\n    init: function (parent) {\n        var self = this;\n        // to properly instantiate services with this as parent, this mixin\n        // assumes that it is used along the EventDispatcherMixin, and that\n        // EventDispatchedMixin's init is called first\n        // as EventDispatcherMixin's init is already called, this handler has\n        // to be bound manually\n        this.on('call_service', this, this._call_service.bind(this));\n\n        // add already registered services from the service registry\n        _.each(core.serviceRegistry.map, function (Service, serviceName) {\n            if (serviceName in self.UndeployedServices) {\n                throw new Error('Service \"' + serviceName + '\" is already loaded.');\n            }\n            self.UndeployedServices[serviceName] = Service;\n        });\n        this._deployServices();\n\n        // listen on newly added services\n        core.serviceRegistry.onAdd(function (serviceName, Service) {\n            if (serviceName in self.services || serviceName in self.UndeployedServices) {\n                throw new Error('Service \"' + serviceName + '\" is already loaded.');\n            }\n            self.UndeployedServices[serviceName] = Service;\n            self._deployServices();\n        });\n    },\n\n    //--------------------------------------------------------------------------\n    // Private\n    //--------------------------------------------------------------------------\n\n    /**\n     * @private\n     */\n    _deployServices: function () {\n        var self = this;\n        var done = false;\n        while (!done) {\n            var serviceName = _.findKey(this.UndeployedServices, function (Service) {\n                // no missing dependency\n                return !_.some(Service.prototype.dependencies, function (depName) {\n                    return !self.services[depName];\n                });\n            });\n            if (serviceName) {\n                var service = new this.UndeployedServices[serviceName](this);\n                this.services[serviceName] = service;\n                delete this.UndeployedServices[serviceName];\n                service.start();\n            } else {\n                done = true;\n            }\n        }\n    },\n\n    //--------------------------------------------------------------------------\n    // Handlers\n    //--------------------------------------------------------------------------\n\n    /**\n     * Call the 'service', using data from the 'event' that\n     * has triggered the service call.\n     *\n     * For the ajax service, the arguments are extended with\n     * the target so that it can call back the caller.\n     *\n     * @private\n     * @param  {OdooEvent} event\n     */\n    _call_service: function (event) {\n        var args = event.data.args || [];\n        if (event.data.service === 'ajax' && event.data.method === 'rpc') {\n            // ajax service uses an extra 'target' argument for rpc\n            args = args.concat(event.target);\n        }\n        var service = this.services[event.data.service];\n        var result = service[event.data.method].apply(service, args);\n        event.data.callback(result);\n    },\n};\n\nreturn ServiceProviderMixin;\n\n});\n\nodoo.define('web.ServicesMixin', function (require) {\n\"use strict\";\n\nvar rpc = require('web.rpc');\n\n/**\n * @mixin\n * @name ServicesMixin\n */\nvar ServicesMixin = {\n    /**\n     * @param  {string} service\n     * @param  {string} method\n     * @return {any} result of the service called\n     */\n    call: function (service, method) {\n        var args = Array.prototype.slice.call(arguments, 2);\n        var result;\n        this.trigger_up('call_service', {\n            service: service,\n            method: method,\n            args: args,\n            callback: function (r) {\n                result = r;\n            },\n        });\n        return result;\n    },\n    /**\n     * @private\n     * @param {Object} libs - @see ajax.loadLibs\n     * @param {Object} [context] - @see ajax.loadLibs\n     * @param {Object} [tplRoute=this._loadLibsTplRoute] - @see ajax.loadLibs\n     * @returns {Promise}\n     */\n    _loadLibs: function (libs, context, tplRoute) {\n        return this.call('ajax', 'loadLibs', libs, context, tplRoute || this._loadLibsTplRoute);\n    },\n    /**\n     * Builds and executes RPC query. Returns a promise resolved with\n     * the RPC result.\n     *\n     * @param {string} params either a route or a model\n     * @param {string} options if a model is given, this argument is a method\n     * @returns {Promise}\n     */\n    _rpc: function (params, options) {\n        var query = rpc.buildQuery(params);\n        var prom = this.call('ajax', 'rpc', query.route, query.params, options, this);\n        if (!prom) {\n            prom = new Promise(function () {});\n            prom.abort = function () {};\n        }\n        var abort = prom.abort ? prom.abort : prom.reject;\n        if (!abort) {\n            throw new Error(\"a rpc promise should always have a reject function\");\n        }\n        prom.abort = abort.bind(prom);\n        return prom;\n    },\n    loadFieldView: function (modelName, context, view_id, view_type, options) {\n        return this.loadViews(modelName, context, [[view_id, view_type]], options).then(function (result) {\n            return result[view_type];\n        });\n    },\n    loadViews: function (modelName, context, views, options) {\n        var self = this;\n        return new Promise(function (resolve) {\n            self.trigger_up('load_views', {\n                modelName: modelName,\n                context: context,\n                views: views,\n                options: options,\n                on_success: resolve,\n            });\n        });\n    },\n    loadFilters: function (modelName, actionId, context) {\n        var self = this;\n        return new Promise(function (resolve, reject) {\n            self.trigger_up('load_filters', {\n                modelName: modelName,\n                actionId: actionId,\n                context: context,\n                on_success: resolve,\n            });\n        });\n    },\n    createFilter: function (filter) {\n        var self = this;\n        return new Promise(function (resolve, reject) {\n            self.trigger_up('create_filter', {\n                filter: filter,\n                on_success: resolve,\n            });\n        });\n    },\n    deleteFilter: function (filterId) {\n        var self = this;\n        return new Promise(function (resolve, reject) {\n            self.trigger_up('delete_filter', {\n                filterId: filterId,\n                on_success: resolve,\n            });\n        });\n    },\n    // Session stuff\n    getSession: function () {\n        var session;\n        this.trigger_up('get_session', {\n            callback: function (result) {\n                session = result;\n            }\n        });\n        return session;\n    },\n    /**\n     * Informs the action manager to do an action. This supposes that the action\n     * manager can be found amongst the ancestors of the current widget.\n     * If that's not the case this method will simply return an unresolved\n     * promise.\n     *\n     * @param {any} action\n     * @param {any} options\n     * @returns {Promise}\n     */\n    do_action: function (action, options) {\n        var self = this;\n        return new Promise(function (resolve, reject) {\n            self.trigger_up('do_action', {\n                action: action,\n                options: options,\n                on_success: resolve,\n                on_fail: (reason) => {\n                    reject(reason);\n                    return \"alreadyThrown\"\n                },\n            });\n        });\n    },\n    /**\n     * Displays a notification.\n     *\n     * @param {Object} options\n     * @param {string} [options.title]\n     * @param {string} [options.subtitle]\n     * @param {string} [options.message]\n     * @param {string} [options.type='warning'] 'info', 'success', 'warning', 'danger' or ''\n     * @param {boolean} [options.sticky=false]\n     * @param {string} [options.className]\n     * @param {boolean} [options.messageIsHtml=false]\n     */\n    displayNotification: function (options) {\n        return this.call('notification', 'notify', options);\n    },\n};\n\nreturn ServicesMixin;\n\n});\n", "odoo.define('web.Session', function (require) {\n\"use strict\";\n\nvar ajax = require('web.ajax');\nvar concurrency = require('web.concurrency');\nvar core = require('web.core');\nvar mixins = require('web.mixins');\nvar utils = require('web.utils');\nconst { session } = require('@web/session');\n\nvar _t = core._t;\nvar qweb = core.qweb;\n\n// To do: refactor session. Session accomplishes several concerns (rpc,\n// configuration, currencies (wtf?), user permissions...). They should be\n// clarified and separated.\n\nvar Session = core.Class.extend(mixins.EventDispatcherMixin, {\n    /**\n\n    @param parent The parent of the newly created object.\n    or `null` if the server to contact is the origin server.\n    @param {Dict} options A dictionary that can contain the following options:\n\n        * \"modules\"\n        * \"use_cors\"\n     */\n    init: function (parent, origin, options) {\n        mixins.EventDispatcherMixin.init.call(this);\n        this.setParent(parent);\n        options = options || {};\n        this.server = null;\n        this.avoid_recursion = false;\n        this.use_cors = options.use_cors || false;\n        this.setup(origin);\n\n        // for historic reasons, the session requires a name to properly work\n        // (see the methods get_cookie and set_cookie).  We should perhaps\n        // remove it totally (but need to make sure the cookies are properly set)\n        this.name = \"instance0\";\n        // TODO: session store in cookie should be optional\n        this.qweb_mutex = new concurrency.Mutex();\n        this.currencies = {};\n        this._groups_def = {};\n        core.bus.on('invalidate_session', this, this._onInvalidateSession);\n    },\n    setup: function (origin, options) {\n        // must be able to customize server\n        var window_origin = location.protocol + \"//\" + location.host;\n        origin = origin ? origin.replace( /\\/+$/, '') : window_origin;\n        if (!_.isUndefined(this.origin) && this.origin !== origin)\n            throw new Error('Session already bound to ' + this.origin);\n        else\n            this.origin = origin;\n        this.prefix = this.origin;\n        this.server = this.origin; // keep chs happy\n        options = options || {};\n        if ('use_cors' in options) {\n            this.use_cors = options.use_cors;\n        }\n    },\n    /**\n     * Setup a session\n     */\n    session_bind: function (origin) {\n        this.setup(origin);\n        qweb.default_dict._s = this.origin;\n        this.uid = null;\n        this.username = null;\n        this.user_context= {};\n        this.db = null;\n        this.active_id = null;\n        return this.session_init();\n    },\n    /**\n     * Init a session, reloads from cookie, if it exists\n     */\n    session_init: function () {\n        var self = this;\n        var prom = this.session_reload();\n\n        if (this.is_frontend || this.is_report) {\n            return prom.then(function () {\n                return self.load_translations();\n            });\n        }\n\n        return prom.then(function () {\n            var promise = self.load_qweb();\n            if (self.session_is_valid()) {\n                return promise.then(function () { return self.load_modules(); });\n            }\n            return Promise.all([\n                    promise,\n                    self.rpc('/web/webclient/bootstrap_translations')\n                        .then(function (trans) {\n                            _t.database.set_bundle(trans);\n                        })\n                    ]);\n        });\n    },\n    session_is_valid: function () {\n        var db = $.deparam.querystring().db;\n        if (db && this.db !== db) {\n            return false;\n        }\n        return !!this.uid;\n    },\n    /**\n     * The session is validated by restoration of a previous session\n     */\n    session_authenticate: function () {\n        var self = this;\n        return Promise.resolve(this._session_authenticate.apply(this, arguments)).then(function () {\n            return self.load_modules();\n        });\n    },\n    /**\n     * The session is validated either by login or by restoration of a previous session\n     */\n    _session_authenticate: function (db, login, password) {\n        var self = this;\n        var params = {db: db, login: login, password: password};\n        return this.rpc(\"/web/session/authenticate\", params).then(function (result) {\n            if (!result.uid) {\n                return Promise.reject();\n            }\n            _.extend(self, result);\n        });\n    },\n    session_logout: function () {\n        $.bbq.removeState();\n        return this.rpc(\"/web/session/destroy\", {});\n    },\n    user_has_group: function (group) {\n        // the frontend session info has no `uid` but an `user_id`\n        if (!this.uid && !this.user_id) {\n            return Promise.resolve(false);\n        }\n        var def = this._groups_def[group];\n        if (!def) {\n            def = this._groups_def[group] = this.rpc('/web/dataset/call_kw/res.users/has_group', {\n                \"model\": \"res.users\",\n                \"method\": \"has_group\",\n                \"args\": [group],\n                \"kwargs\": {}\n            });\n        }\n        return def;\n    },\n    get_cookie: function (name) {\n        if (!this.name) { return null; }\n        var nameEQ = this.name + '|' + name + '=';\n        var cookies = document.cookie.split(';');\n        for(var i=0; i<cookies.length; ++i) {\n            var cookie = cookies[i].replace(/^\\s*/, '');\n            if(cookie.indexOf(nameEQ) === 0) {\n                try {\n                    return JSON.parse(decodeURIComponent(cookie.substring(nameEQ.length)));\n                } catch(err) {\n                    // wrong cookie, delete it\n                    this.set_cookie(name, '', -1);\n                }\n            }\n        }\n        return null;\n    },\n    /**\n     * Create a new cookie with the provided name and value\n     *\n     * @private\n     * @param name the cookie's name\n     * @param value the cookie's value\n     * @param ttl the cookie's time to live, 1 year by default, set to -1 to delete\n     */\n    set_cookie: function (name, value, ttl) {\n        if (!this.name) { return; }\n        ttl = ttl || 24*60*60*365;\n        utils.set_cookie(this.name + '|' + name, value, ttl);\n    },\n    /**\n     * Load additional web addons of that instance and init them\n     *\n     */\n\n    load_modules: function () {\n        var self = this;\n\n        var loaded = Promise.resolve(self.load_translations());\n        var locale = \"/web/webclient/locale/\" + self.user_context.lang || 'en_US';\n        var file_list = [ locale ];\n\n        return loaded.then(function () {\n            return self.load_js(file_list);\n        }).then(function () {\n            self._configureLocale();\n        });\n    },\n    load_translations: function (modules=null) {\n        var lang = this.user_context.lang\n        /* We need to get the website lang at this level.\n           The only way is to get it is to take the HTML tag lang\n           Without it, we will always send undefined if there is no lang\n           in the user_context. */\n        var html = document.documentElement,\n            htmlLang = html.getAttribute('lang');\n        if (!this.user_context.lang && htmlLang) {\n            lang = htmlLang.replace('-', '_');\n        }\n\n        return _t.database.load_translations(this, modules, lang, this.translationURL);\n    },\n    load_js: function (files) {\n        var self = this;\n        return new Promise(function (resolve, reject) {\n            if (files.length !== 0) {\n                var file = files.shift();\n                var url = self.url(file, null);\n                ajax.loadJS(url).then(resolve);\n            } else {\n                resolve();\n            }\n        });\n    },\n    load_qweb: function () {\n        return this.qweb_mutex.exec(async () => {\n            let templates;\n            if (odoo.loadTemplatesPromise) {\n                templates = await odoo.loadTemplatesPromise;\n            } else {\n                var cacheId = this.cache_hashes && this.cache_hashes.qweb;\n                const route = `/web/webclient/qweb/${(cacheId ? cacheId : Date.now())}?bundle=web.assets_qweb`;\n                templates = await (await fetch(route)).text();\n            }\n            const doc = new DOMParser().parseFromString(templates, \"text/xml\");\n            if (!doc) {\n                return;\n            }\n            const owlTemplates = [];\n            for (let child of doc.querySelectorAll(\"templates > [owl]\")) {\n                child.removeAttribute('owl');\n                owlTemplates.push(child.outerHTML);\n                child.remove();\n            }\n            qweb.add_template(doc);\n            this.owlTemplates = `<templates> ${owlTemplates.join('\\n')} </templates>`;\n        });\n    },\n    get_currency: function (currency_id) {\n        return this.currencies[currency_id];\n    },\n    get_file: function (options) {\n        options.session = this;\n        return ajax.get_file(options);\n    },\n    /**\n     * (re)loads the content of a session: db name, username, user id, session\n     * context and status of the support contract\n     *\n     * @returns {Promise} promise indicating the session is done reloading\n     */\n    session_reload: function () {\n        var result = _.extend({}, session);\n        _.extend(this, result);\n        return Promise.resolve();\n    },\n    /**\n     * Executes an RPC call, registering the provided callbacks.\n     *\n     * Registers a default error callback if none is provided, and handles\n     * setting the correct session id and session context in the parameter\n     * objects\n     *\n     * @param {String} url RPC endpoint\n     * @param {Object} params call parameters\n     * @param {Object} options additional options for rpc call\n     * @returns {Promise}\n     */\n    rpc: function (url, params, options) {\n        var self = this;\n        options = _.clone(options || {});\n        options.headers = _.extend({}, options.headers);\n\n        // we add here the user context for ALL queries, mainly to pass\n        // the allowed_company_ids key\n        if (params && params.kwargs) {\n            params.kwargs.context = _.extend(params.kwargs.context || {}, this.user_context);\n        }\n\n        // TODO: remove\n        if (! _.isString(url)) {\n            _.extend(options, url);\n            url = url.url;\n        }\n        if (self.use_cors) {\n            url = self.url(url, null);\n        }\n\n        return ajax.jsonRpc(url, \"call\", params, options);\n    },\n    url: function (path, params) {\n        params = _.extend(params || {});\n        var qs = $.param(params);\n        if (qs.length > 0)\n            qs = \"?\" + qs;\n        var prefix = _.any(['http://', 'https://', '//'], function (el) {\n            return path.length >= el.length && path.slice(0, el.length) === el;\n        }) ? '' : this.prefix;\n        return prefix + path + qs;\n    },\n    /**\n     * Returns the time zone difference (in minutes) from the current locale\n     * (host system settings) to UTC, for a given date. The offset is positive\n     * if the local timezone is behind UTC, and negative if it is ahead.\n     *\n     * @param {string | moment} date a valid string date or moment instance\n     * @returns {integer}\n     */\n    getTZOffset: function (date) {\n        return -new Date(new Date(date).toISOString().replace('Z', '')).getTimezoneOffset();\n    },\n    //--------------------------------------------------------------------------\n    // Public\n    //--------------------------------------------------------------------------\n    /**\n     * Replaces the value of a key in cache_hashes (the hash of some resource computed on the back-end by a unique value\n     * @param {string} key the key in the cache_hashes to invalidate\n     */\n    invalidateCacheKey: function(key) {\n        if (this.cache_hashes && this.cache_hashes[key]) {\n            this.cache_hashes[key] = Date.now();\n        }\n    },\n\n    /**\n     * Reload the currencies (initially given in session_info). This is meant to\n     * be called when changes are made on 'res.currency' records (e.g. when\n     * (de-)activating a currency). For the sake of simplicity, we reload all\n     * session_info.\n     *\n     * FIXME: this whole currencies handling should be moved out of session.\n     *\n     * @returns {$.promise}\n     */\n    reloadCurrencies: function () {\n        var self = this;\n        return this.rpc('/web/session/get_session_info').then(function (result) {\n            self.currencies = result.currencies;\n        });\n    },\n\n    setCompanies: function (main_company_id, company_ids) {\n        var hash = $.bbq.getState();\n        hash.cids = company_ids.sort(function(a, b) {\n            if (a === main_company_id) {\n                return -1;\n            } else if (b === main_company_id) {\n                return 1;\n            } else {\n                return a - b;\n            }\n        }).join(',');\n        utils.set_cookie('cids', hash.cids || String(main_company_id));\n        $.bbq.pushState({'cids': hash.cids}, 0);\n        location.reload();\n    },\n\n    //--------------------------------------------------------------------------\n    // Private\n    //--------------------------------------------------------------------------\n\n    /**\n     * Sets first day of week in current locale according to the user language.\n     *\n     * @private\n     */\n    _configureLocale: function () {\n        // TODO: try to test when re - writing this file in the new system with luxon\n        const dow = (_t.database.parameters.week_start || 0) % 7;\n        moment.updateLocale(moment.locale(), {\n            week: {\n                dow: dow,\n                doy: 7 + dow - 4 // Note: ISO 8601 week date: https://momentjscom.readthedocs.io/en/latest/moment/07-customization/16-dow-doy/\n            },\n        });\n    },\n\n    //--------------------------------------------------------------------------\n    // Handlers\n    //--------------------------------------------------------------------------\n\n    /**\n     * @private\n     */\n    _onInvalidateSession: function () {\n        this.uid = false;\n    },\n});\n\nreturn Session;\n\n});\n", "odoo.define('web.sessionStorage', function (require) {\n'use strict';\n\nvar RamStorage = require('web.RamStorage');\nvar mixins = require('web.mixins');\n\n// use a fake sessionStorage in RAM if the native sessionStorage is unavailable\n// (e.g. private browsing in Safari)\nvar storage;\nvar sessionStorage = window.sessionStorage;\ntry {\n    var uid = new Date();\n    sessionStorage.setItem(uid, uid);\n    sessionStorage.removeItem(uid);\n\n    /*\n     * We create an intermediate object in order to triggered the storage on\n     * this object. the sessionStorage. This simplifies testing and usage as \n     * starages are commutable in services without change. Also, objects\n     * that use storage do not have to know that events go through window,\n     * it's not up to them to handle these cases.\n     */\n    storage = (function () {\n        var storage = Object.create(_.extend({\n                getItem: sessionStorage.getItem.bind(sessionStorage),\n                setItem: sessionStorage.setItem.bind(sessionStorage),\n                removeItem: sessionStorage.removeItem.bind(sessionStorage),\n                clear: sessionStorage.clear.bind(sessionStorage),\n            },\n            mixins.EventDispatcherMixin\n        ));\n        storage.init();\n        $(window).on('storage', function (e) {\n            var key = e.originalEvent.key;\n            var newValue = e.originalEvent.newValue;\n            try {\n                JSON.parse(newValue);\n                if (sessionStorage.getItem(key) === newValue) {\n                    storage.trigger('storage', {\n                        key: key,\n                        newValue: newValue,\n                    });\n                }\n            } catch (error) {}\n        });\n        return storage;\n    })();\n\n} catch (exception) {\n    console.warn('Fail to load sessionStorage');\n    storage = new RamStorage();\n}\n\nreturn storage;\n\n});\n", "odoo.define('web.time', function (require) {\n\"use strict\";\n\nvar translation = require('web.translation');\nvar utils = require('web.utils');\n\nvar lpad = utils.lpad;\nvar rpad = utils.rpad;\nvar _t = translation._t;\n\n/**\n * Replacer function for JSON.stringify, serializes Date objects to UTC\n * datetime in the OpenERP Server format.\n *\n * However, if a serialized value has a toJSON method that method is called\n * *before* the replacer is invoked. Date#toJSON exists, and thus the value\n * passed to the replacer is a string, the original Date has to be fetched\n * on the parent object (which is provided as the replacer's context).\n *\n * @param {String} k\n * @param {Object} v\n * @returns {Object}\n */\nfunction date_to_utc (k, v) {\n    var value = this[k];\n    if (!(value instanceof Date)) { return v; }\n\n    return datetime_to_str(value);\n}\n\n/**\n * Converts a string to a Date javascript object using OpenERP's\n * datetime string format (exemple: '2011-12-01 15:12:35.832').\n * \n * The time zone is assumed to be UTC (standard for OpenERP 6.1)\n * and will be converted to the browser's time zone.\n * \n * @param {String} str A string representing a datetime.\n * @returns {Date}\n */\nfunction str_to_datetime (str) {\n    if(!str) {\n        return str;\n    }\n    var regex = /^(\\d\\d\\d\\d)-(\\d\\d)-(\\d\\d) (\\d\\d):(\\d\\d):(\\d\\d(?:\\.(\\d+))?)$/;\n    var res = regex.exec(str);\n    if ( !res ) {\n        throw new Error(\"'\" + str + \"' is not a valid datetime\");\n    }\n    var tmp = new Date(2000,0,1);\n    tmp.setUTCMonth(1970);\n    tmp.setUTCMonth(0);\n    tmp.setUTCDate(1);\n    tmp.setUTCFullYear(parseFloat(res[1]));\n    tmp.setUTCMonth(parseFloat(res[2]) - 1);\n    tmp.setUTCDate(parseFloat(res[3]));\n    tmp.setUTCHours(parseFloat(res[4]));\n    tmp.setUTCMinutes(parseFloat(res[5]));\n    tmp.setUTCSeconds(parseFloat(res[6]));\n    tmp.setUTCSeconds(parseFloat(res[6]));\n    tmp.setUTCMilliseconds(parseFloat(utils.rpad((res[7] || \"\").slice(0, 3), 3)));\n    return tmp;\n}\n\n/**\n * Converts a string to a Date javascript object using OpenERP's\n * date string format (exemple: '2011-12-01').\n * \n * As a date is not subject to time zones, we assume it should be\n * represented as a Date javascript object at 00:00:00 in the\n * time zone of the browser.\n * \n * @param {String} str A string representing a date.\n * @returns {Date}\n */\nfunction str_to_date (str) {\n    if(!str) {\n        return str;\n    }\n    var regex = /^(\\d\\d\\d\\d)-(\\d\\d)-(\\d\\d)$/;\n    var res = regex.exec(str);\n    if ( !res ) {\n        throw new Error(\"'\" + str + \"' is not a valid date\");\n    }\n    var tmp = new Date(2000,0,1);\n    tmp.setFullYear(parseFloat(res[1]));\n    tmp.setMonth(parseFloat(res[2]) - 1);\n    tmp.setDate(parseFloat(res[3]));\n    tmp.setHours(0);\n    tmp.setMinutes(0);\n    tmp.setSeconds(0);\n    return tmp;\n}\n\n/**\n * Converts a string to a Date javascript object using OpenERP's\n * time string format (exemple: '15:12:35').\n * \n * The OpenERP times are supposed to always be naive times. We assume it is\n * represented using a javascript Date with a date 1 of January 1970 and a\n * time corresponding to the meant time in the browser's time zone.\n * \n * @param {String} str A string representing a time.\n * @returns {Date}\n */\nfunction str_to_time (str) {\n    if(!str) {\n        return str;\n    }\n    var regex = /^(\\d\\d):(\\d\\d):(\\d\\d(?:\\.(\\d+))?)$/;\n    var res = regex.exec(str);\n    if ( !res ) {\n        throw new Error(\"'\" + str + \"' is not a valid time\");\n    }\n    var tmp = new Date();\n    tmp.setFullYear(1970);\n    tmp.setMonth(0);\n    tmp.setDate(1);\n    tmp.setHours(parseFloat(res[1]));\n    tmp.setMinutes(parseFloat(res[2]));\n    tmp.setSeconds(parseFloat(res[3]));\n    tmp.setMilliseconds(parseFloat(rpad((res[4] || \"\").slice(0, 3), 3)));\n    return tmp;\n}\n\n/**\n * Converts a Date javascript object to a string using OpenERP's\n * datetime string format (exemple: '2011-12-01 15:12:35').\n * \n * The time zone of the Date object is assumed to be the one of the\n * browser and it will be converted to UTC (standard for OpenERP 6.1).\n * \n * @param {Date} obj\n * @returns {String} A string representing a datetime.\n */\nfunction datetime_to_str (obj) {\n    if (!obj) {\n        return false;\n    }\n    return lpad(obj.getUTCFullYear(),4) + \"-\" + lpad(obj.getUTCMonth() + 1,2) + \"-\"\n         + lpad(obj.getUTCDate(),2) + \" \" + lpad(obj.getUTCHours(),2) + \":\"\n         + lpad(obj.getUTCMinutes(),2) + \":\" + lpad(obj.getUTCSeconds(),2);\n}\n\n/**\n * Converts a Date javascript object to a string using OpenERP's\n * date string format (exemple: '2011-12-01').\n * \n * As a date is not subject to time zones, we assume it should be\n * represented as a Date javascript object at 00:00:00 in the\n * time zone of the browser.\n * \n * @param {Date} obj\n * @returns {String} A string representing a date.\n */\nfunction date_to_str (obj) {\n    if (!obj) {\n        return false;\n    }\n    return lpad(obj.getFullYear(),4) + \"-\" + lpad(obj.getMonth() + 1,2) + \"-\"\n         + lpad(obj.getDate(),2);\n}\n\n/**\n * Converts a Date javascript object to a string using OpenERP's\n * time string format (exemple: '15:12:35').\n * \n * The OpenERP times are supposed to always be naive times. We assume it is\n * represented using a javascript Date with a date 1 of January 1970 and a\n * time corresponding to the meant time in the browser's time zone.\n * \n * @param {Date} obj\n * @returns {String} A string representing a time.\n */\nfunction time_to_str (obj) {\n    if (!obj) {\n        return false;\n    }\n    return lpad(obj.getHours(),2) + \":\" + lpad(obj.getMinutes(),2) + \":\"\n         + lpad(obj.getSeconds(),2);\n}\n\nfunction auto_str_to_date (value) {\n    try {\n        return str_to_datetime(value);\n    } catch(e) {}\n    try {\n        return str_to_date(value);\n    } catch(e) {}\n    try {\n        return str_to_time(value);\n    } catch(e) {}\n    throw new Error(_.str.sprintf(_t(\"'%s' is not a correct date, datetime nor time\"), value));\n}\n\nfunction auto_date_to_str (value, type) {\n    switch(type) {\n        case 'datetime':\n            return datetime_to_str(value);\n        case 'date':\n            return date_to_str(value);\n        case 'time':\n            return time_to_str(value);\n        default:\n            throw new Error(_.str.sprintf(_t(\"'%s' is not convertible to date, datetime nor time\"), type));\n    }\n}\n\n/**\n * Convert Python strftime to escaped moment.js format.\n *\n * @param {String} value original format\n */\nfunction strftime_to_moment_format (value) {\n    if (_normalize_format_cache[value] === undefined) {\n        var isletter = /[a-zA-Z]/,\n            output = [],\n            inToken = false;\n\n        for (var index=0; index < value.length; ++index) {\n            var character = value[index];\n            if (character === '%' && !inToken) {\n                inToken = true;\n                continue;\n            }\n            if (isletter.test(character)) {\n                if (inToken && normalize_format_table[character] !== undefined) {\n                    character = normalize_format_table[character];\n                } else {\n                    character = '[' + character + ']'; // moment.js escape\n                }\n            }\n            output.push(character);\n            inToken = false;\n        }\n        _normalize_format_cache[value] = output.join('');\n    }\n    return _normalize_format_cache[value];\n}\n\n/**\n * Convert moment.js format to python strftime\n *\n * @param {String} value original format\n */\nfunction moment_to_strftime_format(value) {\n    var regex = /(MMMM|DDDD|dddd|YYYY|MMM|ddd|mm|ss|ww|WW|MM|YY|hh|HH|DD|A|d)/g;\n    return value.replace(regex, function(val){\n        return '%'+inverse_normalize_format_table[val];\n    });\n}\n\nvar _normalize_format_cache = {};\nvar normalize_format_table = {\n    // Python strftime to moment.js conversion table\n    // See openerp/addons/base/views/res_lang_views.xml\n    // for details about supported directives\n    'a': 'ddd',\n    'A': 'dddd',\n    'b': 'MMM',\n    'B': 'MMMM',\n    'd': 'DD',\n    'H': 'HH',\n    'I': 'hh',\n    'j': 'DDDD',\n    'm': 'MM',\n    'M': 'mm',\n    'p': 'A',\n    'S': 'ss',\n    'U': 'ww',\n    'W': 'WW',\n    'w': 'd',\n    'y': 'YY',\n    'Y': 'YYYY',\n    // unsupported directives\n    'c': 'ddd MMM D HH:mm:ss YYYY',\n    'x': 'MM/DD/YY',\n    'X': 'HH:mm:ss'\n};\nvar inverse_normalize_format_table = _.invert(normalize_format_table);\n\n/**\n * Get date format of the user's language\n */\nfunction getLangDateFormat() {\n    return strftime_to_moment_format(_t.database.parameters.date_format);\n}\n\n/**\n * Get time format of the user's language\n */\nfunction getLangTimeFormat() {\n    return strftime_to_moment_format(_t.database.parameters.time_format);\n}\n\n/**\n * Get date time format of the user's language\n */\nfunction getLangDatetimeFormat() {\n    return strftime_to_moment_format(_t.database.parameters.date_format + \" \" + _t.database.parameters.time_format);\n}\n\nconst dateFormatWoZeroCache = {};\n/**\n * Get date format of the user's language - allows non padded\n */\nfunction getLangDateFormatWoZero() {\n    const dateFormat = getLangDateFormat();\n    if (!(dateFormat in dateFormatWoZeroCache)) {\n        dateFormatWoZeroCache[dateFormat] = dateFormat\n            .replace('MM', 'M')\n            .replace('DD', 'D');\n    }\n    return dateFormatWoZeroCache[dateFormat];\n}\n\nconst timeFormatWoZeroCache = {};\n/**\n * Get time format of the user's language - allows non padded\n */\nfunction getLangTimeFormatWoZero() {\n    const timeFormat = getLangTimeFormat();\n    if (!(timeFormat in timeFormatWoZeroCache)) {\n        timeFormatWoZeroCache[timeFormat] = timeFormat\n            .replace('HH', 'H')\n            .replace('mm', 'm')\n            .replace('ss', 's');\n    }\n    return timeFormatWoZeroCache[timeFormat];\n}\n\nreturn {\n    date_to_utc: date_to_utc,\n    str_to_datetime: str_to_datetime,\n    str_to_date: str_to_date,\n    str_to_time: str_to_time,\n    datetime_to_str: datetime_to_str,\n    date_to_str: date_to_str,\n    time_to_str: time_to_str,\n    auto_str_to_date: auto_str_to_date,\n    auto_date_to_str: auto_date_to_str,\n    strftime_to_moment_format: strftime_to_moment_format,\n    moment_to_strftime_format: moment_to_strftime_format,\n    getLangDateFormat: getLangDateFormat,\n    getLangTimeFormat: getLangTimeFormat,\n    getLangDateFormatWoZero: getLangDateFormatWoZero,\n    getLangTimeFormatWoZero: getLangTimeFormatWoZero,\n    getLangDatetimeFormat: getLangDatetimeFormat,\n};\n\n});\n\n", "\nodoo.define('web.translation', function (require) {\n\"use strict\";\n\nvar Class = require('web.Class');\n\nvar TranslationDataBase = Class.extend(/** @lends instance.TranslationDataBase# */{\n    init: function() {\n        this.db = {};\n        this.multi_lang = false\n        this.parameters = {\"direction\": 'ltr',\n                        \"date_format\": '%m/%d/%Y',\n                        \"time_format\": '%H:%M:%S',\n                        \"grouping\": [],\n                        \"decimal_point\": \".\",\n                        \"thousands_sep\": \",\",\n                        \"code\": \"en_US\"};\n    },\n    set_bundle: function(translation_bundle) {\n        var self = this;\n        this.multi_lang = translation_bundle.multi_lang\n        var modules = _.keys(translation_bundle.modules);\n        modules.sort();\n        if (_.include(modules, \"web\")) {\n            modules = [\"web\"].concat(_.without(modules, \"web\"));\n        }\n        _.each(modules, function(name) {\n            self.add_module_translation(translation_bundle.modules[name]);\n        });\n        if (translation_bundle.lang_parameters) {\n            this.parameters = translation_bundle.lang_parameters;\n            this.parameters.grouping = JSON.parse(this.parameters.grouping);\n        }\n    },\n    add_module_translation: function(mod) {\n        var self = this;\n        _.each(mod.messages, function(message) {\n            self.db[message.id] = message.string;\n        });\n    },\n    build_translation_function: function() {\n        var self = this;\n        var fcnt = function(str) {\n            var tmp = self.get(str);\n            return tmp === undefined ? str : tmp;\n        };\n        fcnt.database = this;\n        return fcnt;\n    },\n    get: function(key) {\n        return this.db[key];\n    },\n    /**\n        Loads the translations from an OpenERP server.\n\n        @param {openerp.Session} session The session object to contact the server.\n        @param {Array} [modules] The list of modules to load the translation. If not specified,\n        it will default to all the modules installed in the current database.\n        @param {Object} [lang] lang The language. If not specified it will default to the language\n        of the current user.\n        @param {string} [url='/web/webclient/translations']\n        @returns {Promise}\n    */\n    load_translations: function(session, modules, lang, url) {\n        var self = this;\n        var cacheId = session.cache_hashes && session.cache_hashes.translations;\n        url = url || '/web/webclient/translations';\n        url += '/' + (cacheId ? cacheId : Date.now());\n        const paramsGet = {};\n        if (modules) {\n            paramsGet.mods = modules.join(',');\n        }\n        if (lang) {\n            paramsGet.lang = lang;\n        }\n        return $.get(url, paramsGet).then(function (trans) {\n            self.set_bundle(trans);\n        });\n    }\n});\n\n/**\n * Eager translation function, performs translation immediately at call\n * site. Beware using this outside of method bodies (before the\n * translation database is loaded), you probably want :func:`_lt`\n * instead.\n *\n * @function _t\n * @param {String} source string to translate\n * @returns {String} source translated into the current locale\n */\nvar _t = new TranslationDataBase().build_translation_function();\n/**\n * Lazy translation function, only performs the translation when actually\n * printed (e.g. inserted into a template)\n *\n * Useful when defining translatable strings in code evaluated before the\n * translation database is loaded, as class attributes or at the top-level of\n * an OpenERP Web module\n *\n * @param {String} s string to translate\n * @returns {Object} lazy translation object\n */\nvar _lt = function (s) {\n    return {toString: function () { return _t(s); }};\n};\n\n/** Setup jQuery timeago */\n/*\n * Strings in timeago are \"composed\" with prefixes, words and suffixes. This\n * makes their detection by our translating system impossible. Use all literal\n * strings we're using with a translation mark here so the extractor can do its\n * job.\n */\n{\n    _t('less than a minute ago');\n    _t('about a minute ago');\n    _t('%d minutes ago');\n    _t('about an hour ago');\n    _t('%d hours ago');\n    _t('a day ago');\n    _t('%d days ago');\n    _t('about a month ago');\n    _t('%d months ago');\n    _t('about a year ago');\n    _t('%d years ago');\n}\n\n\nreturn {\n    _t: _t,\n    _lt: _lt,\n    TranslationDataBase: TranslationDataBase,\n};\n\n});\n", "odoo.define('web.utils', function (require) {\n\"use strict\";\n\n/**\n * Utils\n *\n * Various generic utility functions\n */\n\nvar translation = require('web.translation');\nvar cookieUtils = require('web.utils.cookies');\n\nvar _t = translation._t;\nvar id = -1;\n\nvar diacriticsMap = {\n'\\u0041': 'A','\\u24B6': 'A','\\uFF21': 'A','\\u00C0': 'A','\\u00C1': 'A','\\u00C2': 'A','\\u1EA6': 'A','\\u1EA4': 'A','\\u1EAA': 'A','\\u1EA8': 'A',\n'\\u00C3': 'A','\\u0100': 'A','\\u0102': 'A','\\u1EB0': 'A','\\u1EAE': 'A','\\u1EB4': 'A','\\u1EB2': 'A','\\u0226': 'A','\\u01E0': 'A','\\u00C4': 'A',\n'\\u01DE': 'A','\\u1EA2': 'A','\\u00C5': 'A','\\u01FA': 'A','\\u01CD': 'A','\\u0200': 'A','\\u0202': 'A','\\u1EA0': 'A','\\u1EAC': 'A','\\u1EB6': 'A',\n'\\u1E00': 'A','\\u0104': 'A','\\u023A': 'A','\\u2C6F': 'A',\n\n'\\uA732': 'AA',\n'\\u00C6': 'AE','\\u01FC': 'AE','\\u01E2': 'AE',\n'\\uA734': 'AO',\n'\\uA736': 'AU',\n'\\uA738': 'AV','\\uA73A': 'AV',\n'\\uA73C': 'AY',\n'\\u0042': 'B','\\u24B7': 'B','\\uFF22': 'B','\\u1E02': 'B','\\u1E04': 'B','\\u1E06': 'B','\\u0243': 'B','\\u0182': 'B','\\u0181': 'B',\n\n'\\u0043': 'C','\\u24B8': 'C','\\uFF23': 'C','\\u0106': 'C','\\u0108': 'C','\\u010A': 'C','\\u010C': 'C','\\u00C7': 'C','\\u1E08': 'C','\\u0187': 'C',\n'\\u023B': 'C','\\uA73E': 'C',\n\n'\\u0044': 'D','\\u24B9': 'D','\\uFF24': 'D','\\u1E0A': 'D','\\u010E': 'D','\\u1E0C': 'D','\\u1E10': 'D','\\u1E12': 'D','\\u1E0E': 'D','\\u0110': 'D',\n'\\u018B': 'D','\\u018A': 'D','\\u0189': 'D','\\uA779': 'D',\n\n'\\u01F1': 'DZ','\\u01C4': 'DZ',\n'\\u01F2': 'Dz','\\u01C5': 'Dz',\n\n'\\u0045': 'E','\\u24BA': 'E','\\uFF25': 'E','\\u00C8': 'E','\\u00C9': 'E','\\u00CA': 'E','\\u1EC0': 'E','\\u1EBE': 'E','\\u1EC4': 'E','\\u1EC2': 'E',\n'\\u1EBC': 'E','\\u0112': 'E','\\u1E14': 'E','\\u1E16': 'E','\\u0114': 'E','\\u0116': 'E','\\u00CB': 'E','\\u1EBA': 'E','\\u011A': 'E','\\u0204': 'E',\n'\\u0206': 'E','\\u1EB8': 'E','\\u1EC6': 'E','\\u0228': 'E','\\u1E1C': 'E','\\u0118': 'E','\\u1E18': 'E','\\u1E1A': 'E','\\u0190': 'E','\\u018E': 'E',\n\n'\\u0046': 'F','\\u24BB': 'F','\\uFF26': 'F','\\u1E1E': 'F','\\u0191': 'F','\\uA77B': 'F',\n\n'\\u0047': 'G','\\u24BC': 'G','\\uFF27': 'G','\\u01F4': 'G','\\u011C': 'G','\\u1E20': 'G','\\u011E': 'G','\\u0120': 'G','\\u01E6': 'G','\\u0122': 'G',\n'\\u01E4': 'G','\\u0193': 'G','\\uA7A0': 'G','\\uA77D': 'G','\\uA77E': 'G',\n\n'\\u0048': 'H','\\u24BD': 'H','\\uFF28': 'H','\\u0124': 'H','\\u1E22': 'H','\\u1E26': 'H','\\u021E': 'H','\\u1E24': 'H','\\u1E28': 'H','\\u1E2A': 'H',\n'\\u0126': 'H','\\u2C67': 'H','\\u2C75': 'H','\\uA78D': 'H',\n\n'\\u0049': 'I','\\u24BE': 'I','\\uFF29': 'I','\\u00CC': 'I','\\u00CD': 'I','\\u00CE': 'I','\\u0128': 'I','\\u012A': 'I','\\u012C': 'I','\\u0130': 'I',\n'\\u00CF': 'I','\\u1E2E': 'I','\\u1EC8': 'I','\\u01CF': 'I','\\u0208': 'I','\\u020A': 'I','\\u1ECA': 'I','\\u012E': 'I','\\u1E2C': 'I','\\u0197': 'I',\n\n'\\u004A': 'J','\\u24BF': 'J','\\uFF2A': 'J','\\u0134': 'J','\\u0248': 'J',\n\n'\\u004B': 'K','\\u24C0': 'K','\\uFF2B': 'K','\\u1E30': 'K','\\u01E8': 'K','\\u1E32': 'K','\\u0136': 'K','\\u1E34': 'K','\\u0198': 'K','\\u2C69': 'K',\n'\\uA740': 'K','\\uA742': 'K','\\uA744': 'K','\\uA7A2': 'K',\n\n'\\u004C': 'L','\\u24C1': 'L','\\uFF2C': 'L','\\u013F': 'L','\\u0139': 'L','\\u013D': 'L','\\u1E36': 'L','\\u1E38': 'L','\\u013B': 'L','\\u1E3C': 'L',\n'\\u1E3A': 'L','\\u0141': 'L','\\u023D': 'L','\\u2C62': 'L','\\u2C60': 'L','\\uA748': 'L','\\uA746': 'L','\\uA780': 'L',\n\n'\\u01C7': 'LJ',\n'\\u01C8': 'Lj',\n'\\u004D': 'M','\\u24C2': 'M','\\uFF2D': 'M','\\u1E3E': 'M','\\u1E40': 'M','\\u1E42': 'M','\\u2C6E': 'M','\\u019C': 'M',\n\n'\\u004E': 'N','\\u24C3': 'N','\\uFF2E': 'N','\\u01F8': 'N','\\u0143': 'N','\\u00D1': 'N','\\u1E44': 'N','\\u0147': 'N','\\u1E46': 'N','\\u0145': 'N',\n'\\u1E4A': 'N','\\u1E48': 'N','\\u0220': 'N','\\u019D': 'N','\\uA790': 'N','\\uA7A4': 'N',\n\n'\\u01CA': 'NJ',\n'\\u01CB': 'Nj',\n\n'\\u004F': 'O','\\u24C4': 'O','\\uFF2F': 'O','\\u00D2': 'O','\\u00D3': 'O','\\u00D4': 'O','\\u1ED2': 'O','\\u1ED0': 'O','\\u1ED6': 'O','\\u1ED4': 'O',\n'\\u00D5': 'O','\\u1E4C': 'O','\\u022C': 'O','\\u1E4E': 'O','\\u014C': 'O','\\u1E50': 'O','\\u1E52': 'O','\\u014E': 'O','\\u022E': 'O','\\u0230': 'O',\n'\\u00D6': 'O','\\u022A': 'O','\\u1ECE': 'O','\\u0150': 'O','\\u01D1': 'O','\\u020C': 'O','\\u020E': 'O','\\u01A0': 'O','\\u1EDC': 'O','\\u1EDA': 'O',\n'\\u1EE0': 'O','\\u1EDE': 'O','\\u1EE2': 'O','\\u1ECC': 'O','\\u1ED8': 'O','\\u01EA': 'O','\\u01EC': 'O','\\u00D8': 'O','\\u01FE': 'O','\\u0186': 'O',\n'\\u019F': 'O','\\uA74A': 'O','\\uA74C': 'O',\n\n'\\u01A2': 'OI',\n'\\uA74E': 'OO',\n'\\u0222': 'OU',\n'\\u0050': 'P','\\u24C5': 'P','\\uFF30': 'P','\\u1E54': 'P','\\u1E56': 'P','\\u01A4': 'P','\\u2C63': 'P','\\uA750': 'P','\\uA752': 'P','\\uA754': 'P',\n'\\u0051': 'Q','\\u24C6': 'Q','\\uFF31': 'Q','\\uA756': 'Q','\\uA758': 'Q','\\u024A': 'Q',\n\n'\\u0052': 'R','\\u24C7': 'R','\\uFF32': 'R','\\u0154': 'R','\\u1E58': 'R','\\u0158': 'R','\\u0210': 'R','\\u0212': 'R','\\u1E5A': 'R','\\u1E5C': 'R',\n'\\u0156': 'R','\\u1E5E': 'R','\\u024C': 'R','\\u2C64': 'R','\\uA75A': 'R','\\uA7A6': 'R','\\uA782': 'R',\n\n'\\u0053': 'S','\\u24C8': 'S','\\uFF33': 'S','\\u1E9E': 'S','\\u015A': 'S','\\u1E64': 'S','\\u015C': 'S','\\u1E60': 'S','\\u0160': 'S','\\u1E66': 'S',\n'\\u1E62': 'S','\\u1E68': 'S','\\u0218': 'S','\\u015E': 'S','\\u2C7E': 'S','\\uA7A8': 'S','\\uA784': 'S',\n\n'\\u0054': 'T','\\u24C9': 'T','\\uFF34': 'T','\\u1E6A': 'T','\\u0164': 'T','\\u1E6C': 'T','\\u021A': 'T','\\u0162': 'T','\\u1E70': 'T','\\u1E6E': 'T',\n'\\u0166': 'T','\\u01AC': 'T','\\u01AE': 'T','\\u023E': 'T','\\uA786': 'T',\n\n'\\uA728': 'TZ',\n\n'\\u0055': 'U','\\u24CA': 'U','\\uFF35': 'U','\\u00D9': 'U','\\u00DA': 'U','\\u00DB': 'U','\\u0168': 'U','\\u1E78': 'U','\\u016A': 'U','\\u1E7A': 'U',\n'\\u016C': 'U','\\u00DC': 'U','\\u01DB': 'U','\\u01D7': 'U','\\u01D5': 'U','\\u01D9': 'U','\\u1EE6': 'U','\\u016E': 'U','\\u0170': 'U','\\u01D3': 'U',\n'\\u0214': 'U','\\u0216': 'U','\\u01AF': 'U','\\u1EEA': 'U','\\u1EE8': 'U','\\u1EEE': 'U','\\u1EEC': 'U','\\u1EF0': 'U','\\u1EE4': 'U','\\u1E72': 'U',\n'\\u0172': 'U','\\u1E76': 'U','\\u1E74': 'U','\\u0244': 'U',\n\n'\\u0056': 'V','\\u24CB': 'V','\\uFF36': 'V','\\u1E7C': 'V','\\u1E7E': 'V','\\u01B2': 'V','\\uA75E': 'V','\\u0245': 'V',\n'\\uA760': 'VY',\n'\\u0057': 'W','\\u24CC': 'W','\\uFF37': 'W','\\u1E80': 'W','\\u1E82': 'W','\\u0174': 'W','\\u1E86': 'W','\\u1E84': 'W','\\u1E88': 'W','\\u2C72': 'W',\n'\\u0058': 'X','\\u24CD': 'X','\\uFF38': 'X','\\u1E8A': 'X','\\u1E8C': 'X',\n\n'\\u0059': 'Y','\\u24CE': 'Y','\\uFF39': 'Y','\\u1EF2': 'Y','\\u00DD': 'Y','\\u0176': 'Y','\\u1EF8': 'Y','\\u0232': 'Y','\\u1E8E': 'Y','\\u0178': 'Y',\n'\\u1EF6': 'Y','\\u1EF4': 'Y','\\u01B3': 'Y','\\u024E': 'Y','\\u1EFE': 'Y',\n\n'\\u005A': 'Z','\\u24CF': 'Z','\\uFF3A': 'Z','\\u0179': 'Z','\\u1E90': 'Z','\\u017B': 'Z','\\u017D': 'Z','\\u1E92': 'Z','\\u1E94': 'Z','\\u01B5': 'Z',\n'\\u0224': 'Z','\\u2C7F': 'Z','\\u2C6B': 'Z','\\uA762': 'Z',\n\n'\\u0061': 'a','\\u24D0': 'a','\\uFF41': 'a','\\u1E9A': 'a','\\u00E0': 'a','\\u00E1': 'a','\\u00E2': 'a','\\u1EA7': 'a','\\u1EA5': 'a','\\u1EAB': 'a',\n'\\u1EA9': 'a','\\u00E3': 'a','\\u0101': 'a','\\u0103': 'a','\\u1EB1': 'a','\\u1EAF': 'a','\\u1EB5': 'a','\\u1EB3': 'a','\\u0227': 'a','\\u01E1': 'a',\n'\\u00E4': 'a','\\u01DF': 'a','\\u1EA3': 'a','\\u00E5': 'a','\\u01FB': 'a','\\u01CE': 'a','\\u0201': 'a','\\u0203': 'a','\\u1EA1': 'a','\\u1EAD': 'a',\n'\\u1EB7': 'a','\\u1E01': 'a','\\u0105': 'a','\\u2C65': 'a','\\u0250': 'a',\n\n'\\uA733': 'aa',\n'\\u00E6': 'ae','\\u01FD': 'ae','\\u01E3': 'ae',\n'\\uA735': 'ao',\n'\\uA737': 'au',\n'\\uA739': 'av','\\uA73B': 'av',\n'\\uA73D': 'ay',\n'\\u0062': 'b','\\u24D1': 'b','\\uFF42': 'b','\\u1E03': 'b','\\u1E05': 'b','\\u1E07': 'b','\\u0180': 'b','\\u0183': 'b','\\u0253': 'b',\n\n'\\u0063': 'c','\\u24D2': 'c','\\uFF43': 'c','\\u0107': 'c','\\u0109': 'c','\\u010B': 'c','\\u010D': 'c','\\u00E7': 'c','\\u1E09': 'c','\\u0188': 'c',\n'\\u023C': 'c','\\uA73F': 'c','\\u2184': 'c',\n\n'\\u0064': 'd','\\u24D3': 'd','\\uFF44': 'd','\\u1E0B': 'd','\\u010F': 'd','\\u1E0D': 'd','\\u1E11': 'd','\\u1E13': 'd','\\u1E0F': 'd','\\u0111': 'd',\n'\\u018C': 'd','\\u0256': 'd','\\u0257': 'd','\\uA77A': 'd',\n\n'\\u01F3': 'dz','\\u01C6': 'dz',\n\n'\\u0065': 'e','\\u24D4': 'e','\\uFF45': 'e','\\u00E8': 'e','\\u00E9': 'e','\\u00EA': 'e','\\u1EC1': 'e','\\u1EBF': 'e','\\u1EC5': 'e','\\u1EC3': 'e',\n'\\u1EBD': 'e','\\u0113': 'e','\\u1E15': 'e','\\u1E17': 'e','\\u0115': 'e','\\u0117': 'e','\\u00EB': 'e','\\u1EBB': 'e','\\u011B': 'e','\\u0205': 'e',\n'\\u0207': 'e','\\u1EB9': 'e','\\u1EC7': 'e','\\u0229': 'e','\\u1E1D': 'e','\\u0119': 'e','\\u1E19': 'e','\\u1E1B': 'e','\\u0247': 'e','\\u025B': 'e',\n'\\u01DD': 'e',\n\n'\\u0066': 'f','\\u24D5': 'f','\\uFF46': 'f','\\u1E1F': 'f','\\u0192': 'f','\\uA77C': 'f',\n\n'\\u0067': 'g','\\u24D6': 'g','\\uFF47': 'g','\\u01F5': 'g','\\u011D': 'g','\\u1E21': 'g','\\u011F': 'g','\\u0121': 'g','\\u01E7': 'g','\\u0123': 'g',\n'\\u01E5': 'g','\\u0260': 'g','\\uA7A1': 'g','\\u1D79': 'g','\\uA77F': 'g',\n\n'\\u0068': 'h','\\u24D7': 'h','\\uFF48': 'h','\\u0125': 'h','\\u1E23': 'h','\\u1E27': 'h','\\u021F': 'h','\\u1E25': 'h','\\u1E29': 'h','\\u1E2B': 'h',\n'\\u1E96': 'h','\\u0127': 'h','\\u2C68': 'h','\\u2C76': 'h','\\u0265': 'h',\n\n'\\u0195': 'hv',\n\n'\\u0069': 'i','\\u24D8': 'i','\\uFF49': 'i','\\u00EC': 'i','\\u00ED': 'i','\\u00EE': 'i','\\u0129': 'i','\\u012B': 'i','\\u012D': 'i','\\u00EF': 'i',\n'\\u1E2F': 'i','\\u1EC9': 'i','\\u01D0': 'i','\\u0209': 'i','\\u020B': 'i','\\u1ECB': 'i','\\u012F': 'i','\\u1E2D': 'i','\\u0268': 'i','\\u0131': 'i',\n\n'\\u006A': 'j','\\u24D9': 'j','\\uFF4A': 'j','\\u0135': 'j','\\u01F0': 'j','\\u0249': 'j',\n\n'\\u006B': 'k','\\u24DA': 'k','\\uFF4B': 'k','\\u1E31': 'k','\\u01E9': 'k','\\u1E33': 'k','\\u0137': 'k','\\u1E35': 'k','\\u0199': 'k','\\u2C6A': 'k',\n'\\uA741': 'k','\\uA743': 'k','\\uA745': 'k','\\uA7A3': 'k',\n\n'\\u006C': 'l','\\u24DB': 'l','\\uFF4C': 'l','\\u0140': 'l','\\u013A': 'l','\\u013E': 'l','\\u1E37': 'l','\\u1E39': 'l','\\u013C': 'l','\\u1E3D': 'l',\n'\\u1E3B': 'l','\\u017F': 'l','\\u0142': 'l','\\u019A': 'l','\\u026B': 'l','\\u2C61': 'l','\\uA749': 'l','\\uA781': 'l','\\uA747': 'l',\n\n'\\u01C9': 'lj',\n'\\u006D': 'm','\\u24DC': 'm','\\uFF4D': 'm','\\u1E3F': 'm','\\u1E41': 'm','\\u1E43': 'm','\\u0271': 'm','\\u026F': 'm',\n\n'\\u006E': 'n','\\u24DD': 'n','\\uFF4E': 'n','\\u01F9': 'n','\\u0144': 'n','\\u00F1': 'n','\\u1E45': 'n','\\u0148': 'n','\\u1E47': 'n','\\u0146': 'n',\n'\\u1E4B': 'n','\\u1E49': 'n','\\u019E': 'n','\\u0272': 'n','\\u0149': 'n','\\uA791': 'n','\\uA7A5': 'n',\n\n'\\u01CC': 'nj',\n\n'\\u006F': 'o','\\u24DE': 'o','\\uFF4F': 'o','\\u00F2': 'o','\\u00F3': 'o','\\u00F4': 'o','\\u1ED3': 'o','\\u1ED1': 'o','\\u1ED7': 'o','\\u1ED5': 'o',\n'\\u00F5': 'o','\\u1E4D': 'o','\\u022D': 'o','\\u1E4F': 'o','\\u014D': 'o','\\u1E51': 'o','\\u1E53': 'o','\\u014F': 'o','\\u022F': 'o','\\u0231': 'o',\n'\\u00F6': 'o','\\u022B': 'o','\\u1ECF': 'o','\\u0151': 'o','\\u01D2': 'o','\\u020D': 'o','\\u020F': 'o','\\u01A1': 'o','\\u1EDD': 'o','\\u1EDB': 'o',\n'\\u1EE1': 'o','\\u1EDF': 'o','\\u1EE3': 'o','\\u1ECD': 'o','\\u1ED9': 'o','\\u01EB': 'o','\\u01ED': 'o','\\u00F8': 'o','\\u01FF': 'o','\\u0254': 'o',\n'\\uA74B': 'o','\\uA74D': 'o','\\u0275': 'o',\n\n'\\u01A3': 'oi',\n'\\u0223': 'ou',\n'\\uA74F': 'oo',\n'\\u0070': 'p','\\u24DF': 'p','\\uFF50': 'p','\\u1E55': 'p','\\u1E57': 'p','\\u01A5': 'p','\\u1D7D': 'p','\\uA751': 'p','\\uA753': 'p','\\uA755': 'p',\n'\\u0071': 'q','\\u24E0': 'q','\\uFF51': 'q','\\u024B': 'q','\\uA757': 'q','\\uA759': 'q',\n\n'\\u0072': 'r','\\u24E1': 'r','\\uFF52': 'r','\\u0155': 'r','\\u1E59': 'r','\\u0159': 'r','\\u0211': 'r','\\u0213': 'r','\\u1E5B': 'r','\\u1E5D': 'r',\n'\\u0157': 'r','\\u1E5F': 'r','\\u024D': 'r','\\u027D': 'r','\\uA75B': 'r','\\uA7A7': 'r','\\uA783': 'r',\n\n'\\u0073': 's','\\u24E2': 's','\\uFF53': 's','\\u00DF': 's','\\u015B': 's','\\u1E65': 's','\\u015D': 's','\\u1E61': 's','\\u0161': 's','\\u1E67': 's',\n'\\u1E63': 's','\\u1E69': 's','\\u0219': 's','\\u015F': 's','\\u023F': 's','\\uA7A9': 's','\\uA785': 's','\\u1E9B': 's',\n\n'\\u0074': 't','\\u24E3': 't','\\uFF54': 't','\\u1E6B': 't','\\u1E97': 't','\\u0165': 't','\\u1E6D': 't','\\u021B': 't','\\u0163': 't','\\u1E71': 't',\n'\\u1E6F': 't','\\u0167': 't','\\u01AD': 't','\\u0288': 't','\\u2C66': 't','\\uA787': 't',\n\n'\\uA729': 'tz',\n\n'\\u0075': 'u','\\u24E4': 'u','\\uFF55': 'u','\\u00F9': 'u','\\u00FA': 'u','\\u00FB': 'u','\\u0169': 'u','\\u1E79': 'u','\\u016B': 'u','\\u1E7B': 'u',\n'\\u016D': 'u','\\u00FC': 'u','\\u01DC': 'u','\\u01D8': 'u','\\u01D6': 'u','\\u01DA': 'u','\\u1EE7': 'u','\\u016F': 'u','\\u0171': 'u','\\u01D4': 'u',\n'\\u0215': 'u','\\u0217': 'u','\\u01B0': 'u','\\u1EEB': 'u','\\u1EE9': 'u','\\u1EEF': 'u','\\u1EED': 'u','\\u1EF1': 'u','\\u1EE5': 'u','\\u1E73': 'u',\n'\\u0173': 'u','\\u1E77': 'u','\\u1E75': 'u','\\u0289': 'u',\n\n'\\u0076': 'v','\\u24E5': 'v','\\uFF56': 'v','\\u1E7D': 'v','\\u1E7F': 'v','\\u028B': 'v','\\uA75F': 'v','\\u028C': 'v',\n'\\uA761': 'vy',\n'\\u0077': 'w','\\u24E6': 'w','\\uFF57': 'w','\\u1E81': 'w','\\u1E83': 'w','\\u0175': 'w','\\u1E87': 'w','\\u1E85': 'w','\\u1E98': 'w','\\u1E89': 'w',\n'\\u2C73': 'w',\n'\\u0078': 'x','\\u24E7': 'x','\\uFF58': 'x','\\u1E8B': 'x','\\u1E8D': 'x',\n\n'\\u0079': 'y','\\u24E8': 'y','\\uFF59': 'y','\\u1EF3': 'y','\\u00FD': 'y','\\u0177': 'y','\\u1EF9': 'y','\\u0233': 'y','\\u1E8F': 'y','\\u00FF': 'y',\n'\\u1EF7': 'y','\\u1E99': 'y','\\u1EF5': 'y','\\u01B4': 'y','\\u024F': 'y','\\u1EFF': 'y',\n\n'\\u007A': 'z','\\u24E9': 'z','\\uFF5A': 'z','\\u017A': 'z','\\u1E91': 'z','\\u017C': 'z','\\u017E': 'z','\\u1E93': 'z','\\u1E95': 'z','\\u01B6': 'z',\n'\\u0225': 'z','\\u0240': 'z','\\u2C6C': 'z','\\uA763': 'z',\n};\n\nconst patchMap = new WeakMap();\n\n/**\n * Helper function returning an extraction handler to use on array elements to\n * return a certain attribute or mutated form of the element.\n *\n * @private\n * @param {string | function} criterion\n * @returns {(element: any) => any}\n */\nfunction _getExtractorFrom(criterion) {\n    if (criterion) {\n        switch (typeof criterion) {\n            case 'string': return element => element[criterion];\n            case 'function': return criterion;\n            default: throw new Error(\n                `Expected criterion of type 'string' or 'function' and got '${typeof criterion}'`\n            );\n        }\n    } else {\n        return element => element;\n    }\n}\n\nclass AlreadyDefinedPatchError extends Error {\n    constructor() {\n        super(...arguments);\n        this.name = 'AlreadyDefinedPatchError';\n    }\n}\nclass UnknownPatchError extends Error {\n    constructor() {\n        super(...arguments);\n        this.name = 'UnknownPatchError';\n    }\n}\n\nconst __escape = _.escape;\n_.escapeMethod = Symbol('html')\n_.escape = function escape(s) {\n    return s[_.escapeMethod] ? s[_.escapeMethod]() : __escape(s);\n}\n\n// notable issues:\n// * objects can't be negative in JS, so !!\"\" -> false but\n//   !!(new String) -> true, likewise markup\n// TODO (?)\n// * Markup.join / Markup#join => escapes items and returns a Markup\n// * Markup#replace => automatically escapes the replacements (difficult impl)\nclass _Markup extends String {\n    [_.escapeMethod]() {\n        return this;\n    }\n}\n// exposed for qweb2.js\nwindow._Markup = _Markup;\n\n/**\n * Returns a markup object, which acts like a String but is considered safe by\n * `_.escape`, and will therefore be injected as-is (without additional\n * escaping) in templates. Can be used to inject dynamic HTML in templates\n * (where the template itself can't), see first example.\n *\n * Can also be used as a *template tag*, in which case the literal content\n * won't be escaped but the substitutions which are not already markup objects\n * will be.\n *\n * ## WARNINGS:\n * * A markup object is a `String` (boxed) but not a `string` (primitive), they\n *   typecheck differently which can be relevant.\n * * To strip out the \"markupness\", just call `String(markup)`.\n * * Most string operations (e.g. concatenation, `String#replace`, ...) will\n *   also strip out markupness\n * * If the input is empty, returns a regular string (that way boolean tests\n *   work as expected).\n *\n * @returns a markup object\n *\n * @example regular function\n * let h;\n * if (someTest) {\n *     h = Markup(_t(\"This is a <strong>success</strong>\"));\n * } else {\n *     h = Markup(_t(\"Things did <strong>not</strong> work out\"));\n * }\n * qweb.render(\"some_template\", { message: h });\n *\n * @example template tag\n * const escaped = \"<some> text\";\n * const asis = Markup`some <b>text</b>`;\n * const h = Markup`Regular strings get ${escaped} but markup is injected ${asis}`;\n */\nfunction Markup(v, ...exprs) {\n    if (!(v instanceof Array)) {\n        return v ? new _Markup(v) : '';\n    }\n    const elements = [];\n    let i = 0;\n    for(; i < exprs.length; ++i) {\n        elements.push(v[i], _.escape(exprs[i]));\n    }\n    elements.push(v[i]);\n\n    const s = elements.join('');\n    if (!s) { return '' }\n    return new _Markup(s);\n}\n\nvar utils = Object.assign({\n    AlreadyDefinedPatchError,\n    UnknownPatchError,\n    Markup,\n\n    /**\n     * Throws an error if the given condition is not true\n     *\n     * @param {any} bool\n     */\n    assert: function (bool) {\n        if (!bool) {\n            throw new Error(\"AssertionError\");\n        }\n    },\n    /**\n     * Check if the value is a bin_size or not.\n     * If not, compute an approximate size out of the base64 encoded string.\n     *\n     * @param  {string} value original format\n     * @return {string} bin_size (human-readable)\n     */\n    binaryToBinsize: function (value) {\n        if (!this.is_bin_size(value)) {\n            // Computing approximate size out of base64 encoded string\n            // http://en.wikipedia.org/wiki/Base64#MIME\n            return this.human_size(value.length / 1.37);\n        }\n        // already bin_size\n        return value;\n    },\n    /**\n     * Confines a value inside an interval\n     *\n     * @param {number} [val] the value to confine\n     * @param {number} [min] the minimum of the interval\n     * @param {number} [max] the maximum of the interval\n     * @return {number} val if val is in [min, max], min if val < min and max\n     *   otherwise\n     */\n    confine: function (val, min, max) {\n        return Math.max(min, Math.min(max, val));\n    },\n    /**\n     * Looks through the list and returns the first value that matches all\n     * of the key-value pairs listed in properties.\n     * If no match is found, or if list is empty, undefined will be returned.\n     *\n     * @param {Array} list\n     * @param {Object} props\n     * @returns {any|undefined} first element in list that matches all props\n     */\n    findWhere: function (list, props) {\n        if (!Array.isArray(list) || !props) {\n            return;\n        }\n        return list.filter((item) => item !== undefined).find((item) => {\n            return Object.keys(props).every((key) => {\n                return item[key] === props[key];\n            })\n        });\n    },\n    /**\n     * @param {number} value\n     * @param {integer} decimals\n     * @returns {boolean}\n     */\n    float_is_zero: function (value, decimals) {\n        var epsilon = Math.pow(10, -decimals);\n        return Math.abs(utils.round_precision(value, epsilon)) < epsilon;\n    },\n    /**\n     * Generate a unique numerical ID\n     *\n     * @returns {integer}\n     */\n    generateID: function () {\n        return ++id;\n    },\n    /**\n     * Gets dataURL (base64 data) from the given file or blob.\n     * Technically wraps FileReader.readAsDataURL in Promise.\n     *\n     * @param {Blob|File} file\n     * @returns {Promise} resolved with the dataURL, or rejected if the file is\n     *  empty or if an error occurs.\n     */\n    getDataURLFromFile: function (file) {\n        if (!file) {\n            return Promise.reject();\n        }\n        return new Promise(function (resolve, reject) {\n            var reader = new FileReader();\n            reader.addEventListener('load', function () {\n                resolve(reader.result);\n            });\n            reader.addEventListener('abort', reject);\n            reader.addEventListener('error', reject);\n            reader.readAsDataURL(file);\n        });\n    },\n    /**\n     * Returns an object holding different groups defined by a given criterion\n     * or a default one. Each group is a subset of the original given list.\n     * The given criterion can either be:\n     * - a string: a property name on the list elements which value will be the\n     * group name,\n     * - a function: a handler that will return the group name from a given\n     * element.\n     *\n     * @param {any[]} list\n     * @param {string | function} [criterion]\n     * @returns {Object}\n     */\n    groupBy: function (list, criterion) {\n        const extract = _getExtractorFrom(criterion);\n        const groups = {};\n        for (const element of list) {\n            const group = String(extract(element));\n            if (!(group in groups)) {\n                groups[group] = [];\n            }\n            groups[group].push(element);\n        }\n        return groups;\n    },\n    /**\n     * Returns a human readable number (e.g. 34000 -> 34k).\n     *\n     * @param {number} number\n     * @param {integer} [decimals=0]\n     *        maximum number of decimals to use in human readable representation\n     * @param {integer} [minDigits=1]\n     *        the minimum number of digits to preserve when switching to another\n     *        level of thousands (e.g. with a value of '2', 4321 will still be\n     *        represented as 4321 otherwise it will be down to one digit (4k))\n     * @param {function} [formatterCallback]\n     *        a callback to transform the final number before adding the\n     *        thousands symbol (default to adding thousands separators (useful\n     *        if minDigits > 1))\n     * @returns {string}\n     */\n    human_number: function (number, decimals, minDigits, formatterCallback) {\n        number = Math.round(number);\n        decimals = decimals | 0;\n        minDigits = minDigits || 1;\n        formatterCallback = formatterCallback || utils.insert_thousand_seps;\n\n        var d2 = Math.pow(10, decimals);\n        var val = _t('kMGTPE');\n        var symbol = '';\n        var numberMagnitude = number.toExponential().split('e')[1];\n        // the case numberMagnitude >= 21 corresponds to a number\n        // better expressed in the scientific format.\n        if (numberMagnitude >= 21) {\n            // we do not use number.toExponential(decimals) because we want to\n            // avoid the possible useless O decimals: 1e.+24 preferred to 1.0e+24\n            number = Math.round(number * Math.pow(10, decimals - numberMagnitude)) / d2;\n            // formatterCallback seems useless here.\n            return number + 'e' + numberMagnitude;\n        }\n        var sign = Math.sign(number);\n        number = Math.abs(number);\n        for (var i = val.length; i > 0 ; i--) {\n            var s = Math.pow(10, i * 3);\n            if (s <= number / Math.pow(10, minDigits - 1)) {\n                number = Math.round(number * d2 / s) / d2;\n                symbol = val[i - 1];\n                break;\n            }\n        }\n        number = sign * number;\n        return formatterCallback('' + number) + symbol;\n    },\n    /**\n     * Returns a human readable size\n     *\n     * @param {Number} size number of bytes\n     */\n    human_size: function (size) {\n        var units = _t(\"Bytes|Kb|Mb|Gb|Tb|Pb|Eb|Zb|Yb\").split('|');\n        var i = 0;\n        while (size >= 1024) {\n            size /= 1024;\n            ++i;\n        }\n        return size.toFixed(2) + ' ' + units[i].trim();\n    },\n    /**\n     * Insert \"thousands\" separators in the provided number (which is actually\n     * a string)\n     *\n     * @param {String} num\n     * @returns {String}\n     */\n    insert_thousand_seps: function (num) {\n        var negative = num[0] === '-';\n        num = (negative ? num.slice(1) : num);\n        return (negative ? '-' : '') + utils.intersperse(\n            num, _t.database.parameters.grouping, _t.database.parameters.thousands_sep);\n    },\n    /**\n     * Intersperses ``separator`` in ``str`` at the positions indicated by\n     * ``indices``.\n     *\n     * ``indices`` is an array of relative offsets (from the previous insertion\n     * position, starting from the end of the string) at which to insert\n     * ``separator``.\n     *\n     * There are two special values:\n     *\n     * ``-1``\n     *   indicates the insertion should end now\n     * ``0``\n     *   indicates that the previous section pattern should be repeated (until all\n     *   of ``str`` is consumed)\n     *\n     * @param {String} str\n     * @param {Array<Number>} indices\n     * @param {String} separator\n     * @returns {String}\n     */\n    intersperse: function (str, indices, separator) {\n        separator = separator || '';\n        var result = [], last = str.length;\n\n        for(var i=0; i<indices.length; ++i) {\n            var section = indices[i];\n            if (section === -1 || last <= 0) {\n                // Done with string, or -1 (stops formatting string)\n                break;\n            } else if(section === 0 && i === 0) {\n                // repeats previous section, which there is none => stop\n                break;\n            } else if (section === 0) {\n                // repeat previous section forever\n                //noinspection AssignmentToForLoopParameterJS\n                section = indices[--i];\n            }\n            result.push(str.substring(last-section, last));\n            last -= section;\n        }\n\n        var s = str.substring(0, last);\n        if (s) { result.push(s); }\n        return result.reverse().join(separator);\n    },\n    /**\n     * @param {any} object\n     * @param {any} path\n     * @returns\n     */\n    into: function (object, path) {\n        if (!_(path).isArray()) {\n            path = path.split('.');\n        }\n        for (var i = 0; i < path.length; i++) {\n            object = object[path[i]];\n        }\n        return object;\n    },\n    /**\n     * @param {string} v\n     * @returns {boolean}\n     */\n    is_bin_size: function (v) {\n        return (/^\\d+(\\.\\d*)? [^0-9]+$/).test(v);\n    },\n    /**\n     * Checks if a class is an extension of owl.Component.\n     *\n     * @param {any} value A class reference\n     */\n    isComponent: function (value) {\n        return value.prototype instanceof owl.Component;\n    },\n    /**\n     * Checks if a keyboard event concerns\n     * the numpad decimal separator key.\n     *\n     * Some countries may emit a comma instead\n     * of a period when this key get pressed.\n     * More info: https://www.iso.org/schema/isosts/v1.0/doc/n-cdf0.html\n     *\n     * @param {KeyboardEvent} ev\n     * @returns {boolean}\n     */\n    isNumpadDecimalSeparatorKey(ev) {\n        return ['.', ','].includes(ev.key) && ev.code === 'NumpadDecimal';\n    },\n    /**\n     * Returns whether the given anchor is valid.\n     *\n     * This test is useful to prevent a crash that would happen if using an invalid\n     * anchor as a selector.\n     *\n     * @param {string} anchor\n     * @returns {boolean}\n     */\n    isValidAnchor: function (anchor) {\n        return /^#[\\w-]+$/.test(anchor);\n    },\n    /**\n     * @param {any} node\n     * @param {any} human_readable\n     * @param {any} indent\n     * @returns {string}\n     */\n    json_node_to_xml: function (node, human_readable, indent) {\n        // For debugging purpose, this function will convert a json node back to xml\n        indent = indent || 0;\n        var sindent = (human_readable ? (new Array(indent + 1).join('\\t')) : ''),\n            r = sindent + '<' + node.tag,\n            cr = human_readable ? '\\n' : '';\n\n        if (typeof(node) === 'string') {\n            return sindent + node.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/\"/g, '&quot;');\n        } else if (typeof(node.tag) !== 'string' || !node.children instanceof Array || !node.attrs instanceof Object) {\n            throw new Error(\n                _.str.sprintf(_t(\"Node [%s] is not a JSONified XML node\"),\n                            JSON.stringify(node)));\n        }\n        for (var attr in node.attrs) {\n            var vattr = node.attrs[attr];\n            if (typeof(vattr) !== 'string') {\n                // domains, ...\n                vattr = JSON.stringify(vattr);\n            }\n            vattr = vattr.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/\"/g, '&quot;');\n            if (human_readable) {\n                vattr = vattr.replace(/&quot;/g, \"'\");\n            }\n            r += ' ' + attr + '=\"' + vattr + '\"';\n        }\n        if (node.children && node.children.length) {\n            r += '>' + cr;\n            var childs = [];\n            for (var i = 0, ii = node.children.length; i < ii; i++) {\n                childs.push(utils.json_node_to_xml(node.children[i], human_readable, indent + 1));\n            }\n            r += childs.join(cr);\n            r += cr + sindent + '</' + node.tag + '>';\n            return r;\n        } else {\n            return r + '/>';\n        }\n    },\n    /**\n     * Left-pad provided arg 1 with zeroes until reaching size provided by second\n     * argument.\n     *\n     * @see rpad\n     *\n     * @param {number|string} str value to pad\n     * @param {number} size size to reach on the final padded value\n     * @returns {string} padded string\n     */\n    lpad: function (str, size) {\n        str = \"\" + str;\n        return new Array(size - str.length + 1).join('0') + str;\n    },\n    /**\n     * @param {any[]} arr\n     * @param {Function} fn\n     * @returns {any[]}\n     */\n    partitionBy(arr, fn) {\n        let lastGroup = false;\n        let lastValue;\n        return arr.reduce((acc, cur) => {\n            let curVal = fn(cur);\n            if (lastGroup) {\n                if (curVal === lastValue) {\n                    lastGroup.push(cur);\n                } else {\n                    lastGroup = false;\n                }\n            }\n            if (!lastGroup) {\n                lastGroup = [cur];\n                acc.push(lastGroup);\n            }\n            lastValue = curVal;\n            return acc;\n        }, []);\n    },\n    /**\n     * Patch an object and return a function that remove the patch\n     * when called.\n     *\n     * @param {Object} obj Object to patch\n     * @param {string} patchName\n     * @param {Object} patch\n     */\n    patch: function (obj, patchName, patch) {\n        if (!patchMap.has(obj)) {\n            patchMap.set(obj, {\n                original: {},\n                patches: [],\n            });\n        }\n        const objDesc = patchMap.get(obj);\n        if (objDesc.patches.some(p => p.name === patchName)) {\n            throw new AlreadyDefinedPatchError(`Patch ${patchName} is already defined`);\n        }\n        objDesc.patches.push({\n            name: patchName,\n            patch,\n        });\n\n        for (const k in patch) {\n            let prevDesc = null;\n            let proto = obj;\n            do {\n                prevDesc = Object.getOwnPropertyDescriptor(proto, k);\n                proto = Object.getPrototypeOf(proto);\n            } while (!prevDesc && proto);\n\n            const newDesc = Object.getOwnPropertyDescriptor(patch, k);\n            if (!objDesc.original.hasOwnProperty(k)) {\n                objDesc.original[k] = Object.getOwnPropertyDescriptor(obj, k);\n            }\n\n            if (prevDesc) {\n                const patchedFnName = `${k} (patch ${patchName})`;\n\n                if (prevDesc.value && typeof newDesc.value === \"function\") {\n                    makeIntermediateFunction(\"value\", prevDesc, newDesc, patchedFnName);\n                }\n                if (prevDesc.get || prevDesc.set) {\n                    // get and set are defined together. If they are both defined\n                    // in the previous descriptor but only one in the new descriptor\n                    // then the other will be undefined so we need to apply the\n                    // previous descriptor in the new one.\n                    newDesc.get = newDesc.get || prevDesc.get;\n                    newDesc.set = newDesc.set || prevDesc.set;\n                    if (prevDesc.get && typeof newDesc.get === \"function\") {\n                        makeIntermediateFunction(\"get\", prevDesc, newDesc, patchedFnName);\n                    }\n                    if (prevDesc.set && typeof newDesc.set === \"function\") {\n                        makeIntermediateFunction(\"set\", prevDesc, newDesc, patchedFnName);\n                    }\n                }\n            }\n\n            Object.defineProperty(obj, k, newDesc);\n        }\n\n        function makeIntermediateFunction(key, prevDesc, newDesc, patchedFnName) {\n            const _superFn = prevDesc[key];\n            const patchFn = newDesc[key];\n            newDesc[key] = {\n                [patchedFnName](...args) {\n                    const prevSuper = this._super;\n                    this._super = _superFn.bind(this);\n                    const result = patchFn.call(this, ...args);\n                    this._super = prevSuper;\n                    return result;\n                }\n            }[patchedFnName];\n        }\n    },\n    /**\n     * performs a half up rounding with a fixed amount of decimals, correcting for float loss of precision\n     * See the corresponding float_round() in server/tools/float_utils.py for more info\n     * @param {Number} value the value to be rounded\n     * @param {Number} decimals the number of decimals. eg: round_decimals(3.141592,2) -> 3.14\n     */\n    round_decimals: function (value, decimals) {\n        /**\n         * The following decimals introduce numerical errors:\n         * Math.pow(10, -4) = 0.00009999999999999999\n         * Math.pow(10, -5) = 0.000009999999999999999\n         *\n         * Such errors will propagate in round_precision and lead to inconsistencies between Python\n         * and JavaScript. To avoid this, we parse the scientific notation.\n         */\n        return utils.round_precision(value, parseFloat('1e' + -decimals));\n    },\n    /**\n     * performs a half up rounding with arbitrary precision, correcting for float loss of precision\n     * See the corresponding float_round() in server/tools/float_utils.py for more info\n     *\n     * @param {number} value the value to be rounded\n     * @param {number} precision a precision parameter. eg: 0.01 rounds to two digits.\n     */\n    round_precision: function (value, precision) {\n        if (!value) {\n            return 0;\n        } else if (!precision || precision < 0) {\n            precision = 1;\n        }\n        var normalized_value = value / precision;\n        var epsilon_magnitude = Math.log(Math.abs(normalized_value))/Math.log(2);\n        var epsilon = Math.pow(2, epsilon_magnitude - 52);\n        normalized_value += normalized_value >= 0 ? epsilon : -epsilon;\n\n        /**\n         * Javascript performs strictly the round half up method, which is asymmetric. However, in\n         * Python, the method is symmetric. For example:\n         * - In JS, Math.round(-0.5) is equal to -0.\n         * - In Python, round(-0.5) is equal to -1.\n         * We want to keep the Python behavior for consistency.\n         */\n        var sign = normalized_value < 0 ? -1.0 : 1.0;\n        var rounded_value = sign * Math.round(Math.abs(normalized_value));\n        return rounded_value * precision;\n    },\n    /**\n     * @see lpad\n     *\n     * @param {string} str\n     * @param {number} size\n     * @returns {string}\n     */\n    rpad: function (str, size) {\n        str = \"\" + str;\n        return str + new Array(size - str.length + 1).join('0');\n    },\n    /**\n     * Return a shallow copy of a given array sorted by a given criterion or a default one.\n     * The given criterion can either be:\n     * - a string: a property name on the array elements returning the sortable primitive\n     * - a function: a handler that will return the sortable primitive from a given element.\n     *\n     * @param {any[]} array\n     * @param {string | function} [criterion]\n     * @param {('asc' | 'desc')} [order='asc'] sort by ascending if order is 'asc' else descending\n     */\n    sortBy: function (array, criterion, order = 'asc') {\n        const extract = _getExtractorFrom(criterion);\n        return array.slice().sort((elA, elB) => {\n            const a = extract(elA);\n            const b = extract(elB);\n            let result;\n            if (isNaN(a) && isNaN(b)) {\n                result = a > b ? 1 : a < b ? -1 : 0;\n            } else {\n                result = a - b;\n            }\n            return order === 'asc' ? result : -result;\n        });\n    },\n    /**\n     * Returns a string formatted using given values.\n     *\n     * If the value is an object, its keys will replace `%(key)s` expressions.\n     * If the values are a set of strings, they will replace `%s` expressions.\n     * If no value is given, the string will not be formatted.\n     *\n     * `Markup`-aware: if a `Markup` object is provided as format string,\n     * automatically escapes injected values and returns a new `Markup`\n     * object.\n     *\n     * @param {string|Markup} string format string\n     * @param values values injected into the format string, can be either a\n     *               sequence of positional parameters (for positional\n     *               placeholders) or a single Object acting a as map (for named\n     *               placeholders).\n     * @returns {string|Markup}\n     */\n    sprintf(string, ...values) {\n        let finalizer, mapper;\n        finalizer = mapper = a => a;\n        if (string instanceof _Markup) {\n            string = String(string);\n            finalizer = Markup;\n            mapper = _.escape;\n        }\n        if (values.length === 1 && typeof values[0] === 'object') {\n            const valuesDict = values[0];\n            string = string.replace(\n                /%\\((\\w+)\\)s/g,\n                (_, group) => mapper(valuesDict[group]));\n        } else {\n            let i = 0;\n            string = string.replace(/%s/g, () => mapper(values[i++]));\n        }\n        return finalizer(string);\n    },\n    /**\n     * Sort an array in place, keeping the initial order for identical values.\n     *\n     * @param {Array} array\n     * @param {function} iteratee\n     */\n    stableSort: function (array, iteratee) {\n        var stable = array.slice();\n        return array.sort(function stableCompare (a, b) {\n            var order = iteratee(a, b);\n            if (order !== 0) {\n                return order;\n            } else {\n                return stable.indexOf(a) - stable.indexOf(b);\n            }\n        });\n    },\n    /**\n     * @param {any} array\n     * @param {any} elem1\n     * @param {any} elem2\n     */\n    swap: function (array, elem1, elem2) {\n        var i1 = array.indexOf(elem1);\n        var i2 = array.indexOf(elem2);\n        array[i2] = elem1;\n        array[i1] = elem2;\n    },\n\n    /**\n     * @param {string} value\n     * @param {boolean} allow_mailto\n     * @returns boolean\n     */\n    is_email: function (value, allow_mailto) {\n        // http://stackoverflow.com/questions/46155/validate-email-address-in-javascript\n        var re;\n        if (allow_mailto) {\n            re = /^(mailto:)?(([^<>()\\[\\]\\.,;:\\s@\\\"]+(\\.[^<>()\\[\\]\\.,;:\\s@\\\"]+)*)|(\\\".+\\\"))@(([^<>()[\\]\\.,;:\\s@\\\"]+\\.)+[^<>()[\\]\\.,;:\\s@\\\"]{2,})$/i;\n        } else {\n            re = /^(([^<>()\\[\\]\\.,;:\\s@\\\"]+(\\.[^<>()\\[\\]\\.,;:\\s@\\\"]+)*)|(\\\".+\\\"))@(([^<>()[\\]\\.,;:\\s@\\\"]+\\.)+[^<>()[\\]\\.,;:\\s@\\\"]{2,})$/i;\n        }\n        return re.test(value);\n    },\n\n    /**\n     * @param {any} str\n     * @param {any} elseValues\n     * @param {any} trueValues\n     * @param {any} falseValues\n     * @returns\n     */\n    toBoolElse: function (str, elseValues, trueValues, falseValues) {\n        var ret = _.str.toBool(str, trueValues, falseValues);\n        if (_.isUndefined(ret)) {\n            return elseValues;\n        }\n        return ret;\n    },\n    /**\n     * @todo: is this really the correct place?\n     *\n     * @param {any} data\n     * @param {any} f\n     */\n    traverse_records: function (data, f) {\n        if (data.type === 'record') {\n            f(data);\n        } else if (data.data) {\n            for (var i = 0; i < data.data.length; i++) {\n                utils.traverse_records(data.data[i], f);\n            }\n        }\n    },\n    /**\n     * Replace diacritics character with ASCII character\n     *\n     * @param {string} str diacritics string\n     * @param {boolean} casesensetive\n     * @returns {string} ASCII string\n     */\n    unaccent: function (str, casesensetive) {\n        str = str.replace(/[^\\u0000-\\u007E]/g, function (accented) {\n            return diacriticsMap[accented] || accented;\n        });\n        return casesensetive ? str : str.toLowerCase();\n    },\n    /**\n     * We define here an unpatch function.  This is mostly useful if we want to\n     * remove a patch.  For example, for testing purposes\n     *\n     * @param {Object} obj\n     * @param {string} patchName\n     * @returns {Object} the removed patch\n     */\n    unpatch: function (obj, patchName) {\n        const objDesc = patchMap.get(obj);\n        if (!objDesc || !objDesc.patches.some(p => p.name === patchName)) {\n            throw new UnknownPatchError(`Could not find patch ${patchName}`);\n        }\n        patchMap.delete(obj);\n\n        // Restore original methods on the prototype and the class.\n        for (const k in objDesc.original) {\n            if (objDesc.original[k] === undefined) {\n                delete obj[k];\n            } else {\n                Object.defineProperty(obj, k, objDesc.original[k]);\n            }\n        }\n\n        // Re-apply the patches except the one to remove.\n        let removedPatch;\n        for (const patchDesc of objDesc.patches) {\n            if (patchDesc.name !== patchName) {\n                utils.patch(obj, patchDesc.name, patchDesc.patch);\n            } else {\n                removedPatch = patchDesc.patch;\n            }\n        }\n\n        return removedPatch;\n    },\n    /**\n     * @param {any} node\n     * @param {any} strip_whitespace\n     * @returns\n     */\n    xml_to_json: function (node, strip_whitespace) {\n        switch (node.nodeType) {\n            case 9:\n                return utils.xml_to_json(node.documentElement, strip_whitespace);\n            case 3:\n            case 4:\n                return (strip_whitespace && node.data.trim() === '') ? undefined : node.data;\n            case 1:\n                var attrs = $(node).getAttributes();\n                return {\n                    tag: node.tagName.toLowerCase(),\n                    attrs: attrs,\n                    children: _.compact(_.map(node.childNodes, function (node) {\n                        return utils.xml_to_json(node, strip_whitespace);\n                    })),\n                };\n        }\n    },\n    /**\n     * @param {any} node\n     * @returns {string}\n     */\n    xml_to_str: function (node) {\n        var str = \"\";\n        if (window.XMLSerializer) {\n            str = (new XMLSerializer()).serializeToString(node);\n        } else if (window.ActiveXObject) {\n            str = node.xml;\n        } else {\n            throw new Error(_t(\"Could not serialize XML\"));\n        }\n        // Browsers won't deal with self closing tags except void elements:\n        // http://www.w3.org/TR/html-markup/syntax.html\n        var void_elements = 'area base br col command embed hr img input keygen link meta param source track wbr'.split(' ');\n\n        // The following regex is a bit naive but it's ok for the xmlserializer output\n        str = str.replace(/<([a-z]+)([^<>]*)\\s*\\/\\s*>/g, function (match, tag, attrs) {\n            if (void_elements.indexOf(tag) < 0) {\n                return \"<\" + tag + attrs + \"></\" + tag + \">\";\n            } else {\n                return match;\n            }\n        });\n        return str;\n    },\n    /**\n     * Visit a tree of objects, where each children are in an attribute 'children'.\n     * For each children, we call the callback function given in arguments.\n     *\n     * @param {Object} tree an object describing a tree structure\n     * @param {function} f a callback\n     */\n    traverse: function (tree, f) {\n        if (f(tree)) {\n            _.each(tree.children, function (c) { utils.traverse(c, f); });\n        }\n    },\n    /**\n     * Enhanced traverse function with 'path' building on traverse.\n     *\n     * @param {Object} tree an object describing a tree structure\n     * @param {function} f a callback\n     * @param {Object} path the path to the current 'tree' object\n     */\n    traversePath: function (tree, f, path) {\n        path = path || [];\n        f(tree, path);\n        _.each(tree.children, function (node) {\n            utils.traversePath(node, f, path.concat(tree));\n        });\n    },\n    /**\n     * Visit a tree of objects and freeze all\n     *\n     * @param {Object} obj\n     */\n    deepFreeze: function (obj) {\n      var propNames = Object.getOwnPropertyNames(obj);\n      propNames.forEach(function(name) {\n        var prop = obj[name];\n        if (typeof prop == 'object' && prop !== null)\n          utils.deepFreeze(prop);\n      });\n      return Object.freeze(obj);\n    },\n\n    /**\n     * Find the closest value of the given one in the provided array\n     *\n     * @param {Number} num\n     * @param {Array} arr\n     * @returns {Number|undefined}\n     */\n    closestNumber: function (num, arr) {\n        var curr = arr[0];\n        var diff = Math.abs (num - curr);\n        for (var val = 0; val < arr.length; val++) {\n            var newdiff = Math.abs (num - arr[val]);\n            if (newdiff < diff) {\n                diff = newdiff;\n                curr = arr[val];\n            }\n        }\n        return curr;\n    },\n    /**\n     * Returns the domain targeting assets files.\n     *\n     * @returns {Array} Domain of assets files\n     */\n    assetsDomain: function () {\n        return [\n            '&',\n            ['res_model', '=', 'ir.ui.view'],\n            '|',\n            '|',\n            ['name', '=like', '%.assets\\_%.css'],\n            ['name', '=like', '%.assets\\_%.js'],\n            ['name', '=like', '%.report_assets\\_%.css'],\n        ];\n    },\n}, cookieUtils);\n\nreturn utils;\n\n});\n", "odoo.define('web.Widget', function (require) {\n\"use strict\";\n\nvar ajax = require('web.ajax');\nvar core = require('web.core');\nvar mixins = require('web.mixins');\nvar ServicesMixin = require('web.ServicesMixin');\n\n/**\n * Base class for all visual components. Provides a lot of functions helpful\n * for the management of a part of the DOM.\n *\n * Widget handles:\n *\n * - Rendering with QWeb.\n * - Life-cycle management and parenting (when a parent is destroyed, all its\n *   children are destroyed too).\n * - Insertion in DOM.\n *\n * **Guide to create implementations of the Widget class**\n *\n * Here is a sample child class::\n *\n *     var MyWidget = Widget.extend({\n *         // the name of the QWeb template to use for rendering\n *         template: \"MyQWebTemplate\",\n *\n *         init: function (parent) {\n *             this._super(parent);\n *             // stuff that you want to init before the rendering\n *         },\n *         willStart: function () {\n *             // async work that need to be done before the widget is ready\n *             // this method should return a promise\n *         },\n *         start: function() {\n *             // stuff you want to make after the rendering, `this.$el` holds a correct value\n *             this.$(\".my_button\").click(/* an example of event binding * /);\n *\n *             // if you have some asynchronous operations, it's a good idea to return\n *             // a promise in start(). Note that this is quite rare, and if you\n *             // need to fetch some data, this should probably be done in the\n *             // willStart method\n *             var promise = this._rpc(...);\n *             return promise;\n *         }\n *     });\n *\n * Now this class can simply be used with the following syntax::\n *\n *     var myWidget = new MyWidget(this);\n *     myWidget.appendTo($(\".some-div\"));\n *\n * With these two lines, the MyWidget instance was initialized, rendered,\n * inserted into the DOM inside the ``.some-div`` div and its events were\n * bound.\n *\n * And of course, when you don't need that widget anymore, just do::\n *\n *     myWidget.destroy();\n *\n * That will kill the widget in a clean way and erase its content from the dom.\n */\n\nvar Widget = core.Class.extend(mixins.PropertiesMixin, ServicesMixin, {\n    // Backbone-ish API\n    tagName: 'div',\n    id: null,\n    className: null,\n    attributes: {},\n    events: {},\n    /**\n     * The name of the QWeb template that will be used for rendering. Must be\n     * redefined in subclasses or the default render() method can not be used.\n     *\n     * @type {null|string}\n     */\n    template: null,\n    /**\n     * List of paths to xml files that need to be loaded before the widget can\n     * be rendered. This will not induce loading anything that has already been\n     * loaded.\n     *\n     * @type {null|string[]}\n     */\n    xmlDependencies: null,\n    /**\n     * List of paths to css files that need to be loaded before the widget can\n     * be rendered. This will not induce loading anything that has already been\n     * loaded.\n     *\n     * @type {null|string[]}\n     */\n    cssLibs: null,\n    /**\n     * List of paths to js files that need to be loaded before the widget can\n     * be rendered. This will not induce loading anything that has already been\n     * loaded.\n     *\n     * @type {null|string[]}\n     */\n    jsLibs: null,\n    /**\n     * List of xmlID that need to be loaded before the widget can be rendered.\n     * The content css (link file or style tag) and js (file or inline) of the\n     * assets are loaded.\n     * This will not induce loading anything that has already been\n     * loaded.\n     *\n     * @type {null|string[]}\n     */\n    assetLibs: null,\n\n    /**\n     * Constructs the widget and sets its parent if a parent is given.\n     *\n     * @param {Widget|null} parent Binds the current instance to the given Widget\n     *   instance. When that widget is destroyed by calling destroy(), the\n     *   current instance will be destroyed too. Can be null.\n     */\n    init: function (parent) {\n        mixins.PropertiesMixin.init.call(this);\n        this.setParent(parent);\n        // Bind on_/do_* methods to this\n        // We might remove this automatic binding in the future\n        for (var name in this) {\n            if(typeof(this[name]) === \"function\") {\n                if((/^on_|^do_/).test(name)) {\n                    this[name] = this[name].bind(this);\n                }\n            }\n        }\n    },\n    /**\n     * Method called between @see init and @see start. Performs asynchronous\n     * calls required by the rendering and the start method.\n     *\n     * This method should return a Promose which is resolved when start can be\n     * executed.\n     *\n     * @returns {Promise}\n     */\n    willStart: function () {\n        var proms = [];\n        if (this.xmlDependencies) {\n            proms.push.apply(proms, _.map(this.xmlDependencies, function (xmlPath) {\n                return ajax.loadXML(xmlPath, core.qweb);\n            }));\n        }\n        if (this.jsLibs || this.cssLibs || this.assetLibs) {\n            proms.push(this._loadLibs(this));\n        }\n        return Promise.all(proms);\n    },\n    /**\n     * Method called after rendering. Mostly used to bind actions, perform\n     * asynchronous calls, etc...\n     *\n     * By convention, this method should return an object that can be passed to\n     * Promise.resolve() to inform the caller when this widget has been initialized.\n     *\n     * Note that, for historic reasons, many widgets still do work in the start\n     * method that would be more suited to the willStart method.\n     *\n     * @returns {Promise}\n     */\n    start: function () {\n        return Promise.resolve();\n    },\n    /**\n     * Destroys the current widget, also destroys all its children before\n     * destroying itself.\n     */\n    destroy: function () {\n        mixins.PropertiesMixin.destroy.call(this);\n        if (this.$el) {\n            this.$el.remove();\n        }\n    },\n\n    //--------------------------------------------------------------------------\n    // Public\n    //--------------------------------------------------------------------------\n\n    /**\n     * Renders the current widget and appends it to the given jQuery object.\n     *\n     * @param {jQuery} target\n     * @returns {Promise}\n     */\n    appendTo: function (target) {\n        var self = this;\n        return this._widgetRenderAndInsert(function (t) {\n            self.$el.appendTo(t);\n        }, target);\n    },\n    /**\n     * Attach the current widget to a dom element\n     *\n     * @param {jQuery} target\n     * @returns {Promise}\n     */\n    attachTo: function (target) {\n        var self = this;\n        this.setElement(target.$el || target);\n        return this.willStart().then(function () {\n            if (self.__parentedDestroyed) {\n                return;\n            }\n            return self.start();\n        });\n    },\n    /**\n     * Hides the widget\n     */\n    do_hide: function () {\n        if (this.$el) {\n            this.$el.addClass('o_hidden');\n        }\n    },\n    /**\n     * Displays the widget\n     */\n    do_show: function () {\n        if (this.$el) {\n            this.$el.removeClass('o_hidden');\n        }\n    },\n    /**\n     * Displays or hides the widget\n     * @param {boolean} [display] use true to show the widget or false to hide it\n     */\n    do_toggle: function (display) {\n        if (_.isBoolean(display)) {\n            display ? this.do_show() : this.do_hide();\n        } else if (this.$el) {\n            this.$el.hasClass('o_hidden') ? this.do_show() : this.do_hide();\n        }\n    },\n    /**\n     * Renders the current widget and inserts it after to the given jQuery\n     * object.\n     *\n     * @param {jQuery} target\n     * @returns {Promise}\n     */\n    insertAfter: function (target) {\n        var self = this;\n        return this._widgetRenderAndInsert(function (t) {\n            self.$el.insertAfter(t);\n        }, target);\n    },\n    /**\n     * Renders the current widget and inserts it before to the given jQuery\n     * object.\n     *\n     * @param {jQuery} target\n     * @returns {Promise}\n     */\n    insertBefore: function (target) {\n        var self = this;\n        return this._widgetRenderAndInsert(function (t) {\n            self.$el.insertBefore(t);\n        }, target);\n    },\n    /**\n     * Renders the current widget and prepends it to the given jQuery object.\n     *\n     * @param {jQuery} target\n     * @returns {Promise}\n     */\n    prependTo: function (target) {\n        var self = this;\n        return this._widgetRenderAndInsert(function (t) {\n            self.$el.prependTo(t);\n        }, target);\n    },\n    /**\n     * Renders the element. The default implementation renders the widget using\n     * QWeb, `this.template` must be defined. The context given to QWeb contains\n     * the \"widget\" key that references `this`.\n     */\n    renderElement: function () {\n        var $el;\n        if (this.template) {\n            $el = $(core.qweb.render(this.template, {widget: this}).trim());\n        } else {\n            $el = this._makeDescriptive();\n        }\n        this._replaceElement($el);\n    },\n    /**\n     * Renders the current widget and replaces the given jQuery object.\n     *\n     * @param target A jQuery object or a Widget instance.\n     * @returns {Promise}\n     */\n    replace: function (target) {\n        return this._widgetRenderAndInsert(_.bind(function (t) {\n            this.$el.replaceAll(t);\n        }, this), target);\n    },\n    /**\n     * Re-sets the widget's root element (el/$el/$el).\n     *\n     * Includes:\n     *\n     * * re-delegating events\n     * * re-binding sub-elements\n     * * if the widget already had a root element, replacing the pre-existing\n     *   element in the DOM\n     *\n     * @param {HTMLElement | jQuery} element new root element for the widget\n     * @return {Widget} this\n     */\n    setElement: function (element) {\n        if (this.$el) {\n            this._undelegateEvents();\n        }\n\n        this.$el = (element instanceof $) ? element : $(element);\n        this.el = this.$el[0];\n\n        this._delegateEvents();\n\n        return this;\n    },\n\n    //--------------------------------------------------------------------------\n    // Private\n    //--------------------------------------------------------------------------\n\n    /**\n     * Helper method, for ``this.$el.find(selector)``\n     *\n     * @private\n     * @param {string} selector CSS selector, rooted in $el\n     * @returns {jQuery} selector match\n     */\n    $: function (selector) {\n        if (selector === undefined) {\n            return this.$el;\n        }\n        return this.$el.find(selector);\n    },\n    /**\n     * Attach event handlers for events described in the 'events' key\n     *\n     * @private\n     */\n    _delegateEvents: function () {\n        var events = this.events;\n        if (_.isEmpty(events)) { return; }\n\n        for(var key in events) {\n            if (!events.hasOwnProperty(key)) { continue; }\n\n            var method = this.proxy(events[key]);\n\n            var match = /^(\\S+)(\\s+(.*))?$/.exec(key);\n            var event = match[1];\n            var selector = match[3];\n\n            event += '.widget_events';\n            if (!selector) {\n                this.$el.on(event, method);\n            } else {\n                this.$el.on(event, selector, method);\n            }\n        }\n    },\n    /**\n     * Makes a potential root element from the declarative builder of the\n     * widget\n     *\n     * @private\n     * @return {jQuery}\n     */\n    _makeDescriptive: function () {\n        var attrs = _.extend({}, this.attributes || {});\n        if (this.id) {\n            attrs.id = this.id;\n        }\n        if (this.className) {\n            attrs['class'] = this.className;\n        }\n        var $el = $(document.createElement(this.tagName));\n        if (!_.isEmpty(attrs)) {\n            $el.attr(attrs);\n        }\n        return $el;\n    },\n    /**\n     * Re-sets the widget's root element and replaces the old root element\n     * (if any) by the new one in the DOM.\n     *\n     * @private\n     * @param {HTMLElement | jQuery} $el\n     * @returns {Widget} this instance, so it can be chained\n     */\n    _replaceElement: function ($el) {\n        var $oldel = this.$el;\n        this.setElement($el);\n        if ($oldel && !$oldel.is(this.$el)) {\n            if ($oldel.length > 1) {\n                $oldel.wrapAll('<div/>');\n                $oldel.parent().replaceWith(this.$el);\n            } else {\n                $oldel.replaceWith(this.$el);\n            }\n        }\n        return this;\n    },\n    /**\n     * Remove all handlers registered on this.$el\n     *\n     * @private\n     */\n    _undelegateEvents: function () {\n        this.$el.off('.widget_events');\n    },\n    /**\n     * Render the widget.  This is a private method, and should really never be\n     * called by anyone (except this widget).  It assumes that the widget was\n     * not willStarted yet.\n     *\n     * @private\n     * @param {function: jQuery -> any} insertion\n     * @param {jQuery} target\n     * @returns {Promise}\n     */\n    _widgetRenderAndInsert: function (insertion, target) {\n        var self = this;\n        return this.willStart().then(function () {\n            if (self.__parentedDestroyed) {\n                return;\n            }\n            self.renderElement();\n            insertion(target);\n            return self.start();\n        });\n    },\n});\n\nreturn Widget;\n\n});\n", "odoo.define('web.AjaxService', function (require) {\n\"use strict\";\n\nvar AbstractService = require('web.AbstractService');\nvar ajax = require('web.ajax');\nvar core = require('web.core');\nvar session = require('web.session');\n\nvar AjaxService = AbstractService.extend({\n    /**\n     * @param {Object} libs - @see ajax.loadLibs\n     * @param {Object} [context] - @see ajax.loadLibs\n     * @param {Object} [tplRoute] - @see ajax.loadLibs\n     */\n    loadLibs: function (libs, context, tplRoute) {\n        return ajax.loadLibs(libs, context, tplRoute);\n    },\n    rpc: function (route, args, options, target) {\n        var rpcPromise;\n        var promise = new Promise(function (resolve, reject) {\n            rpcPromise = session.rpc(route, args, options);\n            rpcPromise.then(function (result) {\n                if (!target.isDestroyed()) {\n                    resolve(result);\n                }\n            }).guardedCatch(function (reason) {\n                if (!target.isDestroyed()) {\n                    reject(reason);\n                }\n            });\n        });\n        promise.abort = rpcPromise.abort.bind(rpcPromise);\n        return promise;\n    },\n});\n\ncore.serviceRegistry.add('ajax', AjaxService);\n\nreturn AjaxService;\n\n});\n", "odoo.define('web.config', function (require) {\n\"use strict\";\n\nconst Bus = require('web.Bus');\nconst { hasTouch, isAndroid, isIOS, isMobileOS } = require('@web/core/browser/feature_detection');\n\nconst bus = new Bus();\n\n/**\n * This module contains all the (mostly) static 'environmental' information.\n * This is often necessary to allow the rest of the web client to properly\n * render itself.\n *\n * Note that many information currently stored in session should be moved to\n * this file someday.\n */\n\nvar config = {\n    device: {\n        /**\n        * bus to use in order to be able to handle device config related events\n        *   - 'size_changed' : triggered when window size is\n        *     corresponding to a new bootstrap breakpoint. The new size_class\n         *    is provided.\n        */\n        bus: bus,\n        /**\n         * touch is a boolean, true if the device supports touch interaction\n         *\n         * @type Boolean\n         */\n        touch: hasTouch(),\n        /**\n         * size_class is an integer: 0, 1, 2, 3 or 4, depending on the (current)\n         * size of the device.  This is a dynamic property, updated whenever the\n         * browser is resized\n         *\n         * @type Number\n         */\n        size_class: null,\n        /**\n         * Mobile OS (Android) device detection using userAgent.\n         * This flag doesn't depend on the size/resolution of the screen.\n         *\n         * @return Boolean\n         */\n        isAndroid: isAndroid(),\n        /**\n         * Mobile OS (iOS) device detection using userAgent.\n         * This flag doesn't depend on the size/resolution of the screen.\n         *\n         * @return Boolean\n         */\n        isIOS: isIOS(),\n        /**\n         * A frequent use case is to have a different render in 'mobile' mode,\n         * meaning when the screen is small.  This flag (boolean) is true when\n         * the size is XS/VSM/SM. It is also updated dynamically.\n         *\n         * @type Boolean\n         */\n        isMobile: null,\n        /**\n         * Mobile device detection using userAgent.\n         * This flag doesn't depend on the size/resolution of the screen.\n         * It targets mobile devices which suggests that there is a virtual keyboard.\n         *\n         * @return {boolean}\n         */\n        isMobileDevice: isMobileOS(),\n        /**\n         * Mapping between the numbers 0,1,2,3,4,5,6 and some descriptions\n         */\n        SIZES: { XS: 0, VSM: 1, SM: 2, MD: 3, LG: 4, XL: 5, XXL: 6 },\n    },\n    /**\n     * States whether the current environment is in debug or not.\n     *\n     * @param debugMode the debug mode to check, empty for simple debug mode\n     * @returns {boolean}\n     */\n    isDebug: function (debugMode) {\n        if (debugMode) {\n            return odoo.debug && odoo.debug.indexOf(debugMode) !== -1;\n        }\n        return odoo.debug;\n    },\n};\n\n\nvar medias = [\n    window.matchMedia('(max-width: 474px)'),\n    window.matchMedia('(min-width: 475px) and (max-width: 575px)'),\n    window.matchMedia('(min-width: 576px) and (max-width: 767px)'),\n    window.matchMedia('(min-width: 768px) and (max-width: 991px)'),\n    window.matchMedia('(min-width: 992px) and (max-width: 1199px)'),\n    window.matchMedia('(min-width: 1200px) and (max-width: 1533px)'),\n    window.matchMedia('(min-width: 1534px)'),\n];\n\n/**\n * Return the current size class\n *\n * @returns {integer} a number between 0 and 5, included\n */\nfunction _getSizeClass() {\n    for (var i = 0 ; i < medias.length ; i++) {\n        if (medias[i].matches) {\n            return i;\n        }\n    }\n}\n/**\n * Update the size dependant properties in the config object.  This method\n * should be called every time the size class changes.\n */\nfunction _updateSizeProps() {\n    var sc = _getSizeClass();\n    if (sc !== config.device.size_class) {\n        config.device.size_class = sc;\n        config.device.isMobile = config.device.size_class <= config.device.SIZES.SM;\n        config.device.bus.trigger('size_changed', config.device.size_class);\n    }\n}\n\n_.invoke(medias, 'addListener', _updateSizeProps);\n_updateSizeProps();\n\nreturn config;\n\n});\n", "odoo.define('web.core', function (require) {\n\"use strict\";\n\nvar Bus = require('web.Bus');\nvar config = require('web.config');\nvar Class = require('web.Class');\nvar QWeb = require('web.QWeb');\nvar Registry = require('web.Registry');\nvar translation = require('web.translation');\n\n/**\n * Whether the client is currently in \"debug\" mode\n *\n * @type Boolean\n */\nvar bus = new Bus();\n\n_.each('click,dblclick,keydown,keypress,keyup'.split(','), function (evtype) {\n    $('html').on(evtype, function (ev) {\n        bus.trigger(evtype, ev);\n    });\n});\n_.each('resize,scroll'.split(','), function (evtype) {\n    $(window).on(evtype, function (ev) {\n        bus.trigger(evtype, ev);\n    });\n});\n\nreturn {\n    qweb: new QWeb(config.isDebug()),\n\n    // core classes and functions\n    Class: Class,\n    bus: bus,\n    main_bus: new Bus(),\n    _t: translation._t,\n    _lt: translation._lt,\n\n    // registries\n    action_registry: new Registry(),\n    crash_registry: new Registry(),\n    serviceRegistry: new Registry(),\n    /**\n     * @type {String}\n     */\n    csrf_token: odoo.csrf_token,\n};\n\n});\n", "odoo.define('web.LocalStorageService', function (require) {\n'use strict';\n\n/**\n * This module defines a service to access the localStorage object.\n */\n\nvar AbstractStorageService = require('web.AbstractStorageService');\nvar core = require('web.core');\nvar localStorage = require('web.local_storage');\n\nvar LocalStorageService = AbstractStorageService.extend({\n    storage: localStorage,\n});\n\ncore.serviceRegistry.add('local_storage', LocalStorageService);\n\nreturn LocalStorageService;\n\n});\n", "/** @odoo-module **/\n\nimport { loadJS } from \"web.ajax\";\nimport BrowserDetection from \"web.BrowserDetection\";\nimport { _t } from \"web.core\";\n/**\n * Format the traceback of an error.  Basically, we just add the error message\n * in the traceback if necessary (Chrome already does it by default, but not\n * other browser. yay for non standard APIs)\n *\n * @param {Error} error \n * @returns {string}\n */\nexport function formatTraceback(error) {\n  const traceback = error.stack;\n  // Error.prototype.stack is non-standard.\n  // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error\n  // However, most engines provide an implementation.\n  // In particular, Chrome formats the contents of Error.stack\n  // https://v8.dev/docs/stack-trace-api#compatibility\n  const browserDetection = new BrowserDetection();\n  if (browserDetection.isBrowserChrome()) {\n      return error.stack;\n  } else {\n      return `${_t(\"Error:\")} ${error.message}\\n${error.stack}`;\n  }\n}\n\n/**\n* Returns an annotated traceback from an error. This is asynchronous because\n* it needs to fetch the sourcemaps for each script involved in the error,\n* then compute the correct file/line numbers and add the information to the\n* correct line.\n* \n* @param {Error} error \n* @returns {Promise<string>}\n*/\nexport async function annotateTraceback(error) {\n  const traceback = formatTraceback(error);\n  await loadJS('/web/static/lib/stacktracejs/stacktrace.js');\n  // In Firefox, the error stack generated by anonymous code (example: invalid\n  // code in a template) is not compatible with the stacktrace lib. This code\n  // corrects the stack to make it compatible with the lib stacktrace.\n  if (error.stack) {\n    const regex = / line (\\d*) > (Function):(\\d*)/gm;\n    const subst = `:$1`;\n    error.stack = error.stack.replace(regex, subst);\n  }\n  // eslint-disable-next-line no-undef\n  const frames = await StackTrace.fromError(error);\n  const lines = traceback.split('\\n');\n  if (lines[lines.length-1].trim() === \"\") {\n      // firefox traceback have an empty line at the end\n      lines.splice(-1);\n  }\n\n  // Chrome stacks contains some lines with (index 0) which apparently\n  // corresponds to some native functions (at least Promise.all). We need to\n  // ignore them because they will not correspond to a stackframe.\n  const skips = lines.filter(l => l.includes(\"(index 0\")).length;\n  const offset = lines.length - frames.length - skips;\n  let lineIndex = offset;\n  let frameIndex = 0;\n  while (frameIndex < frames.length) {\n      const line = lines[lineIndex];\n      if (line.includes(\"(index 0)\")) {\n          lineIndex++;\n          continue;\n      }\n      const frame = frames[frameIndex];\n      const info = ` (${frame.fileName}:${frame.lineNumber})`;\n      lines[lineIndex] = line + info;\n      lineIndex++;\n      frameIndex++;\n  }\n  return lines.join('\\n');\n}\n", "odoo.define('web.SessionStorageService', function (require) {\n'use strict';\n\n/**\n * This module defines a service to access the sessionStorage object.\n */\n\nvar AbstractStorageService = require('web.AbstractStorageService');\nvar core = require('web.core');\nvar sessionStorage = require('web.sessionStorage');\n\nvar SessionStorageService = AbstractStorageService.extend({\n    storage: sessionStorage,\n});\n\ncore.serviceRegistry.add('session_storage', SessionStorageService);\n\nreturn SessionStorageService;\n\n});\n", "odoo.define(\"web.commonEnv\", function (require) {\n    \"use strict\";\n\n    /**\n     * This file defines the common environment, which contains everything that\n     * is needed in the env for both the backend and the frontend (Odoo\n     * terminology). This module shouldn't be used as is. It should only be\n     * imported by the module defining the final env to use (in the frontend or\n     * in the backend). For instance, module 'web.env' imports it, adds stuff to\n     * it, and exports the final env that is used by the whole webclient\n     * application.\n     *\n     * There should be as much dependencies as possible in the env object. This\n     * will allow an easier testing of components. See [1] for more information\n     * on environments.\n     *\n     * [1] https://github.com/odoo/owl/blob/master/doc/reference/environment.md#content-of-an-environment\n     */\n\n    const { jsonRpc } = require(\"web.ajax\");\n    const { device, isDebug } = require(\"web.config\");\n    const { bus } = require(\"web.core\");\n    const rpc = require(\"web.rpc\");\n    const session = require(\"web.session\");\n    const { _t } = require(\"web.translation\");\n    const utils = require(\"web.utils\");\n\n    const browser = {\n        clearInterval: window.clearInterval.bind(window),\n        clearTimeout: window.clearTimeout.bind(window),\n        Date: window.Date,\n        fetch: (window.fetch || (() => { })).bind(window),\n        Notification: window.Notification,\n        requestAnimationFrame: window.requestAnimationFrame.bind(window),\n        setInterval: window.setInterval.bind(window),\n        setTimeout: window.setTimeout.bind(window),\n    };\n    Object.defineProperty(browser, 'innerHeight', {\n        get: () => window.innerHeight,\n    });\n    Object.defineProperty(browser, 'innerWidth', {\n        get: () => window.innerWidth,\n    });\n\n    // Build the basic env\n    const env = {\n        _t,\n        browser,\n        bus,\n        device,\n        isDebug,\n        qweb: new owl.QWeb({ translateFn: _t }),\n        services: {\n            ajaxJsonRPC() {\n                return jsonRpc(...arguments);\n            },\n            getCookie() {\n                return utils.get_cookie(...arguments);\n            },\n            httpRequest(route, params = {}, readMethod = 'json') {\n                const info = {\n                    method: params.method || 'POST',\n                };\n                if (params.method !== 'GET') {\n                    const formData = new FormData();\n                    for (const key in params) {\n                        if (key === 'method') {\n                            continue;\n                        }\n                        const value = params[key];\n                        if (Array.isArray(value) && value.length) {\n                            for (const val of value) {\n                                formData.append(key, val);\n                            }\n                        } else {\n                            formData.append(key, value);\n                        }\n                    }\n                    info.body = formData;\n                }\n                return fetch(route, info).then(response => response[readMethod]());\n            },\n            navigate(url, params) {\n                window.location = $.param.querystring(url, params);\n            },\n            reloadPage() {\n                window.location.reload();\n            },\n            rpc(params, options) {\n                const query = rpc.buildQuery(params);\n                return session.rpc(query.route, query.params, options);\n            },\n            setCookie() {\n                utils.set_cookie(...arguments);\n            },\n        },\n        session,\n    };\n\n    return env;\n});\n", "odoo.define('web.name_and_signature', function (require) {\n'use strict';\n\nvar core = require('web.core');\nvar config = require('web.config');\nvar utils = require('web.utils');\nvar Widget = require('web.Widget');\n\nvar _t = core._t;\n\n/**\n * This widget allows the user to input his name and to draw his signature.\n * Alternatively the signature can also be generated automatically based on\n * the given name and a selected font, or loaded from an image file.\n */\nvar NameAndSignature = Widget.extend({\n    template: 'web.sign_name_and_signature',\n    xmlDependencies: ['/web/static/src/legacy/xml/name_and_signature.xml'],\n    events: {\n        // name\n        'input .o_web_sign_name_input': '_onInputSignName',\n        // signature\n        'click .o_web_sign_signature': '_onClickSignature',\n        'change .o_web_sign_signature': '_onChangeSignature',\n        // draw\n        'click .o_web_sign_draw_button': '_onClickSignDrawButton',\n        'click .o_web_sign_draw_clear a': '_onClickSignDrawClear',\n        // auto\n        'click .o_web_sign_auto_button': '_onClickSignAutoButton',\n        'click .o_web_sign_auto_select_style a': '_onClickSignAutoSelectStyle',\n        'click .o_web_sign_auto_font_selection a': '_onClickSignAutoFontSelection',\n        'mouseover .o_web_sign_auto_font_selection a': '_onMouseOverSignAutoFontSelection',\n        'touchmove .o_web_sign_auto_font_selection a': '_onTouchStartSignAutoFontSelection',\n        // load\n        'click .o_web_sign_load_button': '_onClickSignLoadButton',\n        'change .o_web_sign_load_file input': '_onChangeSignLoadInput',\n    },\n\n    /**\n     * Allows options.\n     *\n     * @constructor\n     * @param {Widget} parent\n     * @param {Object} [options={}]\n     * @param {number} [options.displaySignatureRatio=3.0] - The ratio used when\n     *  (re)computing the size of the signature (width = height * ratio)\n     * @param {string} [options.defaultName=''] - The default name of\n     *  the signer.\n     * @param {string} [options.defaultFont=''] - The unique and default\n     *  font for auto mode. If empty, all fonts are visible.\n     * * @param {string} [options.fontColor='DarkBlue'] - Color of signature\n     * (must be a string color)\n     * @param {string} [options.noInputName=false] - If set to true,\n     *  the user can not enter his name. If there aren't defaultName,\n     *  auto mode is hidden.\n     * @param {string} [options.mode='draw'] - @see this.setMode\n     * @param {string} [options.signatureType='signature'] - The type of\n     *  signature used in 'auto' mode. Can be one of the following values:\n     *\n     *  - 'signature': it will adapt the characters width to fit the whole\n     *    text in the image.\n     *  - 'initial': it will adapt the space between characters to fill\n     *      the image with the text. The text will be the first letter of\n     *      every word in the name, separated by dots.\n     */\n    init: function (parent, options) {\n        this._super.apply(this, arguments);\n        options = options || {};\n        this.htmlId = _.uniqueId();\n        this.defaultName = options.defaultName || '';\n        this.defaultFont = options.defaultFont || '';\n        this.fontColor = options.fontColor || 'DarkBlue';\n        this.displaySignatureRatio = options.displaySignatureRatio || 3.0;\n        this.signatureType = options.signatureType || 'signature';\n        this.signMode = options.mode || 'draw';\n        this.noInputName = options.noInputName || false;\n        this.currentFont = 0;\n        this.drawTimeout = null;\n        this.drawPreviewTimeout = null;\n    },\n    /**\n     * Loads the fonts.\n     *\n     * @override\n     */\n    willStart: function () {\n        var self = this;\n        return Promise.all([\n            this._super.apply(this, arguments),\n            this._rpc({route: '/web/sign/get_fonts/' + self.defaultFont}).then(function (data) {\n                self.fonts = data;\n            })\n        ]);\n    },\n    /**\n     * Finds the DOM elements, initializes the signature area,\n     * and focus the name field.\n     *\n     * @override\n     */\n    start: function () {\n        var self = this;\n        // signature and name input\n        this.$signatureGroup = this.$('.o_web_sign_signature_group');\n        this.$signatureField = this.$('.o_web_sign_signature');\n        this.$nameInput = this.$('.o_web_sign_name_input');\n        this.$nameInputGroup = this.$('.o_web_sign_name_group');\n\n        // mode selection buttons\n        this.$drawButton = this.$('a.o_web_sign_draw_button');\n        this.$autoButton = this.$('a.o_web_sign_auto_button');\n        this.$loadButton = this.$('a.o_web_sign_load_button');\n\n        // mode: draw\n        this.$drawClear = this.$('.o_web_sign_draw_clear');\n\n        // mode: auto\n        this.$autoSelectStyle = this.$('.o_web_sign_auto_select_style');\n        this.$autoFontSelection = this.$('.o_web_sign_auto_font_selection');\n        this.$autoFontList = this.$('.o_web_sign_auto_font_list');\n        for (var i in this.fonts) {\n            var $img = $('<img/>').addClass('img-fluid');\n            var $a = $('<a/>').addClass('btn p-0').append($img).data('fontNb', i);\n            this.$autoFontList.append($a);\n        }\n\n        // mode: load\n        this.$loadFile = this.$('.o_web_sign_load_file');\n        this.$loadInvalid = this.$('.o_web_sign_load_invalid');\n\n        if (this.fonts && this.fonts.length < 2) {\n            this.$autoSelectStyle.hide();\n        }\n\n        if (this.noInputName) {\n            if (this.defaultName === \"\") {\n                this.$autoButton.hide();\n            }\n            this.$nameInputGroup.hide();\n        }\n\n        // Resize the signature area if it is resized\n        $(window).on('resize.o_web_sign_name_and_signature', _.debounce(function () {\n            if (self.isDestroyed()) {\n                // May happen since this is debounced\n                return;\n            }\n            self.resizeSignature();\n        }, 250));\n\n        return this._super.apply(this, arguments);\n    },\n    /**\n     * @override\n     */\n    destroy: function () {\n        this._super.apply(this, arguments);\n        $(window).off('resize.o_web_sign_name_and_signature');\n    },\n\n    //----------------------------------------------------------------------\n    // Public\n    //----------------------------------------------------------------------\n\n    /**\n     * Focuses the name.\n     */\n    focusName: function () {\n        // Don't focus on mobile\n        if (!config.device.isMobile) {\n            this.$nameInput.focus();\n        }\n    },\n    /**\n     * Gets the name currently given by the user.\n     *\n     * @returns {string} name\n     */\n    getName: function () {\n        return this.$nameInput.val();\n    },\n    /**\n     * Gets the signature currently drawn. The data format is that produced\n     * natively by Canvas - base64 encoded (likely PNG) bitmap data.\n     *\n     * @returns {string[]} Array that contains the signature as a bitmap.\n     *  The first element is the mimetype, the second element is the data.\n     */\n    getSignatureImage: function () {\n        return this.$signatureField.jSignature('getData', 'image');\n    },\n    /**\n     * Gets the signature currently drawn, in a format ready to be used in\n     * an <img/> src attribute.\n     *\n     * @returns {string} the signature currently drawn, src ready\n     */\n    getSignatureImageSrc: function () {\n        return this.$signatureField.jSignature('getData');\n    },\n    /**\n     * Returns whether the drawing area is currently empty.\n     *\n     * @returns {boolean} Whether the drawing area is currently empty.\n     */\n    isSignatureEmpty: function () {\n        var signature = this.$signatureField.jSignature('getData');\n        return signature && this.emptySignature ? this.emptySignature === signature : true;\n    },\n    resizeSignature: function() {\n        if (!this.$signatureField) {\n            return;\n        }\n        // recompute size based on the current width\n        this.$signatureField.css({width: 'unset'});\n        const width = this.$signatureField.width();\n        const height = parseInt(width / this.displaySignatureRatio);\n\n        // necessary because the lib is adding invisible div with margin\n        // signature field too tall without this code\n        this.$signatureField.css({\n            width: width,\n            height: height,\n        });\n        this.$signatureField.find('canvas').css({\n            width: width,\n            height: height,\n        });\n        return {width, height};\n    },\n    /**\n     * (Re)initializes the signature area:\n     *  - set the correct width and height of the drawing based on the width\n     *      of the container and the ratio option\n     *  - empty any previous content\n     *  - correctly reset the empty state\n     *  - call @see setMode with reset\n     *\n     * @returns {Deferred}\n     */\n    resetSignature: function () {\n        if (!this.$signatureField) {\n            // no action if called before start\n            return Promise.reject();\n        }\n\n        const {width, height} = this.resizeSignature();\n\n        this.$signatureField\n            .empty()\n            .jSignature({\n                'decor-color': '#D1D0CE',\n                'background-color': 'rgba(255,255,255,0)',\n                'show-stroke': false,\n                'color': this.fontColor,\n                'lineWidth': 2,\n                'width': width,\n                'height': height,\n            });\n        this.emptySignature = this.$signatureField.jSignature('getData');\n\n        this.setMode(this.signMode, true);\n\n        this.focusName();\n\n        return Promise.resolve();\n    },\n    /**\n     * Changes the signature mode. Toggles the display of the relevant\n     * controls and resets the drawing.\n     *\n     * @param {string} mode - the mode to use. Can be one of the following:\n     *  - 'draw': the user draws the signature manually with the mouse\n     *  - 'auto': the signature is drawn automatically using a selected font\n     *  - 'load': the signature is loaded from an image file\n     * @param {boolean} [reset=false] - Set to true to reset the elements\n     *  even if the @see mode has not changed. By default nothing happens\n     *  if the @see mode is already selected.\n     */\n    setMode: function (mode, reset) {\n        if (reset !== true && mode === this.signMode) {\n            // prevent flickering and unnecessary compute\n            return;\n        }\n\n        this.signMode = mode;\n\n        this.$drawClear.toggleClass('d-none', this.signMode !== 'draw');\n        this.$autoSelectStyle.toggleClass('d-none', this.signMode !== 'auto');\n        this.$loadFile.toggleClass('d-none', this.signMode !== 'load');\n\n        this.$drawButton.toggleClass('active', this.signMode === 'draw');\n        this.$autoButton.toggleClass('active', this.signMode === 'auto');\n        this.$loadButton.toggleClass('active', this.signMode === 'load');\n\n        this.$signatureField.jSignature(this.signMode === 'draw' ? 'enable' : 'disable');\n        this.$signatureField.jSignature('reset');\n\n        if (this.signMode === 'auto') {\n            // draw based on name\n            this._drawCurrentName();\n        } else {\n            // close style dialog\n            this.$autoFontSelection.addClass('d-none');\n        }\n\n        if (this.signMode !== 'load') {\n            // close invalid file alert\n            this.$loadInvalid.addClass('d-none');\n        }\n    },\n    /**\n     * Gets the current name and signature, validates them, and returns\n     * the result. If they are invalid, displays the errors to the user.\n     *\n     * @returns {boolean} whether the current name and signature are valid\n     */\n    validateSignature: function () {\n        var name = this.getName();\n        var isSignatureEmpty = this.isSignatureEmpty();\n        this.$nameInput.parent().toggleClass('o_has_error', !name)\n            .find('.form-control, .custom-select').toggleClass('is-invalid', !name);\n        this.$signatureGroup.toggleClass('border-danger', isSignatureEmpty);\n        return name && !isSignatureEmpty;\n    },\n\n    //----------------------------------------------------------------------\n    // Private\n    //----------------------------------------------------------------------\n\n    /**\n     * Draws the current name with the current font in the signature field.\n     *\n     * @private\n     */\n    _drawCurrentName: function () {\n        var font = this.fonts[this.currentFont];\n        var text = this._getCleanedName();\n        var canvas = this.$signatureField.find('canvas')[0];\n        var img = this._getSVGText(font, text, canvas.width, canvas.height);\n        return this._printImage(img);\n    },\n    /**\n     * Returns the given name after cleaning it by removing characters that\n     * are not supposed to be used in a signature. If @see signatureType is set\n     * to 'initial', returns the first letter of each word, separated by dots.\n     *\n     * @private\n     * @returns {string} cleaned name\n     */\n    _getCleanedName: function () {\n        var text = this.getName();\n        if (this.signatureType === 'initial') {\n            return (text.split(' ').map(function (w) {\n                return w[0];\n            }).join('.') + '.');\n        }\n        return text;\n    },\n    /**\n     * Gets an SVG matching the given parameters, output compatible with the\n     * src attribute of <img/>.\n     *\n     * @private\n     * @param {string} font: base64 encoded font to use\n     * @param {string} text: the name to draw\n     * @param {number} width: the width of the resulting image in px\n     * @param {number} height: the height of the resulting image in px\n     * @returns {string} image = mimetype + image data\n     */\n    _getSVGText: function (font, text, width, height) {\n        var $svg = $(core.qweb.render('web.sign_svg_text', {\n            width: width,\n            height: height,\n            font: font,\n            text: text,\n            type: this.signatureType,\n            color: this.fontColor,\n        }));\n        $svg.attr({\n            'xmlns': \"http://www.w3.org/2000/svg\",\n            'xmlns:xlink': \"http://www.w3.org/1999/xlink\",\n        });\n\n        return \"data:image/svg+xml,\" + encodeURI($svg[0].outerHTML);\n    },\n    /**\n     * Displays the given image in the signature field.\n     * If needed, resizes the image to fit the existing area.\n     *\n     * @private\n     * @param {string} imgSrc - data of the image to display\n     */\n    _printImage: function (imgSrc) {\n        var self = this;\n\n        var image = new Image;\n        image.onload = function () {\n            // don't slow down the UI if the drawing is slow, and prevent\n            // drawing twice when calling this method in rapid succession\n            clearTimeout(self.drawTimeout);\n            self.drawTimeout = setTimeout(function () {\n                var width = 0;\n                var height = 0;\n                var ratio = image.width / image.height;\n\n                var $canvas = self.$signatureField.find('canvas');\n                var context = $canvas[0].getContext('2d');\n\n                if (image.width / $canvas[0].width > image.height / $canvas[0].height) {\n                    width = $canvas[0].width;\n                    height = parseInt(width / ratio);\n                } else {\n                    height = $canvas[0].height;\n                    width = parseInt(height * ratio);\n                }\n                self.$signatureField.jSignature('reset');\n                var ignoredContext = _.pick(context, ['shadowOffsetX', 'shadowOffsetY']);\n                _.extend(context, {shadowOffsetX: 0, shadowOffsetY: 0});\n                context.drawImage(image,\n                    0,\n                    0,\n                    image.width,\n                    image.height,\n                    ($canvas[0].width - width) / 2,\n                    ($canvas[0].height - height) / 2,\n                    width,\n                    height\n                );\n                _.extend(context, ignoredContext);\n                self.trigger_up('signature_changed');\n            }, 0);\n        };\n        image.src = imgSrc;\n    },\n    /**\n     * Sets the font to use in @see mode 'auto'. Redraws the signature if\n     * the font has been changed.\n     *\n     * @private\n     * @param {number} index - index of the font in @see this.fonts\n     */\n    _setFont: function (index) {\n        if (index !== this.currentFont) {\n            this.currentFont = index;\n            this._drawCurrentName();\n        }\n    },\n    /**\n     * Updates the preview buttons by rendering the signature for each font.\n     *\n     * @private\n     */\n    _updatePreviewButtons: function () {\n        var self = this;\n        // don't slow down the UI if the drawing is slow, and prevent\n        // drawing twice when calling this method in rapid succession\n        clearTimeout(this.drawPreviewTimeout);\n        this.drawPreviewTimeout = setTimeout(function () {\n            var height = 100;\n            var width = parseInt(height * self.displaySignatureRatio);\n            var $existingButtons = self.$autoFontList.find('a');\n            for (var i = 0; i < self.fonts.length; i++) {\n                var imgSrc = self._getSVGText(\n                    self.fonts[i],\n                    self._getCleanedName() || _t(\"Your name\"),\n                    width,\n                    height\n                );\n                $existingButtons.eq(i).find('img').attr('src', imgSrc);\n            }\n        }, 0);\n    },\n    /**\n     * Waits for the signature to be not empty and triggers up the event\n     * `signature_changed`.\n     * This is necessary because some methods of jSignature are async but\n     * they don't return a promise and don't trigger any event.\n     *\n     * @private\n     * @param {Deferred} [def=Deferred] - Deferred that will be returned by\n     *  the method and resolved when the signature is not empty anymore.\n     * @returns {Deferred}\n     */\n    _waitForSignatureNotEmpty: function (def) {\n        def = def || $.Deferred();\n        if (!this.isSignatureEmpty()) {\n            this.trigger_up('signature_changed');\n            def.resolve();\n        } else {\n            // Use the existing def to prevent the method from creating a new\n            // one at every loop.\n            setTimeout(this._waitForSignatureNotEmpty.bind(this, def), 10);\n        }\n        return def;\n    },\n\n    //----------------------------------------------------------------------\n    // Handlers\n    //----------------------------------------------------------------------\n\n    /**\n     * Handles click on the signature: closes the font selection.\n     *\n     * @see mode 'auto'\n     * @private\n     * @param {Event} ev\n     */\n    _onClickSignature: function (ev) {\n        this.$autoFontSelection.addClass('d-none');\n    },\n    /**\n     * Handles click on the Auto button: activates @see mode 'auto'.\n     *\n     * @private\n     * @param {Event} ev\n     */\n    _onClickSignAutoButton: function (ev) {\n        ev.preventDefault();\n        this.setMode('auto');\n    },\n    /**\n     * Handles click on a font: uses it and closes the font selection.\n     *\n     * @see mode 'auto'\n     * @private\n     * @param {Event} ev\n     */\n    _onClickSignAutoFontSelection: function (ev) {\n        this.$autoFontSelection.addClass('d-none').removeClass('d-flex').css('width', 0);\n        this._setFont(parseInt($(ev.currentTarget).data('font-nb')));\n    },\n    /**\n     * Handles click on Select Style: opens and updates the font selection.\n     *\n     * @see mode 'auto'\n     * @private\n     * @param {Event} ev\n     */\n    _onClickSignAutoSelectStyle: function (ev) {\n        var self = this;\n        var width = Math.min(\n            self.$autoFontSelection.find('a').first().height() * self.displaySignatureRatio * 1.25,\n            this.$signatureField.width()\n        );\n\n        ev.preventDefault();\n        self._updatePreviewButtons();\n\n        this.$autoFontSelection.removeClass('d-none').addClass('d-flex');\n        this.$autoFontSelection.show().animate({'width': width}, 500, function () {});\n    },\n    /**\n     * Handles click on the Draw button: activates @see mode 'draw'.\n     *\n     * @private\n     * @param {Event} ev\n     */\n    _onClickSignDrawButton: function (ev) {\n        ev.preventDefault();\n        this.setMode('draw');\n    },\n    /**\n     * Handles click on clear: empties the signature field.\n     *\n     * @see mode 'draw'\n     * @private\n     * @param {Event} ev\n     */\n    _onClickSignDrawClear: function (ev) {\n        ev.preventDefault();\n        this.$signatureField.jSignature('reset');\n    },\n    /**\n     * Handles click on the Load button: activates @see mode 'load'.\n     *\n     * @private\n     * @param {Event} ev\n     */\n    _onClickSignLoadButton: function (ev) {\n        ev.preventDefault();\n        // open file upload automatically (saves 1 click)\n        this.$loadFile.find('input').click();\n        this.setMode('load');\n    },\n    /**\n     * Triggers up the signature change event.\n     *\n     * @private\n     * @param {Event} ev\n     */\n    _onChangeSignature: function (ev) {\n        this.trigger_up('signature_changed');\n    },\n    /**\n     * Handles change on load file input: displays the loaded image if the\n     * format is correct, or diplays an error otherwise.\n     *\n     * @see mode 'load'\n     * @private\n     * @param {Event} ev\n     * @return bool|undefined\n     */\n    _onChangeSignLoadInput: function (ev) {\n        var self = this;\n        var f = ev.target.files[0];\n        if (f === undefined) {\n            return false;\n        }\n        if (f.type.substr(0, 5) !== 'image') {\n            this.$signatureField.jSignature('reset');\n            this.$loadInvalid.removeClass('d-none');\n            return false;\n        }\n        this.$loadInvalid.addClass('d-none');\n\n        utils.getDataURLFromFile(f).then(function (result) {\n            self._printImage(result);\n        });\n    },\n    /**\n     * Handles input on name field: if the @see mode is 'auto', redraws the\n     * signature with the new name. Also updates the font selection if open.\n     *\n     * @private\n     * @param {Event} ev\n     */\n    _onInputSignName: function (ev) {\n        if (this.signMode !== 'auto') {\n            return;\n        }\n        this._drawCurrentName();\n        if (!this.$autoFontSelection.hasClass('d-none')) {\n            this._updatePreviewButtons();\n        }\n    },\n    /**\n     * Handles mouse over on font selection: uses this font.\n     *\n     * @see mode 'auto'\n     * @private\n     * @param {Event} ev\n     */\n    _onMouseOverSignAutoFontSelection: function (ev) {\n        this._setFont(parseInt($(ev.currentTarget).data('font-nb')));\n    },\n    /**\n     * Handles touch start on font selection: uses this font.\n     *\n     * @see mode 'auto'\n     * @private\n     * @param {Event} ev\n     */\n    _onTouchStartSignAutoFontSelection: function (ev) {\n        this._setFont(parseInt($(ev.currentTarget).data('font-nb')));\n    },\n});\n\nreturn {\n    NameAndSignature: NameAndSignature,\n};\n});\n", "odoo.define('web/static/src/js/core/smooth_scroll_on_drag.js', function (require) {\n\"use strict\";\n\nconst Class = require('web.Class');\nconst mixins = require('web.mixins');\n\n/**\n * Provides a helper for SmoothScrollOnDrag options.offsetElements\n */\nconst OffsetElementsHelper = Class.extend({\n\n    /**\n     * @constructor\n     * @param {Object} offsetElements\n     * @param {jQuery} [offsetElements.$top] top offset element\n     * @param {jQuery} [offsetElements.$right] right offset element\n     * @param {jQuery} [offsetElements.$bottom] bottom offset element\n     * @param {jQuery} [offsetElements.$left] left offset element\n     */\n    init: function (offsetElements) {\n        this.offsetElements = offsetElements;\n    },\n    top: function () {\n        if (!this.offsetElements.$top || !this.offsetElements.$top.length) {\n            return 0;\n        }\n        return this.offsetElements.$top.get(0).getBoundingClientRect().bottom;\n    },\n    right: function () {\n        if (!this.offsetElements.$right || !this.offsetElements.$right.length) {\n            return 0;\n        }\n        return this.offsetElements.$right.get(0).getBoundingClientRect().left;\n    },\n    bottom: function () {\n        if (!this.offsetElements.$bottom || !this.offsetElements.$bottom.length) {\n            return 0;\n        }\n        return this.offsetElements.$bottom.get(0).getBoundingClientRect().top;\n    },\n    left: function () {\n        if (!this.offsetElements.$left || !this.offsetElements.$left.length) {\n            return 0;\n        }\n        return this.offsetElements.$left.get(0).getBoundingClientRect().right;\n    },\n});\n\n/**\n * Provides smooth scroll behaviour on drag.\n */\nconst SmoothScrollOnDrag = Class.extend(mixins.ParentedMixin, {\n\n    /**\n     * @constructor\n     * @param {Object} parent The parent widget that uses this class.\n     * @param {jQuery} $element The element the smooth scroll on drag has to be set on.\n     * @param {jQuery} $scrollTarget The element the scroll will be triggered on.\n     * @param {Object} [options={}]\n     * @param {Object} [options.jQueryDraggableOptions={}] The configuration to be passed to\n     *        the jQuery draggable function (all will be passed except scroll which will\n     *        be overridden to false).\n     * @param {Number} [options.scrollOffsetThreshold=150] (Integer) The distance from the\n     *        bottom/top of the options.$scrollTarget from which the smooth scroll will be\n     *        triggered.\n     * @param {Number} [options.scrollStep=20] (Integer) The step of the scroll.\n     * @param {Number} [options.scrollTimerInterval=5] (Integer) The interval (in ms) the\n     *        scrollStep will be applied.\n     * @param {Object} [options.scrollBoundaries = {}] Specifies whether scroll can still be triggered\n     *        when dragging $element outside of target.\n     * @param {Object} [options.scrollBoundaries.top = true] Specifies whether scroll can still be triggered\n     *        when dragging $element above the top edge of target.\n     * @param {Object} [options.scrollBoundaries.right = true] Specifies whether scroll can still be triggered\n     *        when dragging $element after the right edge of target.\n     * @param {Object} [options.scrollBoundaries.bottom = true] Specifies whether scroll can still be triggered\n     *        when dragging $element bellow the bottom edge of target.\n     * @param {Object} [options.scrollBoundaries.left = true] Specifies whether scroll can still be triggered\n     *        when dragging $element before the left edge of target.\n     * @param {Object} [options.offsetElements={}] Visible elements in $scrollTarget that\n     *        reduce $scrollTarget drag visible area (scroll will be triggered sooner than\n     *        normally). A selector is passed so that elements such as automatically hidden\n     *        menu can then be correctly handled.\n     * @param {jQuery} [options.offsetElements.$top] Visible top offset element which height will\n     *        be taken into account when triggering scroll at the top of the $scrollTarget.\n     * @param {jQuery} [options.offsetElements.$right] Visible right offset element which width\n     *        will be taken into account when triggering scroll at the right side of the\n     *        $scrollTarget.\n     * @param {jQuery} [options.offsetElements.$bottom] Visible bottom offset element which height\n     *        will be taken into account when triggering scroll at bottom of the $scrollTarget.\n     * @param {jQuery} [options.offsetElements.$left] Visible left offset element which width\n     *        will be taken into account when triggering scroll at the left side of the\n     *        $scrollTarget.\n     * @param {boolean} [options.disableHorizontalScroll = false] Disable horizontal scroll if not needed.\n     */\n    init(parent, $element, $scrollTarget, options = {}) {\n        mixins.ParentedMixin.init.call(this);\n        this.setParent(parent);\n\n        this.$element = $element;\n        this.$scrollTarget = $scrollTarget;\n        this.options = options;\n        this.targetWindow = this.$element[0].ownerDocument.defaultView;\n        const insideIframe = this.targetWindow !== window.top;\n\n        // Setting optional options to their default value if not provided\n        this.options.jQueryDraggableOptions = this.options.jQueryDraggableOptions || {};\n        if (!this.options.jQueryDraggableOptions.cursorAt) {\n            this.$element.on('mousedown.smooth_scroll', this._onElementMouseDown.bind(this));\n        }\n        this.options.scrollOffsetThreshold = this.options.scrollOffsetThreshold || 150;\n        this.options.scrollStep = this.options.scrollStep || 20;\n        this.options.scrollTimerInterval = this.options.scrollTimerInterval || 5;\n        this.options.offsetElements = this.options.offsetElements || {};\n        this.options.offsetElementsManager = new OffsetElementsHelper(this.options.offsetElements);\n        this.options.scrollBoundaries = Object.assign({\n            top: true,\n            right: true,\n            bottom: true,\n            left: true\n        }, this.options.scrollBoundaries);\n\n        this.autoScrollHandler = null;\n\n        this.scrollStepDirectionEnum = {\n            up: -1,\n            right: 1,\n            down: 1,\n            left: -1,\n        };\n\n        this.options.jQueryDraggableOptions.scroll = false;\n        this.options.disableHorizontalScroll = this.options.disableHorizontalScroll || false;\n        const draggableOptions = Object.assign({}, this.options.jQueryDraggableOptions, {\n            start: (ev, ui) => {\n                this._onSmoothDragStart(ev, ui, this.options.jQueryDraggableOptions.start);\n                if (insideIframe) {\n                    this.onParentWindowMouseup = this._onParentWindowMouseup.bind(this);\n                    window.top.addEventListener('mouseup', this.onParentWindowMouseup, {once: true});\n                }\n            },\n            drag: (ev, ui) => this._onSmoothDrag(ev, ui, this.options.jQueryDraggableOptions.drag),\n            stop: (ev, ui) => {\n                if (insideIframe) {\n                    window.top.removeEventListener('mouseup', this.onParentWindowMouseup, {once: true});\n                }\n                this._onSmoothDragStop(ev, ui, this.options.jQueryDraggableOptions.stop);\n            }\n        });\n        this.$element.draggable(draggableOptions);\n    },\n    /**\n     * @override\n     */\n    destroy: function () {\n        mixins.ParentedMixin.destroy.call(this);\n        this.$element.off('.smooth_scroll');\n        this._stopSmoothScroll();\n    },\n\n    //--------------------------------------------------------------------------\n    // Private\n    //--------------------------------------------------------------------------\n\n    /**\n     * Starts the scroll process using the options.\n     * The options will be updated dynamically when the handler _onSmoothDrag\n     * will be called. The interval will be cleared when the handler\n     * _onSmoothDragStop will be called.\n     *\n     * @private\n     * @param {Object} ui The jQuery drag handler ui parameter.\n     */\n    _startSmoothScroll(ui) {\n        this._stopSmoothScroll();\n        this.autoScrollHandler = setInterval(\n            () => {\n                // Prevents Delta's from being different from 0 when scroll should not occur (except when\n                // helper is dragged outside of this.$scrollTarget's visible area as it increases\n                // this.$scrollTarget's scrollHeight).\n                // Also, this code prevents the helper from being incorrectly repositioned when target is\n                // a child of this.$scrollTarget.\n                this.verticalDelta = Math.min(\n                    // Ensures scrolling stops when dragging bellow this.$scrollTarget bottom.\n                    Math.max(\n                        0,\n                        this.$scrollTarget.get(0).scrollHeight\n                        - (this.$scrollTarget.scrollTop() + this.$scrollTarget.innerHeight())\n                    ),\n                    // Ensures scrolling stops when dragging above this.$scrollTarget top.\n                    Math.max(\n                        this.verticalDelta,\n                        -this.$scrollTarget.scrollTop()\n                    )\n                );\n                this.horizontalDelta = Math.min(\n                    //Ensures scrolling stops when dragging left to this.$scrollTarget.\n                    Math.max(\n                        0,\n                        this.$scrollTarget.get(0).scrollWidth\n                        - (this.$scrollTarget.scrollLeft() + this.$scrollTarget.innerWidth())\n                    ),\n                    //Ensures scrolling stops when dragging right to this.$scrollTarget.\n                    Math.max(\n                        this.horizontalDelta,\n                        -this.$scrollTarget.scrollLeft()\n                    )\n                );\n\n                // Keep helper at right position while scrolling when helper is a child of this.$scrollTarget.\n                if (this.scrollTargetIsParent) {\n                    const offset = ui.helper.offset();\n                    ui.helper.offset({\n                        top: offset.top + this.verticalDelta,\n                        left: offset.left + this.horizontalDelta\n                    });\n                }\n                this.$scrollTarget.scrollTop(\n                    this.$scrollTarget.scrollTop() +\n                    this.verticalDelta\n                );\n                if (!this.options.disableHorizontalScroll) {\n                    this.$scrollTarget.scrollLeft(\n                        this.$scrollTarget.scrollLeft() +\n                        this.horizontalDelta\n                    );\n                }\n            },\n            this.options.scrollTimerInterval\n        );\n    },\n    /**\n     * Stops the scroll process if any is running.\n     *\n     * @private\n     */\n    _stopSmoothScroll() {\n        clearInterval(this.autoScrollHandler);\n    },\n    /**\n     * Updates the options depending on the offset position of the draggable\n     * helper. In the same time options are used by an interval to trigger\n     * scroll behaviour.\n     * @see {@link _startSmoothScroll} for interval implementation details.\n     *\n     * @private\n     * @param {Object} ui The jQuery drag handler ui parameter.\n     */\n    _updatePositionOptions(ui) {\n        const draggableHelperOffset = ui.offset;\n        const scrollTargetOffset = this.$scrollTarget.offset();\n        let visibleOffset = {\n            top: draggableHelperOffset.top\n                - scrollTargetOffset.top\n                + this.options.jQueryDraggableOptions.cursorAt.top\n                - this.options.offsetElementsManager.top(),\n            right: scrollTargetOffset.left + this.$scrollTarget.outerWidth()\n                - draggableHelperOffset.left\n                - this.options.jQueryDraggableOptions.cursorAt.left\n                - this.options.offsetElementsManager.right(),\n            bottom: scrollTargetOffset.top + this.$scrollTarget.outerHeight()\n                - draggableHelperOffset.top\n                - this.options.jQueryDraggableOptions.cursorAt.top\n                - this.options.offsetElementsManager.bottom(),\n            left: draggableHelperOffset.left\n                - scrollTargetOffset.left\n                + this.options.jQueryDraggableOptions.cursorAt.left\n                - this.options.offsetElementsManager.left(),\n        };\n\n        // If this.$scrollTarget is the html tag, we need to take the scroll position in to account\n        // as offsets positions are calculated relative to the document (thus <html>).\n        if (this.scrollTargetIsDocument) {\n            const scrollTargetScrollTop = this.$scrollTarget.scrollTop();\n            const scrollTargetScrollLeft = this.$scrollTarget.scrollLeft();\n            visibleOffset.top -= scrollTargetScrollTop;\n            visibleOffset.right += scrollTargetScrollLeft;\n            visibleOffset.bottom += scrollTargetScrollTop;\n            visibleOffset.left -= scrollTargetScrollLeft;\n        }\n\n        const scrollDecelerator = {\n            vertical: 0,\n            horizontal: 0,\n        };\n\n        const scrollStepDirection = {\n            vertical: this.scrollStepDirectionEnum.down,\n            horizontal: this.scrollStepDirectionEnum.right,\n        };\n\n        // Prevent scroll if outside of scroll boundaries\n        if ((!this.options.scrollBoundaries.top && visibleOffset.top < 0) ||\n            (!this.options.scrollBoundaries.right && visibleOffset.right < 0) ||\n            (!this.options.scrollBoundaries.bottom && visibleOffset.bottom < 0) ||\n            (!this.options.scrollBoundaries.left && visibleOffset.left < 0)) {\n                scrollDecelerator.horizontal = 1;\n                scrollDecelerator.vertical = 1;\n        } else {\n            // Manage vertical scroll\n            if (visibleOffset.bottom <= this.options.scrollOffsetThreshold) {\n                scrollDecelerator.vertical = Math.max(0, visibleOffset.bottom)\n                                           / this.options.scrollOffsetThreshold;\n            } else if (visibleOffset.top <= this.options.scrollOffsetThreshold) {\n                scrollDecelerator.vertical = Math.max(0, visibleOffset.top)\n                                           / this.options.scrollOffsetThreshold;\n                scrollStepDirection.vertical = this.scrollStepDirectionEnum.up;\n            } else {\n                scrollDecelerator.vertical = 1;\n            }\n\n            // Manage horizontal scroll\n            if (visibleOffset.right <= this.options.scrollOffsetThreshold) {\n                scrollDecelerator.horizontal = Math.max(0, visibleOffset.right)\n                                             / this.options.scrollOffsetThreshold;\n            } else if (visibleOffset.left <= this.options.scrollOffsetThreshold) {\n                scrollDecelerator.horizontal = Math.max(0, visibleOffset.left)\n                                             / this.options.scrollOffsetThreshold;\n                scrollStepDirection.horizontal = this.scrollStepDirectionEnum.left;\n            } else {\n                scrollDecelerator.horizontal = 1;\n            }\n        }\n\n        this.verticalDelta = Math.ceil(scrollStepDirection.vertical *\n            this.options.scrollStep *\n            (1 - Math.sqrt(scrollDecelerator.vertical)));\n        this.horizontalDelta = Math.ceil(scrollStepDirection.horizontal *\n            this.options.scrollStep *\n            (1 - Math.sqrt(scrollDecelerator.horizontal)));\n    },\n\n    //--------------------------------------------------------------------------\n    // Handlers\n    //--------------------------------------------------------------------------\n\n    /**\n     * Called when mouse button is down on this.$element.\n     * Updates the mouse cursor position variable.\n     *\n     * @private\n     * @param {Object} ev The jQuery mousedown handler event parameter.\n     */\n    _onElementMouseDown(ev) {\n        const elementOffset = $(ev.target).offset();\n        this.options.jQueryDraggableOptions.cursorAt = {\n            top: ev.pageY - elementOffset.top,\n            left: ev.pageX - elementOffset.left,\n        };\n    },\n    /**\n     * Called when dragging the element.\n     * Updates the position options and call the provided callback if any.\n     *\n     * @private\n     * @param {Object} ev The jQuery drag handler event parameter.\n     * @param {Object} ui The jQuery drag handler ui parameter.\n     * @param {Function} onDragCallback The jQuery drag callback.\n     */\n    _onSmoothDrag(ev, ui, onDragCallback) {\n        this._updatePositionOptions(ui);\n        if (typeof onDragCallback === 'function') {\n            onDragCallback.call(ui.helper, ev, ui);\n        }\n    },\n    /**\n     * Called when starting to drag the element.\n     * Updates the position params, starts smooth scrolling process and call the\n     * provided callback if any.\n     *\n     * @private\n     * @param {Object} ev The jQuery drag handler event parameter.\n     * @param {Object} ui The jQuery drag handler ui parameter.\n     * @param {Function} onDragStartCallBack The jQuery drag callback.\n     */\n    _onSmoothDragStart(ev, ui, onDragStartCallBack) {\n        this.scrollTargetIsDocument = this.$scrollTarget.is('html');\n        this.scrollTargetIsParent = this.$scrollTarget.get(0).contains(this.$element.get(0));\n        this._updatePositionOptions(ui);\n        this._startSmoothScroll(ui);\n        if (typeof onDragStartCallBack === 'function') {\n            onDragStartCallBack.call(ui.helper, ev, ui);\n        }\n    },\n    /**\n     * Called when stopping to drag the element.\n     * Stops the smooth scrolling process and call the provided callback if any.\n     *\n     * @private\n     * @param {Object} ev The jQuery drag handler event parameter.\n     * @param {Object} ui The jQuery drag handler ui parameter.\n     * @param {Function} onDragEndCallBack The jQuery drag callback.\n     */\n    _onSmoothDragStop(ev, ui, onDragEndCallBack) {\n        this._stopSmoothScroll();\n        if (typeof onDragEndCallBack === 'function') {\n            onDragEndCallBack.call(ui.helper, ev, ui);\n        }\n    },\n    /**\n     * Called when the mouse is released outside the page iframe (e.g. the\n     * editor panel in Website). This is only useful in Chrome, where the 'stop'\n     * event of jQuery Draggable does not trigger a 'mouseup' event outside of\n     * the \"preview\" page iframe.\n     *\n     * @private\n     */\n    _onParentWindowMouseup() {\n        this.targetWindow.document.dispatchEvent(new Event('mouseup'));\n    },\n});\n\nreturn SmoothScrollOnDrag;\n});\n", "odoo.define('web.Colorpicker', function (require) {\n'use strict';\n\nvar core = require('web.core');\nvar utils = require('web.utils');\nvar Dialog = require('web.Dialog');\nvar Widget = require('web.Widget');\n\nvar _t = core._t;\n\nvar ColorpickerWidget = Widget.extend({\n    xmlDependencies: ['/web/static/src/legacy/xml/colorpicker.xml'],\n    template: 'Colorpicker',\n    events: {\n        'click': '_onClick',\n        'keypress': '_onKeypress',\n        'mousedown .o_color_pick_area': '_onMouseDownPicker',\n        'mousedown .o_color_slider': '_onMouseDownSlider',\n        'mousedown .o_opacity_slider': '_onMouseDownOpacitySlider',\n        'change .o_color_picker_inputs': '_onChangeInputs',\n    },\n\n    /**\n     * @constructor\n     * @param {Widget} parent\n     * @param {Object} [options]\n     * @param {string} [options.defaultColor='#FF0000']\n     * @param {string} [options.noTransparency=false]\n     * @param {boolean} [options.stopClickPropagation=false]\n     */\n    init: function (parent, options) {\n        this._super(...arguments);\n        options = options || {};\n\n        this.pickerFlag = false;\n        this.sliderFlag = false;\n        this.opacitySliderFlag = false;\n        this.colorComponents = {};\n        this.uniqueId = _.uniqueId('colorpicker');\n        this.selectedHexValue = '';\n\n        // Need to be bound on all documents to work in all possible cases (we\n        // have to be able to start dragging/moving from the colorpicker to\n        // anywhere on the screen, crossing iframes).\n        // TODO adapt in master: these events should probably be bound in\n        // `start` instead of `init` (at least to be more conventional).\n        this.$documents = $([window.top, ...Array.from(window.top.frames).filter(frame => {\n            try {\n                const document = frame.document;\n                return !!document;\n            } catch (error) {\n                // We cannot access the document (cross origin).\n                return false;\n            }\n        })].map(w => w.document));\n        this.$documents.on(`mousemove.${this.uniqueId}`, _.throttle((ev) => {\n            this._onMouseMovePicker(ev);\n            this._onMouseMoveSlider(ev);\n            this._onMouseMoveOpacitySlider(ev);\n        }, 50));\n        this.$documents.on(`mouseup.${this.uniqueId}`, _.throttle((ev) => {\n            if (this.pickerFlag || this.sliderFlag || this.opacitySliderFlag) {\n                this._colorSelected();\n            }\n            this.pickerFlag = false;\n            this.sliderFlag = false;\n            this.opacitySliderFlag = false;\n        }, 10));\n\n        this.options = _.clone(options);\n    },\n    /**\n     * @override\n     */\n    start: function () {\n        this.$colorpickerArea = this.$('.o_color_pick_area');\n        this.$colorpickerPointer = this.$('.o_picker_pointer');\n        this.$colorSlider = this.$('.o_color_slider');\n        this.$colorSliderPointer = this.$('.o_slider_pointer');\n        this.$opacitySlider = this.$('.o_opacity_slider');\n        this.$opacitySliderPointer = this.$('.o_opacity_pointer');\n\n        var defaultColor = this.options.defaultColor || '#FF0000';\n        var rgba = ColorpickerWidget.convertCSSColorToRgba(defaultColor);\n        if (rgba) {\n            this._updateRgba(rgba.red, rgba.green, rgba.blue, rgba.opacity);\n        }\n\n        // Pre-fill the inputs. This is because on safari, the baseline for empty\n        // input is not the baseline of where the text would be, but the bottom\n        // of the input itself. (see https://bugs.webkit.org/show_bug.cgi?id=142968)\n        // This will cause the first _updateUI to alter the layout of the colorpicker\n        // which will change its height. Changing the height of an element inside of\n        // the callback to a ResizeObserver observing it will cause an error\n        // (ResizeObserver loop completed with undelivered notifications) that cannot\n        // be caught, which will open the crash manager. Prefilling the inputs sets\n        // the baseline correctly from the start so the layout doesn't change.\n        Object.entries(this.colorComponents).forEach(([component, value]) => {\n            const input = this.el.querySelector(`.o_${component}_input`);\n            if (input) {\n                input.value = value;\n            }\n        });\n        const resizeObserver = new window.ResizeObserver(() => {\n            this._updateUI();\n        });\n        resizeObserver.observe(this.el);\n\n        this.previewActive = true;\n        return this._super.apply(this, arguments);\n    },\n    /**\n     * @override\n     */\n    destroy: function () {\n        this._super.apply(this, arguments);\n        this.$documents.off(`.${this.uniqueId}`);\n    },\n    /**\n     * Sets the currently selected color\n     *\n     * @param {string} color rgb[a]\n     */\n    setSelectedColor: function (color) {\n        var rgba = ColorpickerWidget.convertCSSColorToRgba(color);\n        if (rgba) {\n            const oldPreviewActive = this.previewActive;\n            this.previewActive = false;\n            this._updateRgba(rgba.red, rgba.green, rgba.blue, rgba.opacity);\n            this.previewActive = oldPreviewActive;\n            this._updateUI();\n        }\n    },\n\n    //--------------------------------------------------------------------------\n    // Private\n    //--------------------------------------------------------------------------\n\n    /**\n     * Updates input values, color preview, picker and slider pointer positions.\n     *\n     * @private\n     */\n    _updateUI: function () {\n        var self = this;\n\n        // Update inputs\n        _.each(this.colorComponents, function (value, color) {\n            self.$(_.str.sprintf('.o_%s_input', color)).val(value);\n        });\n\n        // Update preview\n        this.$('.o_color_preview').css('background-color', this.colorComponents.cssColor);\n\n        // Update picker area and picker pointer position\n        this.$colorpickerArea.css('background-color', _.str.sprintf('hsl(%s, 100%%, 50%%)', this.colorComponents.hue));\n        var top = (100 - this.colorComponents.lightness) * this.$colorpickerArea.height() / 100;\n        var left = this.colorComponents.saturation * this.$colorpickerArea.width() / 100;\n        this.$colorpickerPointer.css({\n            top: (top - 5) + 'px',\n            left: (left - 5) + 'px',\n        });\n\n        // Update color slider position\n        var height = this.$colorSlider.height();\n        var y = this.colorComponents.hue * height / 360;\n        this.$colorSliderPointer.css('top', Math.round(y - 2));\n\n        if (! this.options.noTransparency) {\n            // Update opacity slider position\n            var heightOpacity = this.$opacitySlider.height();\n            var z = heightOpacity * (1 - this.colorComponents.opacity / 100.0);\n            this.$opacitySliderPointer.css('top', Math.round(z - 2));\n\n            // Add gradient color on opacity slider\n            this.$opacitySlider.css('background', 'linear-gradient(' + this.colorComponents.hex + ' 0%, transparent 100%)');\n        }\n    },\n    /**\n     * Updates colors according to given hex value. Opacity is left unchanged.\n     *\n     * @private\n     * @param {string} hex - hexadecimal code\n     */\n    _updateHex: function (hex) {\n        var rgb = ColorpickerWidget.convertCSSColorToRgba(hex);\n        if (!rgb) {\n            return;\n        }\n        _.extend(this.colorComponents,\n            {hex: hex},\n            rgb,\n            ColorpickerWidget.convertRgbToHsl(rgb.red, rgb.green, rgb.blue)\n        );\n        this._updateCssColor();\n    },\n    /**\n     * Updates colors according to given RGB values.\n     *\n     * @private\n     * @param {integer} r\n     * @param {integer} g\n     * @param {integer} b\n     * @param {integer} [a]\n     */\n    _updateRgba: function (r, g, b, a) {\n        // Remove full transparency in case some lightness is added\n        const opacity = a || this.colorComponents.opacity;\n        if (opacity < 0.1 && (r > 0.1 || g > 0.1 || b > 0.1)) {\n            a = 100;\n        }\n\n        // We update the hexadecimal code by transforming into a css color and\n        // ignoring the opacity (we don't display opacity component in hexa as\n        // not supported on all browsers)\n        var hex = ColorpickerWidget.convertRgbaToCSSColor(r, g, b);\n        if (!hex) {\n            return;\n        }\n        _.extend(this.colorComponents,\n            {red: r, green: g, blue: b},\n            a === undefined ? {} : {opacity: a},\n            {hex: hex},\n            ColorpickerWidget.convertRgbToHsl(r, g, b)\n        );\n        this._updateCssColor();\n    },\n    /**\n     * Updates colors according to given HSL values.\n     *\n     * @private\n     * @param {integer} h\n     * @param {integer} s\n     * @param {integer} l\n     */\n    _updateHsl: function (h, s, l) {\n        // Remove full transparency in case some lightness is added\n        let a = this.colorComponents.opacity;\n        if (a < 0.1 && l > 0.1) {\n            a = 100;\n        }\n\n        var rgb = ColorpickerWidget.convertHslToRgb(h, s, l);\n        if (!rgb) {\n            return;\n        }\n        // We receive an hexa as we ignore the opacity\n        const hex = ColorpickerWidget.convertRgbaToCSSColor(rgb.red, rgb.green, rgb.blue);\n        _.extend(this.colorComponents,\n            {hue: h, saturation: s, lightness: l},\n            rgb,\n            {hex: hex},\n            {opacity: a},\n        );\n        this._updateCssColor();\n    },\n    /**\n     * Updates color opacity.\n     *\n     * @private\n     * @param {integer} a\n     */\n    _updateOpacity: function (a) {\n        if (a < 0 || a > 100) {\n            return;\n        }\n        _.extend(this.colorComponents,\n            {opacity: a}\n        );\n        this._updateCssColor();\n    },\n    /**\n     * Trigger an event to annonce that the widget value has changed\n     *\n     * @private\n     */\n    _colorSelected: function () {\n        this.trigger_up('colorpicker_select', this.colorComponents);\n    },\n    /**\n     * Updates css color representation.\n     *\n     * @private\n     */\n    _updateCssColor: function () {\n        const r = this.colorComponents.red;\n        const g = this.colorComponents.green;\n        const b = this.colorComponents.blue;\n        const a = this.colorComponents.opacity;\n        _.extend(this.colorComponents,\n            {cssColor: ColorpickerWidget.convertRgbaToCSSColor(r, g, b, a)}\n        );\n        if (this.previewActive) {\n            this.trigger_up('colorpicker_preview', this.colorComponents);\n        }\n    },\n\n    //--------------------------------------------------------------------------\n    // Handlers\n    //--------------------------------------------------------------------------\n\n    /**\n     * @private\n     * @param {Event} ev\n     */\n    _onKeypress: function (ev) {\n        if (ev.charCode === $.ui.keyCode.ENTER) {\n            if (ev.target.tagName === 'INPUT') {\n                this._onChangeInputs(ev);\n            }\n            ev.preventDefault();\n            this.trigger_up('enter_key_color_colorpicker');\n        }\n    },\n    /**\n     * @param {Event} ev\n     */\n    _onClick: function (ev) {\n        if (this.options.stopClickPropagation) {\n            ev.stopPropagation();\n        }\n        ev.originalEvent.__isColorpickerClick = true;\n        $(ev.target).find('> .o_opacity_pointer, > .o_slider_pointer, > .o_picker_pointer').addBack('.o_opacity_pointer, .o_slider_pointer, .o_picker_pointer').focus();\n        if (ev.target.dataset.colorMethod === 'hex' && !this.selectedHexValue) {\n            ev.target.select();\n            this.selectedHexValue = ev.target.value;\n            return;\n        }\n        this.selectedHexValue = '';\n    },\n    /**\n     * Updates color when the user starts clicking on the picker.\n     *\n     * @private\n     * @param {Event} ev\n     */\n    _onMouseDownPicker: function (ev) {\n        this.pickerFlag = true;\n        ev.preventDefault();\n        this._onMouseMovePicker(ev);\n    },\n    /**\n     * Updates saturation and lightness values on mouse drag over picker.\n     *\n     * @private\n     * @param {Event} ev\n     */\n    _onMouseMovePicker: function (ev) {\n        if (!this.pickerFlag) {\n            return;\n        }\n\n        var offset = this.$colorpickerArea.offset();\n        var top = ev.pageY - offset.top;\n        var left = ev.pageX - offset.left;\n        var saturation = Math.round(100 * left / this.$colorpickerArea.width());\n        var lightness = Math.round(100 * (this.$colorpickerArea.height() - top) / this.$colorpickerArea.height());\n        saturation = utils.confine(saturation, 0, 100);\n        lightness = utils.confine(lightness, 0, 100);\n\n        this._updateHsl(this.colorComponents.hue, saturation, lightness);\n        this._updateUI();\n    },\n    /**\n     * Updates color when user starts clicking on slider.\n     *\n     * @private\n     * @param {Event} ev\n     */\n    _onMouseDownSlider: function (ev) {\n        this.sliderFlag = true;\n        ev.preventDefault();\n        this._onMouseMoveSlider(ev);\n    },\n    /**\n     * Updates hue value on mouse drag over slider.\n     *\n     * @private\n     * @param {Event} ev\n     */\n    _onMouseMoveSlider: function (ev) {\n        if (!this.sliderFlag) {\n            return;\n        }\n\n        var y = ev.pageY - this.$colorSlider.offset().top;\n        var hue = Math.round(360 * y / this.$colorSlider.height());\n        hue = utils.confine(hue, 0, 360);\n\n        this._updateHsl(hue, this.colorComponents.saturation, this.colorComponents.lightness);\n        this._updateUI();\n    },\n    /**\n     * Updates opacity when user starts clicking on opacity slider.\n     *\n     * @private\n     * @param {Event} ev\n     */\n    _onMouseDownOpacitySlider: function (ev) {\n        this.opacitySliderFlag = true;\n        ev.preventDefault();\n        this._onMouseMoveOpacitySlider(ev);\n    },\n    /**\n     * Updates opacity value on mouse drag over opacity slider.\n     *\n     * @private\n     * @param {Event} ev\n     */\n    _onMouseMoveOpacitySlider: function (ev) {\n        if (!this.opacitySliderFlag || this.options.noTransparency) {\n            return;\n        }\n\n        var y = ev.pageY - this.$opacitySlider.offset().top;\n        var opacity = Math.round(100 * (1 - y / this.$opacitySlider.height()));\n        opacity = utils.confine(opacity, 0, 100);\n\n        this._updateOpacity(opacity);\n        this._updateUI();\n    },\n    /**\n     * Called when input value is changed -> Updates UI: Set picker and slider\n     * position and set colors.\n     *\n     * @private\n     * @param {Event} ev\n     */\n    _onChangeInputs: function (ev) {\n        switch ($(ev.target).data('colorMethod')) {\n            case 'hex':\n                this._updateHex(this.$('.o_hex_input').val());\n                break;\n            case 'rgb':\n                this._updateRgba(\n                    parseInt(this.$('.o_red_input').val()),\n                    parseInt(this.$('.o_green_input').val()),\n                    parseInt(this.$('.o_blue_input').val())\n                );\n                break;\n            case 'hsl':\n                this._updateHsl(\n                    parseInt(this.$('.o_hue_input').val()),\n                    parseInt(this.$('.o_saturation_input').val()),\n                    parseInt(this.$('.o_lightness_input').val())\n                );\n                break;\n            case 'opacity':\n                this._updateOpacity(parseInt(this.$('.o_opacity_input').val()));\n                break;\n        }\n        this._updateUI();\n        this._colorSelected();\n    },\n});\n\n//--------------------------------------------------------------------------\n// Static\n//--------------------------------------------------------------------------\n\n/**\n * Converts RGB color components to HSL components.\n *\n * @static\n * @param {integer} r - [0, 255]\n * @param {integer} g - [0, 255]\n * @param {integer} b - [0, 255]\n * @returns {Object|false}\n *          - hue [0, 360[ (float)\n *          - saturation [0, 100] (float)\n *          - lightness [0, 100] (float)\n */\nColorpickerWidget.convertRgbToHsl = function (r, g, b) {\n    if (typeof (r) !== 'number' || isNaN(r) || r < 0 || r > 255\n            || typeof (g) !== 'number' || isNaN(g) || g < 0 || g > 255\n            || typeof (b) !== 'number' || isNaN(b) || b < 0 || b > 255) {\n        return false;\n    }\n\n    var red = r / 255;\n    var green = g / 255;\n    var blue = b / 255;\n    var maxColor = Math.max(red, green, blue);\n    var minColor = Math.min(red, green, blue);\n    var delta = maxColor - minColor;\n    var hue = 0;\n    var saturation = 0;\n    var lightness = (maxColor + minColor) / 2;\n    if (delta) {\n        if (maxColor === red) {\n            hue = (green - blue) / delta;\n        }\n        if (maxColor === green) {\n            hue = 2 + (blue - red) / delta;\n        }\n        if (maxColor === blue) {\n            hue = 4 + (red - green) / delta;\n        }\n        if (maxColor) {\n            saturation = delta / (1 - Math.abs(2 * lightness - 1));\n        }\n    }\n    hue = 60 * hue;\n    return {\n        hue: hue < 0 ? hue + 360 : hue,\n        saturation: saturation * 100,\n        lightness: lightness * 100,\n    };\n};\n/**\n * Converts HSL color components to RGB components.\n *\n * @static\n * @param {number} h - [0, 360[ (float)\n * @param {number} s - [0, 100] (float)\n * @param {number} l - [0, 100] (float)\n * @returns {Object|false}\n *          - red [0, 255] (integer)\n *          - green [0, 255] (integer)\n *          - blue [0, 255] (integer)\n */\nColorpickerWidget.convertHslToRgb = function (h, s, l) {\n    if (typeof (h) !== 'number' || isNaN(h) || h < 0 || h > 360\n            || typeof (s) !== 'number' || isNaN(s) || s < 0 || s > 100\n            || typeof (l) !== 'number' || isNaN(l) || l < 0 || l > 100) {\n        return false;\n    }\n\n    var huePrime = h / 60;\n    var saturation = s / 100;\n    var lightness = l / 100;\n    var chroma = saturation * (1 - Math.abs(2 * lightness - 1));\n    var secondComponent = chroma * (1 - Math.abs(huePrime % 2 - 1));\n    var lightnessAdjustment = lightness - chroma / 2;\n    var precision = 255;\n    chroma = Math.round((chroma + lightnessAdjustment) * precision);\n    secondComponent = Math.round((secondComponent + lightnessAdjustment) * precision);\n    lightnessAdjustment = Math.round((lightnessAdjustment) * precision);\n    if (huePrime >= 0 && huePrime < 1) {\n        return {\n            red: chroma,\n            green: secondComponent,\n            blue: lightnessAdjustment,\n        };\n    }\n    if (huePrime >= 1 && huePrime < 2) {\n        return {\n            red: secondComponent,\n            green: chroma,\n            blue: lightnessAdjustment,\n        };\n    }\n    if (huePrime >= 2 && huePrime < 3) {\n        return {\n            red: lightnessAdjustment,\n            green: chroma,\n            blue: secondComponent,\n        };\n    }\n    if (huePrime >= 3 && huePrime < 4) {\n        return {\n            red: lightnessAdjustment,\n            green: secondComponent,\n            blue: chroma,\n        };\n    }\n    if (huePrime >= 4 && huePrime < 5) {\n        return {\n            red: secondComponent,\n            green: lightnessAdjustment,\n            blue: chroma,\n        };\n    }\n    if (huePrime >= 5 && huePrime <= 6) {\n        return {\n            red: chroma,\n            green: lightnessAdjustment,\n            blue: secondComponent,\n        };\n    }\n    return false;\n};\n/**\n * Converts RGBA color components to a normalized CSS color: if the opacity\n * is invalid or equal to 100, a hex is returned; otherwise a rgba() css color\n * is returned.\n *\n * Those choice have multiple reason:\n * - A hex color is more common to c/c from other utilities on the web and is\n *   also shorter than rgb() css colors\n * - Opacity in hexadecimal notations is not supported on all browsers and is\n *   also less common to use.\n *\n * @static\n * @param {integer} r - [0, 255]\n * @param {integer} g - [0, 255]\n * @param {integer} b - [0, 255]\n * @param {float} a - [0, 100]\n * @returns {string}\n */\nColorpickerWidget.convertRgbaToCSSColor = function (r, g, b, a) {\n    if (typeof (r) !== 'number' || isNaN(r) || r < 0 || r > 255\n            || typeof (g) !== 'number' || isNaN(g) || g < 0 || g > 255\n            || typeof (b) !== 'number' || isNaN(b) || b < 0 || b > 255) {\n        return false;\n    }\n    if (typeof (a) !== 'number' || isNaN(a) || a < 0 || Math.abs(a - 100) < Number.EPSILON) {\n        const rr = r < 16 ? '0' + r.toString(16) : r.toString(16);\n        const gg = g < 16 ? '0' + g.toString(16) : g.toString(16);\n        const bb = b < 16 ? '0' + b.toString(16) : b.toString(16);\n        return (`#${rr}${gg}${bb}`).toUpperCase();\n    }\n    return `rgba(${r}, ${g}, ${b}, ${parseFloat((a / 100.0).toFixed(3))})`;\n};\n/**\n * Converts a CSS color (rgb(), rgba(), hexadecimal) to RGBA color components.\n *\n * Note: we don't support using and displaying hexadecimal color with opacity\n * but this method allows to receive one and returns the correct opacity value.\n *\n * @static\n * @param {string} cssColor - hexadecimal code or rgb() or rgba()\n * @returns {Object|false}\n *          - red [0, 255] (integer)\n *          - green [0, 255] (integer)\n *          - blue [0, 255] (integer)\n *          - opacity [0, 100.0] (float)\n */\nColorpickerWidget.convertCSSColorToRgba = function (cssColor) {\n    // Check if cssColor is a rgba() or rgb() color\n    const rgba = cssColor.match(/^rgba?\\((\\d+),\\s*(\\d+),\\s*(\\d+)(?:,\\s*(\\d+(?:\\.\\d+)?))?\\)$/);\n    if (rgba) {\n        if (rgba[4] === undefined) {\n            rgba[4] = 1;\n        }\n        return {\n            red: parseInt(rgba[1]),\n            green: parseInt(rgba[2]),\n            blue: parseInt(rgba[3]),\n            opacity: Math.round(parseFloat(rgba[4]) * 100),\n        };\n    }\n\n    // Otherwise, check if cssColor is an hexadecimal code color\n    if (/^#([0-9A-F]{6}|[0-9A-F]{8})$/i.test(cssColor)) {\n        return {\n            red: parseInt(cssColor.substr(1, 2), 16),\n            green: parseInt(cssColor.substr(3, 2), 16),\n            blue: parseInt(cssColor.substr(5, 2), 16),\n            opacity: (cssColor.length === 9 ? (parseInt(cssColor.substr(7, 2), 16) / 255) : 1) * 100,\n        };\n    }\n\n    // TODO maybe implement a support for receiving css color like 'red' or\n    // 'transparent' (which are now considered non-css color by isCSSColor...)\n    // Note: however, if ever implemented be careful of 'white'/'black' which\n    // actually are color names for our color system...\n\n    return false;\n};\n/**\n * Converts a CSS color (rgb(), rgba(), hexadecimal) to a normalized version\n * of the same color (@see convertRgbaToCSSColor).\n *\n * Normalized color can be safely compared using string comparison.\n *\n * @static\n * @param {string} cssColor - hexadecimal code or rgb() or rgba()\n * @returns {string} - the normalized css color or the given css color if it\n *                     failed to be normalized\n */\nColorpickerWidget.normalizeCSSColor = function (cssColor) {\n    const rgba = ColorpickerWidget.convertCSSColorToRgba(cssColor);\n    if (!rgba) {\n        return cssColor;\n    }\n    return ColorpickerWidget.convertRgbaToCSSColor(rgba.red, rgba.green, rgba.blue, rgba.opacity);\n};\n/**\n * Checks if a given string is a css color.\n *\n * @static\n * @param {string} cssColor\n * @returns {boolean}\n */\nColorpickerWidget.isCSSColor = function (cssColor) {\n    return ColorpickerWidget.convertCSSColorToRgba(cssColor) !== false;\n};\n\n/**\n * Mixes two colors by applying a weighted average of their red, green and blue\n * components.\n *\n * @static\n * @param {string} cssColor1 - hexadecimal code or rgb() or rgba()\n * @param {string} cssColor2 - hexadecimal code or rgb() or rgba()\n * @param {number} weight - a number between 0 and 1\n * @returns {string} - mixed color in hexadecimal format\n */\nColorpickerWidget.mixCssColors = function (cssColor1, cssColor2, weight) {\n    const rgba1 = ColorpickerWidget.convertCSSColorToRgba(cssColor1);\n    const rgba2 = ColorpickerWidget.convertCSSColorToRgba(cssColor2);\n    const rgb1 = [rgba1.red, rgba1.green, rgba1.blue];\n    const rgb2 = [rgba2.red, rgba2.green, rgba2.blue];\n    const [r, g, b] = rgb1.map((_, idx) => Math.round(rgb2[idx] + (rgb1[idx] - rgb2[idx]) * weight));\n    return ColorpickerWidget.convertRgbaToCSSColor(r, g, b);\n};\n\nconst ColorpickerDialog = Dialog.extend({\n    /**\n     * @override\n     */\n    init: function (parent, options) {\n        this.options = options || {};\n        this._super(parent, _.extend({\n            size: 'small',\n            title: _t('Pick a color'),\n            buttons: [\n                {text: _t('Choose'), classes: 'btn-primary', close: true, click: this._onFinalPick.bind(this)},\n                {text: _t('Discard'), close: true},\n            ],\n        }, this.options));\n    },\n    /**\n     * @override\n     */\n    start: function () {\n        const proms = [this._super(...arguments)];\n        this.colorPicker = new ColorpickerWidget(this, _.extend({\n            colorPreview: true,\n        }, this.options));\n        proms.push(this.colorPicker.appendTo(this.$el));\n        return Promise.all(proms);\n    },\n\n    //--------------------------------------------------------------------------\n    // Handlers\n    //--------------------------------------------------------------------------\n\n    /**\n     * @private\n     */\n    _onFinalPick: function () {\n        this.trigger_up('colorpicker:saved', this.colorPicker.colorComponents);\n    },\n});\n\nreturn {\n    ColorpickerDialog: ColorpickerDialog,\n    ColorpickerWidget: ColorpickerWidget,\n};\n});\n", "odoo.define('web.TranslationDialog', function (require) {\n    'use strict';\n\n    var core = require('web.core');\n    var Dialog = require('web.Dialog');\n    var session = require('web.session');\n\n    var _t = core._t;\n\n    var TranslationDialog = Dialog.extend({\n        xmlDependencies: (Dialog.prototype.xmlDependencies || [])\n            .concat(['/web/static/src/legacy/xml/translation_dialog.xml']),\n        template: 'TranslationDialog',\n\n        /**\n         * @constructor\n         * @param {Widget} parent\n         * @param {Object} [options]\n         * @param {string} [options.domain] the domain needed to get the translation terms\n         * @param {string} [options.fieldName] the name of the field currently translated (from the model of the form view)\n         * @param {string} [options.searchName] the name of the actual field that is the reference for translation (in the form of model,field)\n         * @param {string} [options.userLanguageValue] the value of the translation in the language of the user, as seen in the from view (might be empty)\n         * @param {string} [options.dataPointID] the data point id of the record for which we do the translations\n         * @param {boolean} [options.isComingFromTranslationAlert] the initiator of the dialog, might be a link on a field or the translation alert on top of the form\n         * @param {boolean} [options.isText] is the field a text field (multiline) or char (single line)\n         * @param {boolean} [options.showSrc] is the source of the translation should be rendered (for partial translations, i.e. XML content)\n         *\n         */\n        init: function (parent, options) {\n            options = options || {};\n\n            this.fieldName = options.fieldName;\n            this.domain = options.domain;\n            this.searchName = options.searchName;\n            this.userLanguageValue = options.userLanguageValue;\n            this.domain.push(['name', \"=\", `${this.searchName}`]);\n            this.dataPointID = options.dataPointID;\n            this.isComingFromTranslationAlert = options.isComingFromTranslationAlert;\n            this.currentInterfaceLanguage = session.user_context.lang;\n            this.isText = options.isText;\n            this.showSrc = options.showSrc;\n            this.node = options.node;\n\n            this._super(parent, _.extend({\n                size: 'large',\n                title: _.str.sprintf(_t('Translate: %s'), this.fieldName),\n                buttons: [\n                    { text: _t('Save'), classes: 'btn-primary', close: true, click: this._onSave.bind(this) },\n                    { text: _t('Discard'), close: true },\n                ],\n            }, options));\n        },\n        /**\n         * @override\n         */\n        willStart: function () {\n            return Promise.all([\n                this._super(),\n                this._loadLanguages().then((l) => {\n                    this.languages = l;\n                    return this._loadTranslations().then((t) => {\n                        this.translations = t;\n                    });\n                }),\n            ]).then(() => {\n                this.data = this.translations.map((term) => {\n                    let relatedLanguage = this.languages.find((language) => language[0] === term.lang);\n                    if (!term.value && !this.showSrc) {\n                        term.value = term.src;\n                    }\n                    return {\n                        id: term.id,\n                        lang: term.lang,\n                        langName: relatedLanguage[1],\n                        source: term.src,\n                        // we set the translation value coming from the database, except for the language\n                        // the user is currently utilizing. Then we set the translation value coming\n                        // from the value of the field in the form\n                        value: (term.lang === this.currentInterfaceLanguage &&\n                            !this.showSrc &&\n                            !this.isComingFromTranslationAlert) ?\n                            this.userLanguageValue : term.value || ''\n                    };\n                });\n                this.data.sort((left, right) =>\n                    (left.langName < right.langName || (left.langName === right.langName && left.source < right.source)) ? -1 : 1);\n            });\n        },\n\n        //--------------------------------------------------------------------------\n        // Private\n        //--------------------------------------------------------------------------\n        /**\n         * Load the translation terms for the installed language, for the current model and res_id\n         * @private\n         */\n        _loadTranslations: function () {\n            const domain = [...this.domain, ['lang', 'in', this.languages.map(l => l[0])]];\n            return this._rpc({\n                model: 'ir.translation',\n                method: 'search_read',\n                fields: ['lang', 'src', 'value'],\n                domain: domain,\n            });\n        },\n        /**\n         * Load the installed languages long names and code\n         *\n         * The result of the call is put in cache on the prototype of this dialog.\n         * If any new language is installed, a full page refresh will happen,\n         * so there is no need invalidate it.\n         * @private\n         */\n        _loadLanguages: function () {\n            if (TranslationDialog.prototype.installedLanguagesCache)\n                return Promise.resolve(TranslationDialog.prototype.installedLanguagesCache);\n\n            return this._rpc({\n                model: 'res.lang',\n                method: 'get_installed',\n                fields: ['code', 'name', 'iso_code'],\n            }).then((installedLanguages) => {\n                TranslationDialog.prototype.installedLanguagesCache = installedLanguages;\n                return TranslationDialog.prototype.installedLanguagesCache\n            });\n        },\n\n        //--------------------------------------------------------------------------\n        // Handlers\n        //--------------------------------------------------------------------------\n        /**\n         * Save all the terms that have been updated\n         * @private\n         * @returns a promise that is resolved when all the save have occured\n         */\n        _onSave: function () {\n            var updatedTerm = {};\n            var updateFormViewField;\n\n            this.el.querySelectorAll('input[type=text],textarea').forEach((t) => {\n                var initialValue = this.data.find((d) => d.id == t.dataset.id);\n                if (initialValue.value !== t.value) {\n                    updatedTerm[t.dataset.id] = t.value;\n\n                    if (initialValue.lang === this.currentInterfaceLanguage && !this.showSrc) {\n                        // when the user has changed the term for the language he is\n                        // using in the interface, this change should be reflected\n                        // in the form view\n                        // partial translations being handled server side are\n                        // also ignored\n                        var changes = {};\n                        changes[this.fieldName] = updatedTerm[initialValue.id];\n                        updateFormViewField = {\n                            dataPointID: this.dataPointID,\n                            changes: changes,\n                            doNotSetDirty: false,\n                            node: this.node,\n                        };\n                    }\n                }\n            });\n\n            // updatedTerm only contains the id and values of the terms that\n            // have been updated by the user\n            var saveUpdatedTermsProms = Object.keys(updatedTerm).map((id) => {\n                var writeTranslation = {\n                    model: 'ir.translation',\n                    method: 'write',\n                    context: this.context,\n                    args: [[parseInt(id, 10)], { value: updatedTerm[id] }]\n                };\n                return this._rpc(writeTranslation);\n            });\n            return Promise.all(saveUpdatedTermsProms).then(() => {\n                // we might have to update the value of the field on the form\n                // view that opened the translation dialog\n                if (updateFormViewField) {\n                    this.trigger_up('field_changed', updateFormViewField);\n                }\n            });\n        }\n    });\n\n    return TranslationDialog;\n});\n", "\nodoo.define('web_tour.RunningTourActionHelper', function (require) {\n\"use strict\";\n\nvar core = require('web.core');\nvar utils = require('web_tour.utils');\nvar Tip = require('web_tour.Tip');\n\nvar get_first_visible_element = utils.get_first_visible_element;\nvar get_jquery_element_from_selector = utils.get_jquery_element_from_selector;\n\nvar RunningTourActionHelper = core.Class.extend({\n    init: function (tip_widget) {\n        this.tip_widget = tip_widget;\n    },\n    click: function (element) {\n        this._click(this._get_action_values(element));\n    },\n    dblclick: function (element) {\n        this._click(this._get_action_values(element), 2);\n    },\n    tripleclick: function (element) {\n        this._click(this._get_action_values(element), 3);\n    },\n    clicknoleave: function (element) {\n        this._click(this._get_action_values(element), 1, false);\n    },\n    text: function (text, element) {\n        this._text(this._get_action_values(element), text);\n    },\n    remove_text(text, element) {\n        this._text(this._get_action_values(element), '\\n');\n    },\n    text_blur: function (text, element) {\n        this._text_blur(this._get_action_values(element), text);\n    },\n    drag_and_drop: function (to, element) {\n        this._drag_and_drop(this._get_action_values(element), to);\n    },\n    keydown: function (keyCodes, element) {\n        this._keydown(this._get_action_values(element), keyCodes.split(/[,\\s]+/));\n    },\n    auto: function (element) {\n        var values = this._get_action_values(element);\n        if (values.consume_event === \"input\") {\n            this._text(values);\n        } else {\n            this._click(values);\n        }\n    },\n    _get_action_values: function (element) {\n        var $e = get_jquery_element_from_selector(element);\n        var $element = element ? get_first_visible_element($e) : this.tip_widget.$anchor;\n        if ($element.length === 0) {\n            $element = $e.first();\n        }\n        var consume_event = element ? Tip.getConsumeEventType($element) : this.tip_widget.consume_event;\n        return {\n            $element: $element,\n            consume_event: consume_event,\n        };\n    },\n    _click: function (values, nb, leave) {\n        trigger_mouse_event(values.$element, \"mouseover\");\n        values.$element.trigger(\"mouseenter\");\n        for (var i = 1 ; i <= (nb || 1) ; i++) {\n            trigger_mouse_event(values.$element, \"mousedown\");\n            trigger_mouse_event(values.$element, \"mouseup\");\n            trigger_mouse_event(values.$element, \"click\", i);\n            if (i % 2 === 0) {\n                trigger_mouse_event(values.$element, \"dblclick\");\n            }\n        }\n        if (leave !== false) {\n            trigger_mouse_event(values.$element, \"mouseout\");\n            values.$element.trigger(\"mouseleave\");\n        }\n\n        function trigger_mouse_event($element, type, count) {\n            var e = document.createEvent(\"MouseEvents\");\n            e.initMouseEvent(type, true, true, window, count || 0, 0, 0, 0, 0, false, false, false, false, 0, $element[0]);\n            $element[0].dispatchEvent(e);\n        }\n    },\n    _text: function (values, text) {\n        this._click(values);\n\n        text = text || \"Test\";\n        if (values.consume_event === \"input\") {\n            values.$element\n                .trigger({ type: 'keydown', key: text[text.length - 1] })\n                .val(text)\n                .trigger({ type: 'keyup', key: text[text.length - 1] });\n            values.$element[0].dispatchEvent(new InputEvent('input', {\n                bubbles: true,\n            }));\n        } else if (values.$element.is(\"select\")) {\n            var $options = values.$element.find(\"option\");\n            $options.prop(\"selected\", false).removeProp(\"selected\");\n            var $selectedOption = $options.filter(function () { return $(this).val() === text; });\n            if ($selectedOption.length === 0) {\n                $selectedOption = $options.filter(function () { return $(this).text().trim() === text; });\n            }\n            const regex = /option\\s+([0-9]+)/;\n            if ($selectedOption.length === 0 && regex.test(text)) {\n                // Extract position as 1-based, as the nth selectors.\n                const position = parseInt(regex.exec(text)[1]);\n                $selectedOption = $options.eq(position - 1); // eq is 0-based.\n            }\n            $selectedOption.prop(\"selected\", true);\n            this._click(values);\n            // For situations where an `oninput` is defined.\n            values.$element.trigger(\"input\");\n        } else {\n            values.$element.focusIn();\n            values.$element.trigger($.Event( \"keydown\", {key: '_', keyCode: 95}));\n            values.$element.text(text).trigger(\"input\");\n            values.$element.focusInEnd();\n            values.$element.trigger($.Event( \"keyup\", {key: '_', keyCode: 95}));\n        }\n        values.$element.trigger(\"change\");\n    },\n    _text_blur: function (values, text) {\n        this._text(values, text);\n        values.$element.trigger('focusout');\n        values.$element.trigger('blur');\n    },\n    _drag_and_drop: function (values, to) {\n        var $to;\n        var elementCenter = values.\n        $element.offset();\n        elementCenter.left += values.$element.outerWidth() / 2;\n        elementCenter.top += values.$element.outerHeight() / 2;\n        if (to) {\n            $to = get_jquery_element_from_selector(to);\n        } else {\n            $to = $(document.body);\n        }\n\n        const calculateCenter = () => {\n            const toCenter = $to.offset();\n\n            if (to && to.indexOf('iframe') !== -1) {\n                const iFrameOffset = $('iframe').offset();\n                toCenter.left += iFrameOffset.left;\n                toCenter.top += iFrameOffset.top;\n            }\n            toCenter.left += $to.outerWidth() / 2;\n            toCenter.top += $to.outerHeight() / 2;\n            return toCenter;\n        };\n\n        values.$element.trigger($.Event(\"mouseenter\"));\n        values.$element.trigger($.Event(\"mousedown\", {which: 1, pageX: elementCenter.left, pageY: elementCenter.top}));\n        // Some tests depends on elements present only when the element to drag\n        // start to move while some other tests break while moving.\n        if (!$to.length) {\n            values.$element.trigger($.Event(\"mousemove\", {which: 1, pageX: elementCenter.left + 1, pageY: elementCenter.top}));\n            $to = get_jquery_element_from_selector(to);\n        }\n\n        let toCenter = calculateCenter();\n        values.$element.trigger($.Event(\"mousemove\", {which: 1, pageX: toCenter.left, pageY: toCenter.top}));\n        // Recalculate the center as the mousemove might have made the element bigger.\n        toCenter = calculateCenter();\n        values.$element.trigger($.Event(\"mouseup\", {which: 1, pageX: toCenter.left, pageY: toCenter.top}));\n     },\n    _keydown: function (values, keyCodes) {\n        while (keyCodes.length) {\n            const eventOptions = {};\n            const keyCode = keyCodes.shift();\n            let insertedText = null;\n            if (isNaN(keyCode)) {\n                eventOptions.key = keyCode;\n            } else {\n                const code = parseInt(keyCode, 10);\n                eventOptions.keyCode = code;\n                eventOptions.which = code;\n                if (\n                    code === 32 || // spacebar\n                    (code > 47 && code < 58) || // number keys\n                    (code > 64 && code < 91) || // letter keys\n                    (code > 95 && code < 112) || // numpad keys\n                    (code > 185 && code < 193) || // ;=,-./` (in order)\n                    (code > 218 && code < 223) // [\\]' (in order))\n                ) {\n                    insertedText = String.fromCharCode(code);\n                }\n            }\n            values.$element.trigger(Object.assign({ type: \"keydown\" }, eventOptions));\n            if (insertedText) {\n                document.execCommand(\"insertText\", 0, insertedText);\n            }\n            values.$element.trigger(Object.assign({ type: \"keyup\" }, eventOptions));\n        }\n    },\n});\n\nreturn RunningTourActionHelper;\n});\n", "odoo.define('web_tour.Tip', function (require) {\n\"use strict\";\n\nvar config = require('web.config');\nvar core = require('web.core');\nvar Widget = require('web.Widget');\nvar _t = core._t;\n\nvar Tip = Widget.extend({\n    template: \"Tip\",\n    xmlDependencies: ['/web_tour/static/src/xml/tip.xml'],\n    events: {\n        click: '_onTipClicked',\n        mouseenter: '_onMouseEnter',\n        mouseleave: '_onMouseLeave',\n        transitionend: '_onTransitionEnd',\n    },\n    CENTER_ON_TEXT_TAGS: ['P', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6'],\n\n    /**\n     * @param {Widget} parent\n     * @param {Object} [info] description of the tip, containing the following keys:\n     *  - content [String] the html content of the tip\n     *  - event_handlers [Object] description of optional event handlers to bind to the tip:\n     *    - event [String] the event name\n     *    - selector [String] the jQuery selector on which the event should be bound\n     *    - handler [function] the handler\n     *  - position [String] tip's position ('top', 'right', 'left' or 'bottom'), default 'right'\n     *  - width [int] the width in px of the tip when opened, default 270\n     *  - space [int] space in px between anchor and tip, default to 0, added to\n     *    the natural space chosen in css\n     *  - hidden [boolean] if true, the tip won't be visible (but the handlers will still be\n     *    bound on the anchor, so that the tip is consumed if the user clicks on it)\n     *  - overlay [Object] x and y values for the number of pixels the mouseout detection area\n     *    overlaps the opened tip, default {x: 50, y: 50}\n     */\n    init: function(parent, info) {\n        this._super(parent);\n        this.info = _.defaults(info, {\n            position: \"right\",\n            width: 270,\n            space: 0,\n            overlay: {\n                x: 50,\n                y: 50,\n            },\n            content: _t(\"Click here to go to the next step.\"),\n            scrollContent: _t(\"Scroll to reach the next step.\"),\n        });\n        this.position = {\n            top: \"50%\",\n            left: \"50%\",\n        };\n        this.initialPosition = this.info.position;\n        this.viewPortState = 'in';\n        this._onAncestorScroll = _.throttle(this._onAncestorScroll, 0.1);\n    },\n    /**\n     * Attaches the tip to the provided $anchor and $altAnchor.\n     * $altAnchor is an alternative trigger that can consume the step. The tip is\n     * however only displayed on the $anchor.\n     *\n     * Note that the returned promise stays pending if the Tip widget was\n     * destroyed in the meantime.\n     *\n     * @param {jQuery} $anchor the node on which the tip should be placed\n     * @param {jQuery} $altAnchor an alternative node that can consume the step\n     * @return {Promise}\n     */\n    attach_to: async function ($anchor, $altAnchor) {\n        this._setupAnchor($anchor, $altAnchor);\n\n        this.is_anchor_fixed_position = this.$anchor.css(\"position\") === \"fixed\";\n\n        // The body never needs to have the o_tooltip_parent class. It is a\n        // safe place to put the tip in the DOM at initialization and be able\n        // to compute its dimensions and reposition it if required.\n        await this.appendTo(document.body);\n        if (this.isDestroyed()) {\n            return new Promise(() => {});\n        }\n    },\n    start() {\n        this.$tooltip_overlay = this.$(\".o_tooltip_overlay\");\n        this.$tooltip_content = this.$(\".o_tooltip_content\");\n        this.init_width = this.$el.outerWidth();\n        this.init_height = this.$el.outerHeight();\n        this.$el.addClass('active');\n        this.el.style.setProperty('width', `${this.info.width}px`, 'important');\n        this.el.style.setProperty('height', 'auto', 'important');\n        this.el.style.setProperty('transition', 'none', 'important');\n        this.content_width = this.$el.outerWidth(true);\n        this.content_height = this.$el.outerHeight(true);\n        this.$tooltip_content.html(this.info.scrollContent);\n        this.scrollContentWidth = this.$el.outerWidth(true);\n        this.scrollContentHeight = this.$el.outerHeight(true);\n        this.$el.removeClass('active');\n        this.el.style.removeProperty('width');\n        this.el.style.removeProperty('height');\n        this.el.style.removeProperty('transition');\n        this.$tooltip_content.html(this.info.content);\n        this.$window = $(window);\n\n        this.$tooltip_content.css({\n            width: \"100%\",\n            height: \"100%\",\n        });\n\n        _.each(this.info.event_handlers, data => {\n            this.$tooltip_content.on(data.event, data.selector, data.handler);\n        });\n\n        this._bind_anchor_events();\n        this._updatePosition(true);\n\n        this.$el.toggleClass('d-none', !!this.info.hidden);\n        this.el.classList.add('o_tooltip_visible');\n        core.bus.on(\"resize\", this, _.debounce(function () {\n            if (this.isDestroyed()) {\n                // Because of the debounce, destroy() might have been called in the meantime.\n                return;\n            }\n            if (this.tip_opened) {\n                this._to_bubble_mode(true);\n            } else {\n                this._reposition();\n            }\n        }, 500));\n\n        return this._super.apply(this, arguments);\n    },\n    destroy: function () {\n        this._unbind_anchor_events();\n        clearTimeout(this.timerIn);\n        clearTimeout(this.timerOut);\n        // clear this timeout so that we won't call _updatePosition after we\n        // destroy the widget and leave an undesired bubble.\n        clearTimeout(this._transitionEndTimer);\n\n        // Do not remove the parent class if it contains other tooltips\n        const _removeParentClass = $el => {\n            if ($el.children(\".o_tooltip\").not(this.$el[0]).length === 0) {\n                $el.removeClass(\"o_tooltip_parent\");\n            }\n        };\n        if (this.$el && this.$ideal_location) {\n            _removeParentClass(this.$ideal_location);\n        }\n        if (this.$el && this.$furtherIdealLocation) {\n            _removeParentClass(this.$furtherIdealLocation);\n        }\n\n        return this._super.apply(this, arguments);\n    },\n    /**\n     * Updates the $anchor and $altAnchor the tip is attached to.\n     * $altAnchor is an alternative trigger that can consume the step. The tip is\n     * however only displayed on the $anchor.\n     *\n     * @param {jQuery} $anchor the node on which the tip should be placed\n     * @param {jQuery} $altAnchor an alternative node that can consume the step\n     */\n    update: function ($anchor, $altAnchor) {\n        // We unbind/rebind events on each update because we support widgets\n        // detaching and re-attaching nodes to their DOM element without keeping\n        // the initial event handlers, with said node being potential tip\n        // anchors (e.g. FieldMonetary > input element).\n        this._unbind_anchor_events();\n        if (!$anchor.is(this.$anchor)) {\n            this._setupAnchor($anchor, $altAnchor);\n        }\n        this._bind_anchor_events();\n        if (!this.$el) {\n            // Ideally this case should not happen but this is still possible,\n            // as update may be called before the `start` method is called.\n            // The `start` method is calling _updatePosition too anyway.\n            return;\n        }\n        this._delegateEvents();\n        this._updatePosition(true);\n    },\n\n    //--------------------------------------------------------------------------\n    // Public\n    //--------------------------------------------------------------------------\n\n    /**\n     * @return {boolean} true if tip is visible\n     */\n    isShown() {\n        return this.el && !this.info.hidden;\n    },\n\n    //--------------------------------------------------------------------------\n    // Private\n    //--------------------------------------------------------------------------\n\n    /**\n     * Sets the $anchor and $altAnchor the tip is attached to.\n     * $altAnchor is an alternative trigger that can consume the step. The tip is\n     * however only displayed on the $anchor.\n     *\n     * @param {jQuery} $anchor the node on which the tip should be placed\n     * @param {jQuery} $altAnchor an alternative node that can consume the step\n     */\n    _setupAnchor: function ($anchor, $altAnchor) {\n        this.$anchor = $anchor;\n        this.$altAnchor = $altAnchor;\n        this.$ideal_location = this._get_ideal_location();\n        this.$furtherIdealLocation = this._get_ideal_location(this.$ideal_location);\n    },\n    /**\n     * Figures out which direction the tip should take and if it is at the\n     * bottom or the top of the targeted element or if it's an indicator to\n     * scroll. Relocates and repositions if necessary.\n     *\n     * @private\n     * @param {boolean} [forceReposition=false]\n     */\n    _updatePosition: function (forceReposition = false) {\n        if (this.info.hidden) {\n            return;\n        }\n        if (this.isDestroyed()) {\n            // TODO This should not be needed if the chain of events leading\n            // here was fully cancelled by destroy().\n            return;\n        }\n        let halfHeight = 0;\n        if (this.initialPosition === 'right' || this.initialPosition === 'left') {\n            halfHeight = this.$anchor.innerHeight() / 2;\n        }\n\n        const paddingTop = parseInt(this.$ideal_location.css('padding-top'));\n        const topViewport = window.pageYOffset + paddingTop;\n        const botViewport = window.pageYOffset + window.innerHeight;\n        const topOffset = this.$anchor.offset().top;\n        const botOffset = topOffset + this.$anchor.innerHeight();\n\n        // Check if the viewport state change to know if we need to move the anchor of the tip.\n        // up : the target element is above the current viewport\n        // down : the target element is below the current viewport\n        // in : the target element is in the current viewport\n        let viewPortState = 'in';\n        let position = this.info.position;\n        if (botOffset - halfHeight < topViewport) {\n            viewPortState = 'up';\n            position = 'bottom';\n        } else if (topOffset + halfHeight > botViewport) {\n            viewPortState = 'down';\n            position = 'top';\n        } else {\n            // Adjust the placement of the tip regarding its anchor depending\n            // if we came from the bottom or the top.\n            if (topOffset < topViewport + this.$el.innerHeight()) {\n                position = halfHeight ? this.initialPosition : \"bottom\";\n            } else if (botOffset > botViewport - this.$el.innerHeight()) {\n                position = halfHeight ? this.initialPosition : \"top\";\n            }\n        }\n\n        // If the direction or the anchor change : The tip position is updated.\n        if (forceReposition || this.info.position !== position || this.viewPortState !== viewPortState) {\n            this.$el.removeClass('top right bottom left').addClass(position);\n            this.viewPortState = viewPortState;\n            this.info.position = position;\n            let $location;\n            if (this.viewPortState === 'in') {\n                this.$tooltip_content.html(this.info.content);\n                $location = this.$ideal_location;\n            } else {\n                this.$tooltip_content.html(this.info.scrollContent);\n                $location = this.$furtherIdealLocation;\n            }\n            // Update o_tooltip_parent class and tip DOM location. Note:\n            // important to only remove/add the class when necessary to not\n            // notify a DOM mutation which could retrigger this function.\n            const $oldLocation = this.$el.parent();\n            if (!this.tip_opened) {\n                if (!$location.is($oldLocation)) {\n                    $oldLocation.removeClass('o_tooltip_parent');\n                    const cssPosition = $location.css(\"position\");\n                    if (cssPosition === \"static\" || cssPosition === \"relative\") {\n                        $location.addClass(\"o_tooltip_parent\");\n                    }\n                    this.$el.appendTo($location);\n                }\n                this._reposition();\n            }\n        }\n    },\n    _get_ideal_location: function ($anchor = this.$anchor) {\n        var $location = this.info.location ? $(this.info.location) : $anchor;\n        if ($location.is(\"html,body\")) {\n            return $(document.body);\n        }\n\n        var o;\n        var p;\n        do {\n            $location = $location.parent();\n            o = $location.css(\"overflow\");\n            p = $location.css(\"position\");\n        } while (\n            $location.hasClass('dropdown-menu') ||\n            $location.hasClass('o_notebook_headers') ||\n            $location.hasClass('o_forbidden_tooltip_parent') ||\n            (\n                (o === \"visible\" || o.includes(\"hidden\")) && // Possible case where the overflow = \"hidden auto\"\n                p !== \"fixed\" &&\n                $location[0].tagName.toUpperCase() !== 'BODY'\n            )\n        );\n\n        return $location;\n    },\n    _reposition: function () {\n        this.$el.removeClass(\"o_animated\");\n\n        // Reverse left/right position if direction is right to left\n        var appendAt = this.info.position;\n        var rtlMap = {left: 'right', right: 'left'};\n        if (rtlMap[appendAt] && _t.database.parameters.direction === 'rtl') {\n            appendAt = rtlMap[appendAt];\n        }\n\n        // Get the correct tip's position depending of the tip's state\n        let $parent = this.$ideal_location;\n        if ($parent.is('html,body') && this.viewPortState !== \"in\") {\n            this.el.style.setProperty('position', 'fixed', 'important');\n        } else {\n            this.el.style.removeProperty('position');\n        }\n\n        if (this.viewPortState === 'in') {\n            this.$el.position({\n                my: this._get_spaced_inverted_position(appendAt),\n                at: appendAt,\n                of: this.$anchor,\n                collision: \"none\",\n                using: props => {\n                    const {top} = props;\n                    let {left} = props;\n                    const anchorEl = this.$anchor[0];\n                    if (this.CENTER_ON_TEXT_TAGS.includes(anchorEl.nodeName) && anchorEl.hasChildNodes()) {\n                        const textContainerWidth = anchorEl.getBoundingClientRect().width;\n                        const textNode = anchorEl.firstChild;\n                        const range = document.createRange();\n                        range.selectNodeContents(textNode);\n                        const textWidth = range.getBoundingClientRect().width;\n\n                        const alignment = window.getComputedStyle(anchorEl).getPropertyValue('text-align');\n                        const posVertical = (this.info.position === 'top' || this.info.position === 'bottom');\n                        if (alignment === 'left') {\n                            if (posVertical) {\n                                left = left - textContainerWidth / 2 + textWidth / 2;\n                            } else if (this.info.position === 'right') {\n                                left = left - textContainerWidth + textWidth;\n                            }\n                        } else if (alignment === 'right') {\n                            if (posVertical) {\n                                left = left + textContainerWidth / 2 - textWidth / 2;\n                            } else if (this.info.position === 'left') {\n                                left = left + textContainerWidth - textWidth;\n                            }\n                        } else if (alignment === 'center') {\n                            if (this.info.position === 'left') {\n                                left = left + textContainerWidth / 2 - textWidth / 2;\n                            } else if (this.info.position === 'right') {\n                                left = left - textContainerWidth / 2 + textWidth / 2;\n                            }\n                        }\n                    }\n                    this.el.style.setProperty('top', `${top}px`, 'important');\n                    this.el.style.setProperty('left', `${left}px`, 'important');\n                },\n            });\n        } else {\n            const paddingTop = parseInt($parent.css('padding-top'));\n            const paddingLeft = parseInt($parent.css('padding-left'));\n            const paddingRight = parseInt($parent.css('padding-right'));\n            const topPosition = $parent[0].offsetTop;\n            const center = (paddingLeft + paddingRight) + ((($parent[0].clientWidth - (paddingLeft + paddingRight)) / 2) - this.$el[0].offsetWidth / 2);\n            let top;\n            if (this.viewPortState === 'up') {\n                top = topPosition + this.$el.innerHeight() + paddingTop;\n            } else {\n                top = topPosition + $parent.innerHeight() - this.$el.innerHeight() * 2;\n            }\n            this.el.style.setProperty('top', `${top}px`, 'important');\n            this.el.style.setProperty('left', `${center}px`, 'important');\n        }\n\n        // Reverse overlay if direction is right to left\n        var positionRight = _t.database.parameters.direction === 'rtl' ? \"right\" : \"left\";\n        var positionLeft = _t.database.parameters.direction === 'rtl' ? \"left\" : \"right\";\n\n        // get the offset position of this.$el\n        // Couldn't use offset() or position() because their values are not the desired ones in all cases\n        const offset = {top: this.$el[0].offsetTop, left: this.$el[0].offsetLeft};\n        this.$tooltip_overlay.css({\n            top: -Math.min((this.info.position === \"bottom\" ? this.info.space : this.info.overlay.y), offset.top),\n            right: -Math.min((this.info.position === positionRight ? this.info.space : this.info.overlay.x), this.$window.width() - (offset.left + this.init_width)),\n            bottom: -Math.min((this.info.position === \"top\" ? this.info.space : this.info.overlay.y), this.$window.height() - (offset.top + this.init_height)),\n            left: -Math.min((this.info.position === positionLeft ? this.info.space : this.info.overlay.x), offset.left),\n        });\n        this.position = offset;\n\n        this.$el.addClass(\"o_animated\");\n    },\n    _bind_anchor_events: function () {\n        // The consume_event taken for RunningTourActionHelper is the one of $anchor and not $altAnchor.\n        this.consume_event = this.info.consumeEvent || Tip.getConsumeEventType(this.$anchor, this.info.run);\n        this.$consumeEventAnchors = this._getAnchorAndCreateEvent(this.consume_event, this.$anchor);\n        if (this.$altAnchor.length) {\n            const consumeEvent  = this.info.consumeEvent || Tip.getConsumeEventType(this.$altAnchor, this.info.run);\n            this.$consumeEventAnchors = this.$consumeEventAnchors.add(\n                this._getAnchorAndCreateEvent(consumeEvent, this.$altAnchor)\n            );\n        }\n        this.$anchor.on('mouseenter.anchor', () => this._to_info_mode());\n        this.$anchor.on('mouseleave.anchor', () => this._to_bubble_mode());\n\n        this.$scrolableElement = this.$ideal_location.is('html,body') ? $(window) : this.$ideal_location;\n        this.$scrolableElement.on('scroll.Tip', () => this._onAncestorScroll());\n    },\n    /**\n     * Gets the anchor corresponding to the provided arguments and attaches the\n     * event to the $anchor in order to consume the step accordingly.\n     *\n     * @private\n     * @param {String} consumeEvent\n     * @param {jQuery} $anchor the node on which the tip should be placed\n     * @return {jQuery}\n     */\n    _getAnchorAndCreateEvent: function(consumeEvent, $anchor) {\n        let $consumeEventAnchors = $anchor;\n        if (consumeEvent === \"drag\") {\n            // jQuery-ui draggable triggers 'drag' events on the .ui-draggable element,\n            // but the tip is attached to the .ui-draggable-handle element which may\n            // be one of its children (or the element itself)\n            $consumeEventAnchors = $anchor.closest('.ui-draggable');\n        } else if (consumeEvent === \"input\" && !$anchor.is('textarea, input')) {\n            $consumeEventAnchors = $anchor.closest(\"[contenteditable='true']\");\n        } else if (consumeEvent.includes('apply.daterangepicker')) {\n            $consumeEventAnchors = $anchor.parent().children('.o_field_date_range');\n        } else if (consumeEvent === \"sort\") {\n            // when an element is dragged inside a sortable container (with classname\n            // 'ui-sortable'), jQuery triggers the 'sort' event on the container\n            $consumeEventAnchors = $anchor.closest('.ui-sortable');\n        }\n        $consumeEventAnchors.on(consumeEvent + \".anchor\", (function (e) {\n            if (e.type !== \"mousedown\" || e.which === 1) { // only left click\n                if (this.info.consumeVisibleOnly && !this.isShown()) {\n                    // Do not consume non-displayed tips.\n                    return;\n                }\n                this.trigger(\"tip_consumed\");\n                this._unbind_anchor_events();\n            }\n        }).bind(this));\n        return $consumeEventAnchors;\n    },\n    _unbind_anchor_events: function () {\n        if (this.$anchor) {\n            this.$anchor.off(\".anchor\");\n        }\n        if (this.$consumeEventAnchors) {\n            this.$consumeEventAnchors.off(\".anchor\");\n        }\n        if (this.$scrolableElement) {\n            this.$scrolableElement.off('.Tip');\n        }\n    },\n    _get_spaced_inverted_position: function (position) {\n        if (position === \"right\") return \"left+\" + this.info.space;\n        if (position === \"left\") return \"right-\" + this.info.space;\n        if (position === \"bottom\") return \"top+\" + this.info.space;\n        return \"bottom-\" + this.info.space;\n    },\n    _to_info_mode: function (force) {\n        if (this.timerOut !== undefined) {\n            clearTimeout(this.timerOut);\n            this.timerOut = undefined;\n            return;\n        }\n        if (this.tip_opened) {\n            return;\n        }\n\n        if (force === true) {\n            this._build_info_mode();\n        } else {\n            this.timerIn = setTimeout(this._build_info_mode.bind(this), 100);\n        }\n    },\n    _build_info_mode: function () {\n        clearTimeout(this.timerIn);\n        this.timerIn = undefined;\n\n        this.tip_opened = true;\n\n        var offset = this.$el.offset();\n\n        // When this.$el doesn't have any parents, it means that the tip is no\n        // longer in the DOM and so, it shouldn't be open. It happens when the\n        // tip is opened after being destroyed.\n        if (!this.$el.parent().length) {\n            return;\n        }\n\n        if (this.$el.parent()[0] !== this.$el[0].ownerDocument.body) {\n            this.$el.detach();\n            this.el.style.setProperty('top', `${offset.top}px`, 'important');\n            this.el.style.setProperty('left', `${offset.left}px`, 'important');\n            this.$el.appendTo(this.$el[0].ownerDocument.body);\n        }\n\n        var mbLeft = 0;\n        var mbTop = 0;\n        var overflow = false;\n        var posVertical = (this.info.position === \"top\" || this.info.position === \"bottom\");\n        if (posVertical) {\n            overflow = (offset.left + this.content_width + this.info.overlay.x > this.$window.width());\n        } else {\n            overflow = (offset.top + this.content_height + this.info.overlay.y > this.$window.height());\n        }\n        if (posVertical && overflow || this.info.position === \"left\" || (_t.database.parameters.direction === 'rtl' && this.info.position == \"right\")) {\n            mbLeft -= (this.content_width - this.init_width);\n        }\n        if (!posVertical && overflow || this.info.position === \"top\") {\n            mbTop -= (this.viewPortState === 'down') ? this.init_height - 5 : (this.content_height - this.init_height);\n        }\n\n\n        const [contentWidth, contentHeight] = this.viewPortState === 'in'\n            ? [this.content_width, this.content_height]\n            : [this.scrollContentWidth, this.scrollContentHeight];\n        this.$el.toggleClass(\"inverse\", overflow);\n        this.$el.removeClass(\"o_animated\").addClass(\"active\");\n        this.el.style.setProperty('width', `${contentWidth}px`, 'important');\n        this.el.style.setProperty('height', `${contentHeight}px`, 'important');\n        this.el.style.setProperty('margin-left', `${mbLeft}px`, 'important');\n        this.el.style.setProperty('margin-top', `${mbTop}px`, 'important');\n\n        this._transitionEndTimer = setTimeout(() => this._onTransitionEnd(), 400);\n    },\n    _to_bubble_mode: function (force) {\n        if (this.timerIn !== undefined) {\n            clearTimeout(this.timerIn);\n            this.timerIn = undefined;\n            return;\n        }\n        if (!this.tip_opened) {\n            return;\n        }\n\n        if (force === true) {\n            this._build_bubble_mode();\n        } else {\n            this.timerOut = setTimeout(this._build_bubble_mode.bind(this), 300);\n        }\n    },\n    _build_bubble_mode: function () {\n        clearTimeout(this.timerOut);\n        this.timerOut = undefined;\n\n        this.tip_opened = false;\n        this.$el.removeClass(\"active\").addClass(\"o_animated\");\n        this.el.style.setProperty('width', `${this.init_width}px`, 'important');\n        this.el.style.setProperty('height', `${this.init_height}px`, 'important');\n        this.el.style.setProperty('margin', '0', 'important');\n\n        this._transitionEndTimer = setTimeout(() => this._onTransitionEnd(), 400);\n    },\n\n    //--------------------------------------------------------------------------\n    // Handlers\n    //--------------------------------------------------------------------------\n\n    /**\n     * @private\n     */\n    _onAncestorScroll: function () {\n        if (this.tip_opened) {\n            this._to_bubble_mode(true);\n        } else {\n            this._updatePosition(true);\n        }\n    },\n    /**\n     * @private\n     */\n    _onMouseEnter: function () {\n        this._to_info_mode();\n    },\n    /**\n     * @private\n     */\n    _onMouseLeave: function () {\n        this._to_bubble_mode();\n    },\n    /**\n     * On touch devices, closes the tip when clicked.\n     *\n     * Also stop propagation to avoid undesired behavior, such as the kanban\n     * quick create closing when the user clicks on the tooltip.\n     *\n     * @private\n     * @param {MouseEvent} ev\n     */\n    _onTipClicked: function (ev) {\n        if (config.device.touch && this.tip_opened) {\n            this._to_bubble_mode();\n        }\n\n        ev.stopPropagation();\n    },\n    /**\n     * @private\n     */\n    _onTransitionEnd: function () {\n        if (this._transitionEndTimer) {\n            clearTimeout(this._transitionEndTimer);\n            this._transitionEndTimer = undefined;\n            if (!this.tip_opened) {\n                this._updatePosition(true);\n            }\n        }\n    },\n});\n\n/**\n * @static\n * @param {jQuery} $element\n * @param {string} [run] the run parameter of the tip (only strings are useful)\n */\nTip.getConsumeEventType = function ($element, run) {\n    if ($element.hasClass('o_field_many2one') || $element.hasClass('o_field_many2manytags')) {\n        return 'autocompleteselect';\n    } else if ($element.is(\"textarea\") || $element.filter(\"input\").is(function () {\n        var type = $(this).attr(\"type\");\n        return !type || !!type.match(/^(email|number|password|search|tel|text|url)$/);\n    })) {\n        // FieldDateRange triggers a special event when using the widget\n        if ($element.hasClass(\"o_field_date_range\")) {\n            return \"apply.daterangepicker input\";\n        }\n        if (config.device.isMobile &&\n            $element.closest('.o_field_widget').is('.o_field_many2one, .o_field_many2many')) {\n            return \"click\";\n        }\n        return \"input\";\n    } else if ($element.hasClass('ui-draggable-handle')) {\n        return \"drag\";\n    } else if (typeof run === 'string' && run.indexOf('drag_and_drop') === 0) {\n        // this is a heuristic: the element has to be dragged and dropped but it\n        // doesn't have class 'ui-draggable-handle', so we check if it has an\n        // ui-sortable parent, and if so, we conclude that its event type is 'sort'\n        if ($element.closest('.ui-sortable').length) {\n            return 'sort';\n        }\n    }\n    return \"click\";\n};\n\nreturn Tip;\n\n});\n", "odoo.define('web_tour.TourManager', function(require) {\n\"use strict\";\n\nvar core = require('web.core');\nvar config = require('web.config');\nvar local_storage = require('web.local_storage');\nvar mixins = require('web.mixins');\nvar utils = require('web_tour.utils');\nvar TourStepUtils = require('web_tour.TourStepUtils');\nvar RunningTourActionHelper = require('web_tour.RunningTourActionHelper');\nvar ServicesMixin = require('web.ServicesMixin');\nvar session = require('web.session');\nvar Tip = require('web_tour.Tip');\nconst {Markup} = require('web.utils');\n\nvar _t = core._t;\n\nvar RUNNING_TOUR_TIMEOUT = 10000;\n\nvar get_step_key = utils.get_step_key;\nvar get_debugging_key = utils.get_debugging_key;\nvar get_running_key = utils.get_running_key;\nvar get_running_delay_key = utils.get_running_delay_key;\nvar get_first_visible_element = utils.get_first_visible_element;\nvar do_before_unload = utils.do_before_unload;\nvar get_jquery_element_from_selector = utils.get_jquery_element_from_selector;\n\nreturn core.Class.extend(mixins.EventDispatcherMixin, ServicesMixin, {\n    init: function(parent, consumed_tours, disabled = false) {\n        mixins.EventDispatcherMixin.init.call(this);\n        this.setParent(parent);\n\n        this.$body = $('body');\n        this.active_tooltips = {};\n        this.tours = {};\n        // remove the tours being debug from the list of consumed tours\n        this.consumed_tours = (consumed_tours || []).filter(tourName => {\n            return !local_storage.getItem(get_debugging_key(tourName));\n        });\n        this.disabled = disabled;\n        this.running_tour = local_storage.getItem(get_running_key());\n        this.running_step_delay = parseInt(local_storage.getItem(get_running_delay_key()), 10) || 0;\n        this.edition = (_.last(session.server_version_info) === 'e') ? 'enterprise' : 'community';\n        this._log = [];\n        console.log('Tour Manager is ready.  running_tour=' + this.running_tour);\n    },\n    /**\n     * Registers a tour described by the following arguments *in order*\n     *\n     * @param {string} name - tour's name\n     * @param {Object} [options] - options (optional), available options are:\n     * @param {boolean} [options.test=false] - true if this is only for tests\n     * @param {boolean} [options.skip_enabled=false]\n     *        true to add a link in its tips to consume the whole tour\n     * @param {string} [options.url]\n     *        the url to load when manually running the tour\n     * @param {boolean} [options.rainbowMan=true]\n     *        whether or not the rainbowman must be shown at the end of the tour\n     * @param {string} [options.fadeout]\n     *        Delay for rainbowman to disappear. 'fast' will make rainbowman dissapear, quickly,\n     *        'medium', 'slow' and 'very_slow' will wait little longer before disappearing, no\n     *        will keep rainbowman on screen until user clicks anywhere outside rainbowman\n     * @param {boolean} [options.sequence=1000]\n     *        priority sequence of the tour (lowest is first, tours with the same\n     *        sequence will be executed in a non deterministic order).\n     * @param {Promise} [options.wait_for]\n     *        indicates when the tour can be started\n     * @param {string|function} [options.rainbowManMessage]\n              text or function returning the text displayed under the rainbowman\n              at the end of the tour.\n     * @param {Object[]} steps - steps' descriptions, each step being an object\n     *                     containing a tip description\n     */\n    register: function() {\n        var args = Array.prototype.slice.call(arguments);\n        var last_arg = args[args.length - 1];\n        var name = args[0];\n        if (this.tours[name]) {\n            console.warn(_.str.sprintf(\"Tour %s is already defined\", name));\n            return;\n        }\n        var options = args.length === 2 ? {} : args[1];\n        var steps = last_arg instanceof Array ? last_arg : [last_arg];\n        var tour = {\n            name: options.saveAs || name,\n            steps: steps,\n            url: options.url,\n            rainbowMan: options.rainbowMan === undefined ? true : !!options.rainbowMan,\n            rainbowManMessage: options.rainbowManMessage,\n            fadeout: options.fadeout || 'medium',\n            sequence: options.sequence || 1000,\n            test: options.test,\n            wait_for: options.wait_for || Promise.resolve(),\n        };\n        if (options.skip_enabled) {\n            tour.skip_link = Markup`<p><span class=\"o_skip_tour\">${_t('Skip tour')}</span></p>`;\n            tour.skip_handler = function (tip) {\n                this._deactivate_tip(tip);\n                this._consume_tour(name);\n            };\n        }\n        this.tours[tour.name] = tour;\n    },\n    /**\n     * Returns a promise which is resolved once the tour can be started. This\n     * is when the DOM is ready and at the end of the execution stack so that\n     * all tours have potentially been extended by all apps.\n     *\n     * @private\n     * @returns {Promise}\n     */\n    _waitBeforeTourStart: function () {\n        return new Promise(function (resolve) {\n            $(function () {\n                setTimeout(resolve);\n            });\n        });\n    },\n    _register_all: function (do_update) {\n        var self = this;\n        if (this._allRegistered) {\n            return Promise.resolve();\n        }\n        this._allRegistered = true;\n        return self._waitBeforeTourStart().then(function () {\n            return Promise.all(_.map(self.tours, function (tour, name) {\n                return self._register(do_update, tour, name);\n            })).then(() => self.update());\n        });\n    },\n    _register: function (do_update, tour, name) {\n        const debuggingTour = local_storage.getItem(get_debugging_key(name));\n        if (this.disabled && !this.running_tour && !debuggingTour) {\n            this.consumed_tours.push(name);\n        }\n\n        if (tour.ready) return Promise.resolve();\n\n        const tour_is_consumed = this._isTourConsumed(name);\n\n        return tour.wait_for.then((function () {\n            tour.current_step = parseInt(local_storage.getItem(get_step_key(name))) || 0;\n            tour.steps = _.filter(tour.steps, (function (step) {\n                return (!step.edition || step.edition === this.edition) &&\n                    (step.mobile === undefined || step.mobile === config.device.isMobile);\n            }).bind(this));\n\n            if (tour_is_consumed || tour.current_step >= tour.steps.length) {\n                local_storage.removeItem(get_step_key(name));\n                tour.current_step = 0;\n            }\n\n            tour.ready = true;\n\n            if (debuggingTour ||\n                (do_update && (this.running_tour === name ||\n                              (!this.running_tour && !tour.test && !tour_is_consumed)))) {\n                this._to_next_step(name, 0);\n            }\n        }).bind(this));\n    },\n    /**\n     * Resets the given tour to its initial step, and prevent it from being\n     * marked as consumed at reload.\n     *\n     * @param {string} tourName\n     */\n    reset: function (tourName) {\n        // remove it from the list of consumed tours\n        const index = this.consumed_tours.indexOf(tourName);\n        if (index >= 0) {\n            this.consumed_tours.splice(index, 1);\n        }\n        // mark it as being debugged\n        local_storage.setItem(get_debugging_key(tourName), true);\n        // reset it to the first step\n        const tour = this.tours[tourName];\n        tour.current_step = 0;\n        local_storage.removeItem(get_step_key(tourName));\n        this._to_next_step(tourName, 0);\n        // redirect to its starting point (or /web by default)\n        window.location.href = window.location.origin + (tour.url || '/web');\n    },\n    run: function (tour_name, step_delay) {\n        console.log(_.str.sprintf(\"Preparing tour %s\", tour_name));\n        if (this.running_tour) {\n            this._deactivate_tip(this.active_tooltips[this.running_tour]);\n            this._consume_tour(this.running_tour, _.str.sprintf(\"Killing tour %s\", this.running_tour));\n            return;\n        }\n        var tour = this.tours[tour_name];\n        if (!tour) {\n            console.warn(_.str.sprintf(\"Unknown Tour %s\", name));\n            return;\n        }\n        console.log(_.str.sprintf(\"Running tour %s\", tour_name));\n        this.running_tour = tour_name;\n        this.running_step_delay = step_delay || this.running_step_delay;\n        local_storage.setItem(get_running_key(), this.running_tour);\n        local_storage.setItem(get_running_delay_key(), this.running_step_delay);\n\n        this._deactivate_tip(this.active_tooltips[tour_name]);\n\n        tour.current_step = 0;\n        this._to_next_step(tour_name, 0);\n        local_storage.setItem(get_step_key(tour_name), tour.current_step);\n\n        if (tour.url) {\n            this.pause();\n            do_before_unload(null, (function () {\n                this.play();\n                this.update();\n            }).bind(this));\n\n            window.location.href = window.location.origin + tour.url;\n        } else {\n            this.update();\n        }\n    },\n    pause: function () {\n        this.paused = true;\n    },\n    play: function () {\n        this.paused = false;\n    },\n    /**\n     * Checks for tooltips to activate (only from the running tour or specified tour if there\n     * is one, from all active tours otherwise). Should be called each time the DOM changes.\n     */\n    update: function (tour_name) {\n        if (this.paused) return;\n\n        this.$modal_displayed = $('.modal:visible').last();\n\n        tour_name = this.running_tour || tour_name;\n        if (tour_name) {\n            var tour = this.tours[tour_name];\n            if (!tour || !tour.ready) return;\n\n            if (this.running_tour && this.running_tour_timeout === undefined) {\n                this._set_running_tour_timeout(this.running_tour, this.active_tooltips[this.running_tour]);\n            }\n            var self = this;\n            setTimeout(function () {\n                self._check_for_tooltip(self.active_tooltips[tour_name], tour_name);\n            });\n        } else {\n            const sortedTooltips = Object.keys(this.active_tooltips).sort(\n                (a, b) => this.tours[a].sequence - this.tours[b].sequence\n            );\n            let visibleTip = false;\n            for (const tourName of sortedTooltips) {\n                var tip = this.active_tooltips[tourName];\n                tip.hidden = visibleTip;\n                visibleTip = this._check_for_tooltip(tip, tourName) || visibleTip;\n            }\n        }\n    },\n    /**\n     *  Check (and activate or update) a help tooltip for a tour.\n     *\n     * @param {Object} tip\n     * @param {string} tour_name\n     * @returns {boolean} true if a tip was found and activated/updated\n     */\n    _check_for_tooltip: function (tip, tour_name) {\n        if (tip === undefined) {\n            return true;\n        }\n        if ($('body').hasClass('o_ui_blocked')) {\n            this._deactivate_tip(tip);\n            this._log.push(\"blockUI is preventing the tip to be consumed\");\n            return false;\n        }\n\n        var $trigger;\n        if (tip.in_modal !== false && this.$modal_displayed.length) {\n            $trigger = this.$modal_displayed.find(tip.trigger);\n        } else {\n            $trigger = get_jquery_element_from_selector(tip.trigger);\n        }\n        var $visible_trigger = get_first_visible_element($trigger);\n\n        var extra_trigger = true;\n        var $extra_trigger;\n        if (tip.extra_trigger) {\n            $extra_trigger = get_jquery_element_from_selector(tip.extra_trigger);\n            extra_trigger = get_first_visible_element($extra_trigger).length;\n        }\n\n        var $visible_alt_trigger = $();\n        if (tip.alt_trigger) {\n            var $alt_trigger;\n            if (tip.in_modal !== false && this.$modal_displayed.length) {\n                $alt_trigger = this.$modal_displayed.find(tip.alt_trigger);\n            } else {\n                $alt_trigger = get_jquery_element_from_selector(tip.alt_trigger);\n            }\n            $visible_alt_trigger = get_first_visible_element($alt_trigger);\n        }\n\n        var triggered = $visible_trigger.length && extra_trigger;\n        if (triggered) {\n            if (!tip.widget) {\n                this._activate_tip(tip, tour_name, $visible_trigger, $visible_alt_trigger);\n            } else {\n                tip.widget.update($visible_trigger, $visible_alt_trigger);\n            }\n        } else {\n            if ($trigger.iframeContainer || ($extra_trigger && $extra_trigger.iframeContainer)) {\n                var $el = $();\n                if ($trigger.iframeContainer) {\n                    $el = $el.add($trigger.iframeContainer);\n                }\n                if (($extra_trigger && $extra_trigger.iframeContainer) && $trigger.iframeContainer !== $extra_trigger.iframeContainer) {\n                    $el = $el.add($extra_trigger.iframeContainer);\n                }\n                var self = this;\n                $el.off('load').one('load', function () {\n                    $el.off('load');\n                    if (self.active_tooltips[tour_name] === tip) {\n                        self.update(tour_name);\n                    }\n                });\n            }\n            this._deactivate_tip(tip);\n\n            if (this.running_tour === tour_name) {\n                this._log.push(\"_check_for_tooltip\");\n                this._log.push(\"- modal_displayed: \" + this.$modal_displayed.length);\n                this._log.push(\"- trigger '\" + tip.trigger + \"': \" + $trigger.length);\n                this._log.push(\"- visible trigger '\" + tip.trigger + \"': \" + $visible_trigger.length);\n                if ($extra_trigger !== undefined) {\n                    this._log.push(\"- extra_trigger '\" + tip.extra_trigger + \"': \" + $extra_trigger.length);\n                    this._log.push(\"- visible extra_trigger '\" + tip.extra_trigger + \"': \" + extra_trigger);\n                }\n            }\n        }\n        return !!triggered;\n    },\n    /**\n     * Activates the provided tip for the provided tour, $anchor and $alt_trigger.\n     * $alt_trigger is an alternative trigger that can consume the step. The tip is\n     * however only displayed on the $anchor.\n     *\n     * @param {Object} tip\n     * @param {String} tour_name\n     * @param {jQuery} $anchor\n     * @param {jQuery} $alt_trigger\n     * @private\n     */\n    _activate_tip: function(tip, tour_name, $anchor, $alt_trigger) {\n        var tour = this.tours[tour_name];\n        var tip_info = tip;\n        if (tour.skip_link) {\n            tip_info = _.extend(_.omit(tip_info, 'content'), {\n                content: Markup`${tip.content}${tour.skip_link}`,\n                event_handlers: [{\n                    event: 'click',\n                    selector: '.o_skip_tour',\n                    handler: tour.skip_handler.bind(this, tip),\n                }],\n            });\n        }\n        tip.widget = new Tip(this, tip_info);\n        if (this.running_tour !== tour_name) {\n            tip.widget.on('tip_consumed', this, this._consume_tip.bind(this, tip, tour_name));\n        }\n        tip.widget.attach_to($anchor, $alt_trigger).then(this._to_next_running_step.bind(this, tip, tour_name));\n    },\n    _deactivate_tip: function(tip) {\n        if (tip && tip.widget) {\n            tip.widget.destroy();\n            delete tip.widget;\n        }\n    },\n    _describeTip: function(tip) {\n        return tip.content ? tip.content + ' (trigger: ' + tip.trigger + ')' : tip.trigger;\n    },\n    _consume_tip: function(tip, tour_name) {\n        this._deactivate_tip(tip);\n        this._to_next_step(tour_name);\n\n        var is_running = (this.running_tour === tour_name);\n        if (is_running) {\n            var stepDescription = this._describeTip(tip);\n            console.log(_.str.sprintf(\"Tour %s: step '%s' succeeded\", tour_name, stepDescription));\n        }\n\n        if (this.active_tooltips[tour_name]) {\n            local_storage.setItem(get_step_key(tour_name), this.tours[tour_name].current_step);\n            if (is_running) {\n                this._log = [];\n                this._set_running_tour_timeout(tour_name, this.active_tooltips[tour_name]);\n            }\n            this.update(tour_name);\n        } else {\n            this._consume_tour(tour_name);\n        }\n    },\n    _to_next_step: function (tour_name, inc) {\n        var tour = this.tours[tour_name];\n        tour.current_step += (inc !== undefined ? inc : 1);\n        if (this.running_tour !== tour_name) {\n            var index = _.findIndex(tour.steps.slice(tour.current_step), function (tip) {\n                return !tip.auto;\n            });\n            if (index >= 0) {\n                tour.current_step += index;\n            } else {\n                tour.current_step = tour.steps.length;\n            }\n        }\n        this.active_tooltips[tour_name] = tour.steps[tour.current_step];\n    },\n    /**\n     * @private\n     * @param {string} tourName\n     * @returns {boolean}\n     */\n    _isTourConsumed(tourName) {\n        return this.consumed_tours.includes(tourName);\n    },\n    _consume_tour: function (tour_name, error) {\n        delete this.active_tooltips[tour_name];\n        //display rainbow at the end of any tour\n        if (this.tours[tour_name].rainbowMan && this.running_tour !== tour_name &&\n            this.tours[tour_name].current_step === this.tours[tour_name].steps.length) {\n            let message = this.tours[tour_name].rainbowManMessage;\n            if (message) {\n                message = typeof message === 'function' ? message() : message;\n            } else {\n                message = _t('<strong><b>Good job!</b> You went through all steps of this tour.</strong>');\n            }\n            const fadeout = this.tours[tour_name].fadeout;\n            core.bus.trigger('show-effect', {\n                type: \"rainbow_man\",\n                message,\n                fadeout,\n                messageIsHtml: true,\n            });\n        }\n        this.tours[tour_name].current_step = 0;\n        local_storage.removeItem(get_step_key(tour_name));\n        local_storage.removeItem(get_debugging_key(tour_name));\n        if (this.running_tour === tour_name) {\n            this._stop_running_tour_timeout();\n            local_storage.removeItem(get_running_key());\n            local_storage.removeItem(get_running_delay_key());\n            this.running_tour = undefined;\n            this.running_step_delay = undefined;\n            if (error) {\n                _.each(this._log, function (log) {\n                    console.log(log);\n                });\n                console.log(document.body.parentElement.outerHTML);\n                console.error(error); // will be displayed as error info\n            } else {\n                console.log(_.str.sprintf(\"Tour %s succeeded\", tour_name));\n                console.log(\"test successful\"); // browser_js wait for message \"test successful\"\n            }\n            this._log = [];\n        } else {\n            var self = this;\n            this._rpc({\n                    model: 'web_tour.tour',\n                    method: 'consume',\n                    args: [[tour_name]],\n                })\n                .then(function () {\n                    self.consumed_tours.push(tour_name);\n                });\n        }\n    },\n    _set_running_tour_timeout: function (tour_name, step) {\n        this._stop_running_tour_timeout();\n        this.running_tour_timeout = setTimeout((function() {\n            var descr = this._describeTip(step);\n            this._consume_tour(tour_name, _.str.sprintf(\"Tour %s failed at step %s\", tour_name, descr));\n        }).bind(this), (step.timeout || RUNNING_TOUR_TIMEOUT) + this.running_step_delay);\n    },\n    _stop_running_tour_timeout: function () {\n        clearTimeout(this.running_tour_timeout);\n        this.running_tour_timeout = undefined;\n    },\n    _to_next_running_step: function (tip, tour_name) {\n        if (this.running_tour !== tour_name) return;\n        var self = this;\n        this._stop_running_tour_timeout();\n        if (this.running_step_delay) {\n            // warning: due to the delay, it may happen that the $anchor isn't\n            // in the DOM anymore when exec is called, either because:\n            // - it has been removed from the DOM meanwhile and the tip's\n            //   selector doesn't match anything anymore\n            // - it has been re-rendered and thus the selector still has a match\n            //   in the DOM, but executing the step with that $anchor won't work\n            _.delay(exec, this.running_step_delay);\n        } else {\n            exec();\n        }\n\n        function exec() {\n            const anchorIsInDocument = tip.widget.$anchor[0].ownerDocument.contains(tip.widget.$anchor[0]);\n            const uiIsBlocked = $('body').hasClass('o_ui_blocked');\n            if (!anchorIsInDocument || uiIsBlocked) {\n                // trigger is no longer in the DOM, or UI is now blocked, so run the same step again\n                self._deactivate_tip(self.active_tooltips[tour_name]);\n                self._to_next_step(tour_name, 0);\n                self.update();\n                return;\n            }\n            var action_helper = new RunningTourActionHelper(tip.widget);\n            do_before_unload(self._consume_tip.bind(self, tip, tour_name));\n\n            var tour = self.tours[tour_name];\n            if (typeof tip.run === \"function\") {\n                tip.run.call(tip.widget, action_helper);\n            } else if (tip.run !== undefined) {\n                var m = tip.run.match(/^([a-zA-Z0-9_]+) *(?:\\(? *(.+?) *\\)?)?$/);\n                action_helper[m[1]](m[2]);\n            } else if (tour.current_step === tour.steps.length - 1) {\n                console.log('Tour %s: ignoring action (auto) of last step', tour_name);\n            } else {\n                action_helper.auto();\n            }\n        }\n    },\n    stepUtils: new TourStepUtils(this)\n});\n});\n", "odoo.define('web_tour.tour', function (require) {\n\"use strict\";\n\nvar rootWidget = require('root.widget');\nvar rpc = require('web.rpc');\nvar session = require('web.session');\nvar TourManager = require('web_tour.TourManager');\nconst { device } = require('web.config');\n\nconst untrackedClassnames = [\"o_tooltip\", \"o_tooltip_content\", \"o_tooltip_overlay\"];\n\n/**\n * @namespace\n * @property {Object} active_tooltips\n * @property {Object} tours\n * @property {Array} consumed_tours\n * @property {String} running_tour\n * @property {Number} running_step_delay\n * @property {'community' | 'enterprise'} edition\n * @property {Array} _log\n */\nreturn session.is_bound.then(function () {\n    var defs = [];\n    // Load the list of consumed tours and the tip template only if we are admin, in the frontend,\n    // tours being only available for the admin. For the backend, the list of consumed is directly\n    // in the page source.\n    if (session.is_frontend && session.is_admin) {\n        var def = rpc.query({\n                model: 'web_tour.tour',\n                method: 'get_consumed_tours',\n            });\n        defs.push(def);\n    }\n    return Promise.all(defs).then(function (results) {\n        var consumed_tours = session.is_frontend ? results[0] : session.web_tours;\n        const disabled = session.tour_disable || device.isMobile;\n        var tour_manager = new TourManager(rootWidget, consumed_tours, disabled);\n\n        function _isTrackedNode(node) {\n            if (node.classList) {\n                return !untrackedClassnames\n                    .some(className => node.classList.contains(className));\n            }\n            return true;\n        }\n\n        const classSplitRegex = /\\s+/g;\n        const tooltipParentRegex = /\\bo_tooltip_parent\\b/;\n        let currentMutations = [];\n        function _processMutations() {\n            const hasTrackedMutation = currentMutations.some(mutation => {\n                // First check if the mutation applied on an element we do not\n                // track (like the tour tips themself).\n                if (!_isTrackedNode(mutation.target)) {\n                    return false;\n                }\n\n                if (mutation.type === 'characterData') {\n                    return true;\n                }\n\n                if (mutation.type === 'childList') {\n                    // If it is a modification to the DOM hierarchy, only\n                    // consider the addition/removal of tracked nodes.\n                    for (const nodes of [mutation.addedNodes, mutation.removedNodes]) {\n                        for (const node of nodes) {\n                            if (_isTrackedNode(node)) {\n                                return true;\n                            }\n                        }\n                    }\n                    return false;\n                } else if (mutation.type === 'attributes') {\n                    // Get old and new value of the attribute. Note: as we\n                    // compute the new value after a setTimeout, this might not\n                    // actually be the new value for that particular mutation\n                    // record but this is the one after all mutations. This is\n                    // normally not an issue: e.g. \"a\" -> \"a b\" -> \"a\" will be\n                    // seen as \"a\" -> \"a\" (not \"a b\") + \"a b\" -> \"a\" but we\n                    // only need to detect *one* tracked mutation to know we\n                    // have to update tips anyway.\n                    const oldV = mutation.oldValue ? mutation.oldValue.trim() : '';\n                    const newV = (mutation.target.getAttribute(mutation.attributeName) || '').trim();\n\n                    // Not sure why but this occurs, especially on ID change\n                    // (probably some strange jQuery behavior, see below).\n                    // Also sometimes, a class is just considered changed while\n                    // it just loses the spaces around the class names.\n                    if (oldV === newV) {\n                        return false;\n                    }\n\n                    if (mutation.attributeName === 'id') {\n                        // Check if this is not an ID change done by jQuery for\n                        // performance reasons.\n                        return !(oldV.includes('sizzle') || newV.includes('sizzle'));\n                    } else if (mutation.attributeName === 'class') {\n                        // Check if the change is *only* about receiving or\n                        // losing the 'o_tooltip_parent' class, which is linked\n                        // to the tour service system. We have to check the\n                        // potential addition of another class as we compute\n                        // the new value after a setTimeout. So this case:\n                        // 'a' -> 'a b' -> 'a b o_tooltip_parent' produces 2\n                        // mutation records but will be seen here as\n                        // 1) 'a' -> 'a b o_tooltip_parent'\n                        // 2) 'a b' -> 'a b o_tooltip_parent'\n                        const hadClass = tooltipParentRegex.test(oldV);\n                        const newClasses = mutation.target.classList;\n                        const hasClass = newClasses.contains('o_tooltip_parent');\n                        return !(hadClass !== hasClass\n                            && Math.abs(oldV.split(classSplitRegex).length - newClasses.length) === 1);\n                    }\n                }\n\n                return true;\n            });\n\n            // Either all the mutations have been ignored or one was detected as\n            // tracked and will trigger a tour manager update.\n            currentMutations = [];\n\n            // Update the tour manager if required.\n            if (hasTrackedMutation) {\n                tour_manager.update();\n            }\n        }\n\n        // Use a MutationObserver to detect DOM changes. When a mutation occurs,\n        // only add it to the list of mutations to process and delay the\n        // mutation processing. We have to record them all and not in a\n        // debounced way otherwise we may ignore tracked ones in a serie of\n        // 10 tracked mutations followed by an untracked one. Most of them\n        // will trigger a tip check anyway so, most of the time, processing the\n        // first ones will be enough to ensure that a tip update has to be done.\n        let mutationTimer;\n        const observer = new MutationObserver(mutations => {\n            clearTimeout(mutationTimer);\n            currentMutations = currentMutations.concat(mutations);\n            mutationTimer = setTimeout(() => _processMutations(), 750);\n        });\n\n        // Now that the observer is configured, we have to start it when needed.\n        var start_service = (function () {\n            return function (observe) {\n                return new Promise(function (resolve, reject) {\n                    tour_manager._register_all(observe).then(function () {\n                        if (observe) {\n                            observer.observe(document.body, {\n                                attributes: true,\n                                childList: true,\n                                subtree: true,\n                                attributeOldValue: true,\n                                characterData: true,\n                            });\n                        }\n                        resolve();\n                    });\n                });\n            };\n        })();\n\n        // Enable the MutationObserver for the admin or if a tour is running, when the DOM is ready\n        start_service(session.is_admin || tour_manager.running_tour);\n\n        // Override the TourManager so that it enables/disables the observer when necessary\n        if (!session.is_admin) {\n            var run = tour_manager.run;\n            tour_manager.run = function () {\n                var self = this;\n                var args = arguments;\n\n                start_service(true).then(function () {\n                    run.apply(self, args);\n                    if (!self.running_tour) {\n                        observer.disconnect();\n                    }\n                });\n            };\n            var _consume_tour = tour_manager._consume_tour;\n            tour_manager._consume_tour = function () {\n                _consume_tour.apply(this, arguments);\n                observer.disconnect();\n            };\n        }\n        // helper to start a tour manually (or from a python test with its counterpart start_tour function)\n        odoo.startTour = tour_manager.run.bind(tour_manager);\n        return tour_manager;\n    });\n});\n\n});\n", "odoo.define('web_tour.TourStepUtils', function (require) {\n'use strict';\n\nconst {_t, Class} = require('web.core');\nconst {Markup} = require('web.utils');\n\nreturn Class.extend({\n    _getHelpMessage: (functionName, ...args) => `Generated by function tour utils ${functionName}(${args.join(', ')})`,\n\n    addDebugHelp: helpMessage => step => {\n        if (typeof step.debugHelp === 'string') {\n            step.debugHelp = step.debugHelp + '\\n' + helpMessage;\n        } else {\n            step.debugHelp = helpMessage;\n        }\n        return step;\n    },\n\n    editionEnterpriseModifier(step) {\n        step.edition = 'enterprise';\n        return step;\n    },\n\n    mobileModifier(step) {\n        step.mobile = true;\n        return step;\n    },\n\n    showAppsMenuItem() {\n        return {\n            edition: 'community',\n            trigger: '.o_navbar_apps_menu button',\n            auto: true,\n            position: 'bottom',\n        };\n    },\n\n    toggleHomeMenu() {\n        return {\n            edition: 'enterprise',\n            trigger: '.o_main_navbar .o_menu_toggle',\n            content: Markup(_t('Click on the <i>Home icon</i> to navigate across apps.')),\n            position: 'bottom',\n        };\n    },\n\n    autoExpandMoreButtons(extra_trigger) {\n        return {\n            trigger: '.oe_button_box',\n            extra_trigger: extra_trigger,\n            auto: true,\n            run: actions => {\n                const $more = $('.oe_button_box .o_button_more');\n                if ($more.length) {\n                    actions.click($more);\n                }\n            },\n        };\n    },\n\n    goBackBreadcrumbsMobile(description, ...extraTrigger) {\n        return extraTrigger.map(element => ({\n            mobile: true,\n            trigger: '.breadcrumb-item:not(.d-none):first',\n            extra_trigger: element,\n            content: description,\n            position: 'bottom',\n            debugHelp: this._getHelpMessage('goBackBreadcrumbsMobile', description, ...extraTrigger),\n        }));\n    },\n\n    goToAppSteps(dataMenuXmlid, description) {\n        return [\n            this.showAppsMenuItem(),\n            {\n                trigger: `.o_app[data-menu-xmlid=\"${dataMenuXmlid}\"]`,\n                content: description,\n                position: 'right',\n                edition: 'community',\n            },\n            {\n                trigger: `.o_app[data-menu-xmlid=\"${dataMenuXmlid}\"]`,\n                content: description,\n                position: 'bottom',\n                edition: 'enterprise',\n            },\n        ].map(this.addDebugHelp(this._getHelpMessage('goToApp', dataMenuXmlid, description)));\n    },\n\n    openBuggerMenu(extraTrigger) {\n        return {\n            mobile: true,\n            trigger: '.o_mobile_menu_toggle',\n            extra_trigger: extraTrigger,\n            content: _t('Open bugger menu.'),\n            position: 'bottom',\n            debugHelp: this._getHelpMessage('openBuggerMenu', extraTrigger),\n        };\n    },\n\n    statusbarButtonsSteps(innerTextButton, description, extraTrigger) {\n        return [\n            {\n                mobile: true,\n                auto: true,\n                trigger: '.o_statusbar_buttons',\n                extra_trigger: extraTrigger,\n                run: actions => {\n                    const $action = $('.o_statusbar_buttons .btn.dropdown-toggle:contains(Action)');\n                    if ($action.length) {\n                        actions.click($action);\n                    }\n                },\n            }, {\n                trigger: `.o_statusbar_buttons button:enabled:contains('${innerTextButton}')`,\n                content: description,\n                position: 'bottom',\n            },\n        ].map(this.addDebugHelp(this._getHelpMessage('statusbarButtonsSteps', innerTextButton, description, extraTrigger)));\n    },\n\n    simulateEnterKeyboardInSearchModal() {\n        return {\n            mobile: true,\n            trigger: '.o_searchview_input',\n            extra_trigger: '.modal:not(.o_inactive_modal) .dropdown-menu.o_searchview_autocomplete',\n            position: 'bottom',\n            run: action => {\n                const keyEventEnter = new KeyboardEvent('keydown', {\n                    bubbles: true,\n                    cancelable: true,\n                    key: 'Enter',\n                    code: 'Enter',\n                    which: 13,\n                    keyCode: 13,\n                });\n                action.tip_widget.$anchor[0].dispatchEvent(keyEventEnter);\n            },\n            debugHelp: this._getHelpMessage('simulateEnterKeyboardInSearchModal'),\n        };\n    },\n\n    mobileKanbanSearchMany2X(modalTitle, valueSearched) {\n        return [\n            {\n                mobile: true,\n                trigger: '.o_searchview_input',\n                extra_trigger: `.modal:not(.o_inactive_modal) .modal-title:contains('${modalTitle}')`,\n                position: 'bottom',\n                run: `text ${valueSearched}`,\n            },\n            this.simulateEnterKeyboardInSearchModal(),\n            {\n                mobile: true,\n                trigger: `.o_kanban_record .o_kanban_record_title :contains('${valueSearched}')`,\n                position: 'bottom',\n            },\n        ].map(this.addDebugHelp(this._getHelpMessage('mobileKanbanSearchMany2X', modalTitle, valueSearched)));\n    },\n});\n});\n", "odoo.define('web_tour.utils', function(require) {\n\"use strict\";\n\nfunction get_step_key(name) {\n    return 'tour_' + name + '_step';\n}\n\nfunction get_running_key() {\n    return 'running_tour';\n}\n\nfunction get_debugging_key(name) {\n    return `debugging_tour_${name}`;\n}\n\nfunction get_running_delay_key() {\n    return get_running_key() + \"_delay\";\n}\n\nfunction get_first_visible_element($elements) {\n    for (var i = 0 ; i < $elements.length ; i++) {\n        var $i = $elements.eq(i);\n        if ($i.is(':visible:hasVisibility')) {\n            return $i;\n        }\n    }\n    return $();\n}\n\nfunction do_before_unload(if_unload_callback, if_not_unload_callback) {\n    if_unload_callback = if_unload_callback || function () {};\n    if_not_unload_callback = if_not_unload_callback || if_unload_callback;\n\n    var old_before = window.onbeforeunload;\n    var reload_timeout;\n    window.onbeforeunload = function () {\n        clearTimeout(reload_timeout);\n        window.onbeforeunload = old_before;\n        if_unload_callback();\n        if (old_before) return old_before.apply(this, arguments);\n    };\n    reload_timeout = _.defer(function () {\n        window.onbeforeunload = old_before;\n        if_not_unload_callback();\n    });\n}\n\nfunction get_jquery_element_from_selector(selector) {\n    if (_.isString(selector) && selector.indexOf('iframe') !== -1) {\n        var $iframe = $(selector.split('iframe')[0] + ' iframe');\n        var $el = $iframe.contents()\n            .find(selector.split('iframe')[1]);\n        $el.iframeContainer = $iframe[0];\n        return $el;\n    } else {\n        return $(selector);\n    }\n}\n\n\nreturn {\n    get_debugging_key: get_debugging_key,\n    'get_step_key': get_step_key,\n    'get_running_key': get_running_key,\n    'get_running_delay_key': get_running_delay_key,\n    'get_first_visible_element': get_first_visible_element,\n    'do_before_unload': do_before_unload,\n    'get_jquery_element_from_selector' : get_jquery_element_from_selector,\n};\n\n});\n\n", "/**\r\n* vkBeautify - javascript plugin to pretty-print or minify text in XML, JSON, CSS and SQL formats.\r\n*  \r\n* Version - 0.99.00.beta \r\n* Copyright (c) 2012 Vadim Kiryukhin\r\n* vkiryukhin @ gmail.com\r\n* http://www.eslinstructor.net/vkbeautify/\r\n* \r\n* Dual licensed under the MIT and GPL licenses:\r\n*   http://www.opensource.org/licenses/mit-license.php\r\n*   http://www.gnu.org/licenses/gpl.html\r\n*\r\n*   Pretty print\r\n*\r\n*        vkbeautify.xml(text [,indent_pattern]);\r\n*        vkbeautify.json(text [,indent_pattern]);\r\n*        vkbeautify.css(text [,indent_pattern]);\r\n*        vkbeautify.sql(text [,indent_pattern]);\r\n*\r\n*        @text - String; text to beatufy;\r\n*        @indent_pattern - Integer | String;\r\n*                Integer:  number of white spaces;\r\n*                String:   character string to visualize indentation ( can also be a set of white spaces )\r\n*   Minify\r\n*\r\n*        vkbeautify.xmlmin(text [,preserve_comments]);\r\n*        vkbeautify.jsonmin(text);\r\n*        vkbeautify.cssmin(text [,preserve_comments]);\r\n*        vkbeautify.sqlmin(text);\r\n*\r\n*        @text - String; text to minify;\r\n*        @preserve_comments - Bool; [optional];\r\n*                Set this flag to true to prevent removing comments from @text ( minxml and mincss functions only. )\r\n*\r\n*   Examples:\r\n*        vkbeautify.xml(text); // pretty print XML\r\n*        vkbeautify.json(text, 4 ); // pretty print JSON\r\n*        vkbeautify.css(text, '. . . .'); // pretty print CSS\r\n*        vkbeautify.sql(text, '----'); // pretty print SQL\r\n*\r\n*        vkbeautify.xmlmin(text, true);// minify XML, preserve comments\r\n*        vkbeautify.jsonmin(text);// minify JSON\r\n*        vkbeautify.cssmin(text);// minify CSS, remove comments ( default )\r\n*        vkbeautify.sqlmin(text);// minify SQL\r\n*\r\n*/\r\n\r\n(function() {\r\n\r\nfunction createShiftArr(step) {\r\n\r\n\tvar space = '    ';\r\n\t\r\n\tif ( isNaN(parseInt(step)) ) {  // argument is string\r\n\t\tspace = step;\r\n\t} else { // argument is integer\r\n\t\tswitch(step) {\r\n\t\t\tcase 1: space = ' '; break;\r\n\t\t\tcase 2: space = '  '; break;\r\n\t\t\tcase 3: space = '   '; break;\r\n\t\t\tcase 4: space = '    '; break;\r\n\t\t\tcase 5: space = '     '; break;\r\n\t\t\tcase 6: space = '      '; break;\r\n\t\t\tcase 7: space = '       '; break;\r\n\t\t\tcase 8: space = '        '; break;\r\n\t\t\tcase 9: space = '         '; break;\r\n\t\t\tcase 10: space = '          '; break;\r\n\t\t\tcase 11: space = '           '; break;\r\n\t\t\tcase 12: space = '            '; break;\r\n\t\t}\r\n\t}\r\n\r\n\tvar shift = ['\\n']; // array of shifts\r\n\tfor(ix=0;ix<100;ix++){\r\n\t\tshift.push(shift[ix]+space); \r\n\t}\r\n\treturn shift;\r\n}\r\n\r\nfunction vkbeautify(){\r\n\tthis.step = '    '; // 4 spaces\r\n\tthis.shift = createShiftArr(this.step);\r\n};\r\n\r\nvkbeautify.prototype.xml = function(text,step) {\r\n\r\n\tvar ar = text.replace(/>\\s{0,}</g,\"><\")\r\n\t\t\t\t .replace(/</g,\"~::~<\")\r\n\t\t\t\t .replace(/\\s*xmlns\\:/g,\"~::~xmlns:\")\r\n\t\t\t\t .replace(/\\s*xmlns\\=/g,\"~::~xmlns=\")\r\n\t\t\t\t .split('~::~'),\r\n\t\tlen = ar.length,\r\n\t\tinComment = false,\r\n\t\tdeep = 0,\r\n\t\tstr = '',\r\n\t\tix = 0,\r\n\t\tshift = step ? createShiftArr(step) : this.shift;\r\n\r\n\t\tfor(ix=0;ix<len;ix++) {\r\n\t\t\t// start comment or <![CDATA[...]]> or <!DOCTYPE //\r\n\t\t\tif(ar[ix].search(/<!/) > -1) { \r\n\t\t\t\tstr += shift[deep]+ar[ix];\r\n\t\t\t\tinComment = true; \r\n\t\t\t\t// end comment  or <![CDATA[...]]> //\r\n\t\t\t\tif(ar[ix].search(/-->/) > -1 || ar[ix].search(/\\]>/) > -1 || ar[ix].search(/!DOCTYPE/) > -1 ) { \r\n\t\t\t\t\tinComment = false; \r\n\t\t\t\t}\r\n\t\t\t} else \r\n\t\t\t// end comment  or <![CDATA[...]]> //\r\n\t\t\tif(ar[ix].search(/-->/) > -1 || ar[ix].search(/\\]>/) > -1) { \r\n\t\t\t\tstr += ar[ix];\r\n\t\t\t\tinComment = false; \r\n\t\t\t} else \r\n\t\t\t// <elm></elm> //\r\n\t\t\tif( /^<\\w/.exec(ar[ix-1]) && /^<\\/\\w/.exec(ar[ix]) &&\r\n\t\t\t\t/^<[\\w:\\-\\.\\,]+/.exec(ar[ix-1]) == /^<\\/[\\w:\\-\\.\\,]+/.exec(ar[ix])[0].replace('/','')) { \r\n\t\t\t\tstr += ar[ix];\r\n\t\t\t\tif(!inComment) deep--;\r\n\t\t\t} else\r\n\t\t\t // <elm> //\r\n\t\t\tif(ar[ix].search(/<\\w/) > -1 && ar[ix].search(/<\\//) == -1 && ar[ix].search(/\\/>/) == -1 ) {\r\n\t\t\t\tstr = !inComment ? str += shift[deep++]+ar[ix] : str += ar[ix];\r\n\t\t\t} else \r\n\t\t\t // <elm>...</elm> //\r\n\t\t\tif(ar[ix].search(/<\\w/) > -1 && ar[ix].search(/<\\//) > -1) {\r\n\t\t\t\tstr = !inComment ? str += shift[deep]+ar[ix] : str += ar[ix];\r\n\t\t\t} else \r\n\t\t\t// </elm> //\r\n\t\t\tif(ar[ix].search(/<\\//) > -1) { \r\n\t\t\t\tstr = !inComment ? str += shift[--deep]+ar[ix] : str += ar[ix];\r\n\t\t\t} else \r\n\t\t\t// <elm/> //\r\n\t\t\tif(ar[ix].search(/\\/>/) > -1 ) { \r\n\t\t\t\tstr = !inComment ? str += shift[deep]+ar[ix] : str += ar[ix];\r\n\t\t\t} else \r\n\t\t\t// <? xml ... ?> //\r\n\t\t\tif(ar[ix].search(/<\\?/) > -1) { \r\n\t\t\t\tstr += shift[deep]+ar[ix];\r\n\t\t\t} else \r\n\t\t\t// xmlns //\r\n\t\t\tif( ar[ix].search(/xmlns\\:/) > -1  || ar[ix].search(/xmlns\\=/) > -1) { \r\n\t\t\t\tstr += shift[deep]+ar[ix];\r\n\t\t\t} \r\n\t\t\t\r\n\t\t\telse {\r\n\t\t\t\tstr += ar[ix];\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\treturn  (str[0] == '\\n') ? str.slice(1) : str;\r\n}\r\n\r\nvkbeautify.prototype.json = function(text,step) {\r\n\r\n\tvar step = step ? step : this.step;\r\n\t\r\n\tif (typeof JSON === 'undefined' ) return text; \r\n\t\r\n\tif ( typeof text === \"string\" ) return JSON.stringify(JSON.parse(text), null, step);\r\n\tif ( typeof text === \"object\" ) return JSON.stringify(text, null, step);\r\n\t\t\r\n\treturn text; // text is not string nor object\r\n}\r\n\r\nvkbeautify.prototype.css = function(text, step) {\r\n\r\n\tvar ar = text.replace(/\\s{1,}/g,' ')\r\n\t\t\t\t.replace(/\\{/g,\"{~::~\")\r\n\t\t\t\t.replace(/\\}/g,\"~::~}~::~\")\r\n\t\t\t\t.replace(/\\;/g,\";~::~\")\r\n\t\t\t\t.replace(/\\/\\*/g,\"~::~/*\")\r\n\t\t\t\t.replace(/\\*\\//g,\"*/~::~\")\r\n\t\t\t\t.replace(/~::~\\s{0,}~::~/g,\"~::~\")\r\n\t\t\t\t.split('~::~'),\r\n\t\tlen = ar.length,\r\n\t\tdeep = 0,\r\n\t\tstr = '',\r\n\t\tix = 0,\r\n\t\tshift = step ? createShiftArr(step) : this.shift;\r\n\t\t\r\n\t\tfor(ix=0;ix<len;ix++) {\r\n\r\n\t\t\tif( /\\{/.exec(ar[ix]))  { \r\n\t\t\t\tstr += shift[deep++]+ar[ix];\r\n\t\t\t} else \r\n\t\t\tif( /\\}/.exec(ar[ix]))  { \r\n\t\t\t\tstr += shift[--deep]+ar[ix];\r\n\t\t\t} else\r\n\t\t\tif( /\\*\\\\/.exec(ar[ix]))  { \r\n\t\t\t\tstr += shift[deep]+ar[ix];\r\n\t\t\t}\r\n\t\t\telse {\r\n\t\t\t\tstr += shift[deep]+ar[ix];\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn str.replace(/^\\n{1,}/,'');\r\n}\r\n\r\n//----------------------------------------------------------------------------\r\n\r\nfunction isSubquery(str, parenthesisLevel) {\r\n\treturn  parenthesisLevel - (str.replace(/\\(/g,'').length - str.replace(/\\)/g,'').length )\r\n}\r\n\r\nfunction split_sql(str, tab) {\r\n\r\n\treturn str.replace(/\\s{1,}/g,\" \")\r\n\r\n\t\t\t\t.replace(/ AND /ig,\"~::~\"+tab+tab+\"AND \")\r\n\t\t\t\t.replace(/ BETWEEN /ig,\"~::~\"+tab+\"BETWEEN \")\r\n\t\t\t\t.replace(/ CASE /ig,\"~::~\"+tab+\"CASE \")\r\n\t\t\t\t.replace(/ ELSE /ig,\"~::~\"+tab+\"ELSE \")\r\n\t\t\t\t.replace(/ END /ig,\"~::~\"+tab+\"END \")\r\n\t\t\t\t.replace(/ FROM /ig,\"~::~FROM \")\r\n\t\t\t\t.replace(/ GROUP\\s{1,}BY/ig,\"~::~GROUP BY \")\r\n\t\t\t\t.replace(/ HAVING /ig,\"~::~HAVING \")\r\n\t\t\t\t//.replace(/ SET /ig,\" SET~::~\")\r\n\t\t\t\t.replace(/ IN /ig,\" IN \")\r\n\t\t\t\t\r\n\t\t\t\t.replace(/ JOIN /ig,\"~::~JOIN \")\r\n\t\t\t\t.replace(/ CROSS~::~{1,}JOIN /ig,\"~::~CROSS JOIN \")\r\n\t\t\t\t.replace(/ INNER~::~{1,}JOIN /ig,\"~::~INNER JOIN \")\r\n\t\t\t\t.replace(/ LEFT~::~{1,}JOIN /ig,\"~::~LEFT JOIN \")\r\n\t\t\t\t.replace(/ RIGHT~::~{1,}JOIN /ig,\"~::~RIGHT JOIN \")\r\n\t\t\t\t\r\n\t\t\t\t.replace(/ ON /ig,\"~::~\"+tab+\"ON \")\r\n\t\t\t\t.replace(/ OR /ig,\"~::~\"+tab+tab+\"OR \")\r\n\t\t\t\t.replace(/ ORDER\\s{1,}BY/ig,\"~::~ORDER BY \")\r\n\t\t\t\t.replace(/ OVER /ig,\"~::~\"+tab+\"OVER \")\r\n\r\n\t\t\t\t.replace(/\\(\\s{0,}SELECT /ig,\"~::~(SELECT \")\r\n\t\t\t\t.replace(/\\)\\s{0,}SELECT /ig,\")~::~SELECT \")\r\n\t\t\t\t\r\n\t\t\t\t.replace(/ THEN /ig,\" THEN~::~\"+tab+\"\")\r\n\t\t\t\t.replace(/ UNION /ig,\"~::~UNION~::~\")\r\n\t\t\t\t.replace(/ USING /ig,\"~::~USING \")\r\n\t\t\t\t.replace(/ WHEN /ig,\"~::~\"+tab+\"WHEN \")\r\n\t\t\t\t.replace(/ WHERE /ig,\"~::~WHERE \")\r\n\t\t\t\t.replace(/ WITH /ig,\"~::~WITH \")\r\n\t\t\t\t\r\n\t\t\t\t//.replace(/\\,\\s{0,}\\(/ig,\",~::~( \")\r\n\t\t\t\t//.replace(/\\,/ig,\",~::~\"+tab+tab+\"\")\r\n\r\n\t\t\t\t.replace(/ ALL /ig,\" ALL \")\r\n\t\t\t\t.replace(/ AS /ig,\" AS \")\r\n\t\t\t\t.replace(/ ASC /ig,\" ASC \")\t\r\n\t\t\t\t.replace(/ DESC /ig,\" DESC \")\t\r\n\t\t\t\t.replace(/ DISTINCT /ig,\" DISTINCT \")\r\n\t\t\t\t.replace(/ EXISTS /ig,\" EXISTS \")\r\n\t\t\t\t.replace(/ NOT /ig,\" NOT \")\r\n\t\t\t\t.replace(/ NULL /ig,\" NULL \")\r\n\t\t\t\t.replace(/ LIKE /ig,\" LIKE \")\r\n\t\t\t\t.replace(/\\s{0,}SELECT /ig,\"SELECT \")\r\n\t\t\t\t.replace(/\\s{0,}UPDATE /ig,\"UPDATE \")\r\n\t\t\t\t.replace(/ SET /ig,\" SET \")\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t.replace(/~::~{1,}/g,\"~::~\")\r\n\t\t\t\t.split('~::~');\r\n}\r\n\r\nvkbeautify.prototype.sql = function(text,step) {\r\n\r\n\tvar ar_by_quote = text.replace(/\\s{1,}/g,\" \")\r\n\t\t\t\t\t\t\t.replace(/\\'/ig,\"~::~\\'\")\r\n\t\t\t\t\t\t\t.split('~::~'),\r\n\t\tlen = ar_by_quote.length,\r\n\t\tar = [],\r\n\t\tdeep = 0,\r\n\t\ttab = this.step,//+this.step,\r\n\t\tinComment = true,\r\n\t\tinQuote = false,\r\n\t\tparenthesisLevel = 0,\r\n\t\tstr = '',\r\n\t\tix = 0,\r\n\t\tshift = step ? createShiftArr(step) : this.shift;;\r\n\r\n\t\tfor(ix=0;ix<len;ix++) {\r\n\t\t\tif(ix%2) {\r\n\t\t\t\tar = ar.concat(ar_by_quote[ix]);\r\n\t\t\t} else {\r\n\t\t\t\tar = ar.concat(split_sql(ar_by_quote[ix], tab) );\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\tlen = ar.length;\r\n\t\tfor(ix=0;ix<len;ix++) {\r\n\t\t\t\r\n\t\t\tparenthesisLevel = isSubquery(ar[ix], parenthesisLevel);\r\n\t\t\t\r\n\t\t\tif( /\\s{0,}\\s{0,}SELECT\\s{0,}/.exec(ar[ix]))  { \r\n\t\t\t\tar[ix] = ar[ix].replace(/\\,/g,\",\\n\"+tab+tab+\"\")\r\n\t\t\t} \r\n\t\t\t\r\n\t\t\tif( /\\s{0,}\\s{0,}SET\\s{0,}/.exec(ar[ix]))  { \r\n\t\t\t\tar[ix] = ar[ix].replace(/\\,/g,\",\\n\"+tab+tab+\"\")\r\n\t\t\t} \r\n\t\t\t\r\n\t\t\tif( /\\s{0,}\\(\\s{0,}SELECT\\s{0,}/.exec(ar[ix]))  { \r\n\t\t\t\tdeep++;\r\n\t\t\t\tstr += shift[deep]+ar[ix];\r\n\t\t\t} else \r\n\t\t\tif( /\\'/.exec(ar[ix]) )  { \r\n\t\t\t\tif(parenthesisLevel<1 && deep) {\r\n\t\t\t\t\tdeep--;\r\n\t\t\t\t}\r\n\t\t\t\tstr += ar[ix];\r\n\t\t\t}\r\n\t\t\telse  { \r\n\t\t\t\tstr += shift[deep]+ar[ix];\r\n\t\t\t\tif(parenthesisLevel<1 && deep) {\r\n\t\t\t\t\tdeep--;\r\n\t\t\t\t}\r\n\t\t\t} \r\n\t\t\tvar junk = 0;\r\n\t\t}\r\n\r\n\t\tstr = str.replace(/^\\n{1,}/,'').replace(/\\n{1,}/g,\"\\n\");\r\n\t\treturn str;\r\n}\r\n\r\n\r\nvkbeautify.prototype.xmlmin = function(text, preserveComments) {\r\n\r\n\tvar str = preserveComments ? text\r\n\t\t\t\t\t\t\t   : text.replace(/\\<![ \\r\\n\\t]*(--([^\\-]|[\\r\\n]|-[^\\-])*--[ \\r\\n\\t]*)\\>/g,\"\")\r\n\t\t\t\t\t\t\t\t\t .replace(/[ \\r\\n\\t]{1,}xmlns/g, ' xmlns');\r\n\treturn  str.replace(/>\\s{0,}</g,\"><\"); \r\n}\r\n\r\nvkbeautify.prototype.jsonmin = function(text) {\r\n\r\n\tif (typeof JSON === 'undefined' ) return text; \r\n\t\r\n\treturn JSON.stringify(JSON.parse(text), null, 0); \r\n\t\t\t\t\r\n}\r\n\r\nvkbeautify.prototype.cssmin = function(text, preserveComments) {\r\n\t\r\n\tvar str = preserveComments ? text\r\n\t\t\t\t\t\t\t   : text.replace(/\\/\\*([^*]|[\\r\\n]|(\\*+([^*/]|[\\r\\n])))*\\*+\\//g,\"\") ;\r\n\r\n\treturn str.replace(/\\s{1,}/g,' ')\r\n\t\t\t  .replace(/\\{\\s{1,}/g,\"{\")\r\n\t\t\t  .replace(/\\}\\s{1,}/g,\"}\")\r\n\t\t\t  .replace(/\\;\\s{1,}/g,\";\")\r\n\t\t\t  .replace(/\\/\\*\\s{1,}/g,\"/*\")\r\n\t\t\t  .replace(/\\*\\/\\s{1,}/g,\"*/\");\r\n}\r\n\r\nvkbeautify.prototype.sqlmin = function(text) {\r\n\treturn text.replace(/\\s{1,}/g,\" \").replace(/\\s{1,}\\(/,\"(\").replace(/\\s{1,}\\)/,\")\");\r\n}\r\n\r\nwindow.vkbeautify = new vkbeautify();\r\n\r\n})();\r\n\r\n", "odoo.define('web_editor.ace', function (require) {\n'use strict';\n\nvar ajax = require('web.ajax');\nvar config = require('web.config');\nvar concurrency = require('web.concurrency');\nvar core = require('web.core');\nvar dom = require('web.dom');\nvar Dialog = require('web.Dialog');\nvar Widget = require('web.Widget');\nvar localStorage = require('web.local_storage');\n\nvar _t = core._t;\n\n/**\n * Formats a content-check result (@see checkXML, checkSCSS).\n *\n * @param {boolean} isValid\n * @param {integer} [errorLine] needed if isValid is false\n * @param {string} [errorMessage] needed if isValid is false\n * @returns {Object}\n */\nfunction _getCheckReturn(isValid, errorLine, errorMessage) {\n    return {\n        isValid: isValid,\n        error: isValid ? null : {\n            line: errorLine,\n            message: errorMessage,\n        },\n    };\n}\n/**\n * Checks the syntax validity of some XML.\n *\n * @param {string} xml\n * @returns {Object} @see _getCheckReturn\n */\nfunction checkXML(xml) {\n    if (typeof window.DOMParser != 'undefined') {\n        var xmlDoc = (new window.DOMParser()).parseFromString(xml, 'text/xml');\n        var error = xmlDoc.getElementsByTagName('parsererror');\n        if (error.length > 0) {\n            const errorEl = error[0];\n            const sourceTextEls = errorEl.querySelectorAll('sourcetext');\n            let codeEls = null;\n            if (sourceTextEls.length) {\n                codeEls = [...sourceTextEls].map(el => {\n                    const codeEl = document.createElement('code');\n                    codeEl.textContent = el.textContent;\n                    const brEl = document.createElement('br');\n                    brEl.classList.add('o_we_source_text_origin');\n                    el.parentElement.insertBefore(brEl, el);\n                    return codeEl;\n                });\n                for (const el of sourceTextEls) {\n                    el.remove();\n                }\n            }\n            for (const el of [...errorEl.querySelectorAll(':not(code):not(pre):not(br)')]) {\n                const pEl = document.createElement('p');\n                for (const cEl of [...el.childNodes]) {\n                    pEl.appendChild(cEl);\n                }\n                el.parentElement.insertBefore(pEl, el);\n                el.remove();\n            }\n            errorEl.innerHTML = errorEl.innerHTML.replace(/\\r?\\n/g, '<br/>');\n            errorEl.querySelectorAll('.o_we_source_text_origin').forEach((el, i) => {\n                el.after(codeEls[i]);\n            });\n            return _getCheckReturn(false, parseInt(error[0].innerHTML.match(/[Ll]ine[^\\d]+(\\d+)/)[1], 10), errorEl.innerHTML);\n        }\n    } else if (typeof window.ActiveXObject != 'undefined' && new window.ActiveXObject('Microsoft.XMLDOM')) {\n        var xmlDocIE = new window.ActiveXObject('Microsoft.XMLDOM');\n        xmlDocIE.async = 'false';\n        xmlDocIE.loadXML(xml);\n        if (xmlDocIE.parseError.line > 0) {\n            return _getCheckReturn(false, xmlDocIE.parseError.line, xmlDocIE.parseError.reason);\n        }\n    }\n    return _getCheckReturn(true);\n}\n/**\n * Formats some XML so that it has proper indentation and structure.\n *\n * @param {string} xml\n * @returns {string} formatted xml\n */\nfunction formatXML(xml) {\n    // do nothing if an inline script is present to avoid breaking it\n    if (/<script(?: [^>]*)?>[^<][\\s\\S]*<\\/script>/i.test(xml)) {\n        return xml;\n    }\n    return window.vkbeautify.xml(xml, 4);\n}\n/**\n * Checks the syntax validity of some SCSS.\n *\n * @param {string} scss\n * @returns {Object} @see _getCheckReturn\n */\nvar checkSCSS = (function () {\n    var mapping = {\n        '{': '}', '}': '{',\n        '(': ')', ')': '(',\n        '[': ']', ']': '[',\n    };\n    var openings = ['{', '(', '['];\n    var closings = ['}', ')', ']'];\n\n    return function (scss) {\n        var stack = [];\n        var line = 1;\n        for (var i = 0 ; i < scss.length ; i++) {\n            if (_.contains(openings, scss[i])) {\n                stack.push(scss[i]);\n            } else if (_.contains(closings, scss[i])) {\n                if (stack.pop() !== mapping[scss[i]]) {\n                    return _getCheckReturn(false, line, _t(\"Unexpected \") + scss[i]);\n                }\n            } else if (scss[i] === '\\n') {\n                line++;\n            }\n        }\n        if (stack.length > 0) {\n            return _getCheckReturn(false, line, _t(\"Expected \") + mapping[stack.pop()]);\n        }\n        return _getCheckReturn(true);\n    };\n})();\n/**\n * Formats some SCSS so that it has proper indentation and structure.\n *\n * @todo Right now, this does return the given SCSS content, untouched.\n * @param {string} scss\n * @returns {string} formatted scss\n */\nfunction formatSCSS(scss) {\n    return scss;\n}\n\n/**\n * Allows to visualize resources (by default, XML views) and edit them.\n */\nvar ViewEditor = Widget.extend({\n    template: 'web_editor.ace_view_editor',\n    xmlDependencies: ['/web_editor/static/src/xml/ace.xml'],\n    jsLibs: [\n        '/web/static/lib/ace/ace.js',\n        [\n            '/web/static/lib/ace/javascript_highlight_rules.js',\n            '/web/static/lib/ace/mode-xml.js',\n            '/web/static/lib/ace/mode-qweb.js',\n            '/web/static/lib/ace/mode-scss.js',\n            '/web/static/lib/ace/mode-js.js',\n            '/web/static/lib/ace/theme-monokai.js'\n        ]\n    ],\n    events: {\n        'click .o_ace_type_switcher_choice': '_onTypeChoice',\n        'change .o_res_list': '_onResChange',\n        'click .o_ace_filter': '_onFilterChange',\n        'click button[data-action=save]': '_onSaveClick',\n        'click button[data-action=reset]': '_onResetClick',\n        'click button[data-action=format]': '_onFormatClick',\n        'click button[data-action=close]': '_onCloseClick',\n        'click #ace-view-id > .alert-warning .close': '_onCloseWarningClick'\n    },\n\n    /**\n     * Initializes the parameters so that the ace editor knows which information\n     * it has to load.\n     *\n     * @constructor\n     * @param {Widget} parent\n     * @param {string|integer} viewKey\n     *        xml_id or id of the view whose linked resources have to be loaded.\n     * @param {Object} [options]\n     * @param {string|integer} [options.initialResID]\n     *        a specific view ID / SCSS URL to load on start (otherwise the main\n     *        view ID associated with the specified viewKey will be used)\n     * @param {string} [options.position=right]\n     * @param {boolean} [options.doNotLoadViews=false]\n     * @param {boolean} [options.doNotLoadSCSS=false]\n     * @param {boolean} [options.doNotLoadJS=false]\n     * @param {boolean} [options.includeBundles=false]\n     * @param {string} [options.filesFilter=custom]\n     * @param {string[]} [options.defaultBundlesRestriction]\n     */\n    init: function (parent, viewKey, options) {\n        this._super.apply(this, arguments);\n\n        this.context = options.context;\n\n        this.viewKey = viewKey;\n        this.options = _.defaults({}, options, {\n            position: 'right',\n            doNotLoadViews: false,\n            doNotLoadSCSS: false,\n            doNotLoadJS: false,\n            includeBundles: false,\n            filesFilter: 'custom',\n            defaultBundlesRestriction: [],\n        });\n\n        this.resources = {xml: {}, scss: {}, js: {}};\n        this.editingSessions = {xml: {}, scss: {}, js: {}};\n        this.currentType = 'xml';\n\n        // Alias\n        this.views = this.resources.xml;\n        this.scss = this.resources.scss;\n        this.js = this.resources.js;\n    },\n    /**\n     * Loads everything the ace library needs to work.\n     * It also loads the resources to visualize (@see _loadResources).\n     *\n     * @override\n     */\n    willStart: function () {\n        return Promise.all([\n            this._super.apply(this, arguments),\n            this._loadResources()\n        ]);\n    },\n    /**\n     * Initializes the library and initial view once the DOM is ready. It also\n     * initializes the resize feature of the ace editor.\n     *\n     * @override\n     */\n    start: function () {\n        this.$viewEditor = this.$('#ace-view-editor');\n\n        this.$typeSwitcherChoices = this.$('.o_ace_type_switcher_choice');\n        this.$typeSwitcherBtn = this.$('.o_ace_type_switcher > .dropdown-toggle');\n\n        this.$lists = {\n            xml: this.$('#ace-view-list'),\n            scss: this.$('#ace-scss-list'),\n            js: this.$('#ace-js-list'),\n        };\n        this.$includeBundlesArea = this.$('.oe_include_bundles');\n        this.$includeAllSCSSArea = this.$('.o_include_all_scss');\n        this.$viewID = this.$('#ace-view-id > span');\n        this.$warningMessage = this.$('#ace-view-id > .alert-warning');\n\n        this.$formatButton = this.$('button[data-action=format]');\n        this.$resetButton = this.$('button[data-action=reset]');\n\n        this.aceEditor = window.ace.edit(this.$viewEditor[0]);\n        this.aceEditor.setTheme('ace/theme/monokai');\n        this.$editor = this.$('.ace_editor');\n\n        var refX = 0;\n        var resizing = false;\n        var minWidth = 400;\n        var debounceStoreEditorWidth = _.debounce(storeEditorWidth, 500);\n\n        this._updateViewSelectDOM();\n\n        var initResID;\n        var initType;\n        if (this.options.initialResID) {\n            initResID = this.options.initialResID;\n            if (_.isString(initResID) && initResID[0] === '/') {\n                if (_.str.endsWith(initResID, '.scss')) {\n                    initType = 'scss';\n                } else {\n                    initType = 'js';\n                }\n            } else {\n                initType = 'xml';\n            }\n        } else {\n            if (!this.options.doNotLoadSCSS) {\n                initResID = this.sortedSCSS[0][1][0].url; // first bundle, scss files, first one\n                initType = 'scss';\n            }\n            if (!this.options.doNotLoadJS) {\n                initResID = this.sortedJS[0][1][0].url; // first bundle, js files, first one\n                initType = 'js';\n            }\n            if (!this.options.doNotLoadViews) {\n                if (typeof this.viewKey === \"number\") {\n                    initResID = this.viewKey;\n                } else {\n                    var view = _.findWhere(this.views, {xml_id: this.viewKey});\n                    if (!view) {\n                        view = _.findWhere(this.views, {key: this.viewKey});\n                    }\n                    initResID = view.id;\n                }\n                initType = 'xml';\n            }\n        }\n        if (initResID) {\n            this._displayResource(initResID, initType);\n        }\n\n        if (!this.sortedViews.length || !this.sortedSCSS.length) {\n            _.defer((function () {\n                this._switchType(this.sortedViews.length ? 'xml' : 'scss');\n                this.$typeSwitcherBtn.parent('.btn-group').addClass('d-none');\n            }).bind(this));\n        }\n\n        $(document).on('mouseup.ViewEditor', stopResizing.bind(this)).on('mousemove.ViewEditor', updateWidth.bind(this));\n        if (this.options.position === 'left') {\n            this.$('.ace_scroller').after($('<div>').addClass('ace_resize_bar'));\n            this.$('.ace_gutter').css({'cursor': 'default'});\n            this.$el.on('mousedown.ViewEditor', '.ace_resize_bar', startResizing.bind(this));\n        } else {\n            this.$el.on('mousedown.ViewEditor', '.ace_gutter', startResizing.bind(this));\n        }\n\n        resizeEditor.call(this, readEditorWidth.call(this));\n\n        return this._super.apply(this, arguments);\n\n        function resizeEditor(target) {\n            var width = Math.min(document.body.clientWidth, Math.max(parseInt(target, 10), minWidth));\n            this.$editor.width(width);\n            this.aceEditor.resize();\n            this.$el.width(width);\n\n            if (this.$errorLine) {\n                this.$errorLine.popover('update');\n            }\n        }\n        function storeEditorWidth() {\n            localStorage.setItem('ace_editor_width', this.$el.width());\n        }\n        function readEditorWidth() {\n            var width = localStorage.getItem('ace_editor_width');\n            return parseInt(width || 720, 10);\n        }\n        function startResizing(e) {\n            refX = e.pageX;\n            resizing = true;\n        }\n        function stopResizing() {\n            if (resizing) {\n                resizing = false;\n\n                if (this.errorSession) {\n                    // To trigger an update of the error display\n                    this.errorSession.setScrollTop(this.errorSession.getScrollTop() + 1);\n                }\n            }\n        }\n        function updateWidth(e) {\n            if (!resizing) return;\n\n            var offset = e.pageX - refX;\n            if (this.options.position === 'left') {\n                offset = - offset;\n            }\n            var width = this.$el.width() - offset;\n            refX = e.pageX;\n            resizeEditor.call(this, width);\n            debounceStoreEditorWidth.call(this);\n        }\n    },\n    /**\n     * @override\n     */\n    destroy: function () {\n        this._super.apply(this, arguments);\n        this.$el.off('.ViewEditor');\n        $(document).off('.ViewEditor');\n    },\n\n    //--------------------------------------------------------------------------\n    // Private\n    //--------------------------------------------------------------------------\n\n    /**\n     * Initializes a text editor for the specified resource.\n     *\n     * @private\n     * @param {integer|string} resID - the ID/URL of the view/scss/js file\n     * @param {string} [type] (default to the currently selected one)\n     * @returns {ace.EditSession}\n     */\n    _buildEditingSession: function (resID, type) {\n        var self = this;\n        type = type || this.currentType;\n        var editingSession = new window.ace.EditSession(this.resources[type][resID].arch);\n        editingSession.setUseWorker(false);\n        let mode = (type || this.currentType);\n        editingSession.setMode('ace/mode/' + (mode === 'xml' ? 'qweb' : mode));\n        editingSession.setUndoManager(new window.ace.UndoManager());\n        editingSession.on('change', function () {\n            _.defer(function () {\n                self._toggleDirtyInfo(resID);\n                self._showErrorLine();\n            });\n        });\n        return editingSession;\n    },\n    /**\n     * Forces the view/scss/js file identified by its ID/URL to be displayed in the\n     * editor. The method will update the resource select DOM element as well if\n     * necessary.\n     *\n     * @private\n     * @param {integer|string} resID\n     * @param {string} [type] - the type of resource (either 'xml', 'scss' or 'js')\n     */\n    _displayResource: function (resID, type) {\n        if (type) {\n            this._switchType(type);\n        }\n\n        if (!this.resources[this.currentType].hasOwnProperty(resID)) {\n            // This could happen if trying to switch to a file which is not\n            // visible with the default filters. In that case, we prefer the\n            // user to have to switch explicitely to the right filters again.\n            return;\n        }\n\n        var editingSession = this.editingSessions[this.currentType][resID];\n        if (!editingSession) {\n            editingSession = this.editingSessions[this.currentType][resID] = this._buildEditingSession(resID);\n        }\n        this.aceEditor.setSession(editingSession);\n\n        if (this.currentType === 'xml') {\n            this.$viewID.text(_.str.sprintf(_t(\"Template ID: %s\"), this.views[resID].key));\n        } else if (this.currentType === 'scss') {\n            this.$viewID.text(_.str.sprintf(_t(\"SCSS file: %s\"), resID));\n        } else {\n            this.$viewID.text(_.str.sprintf(_t(\"JS file: %s\"), resID));\n        }\n        const isCustomized = this._isCustomResource(resID);\n        this.$lists[this.currentType].select2('val', resID);\n\n        this.$resetButton.toggleClass('d-none', this.currentType === 'xml' || !isCustomized);\n\n        this.$warningMessage.toggleClass('d-none',\n            this.currentType !== 'xml' && (resID.indexOf('/user_custom_') >= 0) || isCustomized);\n\n        this.aceEditor.resize(true);\n    },\n    /**\n     * Formats the current resource being vizualized.\n     * (@see formatXML, formatSCSS)\n     *\n     * @private\n     */\n    _formatResource: function () {\n        var res = this.aceEditor.getValue();\n        var check = (this.currentType === 'xml' ? checkXML : checkSCSS)(res);\n        if (check.isValid) {\n            this.aceEditor.setValue((this.currentType === 'xml' ? formatXML : formatSCSS)(res));\n        } else {\n            this._showErrorLine(check.error.line, check.error.message, this._getSelectedResource());\n        }\n    },\n    /**\n     * Returns the currently selected resource data.\n     *\n     * @private\n     * @returns {integer|string} view ID or scss file URL\n     */\n    _getSelectedResource: function () {\n        var value = this.$lists[this.currentType].select2('val');\n        return parseInt(value, 10) || value;\n    },\n    /**\n     * Checks resource is customized or not.\n     *\n     * @private\n     * @param {integer|string} resID\n     */\n    _isCustomResource(resID) {\n        // TODO we should be able to detect if the XML template is customized\n        // to not show the warning in that case\n        let isCustomized = false;\n        if (this.currentType === 'scss') {\n            isCustomized = this.scss[resID].customized;\n        } else if (this.currentType === 'js') {\n            isCustomized = this.js[resID].customized;\n        }\n        return isCustomized;\n    },\n    /**\n     * Loads data the ace editor will vizualize and process it. Default behavior\n     * is loading the activate views, index them and build their hierarchy.\n     *\n     * @private\n     * @returns {Promise}\n     */\n    _loadResources: function () {\n        // Reset resources\n        this.resources = {xml: {}, scss: {}, js: {}};\n        this.editingSessions = {xml: {}, scss: {}, js: {}};\n        this.views = this.resources.xml;\n        this.scss = this.resources.scss;\n        this.js = this.resources.js;\n\n        // Load resources\n        return this._rpc({\n            route: '/web_editor/get_assets_editor_resources',\n            params: {\n                key: this.viewKey,\n                get_views: !this.options.doNotLoadViews,\n                get_scss: !this.options.doNotLoadSCSS,\n                get_js: !this.options.doNotLoadJS,\n                bundles: this.options.includeBundles,\n                bundles_restriction: this.options.filesFilter === 'all' ? [] : this.options.defaultBundlesRestriction,\n                only_user_custom_files: this.options.filesFilter === 'custom',\n            },\n        }).then((function (resources) {\n            _processViews.call(this, resources.views || []);\n            _processJSorSCSS.call(this, resources.scss || [], 'scss');\n            _processJSorSCSS.call(this, resources.js || [], 'js');\n        }).bind(this));\n\n        function _processViews(views) {\n            // Only keep the active views and index them by ID.\n            _.extend(this.views, _.indexBy(_.filter(views, function (view) {\n                return view.active;\n            }), 'id'));\n\n            // Initialize a 0 level for each view and assign them an array containing their children.\n            var self = this;\n            var roots = [];\n            _.each(this.views, function (view) {\n                view.level = 0;\n                view.children = [];\n            });\n            _.each(this.views, function (view) {\n                var parentId = view.inherit_id[0];\n                var parent = parentId && self.views[parentId];\n                if (parent) {\n                    parent.children.push(view);\n                } else {\n                    roots.push(view);\n                }\n            });\n\n            // Assign the correct level based on children key and save a sorted array where\n            // each view is followed by their children.\n            this.sortedViews = [];\n            function visit(view, level) {\n                view.level = level;\n                self.sortedViews.push(view);\n                _.each(view.children, function (child) {\n                    visit(child, level + 1);\n                });\n            }\n            _.each(roots, function (root) {\n                visit(root, 0);\n            });\n        }\n\n        function _processJSorSCSS(data, type) {\n            // The received scss or js data is already sorted by bundle and DOM order\n            if (type === 'scss') {\n                this.sortedSCSS = data;\n            } else {\n                this.sortedJS = data;\n            }\n\n            // Store the URL ungrouped by bundle and use the URL as key (resource ID)\n            var resources = type === 'scss' ? this.scss : this.js;\n            _.each(data, function (bundleInfos) {\n                _.each(bundleInfos[1], function (info) { info.bundle = bundleInfos[0]; });\n                _.extend(resources, _.indexBy(bundleInfos[1], 'url'));\n            });\n        }\n    },\n    /**\n     * Forces the view/scss/js file identified by its ID/URL to be reset to the way\n     * it was before the user started editing it.\n     *\n     * @todo views reset is not supported yet\n     *\n     * @private\n     * @param {integer|string} [resID] (default to the currently selected one)\n     * @param {string} [type] (default to the currently selected one)\n     * @returns {Promise}\n     */\n    _resetResource: function (resID, type) {\n        resID = resID || this._getSelectedResource();\n        type = type || this.currentType;\n\n        if (this.currentType === 'xml') {\n            return Promise.reject(_t(\"Reseting views is not supported yet\"));\n        } else {\n            var resource = type === 'scss' ? this.scss[resID] : this.js[resID];\n            return this._rpc({\n                route: '/web_editor/reset_asset',\n                params: {\n                    url: resID,\n                    bundle: resource.bundle,\n                },\n            });\n        }\n    },\n    /**\n     * Saves a unique SCSS or JS file.\n     *\n     * @private\n     * @param {Object} session - contains the 'id' (url) and the 'text' of the\n     *                         SCSS or JS file to save.\n     * @return {Promise} status indicates if the save is finished or if an\n     *                    error occured.\n     */\n    _saveSCSSorJS: function (session) {\n        var self = this;\n        var sessionIdEndsWithJS = _.string.endsWith(session.id, '.js');\n        var bundle = sessionIdEndsWithJS ? this.js[session.id].bundle : this.scss[session.id].bundle;\n        var fileType = sessionIdEndsWithJS ? 'js' : 'scss';\n        return self._rpc({\n            route: '/web_editor/save_asset',\n            params: {\n                url: session.id,\n                bundle,\n                content: session.text,\n                file_type: fileType,\n            },\n        }).then(function () {\n            self._toggleDirtyInfo(session.id, fileType, false);\n        });\n    },\n    /**\n     * Saves every resource that has been modified. If one cannot be saved, none\n     * is saved and an error message is displayed.\n     *\n     * @private\n     * @return {Promise} status indicates if the save is finished or if an\n     *                    error occured.\n     */\n    _saveResources: function () {\n        var self = this;\n        var toSave = {};\n        var errorFound = false;\n        _.each(this.editingSessions, (function (editingSessions, type) {\n            if (errorFound) return;\n\n            var dirtySessions = _.pick(editingSessions, function (session) {\n                return session.getUndoManager().hasUndo();\n            });\n            toSave[type] = _.map(dirtySessions, function (session, resID) {\n                return {\n                    id: parseInt(resID, 10) || resID,\n                    text: session.getValue(),\n                };\n            });\n\n            this._showErrorLine();\n            for (var i = 0 ; i < toSave[type].length && !errorFound ; i++) {\n                var check = (type === 'xml' ? checkXML : checkSCSS)(toSave[type][i].text);\n                if (!check.isValid) {\n                    this._showErrorLine(check.error.line, check.error.message, toSave[type][i].id, type);\n                    errorFound = toSave[type][i];\n                }\n            }\n        }).bind(this));\n        if (errorFound) return Promise.reject(errorFound);\n\n        var defs = [];\n        var mutex = new concurrency.Mutex();\n        _.each(toSave, (function (_toSave, type) {\n            // Child views first as COW on a parent would delete them\n            _toSave = _.sortBy(_toSave, 'id').reverse();\n            _.each(_toSave, function (session) {\n                defs.push(mutex.exec(function () {\n                    return (type === 'xml' ? self._saveView(session) : self._saveSCSSorJS(session));\n                }));\n            });\n        }).bind(this));\n\n        var self = this;\n        return Promise.all(defs).guardedCatch(function (results) {\n            // some overrides handle errors themselves\n            if (results === undefined) {\n                return;\n            }\n            var error = results[1];\n            Dialog.alert(self, '', {\n                title: _t(\"Server error\"),\n                $content: $('<div/>').html(\n                    _t(\"A server error occured. Please check you correctly signed in and that the file you are saving is correctly formatted.\")\n                    + '<br/>'\n                    + error\n                )\n            });\n        });\n    },\n    /**\n     * Saves an unique XML view.\n     *\n     * @private\n     * @param {Object} session - the 'id' and the 'text' of the view to save.\n     * @returns {Promise} status indicates if the save is finished or if an\n     *                     error occured.\n     */\n    _saveView: function (session) {\n        var self = this;\n        return new Promise(function (resolve, reject) {\n            self._rpc({\n                model: 'ir.ui.view',\n                method: 'write',\n                args: [[session.id], {arch: session.text}],\n            }, {\n                noContextKeys: 'lang',\n            }).then(function () {\n                self._toggleDirtyInfo(session.id, 'xml', false);\n                resolve();\n            }, function (source, error) {\n                reject(session, error);\n            });\n        });\n    },\n    /**\n     * Shows a line which produced an error. Red color is added to the editor,\n     * the cursor move to the line and a message is opened on click on the line\n     * number. If called without argument, the effects are removed.\n     *\n     * @private\n     * @param {integer} [line] - the line number to highlight\n     * @param {string} [message] - to show on click on the line number\n     * @param {integer|string} [resID]\n     * @param {string} [type]\n     */\n    _showErrorLine: function (line, message, resID, type) {\n        if (line === undefined || line <= 0) {\n            __restore.call(this);\n            return;\n        }\n\n        if (type) {\n            this._switchType(type);\n        }\n\n        if (this._getSelectedResource() === resID) {\n            __showErrorLine.call(this, line);\n        } else {\n            var onChangeSession = (function () {\n                this.aceEditor.off('changeSession', onChangeSession);\n                _.delay(__showErrorLine.bind(this, line), 400);\n            }).bind(this);\n            this.aceEditor.on('changeSession', onChangeSession);\n            this._displayResource(resID, this.currentType);\n        }\n\n        function __restore() {\n            if (this.errorSession) {\n                this.errorSession.off('change', this.errorSessionChangeCallback);\n                this.errorSession.off('changeScrollTop', this.errorSessionScrollCallback);\n                this.errorSession = undefined;\n            }\n            __restoreErrorLine.call(this);\n\n            if (this.$errorContent) { // TODO remove in master\n                this.$errorContent.removeClass('o_error');\n                this.$errorContent = undefined;\n            }\n        }\n\n        function __restoreErrorLine() {\n            if (this.$errorLine) {\n                this.$errorLine.removeClass('o_error');\n                this.$errorLine.popover('hide');\n                this.$errorLine.popover('dispose');\n                this.$errorLine = undefined;\n            }\n        }\n\n        function __updateErrorLineDisplay(line) {\n            __restoreErrorLine.call(this);\n\n            const $lines = this.$viewEditor.find('.ace_gutter-cell');\n            this.$errorLine = $lines.filter(function (i, el) {\n                return parseInt($(el).text()) === line;\n            });\n            if (!this.$errorLine.length) {\n                const $firstLine = $lines.first();\n                const firstLineNumber = parseInt($firstLine.text());\n                this.$errorLine = line < firstLineNumber ? $lines.eq(1) : $lines.eq($lines.length - 2);\n            }\n            this.$errorLine.addClass('o_error');\n            this.$errorLine.popover({\n                animation: false,\n                html: true,\n                content: message,\n                placement: 'left',\n                container: 'body',\n                trigger: 'manual',\n                template: '<div class=\"popover o_ace_error_popover\" role=\"tooltip\"><div class=\"arrow\"></div><h3 class=\"popover-header\"></h3><div class=\"popover-body\"></div></div>'\n            });\n            this.$errorLine.popover('show');\n        }\n\n        function __showErrorLine(line) {\n            this.$errorContent = this.$viewEditor.find('.ace_scroller').addClass('o_error'); // TODO remove in master\n\n            this.errorSession = this.aceEditor.getSession();\n            this.errorSessionChangeCallback = __restore.bind(this);\n            this.errorSession.on('change', this.errorSessionChangeCallback);\n            this.errorSessionScrollCallback = _.debounce(__updateErrorLineDisplay.bind(this, line), 10);\n            this.errorSession.on('changeScrollTop', this.errorSessionScrollCallback);\n\n            __updateErrorLineDisplay.call(this, line);\n\n            setTimeout(() => this.aceEditor.gotoLine(line), 100);\n        }\n    },\n    /**\n     * Switches to the SCSS, XML or JS edition. Calling this method will adapt all\n     * DOM elements to keep the editor consistent.\n     *\n     * @private\n     * @param {string} type - either 'xml', 'scss' or 'js'\n     */\n    _switchType: function (type) {\n        this.currentType = type;\n        this.$typeSwitcherBtn.html(this.$typeSwitcherChoices.filter('[data-type=' + type + ']').html());\n        _.each(this.$lists, function ($list, _type) { $list.toggleClass('d-none', type !== _type); });\n        this.$lists[type].change();\n\n        this.$includeBundlesArea.toggleClass('d-none', this.currentType !== 'xml' || !config.isDebug());\n        this.$includeAllSCSSArea.toggleClass('d-none', this.currentType !== 'scss' || !config.isDebug());\n        this.$includeAllSCSSArea.find('[data-value=\"restricted\"]').toggleClass('d-none', this.options.defaultBundlesRestriction.length === 0);\n        this.$formatButton.toggleClass('d-none', this.currentType !== 'xml');\n    },\n    /**\n     * Updates the select option DOM element associated with a particular resID\n     * to indicate if the option is dirty or not.\n     *\n     * @private\n     * @param {integer|string} resID\n     * @param {string} [type] (default to the currently selected one)\n     * @param {boolean} [isDirty] true if the view is dirty, default to content\n     *                            of UndoManager\n     */\n    _toggleDirtyInfo: function (resID, type, isDirty) {\n        type = type || this.currentType;\n\n        if (!resID || !this.editingSessions[type][resID]) return;\n\n        var $option = this.$lists[type].find('[value=\"' + resID + '\"]');\n        if (isDirty === undefined) {\n            isDirty = this.editingSessions[type][resID].getUndoManager().hasUndo();\n        }\n        $option.data('dirty', isDirty);\n    },\n    /**\n     * Renders the content of the view/file <select/> DOM element according to\n     * current widget data.\n     *\n     * @private\n     */\n    _updateViewSelectDOM: function () {\n        var currentId = this._getSelectedResource();\n\n        var self = this;\n        this.$lists.xml.empty();\n        _.each(this.sortedViews, function (view) {\n            self.$lists.xml.append($('<option/>', {\n                value: view.id,\n                text: view.name,\n                selected: currentId === view.id,\n                'data-level': view.level,\n                'data-debug': view.xml_id,\n            }));\n        });\n\n        this.$lists.scss.empty();\n        _populateList(this.sortedSCSS, this.$lists.scss, 5);\n\n        this.$lists.js.empty();\n        _populateList(this.sortedJS, this.$lists.js, 3);\n\n        this.$lists.xml.select2('destroy');\n        this.$lists.xml.select2({\n            formatResult: _formatDisplay.bind(this, false),\n            formatSelection: _formatDisplay.bind(this, true),\n        });\n        this.$lists.xml.data('select2').dropdown.addClass('o_ace_select2_dropdown');\n        this.$lists.scss.select2('destroy');\n        this.$lists.scss.select2({\n            formatResult: _formatDisplay.bind(this, false),\n            formatSelection: _formatDisplay.bind(this, true),\n        });\n        this.$lists.scss.data('select2').dropdown.addClass('o_ace_select2_dropdown');\n        this.$lists.js.select2('destroy');\n        this.$lists.js.select2({\n            formatResult: _formatDisplay.bind(this, false),\n            formatSelection: _formatDisplay.bind(this, true),\n        });\n        this.$lists.js.data('select2').dropdown.addClass('o_ace_select2_dropdown');\n\n        function _populateList(sortedData, $list, lettersToRemove) {\n            _.each(sortedData, function (bundleInfos) {\n                var $optgroup = $('<optgroup/>', {\n                    label: bundleInfos[0],\n                }).appendTo($list);\n                _.each(bundleInfos[1], function (dataInfo) {\n                    var name = dataInfo.url.substring(_.lastIndexOf(dataInfo.url, '/') + 1, dataInfo.url.length - lettersToRemove);\n                    $optgroup.append($('<option/>', {\n                        value: dataInfo.url,\n                        text: name,\n                        selected: currentId === dataInfo.url,\n                        'data-debug': dataInfo.url,\n                        'data-customized': dataInfo.customized\n                    }));\n                });\n            });\n        }\n\n        function _formatDisplay(isSelected, data) {\n            var $elem = $(data.element);\n\n            var text = data.text || '';\n            if (!isSelected) {\n                text = Array(($elem.data('level') || 0) + 1).join('-') + ' ' + text;\n            }\n            var $div = $('<div/>',  {\n                text: text,\n                class: 'o_ace_select2_result',\n            });\n\n            if ($elem.data('dirty') || $elem.data('customized')) {\n                $div.prepend($('<span/>', {\n                    class: 'mr8 fa fa-floppy-o ' + ($elem.data('dirty') ? 'text-warning' : 'text-success'),\n                }));\n            }\n\n            if (!isSelected && config.isDebug() && $elem.data('debug')) {\n                $div.append($('<span/>', {\n                    text: ' (' + $elem.data('debug') + ')',\n                    class: 'ml4 small text-muted',\n                }));\n            }\n\n            return $div;\n        }\n    },\n\n    //--------------------------------------------------------------------------\n    // Handlers\n    //--------------------------------------------------------------------------\n\n    /**\n     * Called when the close button is clicked -> hides the ace editor.\n     *\n     * @private\n     */\n    _onCloseClick: function () {\n        this._showErrorLine();\n        this.do_hide();\n    },\n    /**\n     * Called when the format button is clicked -> format the current resource.\n     *\n     * @private\n     */\n    _onFormatClick: function () {\n        this._formatResource();\n    },\n    /**\n     * Called when a filter dropdown item is cliked. Reload the resources\n     * according to the new filter and make it visually active.\n     *\n     * @private\n     * @param {Event} ev\n     */\n    _onFilterChange: function (ev) {\n        var $item = $(ev.target);\n        $item.addClass('active').siblings().removeClass('active');\n        if ($item.data('type') === 'xml') {\n            this.options.includeBundles = $(ev.target).data('value') === 'all';\n        } else {\n            this.options.filesFilter = $item.data('value');\n        }\n        this._loadResources().then(this._updateViewSelectDOM.bind(this));\n    },\n    /**\n     * Called when another resource is selected -> displays it.\n     *\n     * @private\n     */\n    _onResChange: function () {\n        this._displayResource(this._getSelectedResource());\n    },\n    /**\n     * Called when the reset button is clicked -> resets the resources to its\n     * original standard odoo state.\n     *\n     * @private\n     */\n    _onResetClick: function () {\n        var self = this;\n        Dialog.confirm(this, _t(\"If you reset this file, all your customizations will be lost as it will be reverted to the default file.\"), {\n            title: _t(\"Careful !\"),\n            confirm_callback: function () {\n                self._resetResource(self._getSelectedResource());\n            },\n        });\n    },\n    /**\n     * Called when the save button is clicked -> saves the dirty resources and\n     * reloads.\n     *\n     * @private\n     */\n    _onSaveClick: function (ev) {\n        const restore = dom.addButtonLoadingEffect(ev.currentTarget);\n        this._saveResources().then(restore).guardedCatch(restore);\n    },\n    /**\n     * Called when the user wants to switch from xml to scss or vice-versa ->\n     * adapt resources choices and displays a resource of that type.\n     *\n     * @private\n     * @param {Event} ev\n     */\n    _onTypeChoice: function (ev) {\n        ev.preventDefault();\n        this._switchType($(ev.target).data('type'));\n    },\n    /**\n     * Allows to hide the warning message without removing it from the DOM\n     * -> by default Bootstrap removes alert from the DOM\n     */\n    _onCloseWarningClick: function () {\n        this.$warningMessage.addClass('d-none');\n    },\n});\n\nreturn ViewEditor;\n});\n", "/** @odoo-module **/\n\n// Redefine the getRangeAt function in order to avoid an error appearing\n// sometimes when an input element is focused on Firefox.\n// The error happens because the range returned by getRangeAt is \"restricted\".\n// Ex: Range { commonAncestorContainer: Restricted, startContainer: Restricted,\n// startOffset: 0, endContainer: Restricted, endOffset: 0, collapsed: true }\n// The solution consists in detecting when the range is restricted and then\n// redefining it manually based on the current selection.\nconst originalGetRangeAt = Selection.prototype.getRangeAt;\nSelection.prototype.getRangeAt = function () {\n    let range = originalGetRangeAt.apply(this, arguments);\n    // Check if the range is restricted\n    if (range.startContainer && !Object.getPrototypeOf(range.startContainer)) {\n        // Define the range manually based on the selection\n        range = document.createRange();\n        range.setStart(this.anchorNode, 0);\n        range.setEnd(this.focusNode, 0);\n    }\n    return range;\n};\n", "odoo.define('web_editor.utils', function (require) {\n'use strict';\n\nconst {ColorpickerWidget} = require('web.Colorpicker');\n\n/**\n * window.getComputedStyle cannot work properly with CSS shortcuts (like\n * 'border-width' which is a shortcut for the top + right + bottom + left border\n * widths. If an option wants to customize such a shortcut, it should be listed\n * here with the non-shortcuts property it stands for, in order.\n *\n * @type {Object<string[]>}\n */\nconst CSS_SHORTHANDS = {\n    'border-width': ['border-top-width', 'border-right-width', 'border-bottom-width', 'border-left-width'],\n    'border-radius': ['border-top-left-radius', 'border-top-right-radius', 'border-bottom-right-radius', 'border-bottom-left-radius'],\n    'border-color': ['border-top-color', 'border-right-color', 'border-bottom-color', 'border-left-color'],\n    'border-style': ['border-top-style', 'border-right-style', 'border-bottom-style', 'border-left-style'],\n    'padding': ['padding-top', 'padding-right', 'padding-bottom', 'padding-left'],\n};\n/**\n * Key-value mapping to list converters from an unit A to an unit B.\n * - The key is a string in the format '$1-$2' where $1 is the CSS symbol of\n *   unit A and $2 is the CSS symbol of unit B.\n * - The value is a function that converts the received value (expressed in\n *   unit A) to another value expressed in unit B. Two other parameters is\n *   received: the css property on which the unit applies and the jQuery element\n *   on which that css property may change.\n */\nconst CSS_UNITS_CONVERSION = {\n    's-ms': () => 1000,\n    'ms-s': () => 0.001,\n    'rem-px': () => _computePxByRem(),\n    'px-rem': () => _computePxByRem(true),\n    '%-px': () => -1, // Not implemented but should simply be ignored for now\n    'px-%': () => -1, // Not implemented but should simply be ignored for now\n};\n/**\n * Colors of the default palette, used for substitution in shapes/illustrations.\n * key: number of the color in the palette (ie, o-color-<1-5>)\n * value: color hex code\n */\nconst DEFAULT_PALETTE = {\n    '1': '#3AADAA',\n    '2': '#7C6576',\n    '3': '#F6F6F6',\n    '4': '#FFFFFF',\n    '5': '#383E45',\n};\n/**\n * Set of all the data attributes relative to the background images.\n */\nconst BACKGROUND_IMAGE_ATTRIBUTES = new Set([\n    \"originalId\", \"originalSrc\", \"mimetype\", \"resizeWidth\", \"glFilter\", \"quality\", \"bgSrc\",\n    \"filterOptions\",\n]);\n\n/**\n * Computes the number of \"px\" needed to make a \"rem\" unit. Subsequent calls\n * returns the cached computed value.\n *\n * @param {boolean} [toRem=false]\n * @returns {float} - number of px by rem if 'toRem' is false\n *                  - the inverse otherwise\n */\nfunction _computePxByRem(toRem) {\n    if (_computePxByRem.PX_BY_REM === undefined) {\n        const htmlStyle = window.getComputedStyle(document.documentElement);\n        _computePxByRem.PX_BY_REM = parseFloat(htmlStyle['font-size']);\n    }\n    return toRem ? (1 / _computePxByRem.PX_BY_REM) : _computePxByRem.PX_BY_REM;\n}\n/**\n * Converts the given (value + unit) string to a numeric value expressed in\n * the other given css unit.\n *\n * e.g. fct('400ms', 's') -> 0.4\n *\n * @param {string} value\n * @param {string} unitTo\n * @param {string} [cssProp] - the css property on which the unit applies\n * @param {jQuery} [$target] - the jQuery element on which that css property\n *                             may change\n * @returns {number}\n */\nfunction _convertValueToUnit(value, unitTo, cssProp, $target) {\n    const m = _getNumericAndUnit(value);\n    if (!m) {\n        return NaN;\n    }\n    const numValue = parseFloat(m[0]);\n    const valueUnit = m[1];\n    return _convertNumericToUnit(numValue, valueUnit, unitTo, cssProp, $target);\n}\n/**\n * Converts the given numeric value expressed in the given css unit into\n * the corresponding numeric value expressed in the other given css unit.\n *\n * e.g. fct(400, 'ms', 's') -> 0.4\n *\n * @param {number} value\n * @param {string} unitFrom\n * @param {string} unitTo\n * @param {string} [cssProp] - the css property on which the unit applies\n * @param {jQuery} [$target] - the jQuery element on which that css property\n *                             may change\n * @returns {number}\n */\nfunction _convertNumericToUnit(value, unitFrom, unitTo, cssProp, $target) {\n    if (Math.abs(value) < Number.EPSILON || unitFrom === unitTo) {\n        return value;\n    }\n    const converter = CSS_UNITS_CONVERSION[`${unitFrom}-${unitTo}`];\n    if (converter === undefined) {\n        throw new Error(`Cannot convert '${unitFrom}' units into '${unitTo}' units !`);\n    }\n    return value * converter(cssProp, $target);\n}\n/**\n * Returns the numeric value and unit of a css value.\n *\n * e.g. fct('400ms') -> [400, 'ms']\n *\n * @param {string} value\n * @returns {Array|null}\n */\nfunction _getNumericAndUnit(value) {\n    const m = value.trim().match(/^(-?[0-9.]+)([A-Za-z% -]*)$/);\n    if (!m) {\n        return null;\n    }\n    return [m[1].trim(), m[2].trim()];\n}\n/**\n * Checks if two css values are equal.\n *\n * @param {string} value1\n * @param {string} value2\n * @param {string} [cssProp] - the css property on which the unit applies\n * @param {jQuery} [$target] - the jQuery element on which that css property\n *                             may change\n * @returns {boolean}\n */\nfunction _areCssValuesEqual(value1, value2, cssProp, $target) {\n    // String comparison first\n    if (value1 === value2) {\n        return true;\n    }\n\n    // It could be a CSS variable, in that case the actual value has to be\n    // retrieved before comparing.\n    if (value1.startsWith('var(--')) {\n        value1 = _getCSSVariableValue(value1.substring(6, value1.length - 1));\n    }\n    if (value2.startsWith('var(--')) {\n        value2 = _getCSSVariableValue(value2.substring(6, value2.length - 1));\n    }\n    if (value1 === value2) {\n        return true;\n    }\n\n    // They may be colors, normalize then re-compare the resulting string\n    const color1 = ColorpickerWidget.normalizeCSSColor(value1);\n    const color2 = ColorpickerWidget.normalizeCSSColor(value2);\n    if (color1 === color2) {\n        return true;\n    }\n\n    // They may be gradients\n    const value1IsGradient = _isColorGradient(value1);\n    const value2IsGradient = _isColorGradient(value2);\n    if (value1IsGradient !== value2IsGradient) {\n        return false;\n    }\n    if (value1IsGradient) {\n        // Kinda hacky and probably inneficient but probably the easiest way:\n        // applied the value as background-image of two fakes elements and\n        // compare their computed value.\n        const temp1El = document.createElement('div');\n        temp1El.style.backgroundImage = value1;\n        document.body.appendChild(temp1El);\n        value1 = getComputedStyle(temp1El).backgroundImage;\n        document.body.removeChild(temp1El);\n\n        const temp2El = document.createElement('div');\n        temp2El.style.backgroundImage = value2;\n        document.body.appendChild(temp2El);\n        value2 = getComputedStyle(temp2El).backgroundImage;\n        document.body.removeChild(temp2El);\n\n        return value1 === value2;\n    }\n\n    // In case the values are meant as box-shadow, this is difficult to compare.\n    // In this case we use the kinda hacky and probably inneficient but probably\n    // easiest way: applying the value as box-shadow of two fakes elements and\n    // compare their computed value.\n    if (cssProp === 'box-shadow') {\n        const temp1El = document.createElement('div');\n        temp1El.style.boxShadow = value1;\n        document.body.appendChild(temp1El);\n        value1 = getComputedStyle(temp1El).boxShadow;\n        document.body.removeChild(temp1El);\n\n        const temp2El = document.createElement('div');\n        temp2El.style.boxShadow = value2;\n        document.body.appendChild(temp2El);\n        value2 = getComputedStyle(temp2El).boxShadow;\n        document.body.removeChild(temp2El);\n\n        return value1 === value2;\n    }\n\n    // Convert the second value in the unit of the first one and compare\n    // floating values\n    const data = _getNumericAndUnit(value1);\n    if (!data) {\n        return false;\n    }\n    const numValue1 = data[0];\n    const numValue2 = _convertValueToUnit(value2, data[1], cssProp, $target);\n    return (Math.abs(numValue1 - numValue2) < Number.EPSILON);\n}\n/**\n * @param {string|number} name\n * @returns {boolean}\n */\nfunction _isColorCombinationName(name) {\n    const number = parseInt(name);\n    return (!isNaN(number) && number % 100 !== 0);\n}\n/**\n * @param {string[]} colorNames\n * @param {string} [prefix='bg-']\n * @returns {string[]}\n */\nfunction _computeColorClasses(colorNames, prefix = 'bg-') {\n    let hasCCClasses = false;\n    const isBgPrefix = (prefix === 'bg-');\n    const classes = colorNames.map(c => {\n        if (isBgPrefix && _isColorCombinationName(c)) {\n            hasCCClasses = true;\n            return `o_cc${c}`;\n        }\n        return (prefix + c);\n    });\n    if (hasCCClasses) {\n        classes.push('o_cc');\n    }\n    return classes;\n}\n/**\n * @param {string} key\n * @param {CSSStyleDeclaration} [htmlStyle] if not provided, it is computed\n * @returns {string}\n */\nfunction _getCSSVariableValue(key, htmlStyle) {\n    if (htmlStyle === undefined) {\n        htmlStyle = window.getComputedStyle(document.documentElement);\n    }\n    // Get trimmed value from the HTML element\n    let value = htmlStyle.getPropertyValue(`--${key}`).trim();\n    // If it is a color value, it needs to be normalized\n    value = ColorpickerWidget.normalizeCSSColor(value);\n    // Normally scss-string values are \"printed\" single-quoted. That way no\n    // magic conversation is needed when customizing a variable: either save it\n    // quoted for strings or non quoted for colors, numbers, etc. However,\n    // Chrome has the annoying behavior of changing the single-quotes to\n    // double-quotes when reading them through getPropertyValue...\n    return value.replace(/\"/g, \"'\");\n}\n/**\n * Normalize a color in case it is a variable name so it can be used outside of\n * css.\n *\n * @param {string} color the color to normalize into a css value\n * @returns {string} the normalized color\n */\nfunction _normalizeColor(color) {\n    if (ColorpickerWidget.isCSSColor(color)) {\n        return color;\n    }\n    return _getCSSVariableValue(color);\n}\n/**\n * Parse an element's background-image's url.\n *\n * @param {string} string a css value in the form 'url(\"...\")'\n * @returns {string|false} the src of the image or false if not parsable\n */\nfunction _getBgImageURL(el) {\n    const parts = _backgroundImageCssToParts($(el).css('background-image'));\n    const string = parts.url || '';\n    const match = string.match(/^url\\((['\"])(.*?)\\1\\)$/);\n    if (!match) {\n        return '';\n    }\n    const matchedURL = match[2];\n    // Make URL relative if possible\n    const fullURL = new URL(matchedURL, window.location.origin);\n    if (fullURL.origin === window.location.origin) {\n        return fullURL.href.slice(fullURL.origin.length);\n    }\n    return matchedURL;\n}\n/**\n * Extracts url and gradient parts from the background-image CSS property.\n *\n * @param {string} CSS 'background-image' property value\n * @returns {Object} contains the separated 'url' and 'gradient' parts\n */\nfunction _backgroundImageCssToParts(css) {\n    const parts = {};\n    css = css || '';\n    if (css.startsWith('url(')) {\n        const urlEnd = css.indexOf(')') + 1;\n        parts.url = css.substring(0, urlEnd).trim();\n        const commaPos = css.indexOf(',', urlEnd);\n        css = commaPos > 0 ? css.substring(commaPos + 1) : '';\n    }\n    if (_isColorGradient(css)) {\n        parts.gradient = css.trim();\n    }\n    return parts;\n}\n/**\n * Combines url and gradient parts into a background-image CSS property value\n *\n * @param {Object} contains the separated 'url' and 'gradient' parts\n * @returns {string} CSS 'background-image' property value\n */\nfunction _backgroundImagePartsToCss(parts) {\n    let css = parts.url || '';\n    if (parts.gradient) {\n        css += (css ? ', ' : '') + parts.gradient;\n    }\n    return css || 'none';\n}\n/**\n * @param {string} [value]\n * @returns {boolean}\n */\nfunction _isColorGradient(value) {\n    // FIXME duplicated in odoo-editor/utils.js\n    return value && value.includes('-gradient(');\n}\n/**\n * Returns the class of the element that matches the specified prefix.\n *\n * @private\n * @param {Element} el element from which to recover the color class\n * @param {string[]} colorNames\n * @param {string} prefix prefix of the color class to recover\n * @returns {string} color class matching the prefix or an empty string\n */\nfunction _getColorClass(el, colorNames, prefix) {\n    const prefixedColorNames = _computeColorClasses(colorNames, prefix);\n    return el.classList.value.split(' ').filter(cl => prefixedColorNames.includes(cl)).join(' ');\n}\n/**\n * Add one or more new attributes related to background images in the\n * BACKGROUND_IMAGE_ATTRIBUTES set.\n *\n * @param {...string} newAttributes The new attributes to add in the\n * BACKGROUND_IMAGE_ATTRIBUTES set.\n */\nfunction _addBackgroundImageAttributes(...newAttributes) {\n    BACKGROUND_IMAGE_ATTRIBUTES.add(...newAttributes);\n}\n/**\n * Check if an attribute is in the BACKGROUND_IMAGE_ATTRIBUTES set.\n *\n * @param {string} attribute The attribute that has to be checked.\n */\nfunction _isBackgroundImageAttribute(attribute) {\n    return BACKGROUND_IMAGE_ATTRIBUTES.has(attribute);\n}\n/**\n * Checks if an element supposedly marked with the o_editable_media class should\n * in fact be editable (checks if its environment looks like a non editable\n * environment whose media should be editable).\n *\n * TODO: the name of this function is voluntarily bad to reflect the fact that\n * this system should be improved. The combination of o_not_editable,\n * o_editable, getContentEditableAreas, getReadOnlyAreas and other concepts\n * related to what should be editable or not should be reviewed.\n *\n * @returns {boolean}\n */\nfunction _shouldEditableMediaBeEditable(mediaEl) {\n    // Some sections of the DOM are contenteditable=\"false\" (for\n    // example with the help of the o_not_editable class) but have\n    // inner media that should be editable (the fact the container\n    // is not is to prevent adding text in between those medias).\n    // This case is complex and the solution to support it is not\n    // perfect: we mark those media with a class and check that the\n    // first non editable ancestor is in fact in an editable parent.\n    const parentEl = mediaEl.parentElement;\n    const nonEditableAncestorRootEl = parentEl && parentEl.closest('[contenteditable=\"false\"]');\n    return nonEditableAncestorRootEl\n        && nonEditableAncestorRootEl.parentElement\n        && nonEditableAncestorRootEl.parentElement.isContentEditable;\n}\n\nreturn {\n    CSS_SHORTHANDS: CSS_SHORTHANDS,\n    CSS_UNITS_CONVERSION: CSS_UNITS_CONVERSION,\n    DEFAULT_PALETTE: DEFAULT_PALETTE,\n    computePxByRem: _computePxByRem,\n    convertValueToUnit: _convertValueToUnit,\n    convertNumericToUnit: _convertNumericToUnit,\n    getNumericAndUnit: _getNumericAndUnit,\n    areCssValuesEqual: _areCssValuesEqual,\n    isColorCombinationName: _isColorCombinationName,\n    isColorGradient: _isColorGradient,\n    computeColorClasses: _computeColorClasses,\n    getCSSVariableValue: _getCSSVariableValue,\n    normalizeColor: _normalizeColor,\n    getBgImageURL: _getBgImageURL,\n    backgroundImageCssToParts: _backgroundImageCssToParts,\n    backgroundImagePartsToCss: _backgroundImagePartsToCss,\n    getColorClass: _getColorClass,\n    addBackgroundImageAttributes: _addBackgroundImageAttributes,\n    isBackgroundImageAttribute: _isBackgroundImageAttribute,\n    shouldEditableMediaBeEditable: _shouldEditableMediaBeEditable,\n};\n});\n", "/** @odoo-module **/\n\nexport function isImg(node) {\n    return (node && (node.nodeName === \"IMG\" || (node.className && node.className.match(/(^|\\s)(media_iframe_video|o_image|fa)(\\s|$)/i))));\n}\n\n/**\n * Returns a list of all the ancestors nodes of the provided node.\n *\n * @param {Node} node\n * @param {Node} [stopElement] include to prevent bubbling up further than the stopElement.\n * @returns {HTMLElement[]}\n */\nexport function ancestors(node, stopElement) {\n    if (!node || !node.parentElement || node === stopElement) return [];\n    return [node.parentElement, ...ancestors(node.parentElement, stopElement)];\n}", "/** @odoo-module **/\n\nexport const DIRECTIONS = {\n    LEFT: false,\n    RIGHT: true,\n};\nexport const CTYPES = {\n    // Short for CONTENT_TYPES\n    // Inline group\n    CONTENT: 1,\n    SPACE: 2,\n\n    // Block group\n    BLOCK_OUTSIDE: 4,\n    BLOCK_INSIDE: 8,\n\n    // Br group\n    BR: 16,\n};\nexport function ctypeToString(ctype) {\n    return Object.keys(CTYPES).find((key) => CTYPES[key] === ctype);\n}\nexport const CTGROUPS = {\n    // Short for CONTENT_TYPE_GROUPS\n    INLINE: CTYPES.CONTENT | CTYPES.SPACE,\n    BLOCK: CTYPES.BLOCK_OUTSIDE | CTYPES.BLOCK_INSIDE,\n    BR: CTYPES.BR,\n};\nconst tldWhitelist = [\n    'com', 'net', 'org', 'ac', 'ad', 'ae', 'af', 'ag', 'ai', 'al', 'am', 'an',\n    'ao', 'aq', 'ar', 'as', 'at', 'au', 'aw', 'ax', 'az', 'ba', 'bb', 'bd',\n    'be', 'bf', 'bg', 'bh', 'bi', 'bj', 'bl', 'bm', 'bn', 'bo', 'br', 'bq',\n    'bs', 'bt', 'bv', 'bw', 'by', 'bz', 'ca', 'cc', 'cd', 'cf', 'cg', 'ch',\n    'ci', 'ck', 'cl', 'cm', 'cn', 'co', 'cr', 'cs', 'cu', 'cv', 'cw', 'cx',\n    'cy', 'cz', 'dd', 'de', 'dj', 'dk', 'dm', 'do', 'dz', 'ec', 'ee', 'eg',\n    'eh', 'er', 'es', 'et', 'eu', 'fi', 'fj', 'fk', 'fm', 'fo', 'fr', 'ga',\n    'gb', 'gd', 'ge', 'gf', 'gg', 'gh', 'gi', 'gl', 'gm', 'gn', 'gp', 'gq',\n    'gr', 'gs', 'gt', 'gu', 'gw', 'gy', 'hk', 'hm', 'hn', 'hr', 'ht', 'hu',\n    'id', 'ie', 'il', 'im', 'in', 'io', 'iq', 'ir', 'is', 'it', 'je', 'jm',\n    'jo', 'jp', 'ke', 'kg', 'kh', 'ki', 'km', 'kn', 'kp', 'kr', 'kw', 'ky',\n    'kz', 'la', 'lb', 'lc', 'li', 'lk', 'lr', 'ls', 'lt', 'lu', 'lv', 'ly',\n    'ma', 'mc', 'md', 'me', 'mf', 'mg', 'mh', 'mk', 'ml', 'mm', 'mn', 'mo',\n    'mp', 'mq', 'mr', 'ms', 'mt', 'mu', 'mv', 'mw', 'mx', 'my', 'mz', 'na',\n    'nc', 'ne', 'nf', 'ng', 'ni', 'nl', 'no', 'np', 'nr', 'nu', 'nz', 'om',\n    'pa', 'pe', 'pf', 'pg', 'ph', 'pk', 'pl', 'pm', 'pn', 'pr', 'ps', 'pt',\n    'pw', 'py', 'qa', 're', 'ro', 'rs', 'ru', 'rw', 'sa', 'sb', 'sc', 'sd',\n    'se', 'sg', 'sh', 'si', 'sj', 'sk', 'sl', 'sm', 'sn', 'so', 'sr', 'ss',\n    'st', 'su', 'sv', 'sx', 'sy', 'sz', 'tc', 'td', 'tf', 'tg', 'th', 'tj',\n    'tk', 'tl', 'tm', 'tn', 'to', 'tp', 'tr', 'tt', 'tv', 'tw', 'tz', 'ua',\n    'ug', 'uk', 'um', 'us', 'uy', 'uz', 'va', 'vc', 've', 'vg', 'vi', 'vn',\n    'vu', 'wf', 'ws', 'ye', 'yt', 'yu', 'za', 'zm', 'zr', 'zw', 'co\\\\.uk'];\n\nconst urlRegexBase = `|(?:[-a-zA-Z0-9@:%._\\\\+~#=]{1,64}\\\\.))[-a-zA-Z0-9@:%._\\\\+~#=]{2,256}\\\\.[a-zA-Z][a-zA-Z0-9]{1,62}|(?:[-a-zA-Z0-9@:%._\\\\+~#=]{2,256}\\\\.(?:${tldWhitelist.join('|')})))\\\\b(?:(?!\\\\.)[^\\\\s]*`;\nconst httpRegex = `(?:https?:\\\\/\\\\/)`;\nconst httpCapturedRegex= `(https?:\\\\/\\\\/)`;\n\nexport const URL_REGEX = new RegExp(`((?:(?:${httpRegex}${urlRegexBase}))`, 'gi');\nexport const URL_REGEX_WITH_INFOS = new RegExp(`((?:(?:${httpCapturedRegex}${urlRegexBase}))`, 'gi');\nexport const YOUTUBE_URL_GET_VIDEO_ID =\n    /^(?:(?:https?:)?\\/\\/)?(?:(?:www|m)\\.)?(?:youtube\\.com|youtu\\.be)(?:\\/(?:[\\w-]+\\?v=|embed\\/|v\\/)?)([^\\s?&#]+)(?:\\S+)?$/i;\n\n//------------------------------------------------------------------------------\n// Position and sizes\n//------------------------------------------------------------------------------\n\n/**\n * @param {Node} node\n * @returns {Array.<HTMLElement, number>}\n */\nexport function leftPos(node) {\n    return [node.parentNode, childNodeIndex(node)];\n}\n/**\n * @param {Node} node\n * @returns {Array.<HTMLElement, number>}\n */\nexport function rightPos(node) {\n    return [node.parentNode, childNodeIndex(node) + 1];\n}\n/**\n * @param {Node} node\n * @returns {Array.<HTMLElement, number, HTMLElement, number>}\n */\nexport function boundariesOut(node) {\n    const index = childNodeIndex(node);\n    return [node.parentNode, index, node.parentNode, index + 1];\n}\n/**\n * @param {Node} node\n * @returns {Array.<Node, number>}\n */\nexport function startPos(node) {\n    return [node, 0];\n}\n/**\n * @param {Node} node\n * @returns {Array.<Node, number>}\n */\nexport function endPos(node) {\n    return [node, nodeSize(node)];\n}\n/**\n * @param {Node} node\n * @returns {Array.<node, number, node, number>}\n */\nexport function boundariesIn(node) {\n    return [node, 0, node, nodeSize(node)];\n}\n/**\n * Returns the given node's position relative to its parent (= its index in the\n * child nodes of its parent).\n *\n * @param {Node} node\n * @returns {number}\n */\nexport function childNodeIndex(node) {\n    let i = 0;\n    while (node.previousSibling) {\n        i++;\n        node = node.previousSibling;\n    }\n    return i;\n}\n/**\n * Returns the size of the node = the number of characters for text nodes and\n * the number of child nodes for element nodes.\n *\n * @param {Node} node\n * @returns {number}\n */\nexport function nodeSize(node) {\n    const isTextNode = node.nodeType === Node.TEXT_NODE;\n    return isTextNode ? node.length : node.childNodes.length;\n}\n\n//------------------------------------------------------------------------------\n// DOM Path and node search functions\n//------------------------------------------------------------------------------\n\nexport const closestPath = function* (node) {\n    while (node) {\n        yield node;\n        node = node.parentNode;\n    }\n};\n\n/**\n * Values which can be returned while browsing the DOM which gives information\n * to why the path ended.\n */\nconst PATH_END_REASONS = {\n    NO_NODE: 0,\n    BLOCK_OUT: 1,\n    BLOCK_HIT: 2,\n    OUT_OF_SCOPE: 3,\n};\n/**\n * Creates a generator function according to the given parameters. Pre-made\n * generators to traverse the DOM are made using this function:\n *\n * @see leftLeafFirstPath\n * @see leftLeafOnlyNotBlockPath\n * @see leftLeafOnlyInScopeNotBlockNoEditablePath\n * @see rightLeafOnlyNotBlockPath\n * @see rightLeafOnlyPathNotBlockNotEditablePath\n * @see rightLeafOnlyInScopeNotBlockPath\n * @see rightLeafOnlyNotBlockNotEditablePath\n *\n * @param {number} direction\n * @param {boolean} [options.leafOnly] if true, do not yield any non-leaf node\n * @param {boolean} [options.inScope] if true, stop the generator as soon as a node is not\n *                      a descendant of `node` provided when traversing the\n *                      generated function.\n * @param {Function} [options.stopTraverseFunction] a function that takes a node\n *                      and should return true when a node descendant should not\n *                      be traversed.\n * @param {Function} [options.stopFunction] function that makes the generator stop when a\n *                      node is encountered.\n */\nexport function createDOMPathGenerator(\n    direction,\n    { leafOnly = false, inScope = false, stopTraverseFunction, stopFunction } = {},\n) {\n    const nextDeepest =\n        direction === DIRECTIONS.LEFT\n            ? node => lastLeaf(node.previousSibling, stopTraverseFunction)\n            : node => firstLeaf(node.nextSibling, stopTraverseFunction);\n\n    const firstNode =\n        direction === DIRECTIONS.LEFT\n            ? (node, offset) => lastLeaf(node.childNodes[offset - 1], stopTraverseFunction)\n            : (node, offset) => firstLeaf(node.childNodes[offset], stopTraverseFunction);\n\n    // Note \"reasons\" is a way for the caller to be able to know why the\n    // generator ended yielding values.\n    return function* (node, offset, reasons = []) {\n        let movedUp = false;\n\n        let currentNode = firstNode(node, offset);\n        if (!currentNode) {\n            movedUp = true;\n            currentNode = node;\n        }\n\n        while (currentNode) {\n            if (stopFunction && stopFunction(currentNode)) {\n                reasons.push(movedUp ? PATH_END_REASONS.BLOCK_OUT : PATH_END_REASONS.BLOCK_HIT);\n                break;\n            }\n            if (inScope && currentNode === node) {\n                reasons.push(PATH_END_REASONS.OUT_OF_SCOPE);\n                break;\n            }\n            if (!(leafOnly && movedUp)) {\n                yield currentNode;\n            }\n\n            movedUp = false;\n            let nextNode = nextDeepest(currentNode);\n            if (!nextNode) {\n                movedUp = true;\n                nextNode = currentNode.parentNode;\n            }\n            currentNode = nextNode;\n        }\n\n        reasons.push(PATH_END_REASONS.NO_NODE);\n    };\n}\n\n/**\n * Find a node.\n * @param {findCallback} findCallback - This callback check if this function\n *      should return `node`.\n * @param {findCallback} stopCallback - This callback check if this function\n *      should stop when it receive `node`.\n */\nexport function findNode(domPath, findCallback = () => true, stopCallback = () => false) {\n    for (const node of domPath) {\n        if (findCallback(node)) {\n            return node;\n        }\n        if (stopCallback(node)) {\n            break;\n        }\n    }\n    return null;\n}\n/**\n * This callback check if findNode should return `node`.\n * @callback findCallback\n * @param {Node} node\n * @return {Boolean}\n */\n/**\n * This callback check if findNode should stop when it receive `node`.\n * @callback stopCallback\n * @param {Node} node\n */\n\n/**\n * Returns the closest HTMLElement of the provided Node\n * if a 'selector' is provided, Returns the closest HTMLElement that match the selector\n *\n * @param {Node} node\n * @param {string} [selector=undefined]\n * @param {boolean} [restrictToEditable=false]\n * @returns {HTMLElement}\n */\nexport function closestElement(node, selector, restrictToEditable=false) {\n    let element = node;\n    while (element && element.nodeType !== Node.ELEMENT_NODE) {\n        element = element.parentNode;\n    }\n    if (element && selector) {\n        element = element.closest(selector);\n    }\n    return restrictToEditable && element && element.querySelector('.odoo-editor-editable') ? null : element;\n}\n\n/**\n * Returns a list of all the ancestors nodes of the provided node.\n *\n * @param {Node} node\n * @param {Node} [editable] include to prevent bubbling up further than the editable.\n * @returns {HTMLElement[]}\n */\nexport function ancestors(node, editable) {\n    if (!node || !node.parentElement || node === editable) return [];\n    return [node.parentElement, ...ancestors(node.parentElement, editable)];\n}\n\n/**\n * Take a node, return all of its descendants, in depth-first order.\n *\n * @param {Node} node\n * @returns {Node[]}\n */\nexport function descendants(node) {\n    const posterity = [];\n    for (const child of (node.childNodes || [])) {\n        posterity.push(child, ...descendants(child));\n    }\n    return posterity;\n}\n\nexport function closestBlock(node) {\n    return findNode(closestPath(node), node => isBlock(node));\n}\n/**\n * Returns the deepest child in last position.\n *\n * @param {Node} node\n * @param {Function} [stopTraverseFunction]\n * @returns {Node}\n */\nexport function lastLeaf(node, stopTraverseFunction) {\n    while (node && node.lastChild && !(stopTraverseFunction && stopTraverseFunction(node))) {\n        node = node.lastChild;\n    }\n    return node;\n}\n/**\n * Returns the deepest child in first position.\n *\n * @param {Node} node\n * @param {Function} [stopTraverseFunction]\n * @returns {Node}\n */\nexport function firstLeaf(node, stopTraverseFunction) {\n    while (node && node.firstChild && !(stopTraverseFunction && stopTraverseFunction(node))) {\n        node = node.firstChild;\n    }\n    return node;\n}\nexport function previousLeaf(node, editable, skipInvisible = false) {\n    let ancestor = node;\n    while (ancestor && !ancestor.previousSibling && ancestor !== editable) {\n        ancestor = ancestor.parentElement;\n    }\n    if (ancestor && ancestor !== editable) {\n        if (skipInvisible && !isVisible(ancestor.previousSibling)) {\n            return previousLeaf(ancestor.previousSibling, editable, skipInvisible);\n        } else {\n            const last = lastLeaf(ancestor.previousSibling);\n            if (skipInvisible && !isVisible(last)) {\n                return previousLeaf(last, editable, skipInvisible);\n            } else {\n                return last;\n            }\n        }\n    }\n}\nexport function nextLeaf(node, editable, skipInvisible = false) {\n    let ancestor = node;\n    while (ancestor && !ancestor.nextSibling && ancestor !== editable) {\n        ancestor = ancestor.parentElement;\n    }\n    if (ancestor && ancestor !== editable) {\n        if (skipInvisible && ancestor.nextSibling && !isVisible(ancestor.nextSibling)) {\n            return nextLeaf(ancestor.nextSibling, editable, skipInvisible);\n        } else {\n            const first = firstLeaf(ancestor.nextSibling);\n            if (skipInvisible && !isVisible(first)) {\n                return nextLeaf(first, editable, skipInvisible);\n            } else {\n                return first;\n            }\n        }\n    }\n}\n/**\n * Returns all the previous siblings of the given node until the first\n * sibling that does not satisfy the predicate, in lookup order.\n *\n * @param {Node} node\n * @param {Function} [predicate] (node: Node) => boolean\n */\nexport function getAdjacentPreviousSiblings(node, predicate = n => !!n) {\n    let previous = node.previousSibling;\n    const list = [];\n    while (previous && predicate(previous)) {\n        list.push(previous);\n        previous = previous.previousSibling;\n    }\n    return list;\n}\n/**\n * Returns all the next siblings of the given node until the first\n * sibling that does not satisfy the predicate, in lookup order.\n *\n * @param {Node} node\n * @param {Function} [predicate] (node: Node) => boolean\n */\nexport function getAdjacentNextSiblings(node, predicate = n => !!n) {\n    let next = node.nextSibling;\n    const list = [];\n    while (next && predicate(next)) {\n        list.push(next);\n        next = next.nextSibling;\n    }\n    return list;\n}\n/**\n * Returns all the adjacent siblings of the given node until the first sibling\n * (in both directions) that does not satisfy the predicate, in index order. If\n * the given node does not satisfy the predicate, an empty array is returned.\n *\n * @param {Node} node\n * @param {Function} [predicate] (node: Node) => boolean\n */\nexport function getAdjacents(node, predicate = n => !!n) {\n    const previous = getAdjacentPreviousSiblings(node, predicate);\n    const next = getAdjacentNextSiblings(node, predicate);\n    return predicate(node) ? [...previous.reverse(), node, ...next] : [];\n}\n\n//------------------------------------------------------------------------------\n// Cursor management\n//------------------------------------------------------------------------------\n\n/**\n * From a given position, returns the normalized version.\n *\n * E.g. <b>abc</b>[]def -> <b>abc[]</b>def\n *\n * @param {Node} node\n * @param {number} offset\n * @param {boolean} [full=true] (if not full, it means we only normalize\n *     positions which are not possible, like the cursor inside an image).\n */\nexport function getNormalizedCursorPosition(node, offset, full = true) {\n    if (isVisibleEmpty(node) || !closestElement(node).isContentEditable) {\n        // Cannot put cursor inside those elements, put it after instead.\n        [node, offset] = rightPos(node);\n    }\n\n    // Be permissive about the received offset.\n    offset = Math.min(Math.max(offset, 0), nodeSize(node));\n\n    if (full) {\n        // Put the cursor in deepest inline node around the given position if\n        // possible.\n        let el;\n        let elOffset;\n        if (node.nodeType === Node.ELEMENT_NODE) {\n            el = node;\n            elOffset = offset;\n        } else if (node.nodeType === Node.TEXT_NODE) {\n            if (offset === 0) {\n                el = node.parentNode;\n                elOffset = childNodeIndex(node);\n            } else if (offset === node.length) {\n                el = node.parentNode;\n                elOffset = childNodeIndex(node) + 1;\n            }\n        }\n        if (el) {\n            const leftInlineNode = leftLeafOnlyInScopeNotBlockNoEditablePath(el, elOffset).next()\n                .value;\n            let leftVisibleEmpty = false;\n            if (leftInlineNode) {\n                leftVisibleEmpty =\n                    isVisibleEmpty(leftInlineNode) ||\n                    !closestElement(leftInlineNode).isContentEditable;\n                [node, offset] = leftVisibleEmpty\n                    ? rightPos(leftInlineNode)\n                    : endPos(leftInlineNode);\n            }\n            if (!leftInlineNode || leftVisibleEmpty) {\n                const rightInlineNode = rightLeafOnlyInScopeNotBlockPath(el, elOffset).next().value;\n                if (rightInlineNode) {\n                    const rightVisibleEmpty =\n                        isVisibleEmpty(rightInlineNode) ||\n                        !closestElement(rightInlineNode).isContentEditable;\n                    if (!(leftVisibleEmpty && rightVisibleEmpty)) {\n                        [node, offset] = rightVisibleEmpty\n                            ? leftPos(rightInlineNode)\n                            : startPos(rightInlineNode);\n                    }\n                }\n            }\n        }\n    }\n\n    const prevNode = node.nodeType === Node.ELEMENT_NODE && node.childNodes[offset - 1];\n    if (prevNode && prevNode.nodeName === 'BR' && isFakeLineBreak(prevNode)) {\n        // If trying to put the cursor on the right of a fake line break, put\n        // it before instead.\n        offset--;\n    }\n\n    return [node, offset];\n}\n/**\n * @param {Node} anchorNode\n * @param {number} anchorOffset\n * @param {Node} focusNode\n * @param {number} focusOffset\n * @param {boolean} [normalize=true]\n * @returns {?Array.<Node, number}\n */\nexport function setSelection(\n    anchorNode,\n    anchorOffset,\n    focusNode = anchorNode,\n    focusOffset = anchorOffset,\n    normalize = true,\n) {\n    if (\n        !anchorNode ||\n        !anchorNode.parentElement ||\n        !anchorNode.parentElement.closest('body') ||\n        !focusNode ||\n        !focusNode.parentElement ||\n        !focusNode.parentElement.closest('body')\n    ) {\n        return null;\n    }\n    const document = anchorNode.ownerDocument;\n\n    const seemsCollapsed = anchorNode === focusNode && anchorOffset === focusOffset;\n    [anchorNode, anchorOffset] = getNormalizedCursorPosition(anchorNode, anchorOffset, normalize);\n    [focusNode, focusOffset] = seemsCollapsed\n        ? [anchorNode, anchorOffset]\n        : getNormalizedCursorPosition(focusNode, focusOffset, normalize);\n\n    const direction = getCursorDirection(anchorNode, anchorOffset, focusNode, focusOffset);\n    const sel = document.getSelection();\n    if (!sel) {\n        return null;\n    }\n    try {\n        const range = new Range();\n        if (direction === DIRECTIONS.RIGHT) {\n            range.setStart(anchorNode, anchorOffset);\n            range.collapse(true);\n        } else {\n            range.setEnd(anchorNode, anchorOffset);\n            range.collapse(false);\n        }\n        sel.removeAllRanges();\n        sel.addRange(range);\n        sel.extend(focusNode, focusOffset);\n    } catch (e) {\n        // Firefox throws NS_ERROR_FAILURE when setting selection on element\n        // with contentEditable=false for no valid reason since non-editable\n        // content are selectable by the user anyway.\n        if (e.name !== 'NS_ERROR_FAILURE') {\n            throw e;\n        }\n    }\n\n    return [anchorNode, anchorOffset, focusNode, focusOffset];\n}\n/**\n * @param {Node} node\n * @param {boolean} [normalize=true]\n * @returns {?Array.<Node, number}\n */\nexport function setCursorStart(node, normalize = true) {\n    const pos = startPos(node);\n    return setSelection(...pos, ...pos, normalize);\n}\n/**\n * @param {Node} node\n * @param {boolean} [normalize=true]\n * @returns {?Array.<Node, number}\n */\nexport function setCursorEnd(node, normalize = true) {\n    const pos = endPos(node);\n    return setSelection(...pos, ...pos, normalize);\n}\n/**\n * From selection position, checks if it is left-to-right or right-to-left.\n *\n * @param {Node} anchorNode\n * @param {number} anchorOffset\n * @param {Node} focusNode\n * @param {number} focusOffset\n * @returns {boolean} the direction of the current range if the selection not is collapsed | false\n */\nexport function getCursorDirection(anchorNode, anchorOffset, focusNode, focusOffset) {\n    if (anchorNode === focusNode) {\n        if (anchorOffset === focusOffset) return false;\n        return anchorOffset < focusOffset ? DIRECTIONS.RIGHT : DIRECTIONS.LEFT;\n    }\n    return anchorNode.compareDocumentPosition(focusNode) & Node.DOCUMENT_POSITION_FOLLOWING\n        ? DIRECTIONS.RIGHT\n        : DIRECTIONS.LEFT;\n}\n/**\n * Returns an array containing all the nodes traversed when walking the\n * selection.\n *\n * @param {Node} editable\n * @returns {Node[]}\n */\nexport function getTraversedNodes(editable, range = getDeepRange(editable)) {\n    const document = editable.ownerDocument;\n    if (!range) return [];\n    const iterator = document.createNodeIterator(range.commonAncestorContainer);\n    let node;\n    do {\n        node = iterator.nextNode();\n    } while (node && node !== range.startContainer);\n    const traversedNodes = new Set([node, ...descendants(node)]);\n    while (node && node !== range.endContainer) {\n        node = iterator.nextNode();\n        node && traversedNodes.add(node);\n    }\n    return [...traversedNodes];\n}\n/**\n * Returns an array containing all the nodes fully contained in the selection.\n *\n * @param {Node} editable\n * @returns {Node[]}\n */\nexport function getSelectedNodes(editable) {\n    const document = editable.ownerDocument;\n    const sel = document.getSelection();\n    if (!sel.rangeCount) {\n        return [];\n    }\n    const range = sel.getRangeAt(0);\n    return getTraversedNodes(editable).filter(\n        node => range.isPointInRange(node, 0) && range.isPointInRange(node, nodeSize(node)),\n    );\n}\n\n/**\n * Returns the current range (if any), adapted to target the deepest\n * descendants.\n *\n * @param {Node} editable\n * @param {object} [options]\n * @param {Selection} [options.range] the range to use.\n * @param {Selection} [options.sel] the selection to use.\n * @param {boolean} [options.splitText] split the targeted text nodes at offset.\n * @param {boolean} [options.select] select the new range if it changed (via splitText).\n * @param {boolean} [options.correctTripleClick] adapt the range if it was a triple click.\n * @returns {Range}\n */\nexport function getDeepRange(editable, { range, sel, splitText, select, correctTripleClick } = {}) {\n    sel = sel || editable.ownerDocument.getSelection();\n    // if browser wrongly return br element as anchor node, replace by its parent\n    if (sel.isCollapsed && sel.anchorNode && sel.anchorNode.nodeName === \"BR\") {\n        setCursorStart(sel.anchorNode.parentElement, false);\n    }\n    range = range ? range.cloneRange() : sel.rangeCount && sel.getRangeAt(0).cloneRange();\n    if (!range) return;\n    let start = range.startContainer;\n    let startOffset = range.startOffset;\n    let end = range.endContainer;\n    let endOffset = range.endOffset;\n\n    const isBackwards =\n        !range.collapsed && start === sel.focusNode && startOffset === sel.focusOffset;\n\n    // Target the deepest descendant of the range nodes.\n    [start, startOffset] = getDeepestPosition(start, startOffset);\n    [end, endOffset] = getDeepestPosition(end, endOffset);\n\n    // Split text nodes if that was requested.\n    if (splitText) {\n        const isInSingleContainer = start === end;\n        if (\n            end.nodeType === Node.TEXT_NODE &&\n            endOffset !== 0 &&\n            endOffset !== end.textContent.length\n        ) {\n            const endParent = end.parentNode;\n            const splitOffset = splitTextNode(end, endOffset);\n            end = endParent.childNodes[splitOffset - 1] || endParent.firstChild;\n            if (isInSingleContainer) {\n                start = end;\n            }\n            endOffset = end.textContent.length;\n        }\n        if (\n            start.nodeType === Node.TEXT_NODE &&\n            startOffset !== 0 &&\n            startOffset !== start.textContent.length\n        ) {\n            splitTextNode(start, startOffset);\n            startOffset = 0;\n            if (isInSingleContainer) {\n                endOffset = start.textContent.length;\n            }\n        }\n    }\n    // A selection spanning multiple nodes and ending at position 0 of a node,\n    // like the one resulting from a triple click, is corrected so that it ends\n    // at the last position of the previous node instead.\n    const endLeaf = firstLeaf(end);\n    const beforeEnd = endLeaf.previousSibling;\n    const previous = previousLeaf(endLeaf, editable, true);\n    if (\n        correctTripleClick &&\n        !endOffset &&\n        (start !== end || startOffset !== endOffset) &&\n        (!beforeEnd || (beforeEnd.nodeType === Node.TEXT_NODE && !isVisibleStr(beforeEnd))) &&\n        previous && !closestElement(previous, 'table')\n    ) {\n        if (closestElement(previous).isContentEditable) {\n            [end, endOffset] = [previous, nodeSize(previous)];\n        }\n    }\n\n    if (select) {\n        if (isBackwards) {\n            [start, end, startOffset, endOffset] = [end, start, endOffset, startOffset];\n            range.setEnd(start, startOffset);\n            range.collapse(false);\n        } else {\n            range.setStart(start, startOffset);\n            range.collapse(true);\n        }\n        sel.removeAllRanges();\n        sel.addRange(range);\n        try {\n            sel.extend(end, endOffset);\n        } catch (e) {\n            // Firefox yells not happy when setting selection on elem with contentEditable=false.\n        }\n        range = sel.getRangeAt(0);\n    } else {\n        range.setStart(start, startOffset);\n        range.setEnd(end, endOffset);\n    }\n    return range;\n}\n\nfunction getNextVisibleNode(node) {\n    while (node && !isVisible(node)) {\n        node = node.nextSibling;\n    }\n    return node;\n}\n\nexport function getDeepestPosition(node, offset) {\n    let found = false;\n    while (node.hasChildNodes()) {\n        let newNode = node.childNodes[offset];\n        if (newNode) {\n            newNode = getNextVisibleNode(newNode);\n            if (!newNode || isVisibleEmpty(newNode)) break;\n            found = true;\n            node = newNode;\n            offset = 0;\n        } else {\n            break;\n        }\n    }\n    if (!found) {\n        while (node.hasChildNodes()) {\n            let newNode = node.childNodes[offset - 1];\n            newNode = getNextVisibleNode(newNode);\n            if (!newNode || isVisibleEmpty(newNode)) break;\n            node = newNode;\n            offset = nodeSize(node);\n        }\n    }\n    let didMove = false;\n    let reversed = false;\n    while (!isVisible(node) && (node.previousSibling || (!reversed && node.nextSibling))) {\n        reversed = reversed || !node.nextSibling;\n        node = reversed ? node.previousSibling : node.nextSibling;\n        offset = reversed ? nodeSize(node) : 0;\n        didMove = true;\n    }\n    return didMove && isVisible(node) ? getDeepestPosition(node, offset) : [node, offset];\n}\n\nexport function getCursors(document) {\n    const sel = document.getSelection();\n    if (\n        getCursorDirection(sel.anchorNode, sel.anchorOffset, sel.focusNode, sel.focusOffset) ===\n        DIRECTIONS.LEFT\n    )\n        return [\n            [sel.focusNode, sel.focusOffset],\n            [sel.anchorNode, sel.anchorOffset],\n        ];\n    return [\n        [sel.anchorNode, sel.anchorOffset],\n        [sel.focusNode, sel.focusOffset],\n    ];\n}\n\nexport function preserveCursor(document) {\n    const sel = document.getSelection();\n    const cursorPos = [sel.anchorNode, sel.anchorOffset, sel.focusNode, sel.focusOffset];\n    return replace => {\n        replace = replace || new Map();\n        cursorPos[0] = replace.get(cursorPos[0]) || cursorPos[0];\n        cursorPos[2] = replace.get(cursorPos[2]) || cursorPos[2];\n        setSelection(...cursorPos, false);\n    };\n}\n\n//------------------------------------------------------------------------------\n// Format utils\n//------------------------------------------------------------------------------\n\nconst formatsSpecs = {\n    italic: {\n        tagName: 'em',\n        isFormatted: isItalic,\n        isTag: (node) => ['EM', 'I'].includes(node.tagName),\n        hasStyle: (node) => Boolean(node.style && node.style['font-style']),\n        addStyle: (node) => node.style['font-style'] = 'italic',\n        addNeutralStyle: (node) => node.style['font-style'] = 'normal',\n        removeStyle: (node) => removeStyle(node, 'font-style'),\n    },\n    bold: {\n        tagName: 'strong',\n        isFormatted: isBold,\n        isTag: (node) => ['STRONG', 'B'].includes(node.tagName),\n        hasStyle: (node) => Boolean(node.style && node.style['font-weight']),\n        addStyle: (node) => node.style['font-weight'] = 'bolder',\n        addNeutralStyle: (node) => {\n            node.style['font-weight'] = 'normal'\n        },\n        removeStyle: (node) => removeStyle(node, 'font-weight'),\n    },\n    underline: {\n        tagName: 'u',\n        isFormatted: isUnderline,\n        isTag: (node) => node.tagName === 'U',\n        hasStyle: (node) => node.style && node.style['text-decoration-line'].includes('underline'),\n        addStyle: (node) => node.style['text-decoration-line'] += ' underline',\n        removeStyle: (node) => removeStyle(node, 'text-decoration-line', 'underline'),\n    },\n    strikeThrough: {\n        tagName: 's',\n        isFormatted: isStrikeThrough,\n        isTag: (node) => node.tagName === 'S',\n        hasStyle: (node) => node.style && node.style['text-decoration-line'].includes('line-through'),\n        addStyle: (node) => node.style['text-decoration-line'] += ' line-through',\n        removeStyle: (node) => removeStyle(node, 'text-decoration-line', 'line-through'),\n    },\n    fontSize: {\n        isFormatted: isFontSize,\n        hasStyle: (node) => node.style && node.style['font-size'],\n        addStyle: (node, props) => node.style['font-size'] = props.size,\n        removeStyle: (node) => removeStyle(node, 'font-size'),\n    },\n    switchDirection: {\n        isFormatted: isDirectionSwitched,\n    }\n\n}\n\nconst removeStyle = (node, styleName, item) => {\n    if (item) {\n        const newStyle = node.style[styleName].split(' ').filter(x => x !== item).join(' ');\n        node.style[styleName] = newStyle || null;\n    } else {\n        node.style[styleName] = null;\n    }\n    if (node.getAttribute('style') === '') {\n        node.removeAttribute('style');\n    }\n};\nconst getOrCreateSpan = (node, ancestors) => {\n    const span = ancestors.find((element) => element.tagName === 'SPAN' && element.isConnected);\n    if (span) {\n        return span;\n    } else {\n        const span = document.createElement('span');\n        node.after(span);\n        span.append(node);\n        return span;\n    }\n}\nconst removeFormat = (node, formatSpec) => {\n    node = closestElement(node);\n    if (formatSpec.hasStyle(node)) {\n        formatSpec.removeStyle(node);\n        if (['SPAN', 'FONT'].includes(node.tagName) && !node.getAttributeNames().length) {\n            return unwrapContents(node);\n        }\n    }\n\n    if (formatSpec.isTag && formatSpec.isTag(node)) {\n        const attributesNames = node.getAttributeNames().filter((name)=> {\n            return name !== 'oe-zws-empty-inline';\n        });\n        if (attributesNames.length) {\n            // Change tag name\n            const newNode = document.createElement('span');\n            while (node.firstChild) {\n                newNode.appendChild(node.firstChild);\n            }\n            for (let index = node.attributes.length - 1; index >= 0; --index) {\n                newNode.attributes.setNamedItem(node.attributes[index].cloneNode());\n            }\n            node.parentNode.replaceChild(newNode, node);\n        } else {\n            unwrapContents(node);\n        }\n    }\n}\n\nexport const formatSelection = (editor, formatName, {applyStyle, formatProps} = {}) => {\n    const selection = editor.document.getSelection();\n    if (!selection.rangeCount) return;\n    const wasCollapsed = selection.getRangeAt(0).collapsed;\n\n    const direction = getCursorDirection(selection.anchorNode, selection.anchorOffset, selection.focusNode, selection.focusOffset);\n    getDeepRange(editor.editable, { splitText: true, select: true, correctTripleClick: true });\n\n    if (typeof applyStyle === 'undefined') {\n        applyStyle = !isSelectionFormat(editor.editable, formatName);\n    }\n\n    let zws;\n    if (wasCollapsed) {\n        if (selection.anchorNode.nodeType === Node.TEXT_NODE && selection.anchorNode.textContent === '\\u200b') {\n            zws = selection.anchorNode;\n            selection.getRangeAt(0).selectNode(zws);\n        } else {\n            zws = insertAndSelectZws(selection);\n        }\n        getDeepRange(editor.editable, { splitText: true, select: true, correctTripleClick: true });\n    }\n\n    const selectedTextNodes = getSelectedNodes(editor.editable)\n        .filter(n => n.nodeType === Node.TEXT_NODE && isVisibleTextNode(n));\n\n    const formatSpec = formatsSpecs[formatName];\n    for (const selectedTextNode of selectedTextNodes) {\n        const inlineAncestors = [];\n        let currentNode = selectedTextNode;\n        let parentNode = selectedTextNode.parentElement;\n\n        // Remove the format on all inline ancestors until a block or an element\n        // with a class (in case the formating comes from the class).\n        while (parentNode && (!isBlock(parentNode) && !(parentNode.classList && parentNode.classList.length))) {\n            const isUselessZws = parentNode.tagName === 'SPAN' &&\n                parentNode.hasAttribute('oe-zws-empty-inline') &&\n                parentNode.getAttributeNames().length === 1;\n\n            if (isUselessZws) {\n                unwrapContents(parentNode);\n            } else {\n                const newLastAncestorInlineFormat = splitAroundUntil(currentNode, parentNode);\n                removeFormat(newLastAncestorInlineFormat, formatSpec);\n                if (newLastAncestorInlineFormat.isConnected) {\n                    inlineAncestors.push(newLastAncestorInlineFormat);\n                    currentNode = newLastAncestorInlineFormat;\n                }\n            }\n\n            parentNode = currentNode.parentElement;\n        }\n\n        const firstBlockOrClassHasFormat = formatSpec.isFormatted(parentNode, formatProps);\n\n        if (firstBlockOrClassHasFormat && !applyStyle) {\n            formatSpec.addNeutralStyle && formatSpec.addNeutralStyle(getOrCreateSpan(selectedTextNode, inlineAncestors));\n        } else if (!firstBlockOrClassHasFormat && applyStyle) {\n            const tag = formatSpec.tagName && document.createElement(formatSpec.tagName);\n            if (tag) {\n                selectedTextNode.after(tag);\n                tag.append(selectedTextNode);\n\n                if (!formatSpec.isFormatted(tag, formatProps)) {\n                    tag.after(selectedTextNode);\n                    tag.remove();\n                    formatSpec.addStyle(getOrCreateSpan(selectedTextNode, inlineAncestors), formatProps);\n                }\n            } else if (formatName !== 'fontSize' || formatProps.size !== undefined) {\n                formatSpec.addStyle(getOrCreateSpan(selectedTextNode, inlineAncestors), formatProps);\n            }\n        }\n    }\n\n    if (zws) {\n        const siblings = [...zws.parentElement.childNodes];\n        if (\n            selectedTextNodes.includes(siblings[0]) &&\n            selectedTextNodes.includes(siblings[siblings.length - 1])\n        ) {\n            zws.parentElement.setAttribute('oe-zws-empty-inline', '');\n        } else {\n            const span = document.createElement('span');\n            span.setAttribute('oe-zws-empty-inline', '');\n            zws.before(span);\n            span.append(zws);\n        }\n    }\n\n    if (selectedTextNodes[0] && selectedTextNodes[0].textContent === '\\u200B') {\n        setSelection(selectedTextNodes[0], 0);\n    } else if (selectedTextNodes.length) {\n        const firstNode = selectedTextNodes[0];\n        const lastNode = selectedTextNodes[selectedTextNodes.length - 1];\n        if (direction === DIRECTIONS.RIGHT) {\n            setSelection(firstNode, 0, lastNode, lastNode.length, false);\n        } else {\n            setSelection(lastNode, lastNode.length, firstNode, 0, false);\n        }\n    }\n}\n\n//------------------------------------------------------------------------------\n// DOM Info utils\n//------------------------------------------------------------------------------\n\n/**\n * The following is a complete list of all HTML \"block-level\" elements.\n *\n * Source:\n * https://developer.mozilla.org/en-US/docs/Web/HTML/Block-level_elements\n *\n **/\nconst blockTagNames = [\n    'ADDRESS',\n    'ARTICLE',\n    'ASIDE',\n    'BLOCKQUOTE',\n    'DETAILS',\n    'DIALOG',\n    'DD',\n    'DIV',\n    'DL',\n    'DT',\n    'FIELDSET',\n    'FIGCAPTION',\n    'FIGURE',\n    'FOOTER',\n    'FORM',\n    'H1',\n    'H2',\n    'H3',\n    'H4',\n    'H5',\n    'H6',\n    'HEADER',\n    'HGROUP',\n    'HR',\n    'LI',\n    'MAIN',\n    'NAV',\n    'OL',\n    'P',\n    'PRE',\n    'SECTION',\n    'TABLE',\n    'UL',\n    // The following elements are not in the W3C list, for some reason.\n    'SELECT',\n    'OPTION',\n    'TR',\n    'TD',\n    'TBODY',\n    'THEAD',\n    'TH',\n];\nconst computedStyles = new WeakMap();\n/**\n * Return true if the given node is a block-level element, false otherwise.\n *\n * @param node\n */\nexport function isBlock(node) {\n    if (node.nodeType !== Node.ELEMENT_NODE) {\n        return false;\n    }\n    const tagName = node.nodeName.toUpperCase();\n    // Every custom jw-* node will be considered as blocks.\n    if (\n        tagName.startsWith('JW-') ||\n        (tagName === 'T' &&\n            node.getAttribute('t-esc') === null &&\n            node.getAttribute('t-out') === null &&\n            node.getAttribute('t-raw') === null)\n    ) {\n        return true;\n    }\n    if (tagName === 'BR') {\n        // A <br> is always inline but getComputedStyle(br).display mistakenly\n        // returns 'block' if its parent is display:flex (at least on Chrome and\n        // Firefox (Linux)). Browsers normally support setting a <br>'s display\n        // property to 'none' but any other change is not supported. Therefore\n        // it is safe to simply declare that a <br> is never supposed to be a\n        // block.\n        return false;\n    }\n    // The node might not be in the DOM, in which case it has no CSS values.\n    if (!node.isConnected) {\n        return blockTagNames.includes(tagName);\n    }\n    // We won't call `getComputedStyle` more than once per node.\n    let style = computedStyles.get(node);\n    if (!style) {\n        style = node.ownerDocument.defaultView.getComputedStyle(node);\n        computedStyles.set(node, style);\n    }\n    if (style.display) {\n        return !style.display.includes('inline') && style.display !== 'contents';\n    }\n    return blockTagNames.includes(tagName);\n}\n\n/**\n * Return true if the given node appears bold. The node is considered to appear\n * bold if its font weight is bigger than 500 (eg.: Heading 1), or if its font\n * weight is bigger than that of its closest block.\n *\n * @param {Node} node\n * @returns {boolean}\n */\nexport function isBold(node) {\n    const fontWeight = +getComputedStyle(closestElement(node)).fontWeight;\n    return fontWeight > 500 || fontWeight > +getComputedStyle(closestBlock(node)).fontWeight;\n}\n/**\n * Return true if the given node appears italic.\n *\n * @param {Node} node\n * @returns {boolean}\n */\nexport function isItalic(node) {\n    return getComputedStyle(closestElement(node)).fontStyle === 'italic';\n}\n/**\n * Return true if the given node appears underlined.\n *\n * @param {Node} node\n * @returns {boolean}\n */\nexport function isUnderline(node) {\n    let parent = closestElement(node);\n    while (parent) {\n        if (getComputedStyle(parent).textDecorationLine.includes('underline')) {\n            return true;\n        }\n        parent = parent.parentElement;\n    }\n    return false;\n}\n/**\n * Return true if the given node appears struck through.\n *\n * @param {Node} node\n * @returns {boolean}\n */\nexport function isStrikeThrough(node) {\n    let parent = closestElement(node);\n    while (parent) {\n        if (getComputedStyle(parent).textDecorationLine.includes('line-through')) {\n            return true;\n        }\n        parent = parent.parentElement;\n    }\n    return false;\n}\n/**\n * Return true if the given node font-size is equal to `props.size`.\n *\n * @param {Object} props\n * @param {Node} props.node A node to compare the font-size against.\n * @param {String} props.size The font-size value of the node that will be\n *     checked against.\n * @returns {boolean}\n */\nexport function isFontSize(node, props) {\n    const element = closestElement(node);\n    return getComputedStyle(element)['font-size'] === props.size;\n}\n/**\n * Return true if the given node appears in a different direction than that of\n * the editable ('ltr' or 'rtl').\n *\n * Note: The direction of the editable is set on its \"dir\" attribute, to the\n * value of the \"direction\" option on instantiation of the editor.\n *\n * @param {Node} node\n * @param {Element} editable\n * @returns {boolean}\n */\n export function isDirectionSwitched(node, editable) {\n    const defaultDirection = editable.getAttribute('dir');\n    return getComputedStyle(closestElement(node)).direction !== defaultDirection;\n}\n/**\n * Return true if the current selection on the editable appears as the given\n * format. The selection is considered to appear as that format if every text\n * node in it appears as that format.\n *\n * @param {Element} editable\n * @param {String} format 'bold'|'italic'|'underline'|'strikeThrough'|'switchDirection'\n * @returns {boolean}\n */\nexport function isSelectionFormat(editable, format) {\n    const selectedNodes = getTraversedNodes(editable)\n        .filter(n => n.nodeType === Node.TEXT_NODE && n.nodeValue.trim().length);\n    const isFormatted = formatsSpecs[format].isFormatted;\n    return selectedNodes.every(n => isFormatted(n, editable));\n}\n\nexport function isUnbreakable(node) {\n    if (!node || node.nodeType === Node.TEXT_NODE) {\n        return false;\n    }\n    if (node.nodeType !== Node.ELEMENT_NODE) {\n        return true;\n    }\n    return (\n        isUnremovable(node) || // An unremovable node is always unbreakable.\n        ['THEAD', 'TBODY', 'TFOOT', 'TR', 'TH', 'TD', 'SECTION', 'DIV'].includes(node.tagName) ||\n        node.hasAttribute('t') ||\n        (node.nodeType === Node.ELEMENT_NODE &&\n            (node.nodeName === 'T' ||\n                node.getAttribute('t-if') ||\n                node.getAttribute('t-esc') ||\n                node.getAttribute('t-elif') ||\n                node.getAttribute('t-else') ||\n                node.getAttribute('t-foreach') ||\n                node.getAttribute('t-value') ||\n                node.getAttribute('t-out') ||\n                node.getAttribute('t-raw'))) ||\n        node.classList.contains('oe_unbreakable')\n    );\n}\n\nexport function isUnremovable(node) {\n    return (\n        (node.nodeType !== Node.ELEMENT_NODE && node.nodeType !== Node.TEXT_NODE) ||\n        node.oid === 'root' ||\n        (node.nodeType === Node.ELEMENT_NODE &&\n            (node.classList.contains('o_editable') || node.getAttribute('t-set') || node.getAttribute('t-call'))) ||\n        (node.classList && node.classList.contains('oe_unremovable')) ||\n        (node.nodeName === 'SPAN' && node.parentElement && node.parentElement.getAttribute('data-oe-type') === 'monetary') ||\n        (node.ownerDocument && node.ownerDocument.defaultWindow && !ancestors(node).find(ancestor => ancestor.oid === 'root')) // Node is in DOM but not in editable.\n    );\n}\n\nexport function containsUnbreakable(node) {\n    if (!node) {\n        return false;\n    }\n    return isUnbreakable(node) || containsUnbreakable(node.firstChild);\n}\nexport function isFontAwesome(node) {\n    return (\n        node &&\n        (node.nodeName === 'I' || node.nodeName === 'SPAN') &&\n        ['fa', 'fab', 'fad', 'far'].some(faClass => node.classList.contains(faClass))\n    );\n}\nexport function isZWS(node) {\n    return (\n        node &&\n        node.textContent === '\\u200B'\n    );\n}\nexport function isMediaElement(node) {\n    return (\n        isFontAwesome(node) ||\n        (node.classList &&\n            (node.classList.contains('o_image') || node.classList.contains('media_iframe_video')))\n    );\n}\nexport function isVoidElement(node) {\n    return isMediaElement(node) || node.tagName === 'HR';\n}\n\nexport function containsUnremovable(node) {\n    if (!node) {\n        return false;\n    }\n    return isUnremovable(node) || containsUnremovable(node.firstChild);\n}\n\nexport function getInSelection(document, selector) {\n    const selection = document.getSelection();\n    const range = selection && !!selection.rangeCount && selection.getRangeAt(0);\n    if (range) {\n        const selectorInStartAncestors = closestElement(range.startContainer, selector);\n        if (selectorInStartAncestors) {\n            return selectorInStartAncestors;\n        } else {\n            const commonElementAncestor = closestElement(range.commonAncestorContainer);\n            return commonElementAncestor && [...commonElementAncestor.querySelectorAll(selector)].find(\n                node => range.intersectsNode(node),\n            );\n        }\n    }\n}\n\n// This is a list of \"paragraph-related elements\", defined as elements that\n// behave like paragraphs.\nconst paragraphRelatedElements = [\n    'P',\n    'H1',\n    'H2',\n    'H3',\n    'H4',\n    'H5',\n    'H6',\n    'PRE',\n    'BLOCKQUOTE',\n];\n\n/**\n * Return true if the given node allows \"paragraph-related elements\".\n *\n * @see paragraphRelatedElements\n * @param {Node} node\n * @returns {boolean}\n */\nexport function allowsParagraphRelatedElements(node) {\n    return isBlock(node) && !paragraphRelatedElements.includes(node.nodeName);\n}\n\n/**\n * Take a node and unwrap all of its block contents recursively. All blocks\n * (except for firstChilds) are preceded by a <br> in order to preserve the line\n * breaks.\n *\n * @param {Node} node\n */\nexport function makeContentsInline(node) {\n    let childIndex = 0;\n    for (const child of node.childNodes) {\n        if (isBlock(child)) {\n            if (childIndex && paragraphRelatedElements.includes(child.nodeName)) {\n                child.before(document.createElement('br'));\n            }\n            for (const grandChild of child.childNodes) {\n                child.before(grandChild);\n                makeContentsInline(grandChild);\n            }\n            child.remove();\n        }\n        childIndex += 1;\n    }\n}\n\n/**\n * Returns an array of url infos for url matched in the given string.\n *\n * @param {String} string\n * @returns {Array}\n */\nexport function getUrlsInfosInString(string) {\n    let infos = [],\n        match;\n    while ((match = URL_REGEX_WITH_INFOS.exec(string))) {\n        infos.push({\n            url: match[2] ? match[0] : 'https://' + match[0],\n            label: match[0],\n            index: match.index,\n            length: match[0].length,\n        });\n    }\n    return infos;\n}\n\n// optimize: use the parent Oid to speed up detection\nexport function getOuid(node, optimize = false) {\n    while (node && !isUnbreakable(node)) {\n        if (node.ouid && optimize) return node.ouid;\n        node = node.parentNode;\n    }\n    return node && node.oid;\n}\n/**\n * Returns true if the provided node can suport html content.\n *\n * @param {Node} node\n * @returns {boolean}\n */\nexport function isHtmlContentSupported(node) {\n    return !closestElement(node, '[data-oe-model]:not([data-oe-field=\"arch\"]):not([data-oe-type=\"html\"]),[data-oe-translation-id]', true);\n}\n/**\n * Returns whether the given node is a element that could be considered to be\n * removed by itself = self closing tags.\n *\n * @param {Node} node\n * @returns {boolean}\n */\nconst selfClosingElementTags = ['BR', 'IMG', 'INPUT'];\nexport function isVisibleEmpty(node) {\n    return selfClosingElementTags.includes(node.nodeName);\n}\n/**\n * Returns true if the given node is in a PRE context for whitespace handling.\n *\n * @param {Node} node\n * @returns {boolean}\n */\nexport function isInPre(node) {\n    const element = node.nodeType === Node.TEXT_NODE ? node.parentElement : node;\n    return (\n        !!element &&\n        (!!element.closest('pre') ||\n            getComputedStyle(element).getPropertyValue('white-space') === 'pre')\n    );\n}\n/**\n * Returns whether the given string (or given text node value)\n * has at least one visible character or one non colapsed whitespace characters in it.\n */\nconst nonWhitespacesRegex = /[\\S\\u00A0]/;\nexport function isVisibleStr(value) {\n    const str = typeof value === 'string' ? value : value.nodeValue;\n    return nonWhitespacesRegex.test(str);\n}\n/**\n * @param {Node} node\n * @returns {boolean}\n */\nexport function isContentTextNode(node) {\n    return node.nodeType === Node.TEXT_NODE && (isVisible(node) || isInPre(node));\n}\n/**\n * Returns whether removing the given node from the DOM will have a visible\n * effect or not.\n *\n * Note: TODO this is not handling all cases right now, just the ones the\n * caller needs at the moment. For example a space text node between two inlines\n * will always return 'true' while it is sometimes invisible.\n *\n * @param {Node} node\n * @param {boolean} areBlocksAlwaysVisible\n * @returns {boolean}\n */\nexport function isVisible(node, areBlocksAlwaysVisible = true) {\n    if (!node) return false;\n    if (node.nodeType === Node.TEXT_NODE) {\n        return isVisibleTextNode(node);\n    }\n    if ((areBlocksAlwaysVisible && isBlock(node)) || isVisibleEmpty(node)) {\n        return true;\n    }\n    return [...node.childNodes].some(n => isVisible(n));\n}\n\nfunction isVisibleTextNode(testedNode) {\n    if (!testedNode.length) {\n        return false;\n    }\n    if (isVisibleStr(testedNode)) {\n        return true;\n    }\n    // The following assumes node is made entirely of whitespace and is not\n    // preceded of followed by a block.\n    // Find out contiguous preceding and following text nodes\n    let preceding;\n    let following;\n    // Control variable to know whether the current node has been found\n    let foundTestedNode;\n    const currentNodeParentBlock = closestBlock(testedNode);\n    const nodeIterator = document.createNodeIterator(currentNodeParentBlock);\n    for (let node = nodeIterator.nextNode(); node; node = nodeIterator.nextNode()) {\n        if (node.nodeType === Node.TEXT_NODE) {\n            // If we already found the tested node, the current node is the\n            // contiguous following, and we can stop looping\n            // If the current node is the tested node, mark it as found and\n            // continue.\n            // If we haven't reached the tested node, overwrite the preceding\n            // node.\n            if (foundTestedNode) {\n                following = node;\n                break;\n            } else if (testedNode === node) {\n                foundTestedNode = true;\n            } else {\n                preceding = node;\n            }\n        } else if (isBlock(node)) {\n            // If we found the tested node, then the following node is irrelevant\n            // If we didn't, then the current preceding node is irrelevant\n            if (foundTestedNode) {\n                break;\n            } else {\n                preceding = null;\n            }\n        }\n    }\n    while (following && /^[\\n\\t ]*$/.test(following.textContent)) {\n        following = following.nextSibling;\n    }\n    // Missing preceding or following: invisible.\n    // Preceding or following not in the same block as tested node: invisible.\n    if (\n        !(preceding && following) ||\n        currentNodeParentBlock !== closestBlock(preceding) ||\n        currentNodeParentBlock !== closestBlock(following)\n    ) {\n        return false;\n    }\n    // Preceding is whitespace or following is whitespace: invisible\n    return !/^[\\n\\t ]*$/.test(preceding.textContent);\n}\n\nexport function parentsGet(node, root = undefined) {\n    const parents = [];\n    while (node) {\n        parents.unshift(node);\n        if (node === root) {\n            break;\n        }\n        node = node.parentNode;\n    }\n    return parents;\n}\n\nexport function commonParentGet(node1, node2, root = undefined) {\n    if (!node1 || !node2) {\n        return null;\n    }\n    const n1p = parentsGet(node1, root);\n    const n2p = parentsGet(node2, root);\n    while (n1p.length > 1 && n1p[1] === n2p[1]) {\n        n1p.shift();\n        n2p.shift();\n    }\n    // Check  in case at least one of them is not in the DOM.\n    return n1p[0] === n2p[0] ? n1p[0] : null;\n}\n\nexport function getListMode(pnode) {\n    if (pnode.tagName == 'OL') return 'OL';\n    return pnode.classList.contains('o_checklist') ? 'CL' : 'UL';\n}\n\nexport function createList(mode) {\n    const node = document.createElement(mode == 'OL' ? 'OL' : 'UL');\n    if (mode == 'CL') {\n        node.classList.add('o_checklist');\n    }\n    return node;\n}\n\nexport function insertListAfter(afterNode, mode, content = []) {\n    const list = createList(mode);\n    afterNode.after(list);\n    list.append(\n        ...content.map(c => {\n            const li = document.createElement('LI');\n            li.append(...[].concat(c));\n            return li;\n        }),\n    );\n    return list;\n}\n\nexport function toggleClass(node, className) {\n    node.classList.toggle(className);\n    if (!node.className) {\n        node.removeAttribute('class');\n    }\n}\n\n/**\n * Returns whether or not the given node is a BR element which does not really\n * act as a line break, but as a placeholder for the cursor or to make some left\n * element (like a space) visible.\n *\n * @param {HTMLBRElement} brEl\n * @returns {boolean}\n */\nexport function isFakeLineBreak(brEl) {\n    return !(getState(...rightPos(brEl), DIRECTIONS.RIGHT).cType & (CTYPES.CONTENT | CTGROUPS.BR));\n}\n/**\n * Checks whether or not the given block has any visible content, except for\n * a placeholder BR.\n *\n * @param {HTMLElement} blockEl\n * @returns {boolean}\n */\nexport function isEmptyBlock(blockEl) {\n    if (!blockEl || blockEl.nodeType !== Node.ELEMENT_NODE) {\n        return false;\n    }\n    if (isVisibleStr(blockEl.textContent)) {\n        return false;\n    }\n    if (blockEl.querySelectorAll('br').length >= 2) {\n        return false;\n    }\n    const nodes = blockEl.querySelectorAll('*');\n    for (const node of nodes) {\n        // There is no text and no double BR, the only thing that could make\n        // this visible is a \"visible empty\" node like an image.\n        if (node.nodeName != 'BR' && (isVisibleEmpty(node) || isFontAwesome(node))) {\n            return false;\n        }\n    }\n    return true;\n}\n/**\n * Checks whether or not the given block element has something to make it have\n * a visible height (except for padding / border).\n *\n * @param {HTMLElement} blockEl\n * @returns {boolean}\n */\nexport function isShrunkBlock(blockEl) {\n    return (\n        isEmptyBlock(blockEl) &&\n        !blockEl.querySelector('br') &&\n        blockEl.nodeName !== \"IMG\"\n    );\n}\n\n/**\n * @param {string} [value]\n * @returns {boolean}\n */\nexport function isColorGradient(value) {\n    // FIXME duplicated in @web_editor/utils.js\n    return value && value.includes('-gradient(');\n}\n\n//------------------------------------------------------------------------------\n// DOM Modification\n//------------------------------------------------------------------------------\n\n/**\n * Splits a text node in two parts.\n * If the split occurs at the beginning or the end, the text node stays\n * untouched and unsplit. If a split actually occurs, the original text node\n * still exists and become the right part of the split.\n *\n * Note: if split after or before whitespace, that whitespace may become\n * invisible, it is up to the caller to replace it by nbsp if needed.\n *\n * @param {Text} textNode\n * @param {number} offset\n * @param {DIRECTION} originalNodeSide Whether the original node ends up on left\n * or right after the split\n * @returns {number} The parentOffset if the cursor was between the two text\n *          node parts after the split.\n */\nexport function splitTextNode(textNode, offset, originalNodeSide = DIRECTIONS.RIGHT) {\n    let parentOffset = childNodeIndex(textNode);\n\n    if (offset > 0) {\n        parentOffset++;\n\n        if (offset < textNode.length) {\n            const left = textNode.nodeValue.substring(0, offset);\n            const right = textNode.nodeValue.substring(offset);\n            if (originalNodeSide === DIRECTIONS.LEFT) {\n                const newTextNode = document.createTextNode(right);\n                textNode.after(newTextNode);\n                textNode.nodeValue = left;\n            } else {\n                const newTextNode = document.createTextNode(left);\n                textNode.before(newTextNode);\n                textNode.nodeValue = right;\n            }\n        }\n    }\n    return parentOffset;\n}\n\n/**\n * Split the given element at the given offset. The element will be removed in\n * the process so caution is advised in dealing with its reference. Returns a\n * tuple containing the new elements on both sides of the split.\n *\n * @param {Element} element\n * @param {number} offset\n * @returns {[Element, Element]}\n */\nexport function splitElement(element, offset) {\n    const before = element.cloneNode();\n    const after = element.cloneNode();\n    let index = 0;\n    for (const child of [...element.childNodes]) {\n        index < offset ? before.appendChild(child) : after.appendChild(child);\n        index++;\n    }\n    element.before(before);\n    element.after(after);\n    element.remove();\n    return [before, after];\n}\n\n/**\n * Split around the given elements, until a given ancestor (included). Elements\n * will be removed in the process so caution is advised in dealing with their\n * references. Returns the new split root element that is a clone of\n * limitAncestor or the original limitAncestor if no split occured.\n *\n * @see splitElement\n * @param {Node[] | Node} elements\n * @param {Node} limitAncestor\n * @returns {[Node, Node]}\n */\nexport function splitAroundUntil(elements, limitAncestor) {\n    elements = Array.isArray(elements) ? elements : [elements];\n    const firstNode = elements[0];\n    const lastNode = elements[elements.length - 1];\n    if ([firstNode, lastNode].includes(limitAncestor)) {\n        return limitAncestor;\n    }\n    let before = firstNode.previousSibling;\n    let after = lastNode.nextSibling;\n    let beforeSplit, afterSplit;\n    if (!before && !after && elements[0] !== limitAncestor) {\n        return splitAroundUntil(elements[0].parentElement, limitAncestor);\n    }\n    // Split up ancestors up to font\n    while (after && after.parentElement !== limitAncestor) {\n        afterSplit = splitElement(after.parentElement, childNodeIndex(after))[0];\n        after = afterSplit.nextSibling;\n    }\n    if (after) {\n        afterSplit = splitElement(limitAncestor, childNodeIndex(after))[0];\n        limitAncestor = afterSplit;\n    }\n    while (before && before.parentElement !== limitAncestor) {\n        beforeSplit = splitElement(before.parentElement, childNodeIndex(before) + 1)[1];\n        before = beforeSplit.previousSibling;\n    }\n    if (before) {\n        beforeSplit = splitElement(limitAncestor, childNodeIndex(before) + 1)[1];\n    }\n    return beforeSplit || afterSplit || limitAncestor;\n}\n\nexport function insertText(sel, content) {\n    if (sel.anchorNode.nodeType === Node.TEXT_NODE) {\n        const pos = [sel.anchorNode.parentElement, splitTextNode(sel.anchorNode, sel.anchorOffset)];\n        setSelection(...pos, ...pos, false);\n    }\n    const txt = document.createTextNode(content || '#');\n    const restore = prepareUpdate(sel.anchorNode, sel.anchorOffset);\n    sel.getRangeAt(0).insertNode(txt);\n    restore();\n    setSelection(...boundariesOut(txt), false);\n    return txt;\n}\n\n/**\n * Remove node from the DOM while preserving their contents if any.\n *\n * @param {Node} node\n * @returns {Node[]}\n */\nexport function unwrapContents(node) {\n    const contents = [...node.childNodes];\n    for (const child of contents) {\n        node.parentNode.insertBefore(child, node);\n    }\n    node.parentNode.removeChild(node);\n    return contents;\n}\n\n/**\n * Add a BR in the given node if its closest ancestor block has nothing to make\n * it visible, and/or add a zero-width space in the given node if it's an empty\n * inline unremovable so the cursor can stay in it.\n *\n * @param {HTMLElement} el\n * @returns {Object} { br: the inserted <br> if any,\n *                     zws: the inserted zero-width space if any }\n */\nexport function fillEmpty(el) {\n    const fillers = {};\n    const blockEl = closestBlock(el);\n    if (isShrunkBlock(blockEl)) {\n        const br = document.createElement('br');\n        blockEl.appendChild(br);\n        fillers.br = br;\n    }\n    if (!isVisible(el) && !el.hasAttribute('oe-zws-empty-inline')) {\n        // As soon as there is actual content in the node, the zero-width space\n        // is removed by the sanitize function.\n        const zws = document.createTextNode('\\u200B');\n        el.appendChild(zws);\n        el.setAttribute(\"oe-zws-empty-inline\", \"\");\n        fillers.zws = zws;\n        const previousSibling = el.previousSibling;\n        if (previousSibling && previousSibling.nodeName === \"BR\") {\n            previousSibling.remove();\n        }\n        setSelection(zws, 0, zws, 0);\n    }\n    return fillers;\n}\n/**\n * Takes a selection (assumed to be collapsed) and insert a zero-width space at\n * its anchor point. Then, select that zero-width space.\n *\n * @param {Selection} selection\n * @returns {Node} the inserted zero-width space\n */\nexport function insertAndSelectZws(selection) {\n    const offset = selection.anchorOffset;\n    const zws = insertText(selection, '\\u200B');\n    splitTextNode(zws, offset);\n    selection.getRangeAt(0).selectNode(zws);\n    return zws;\n}\n/**\n * Removes the given node if invisible and all its invisible ancestors.\n *\n * @param {Node} node\n * @returns {Node} the first visible ancestor of node (or itself)\n */\nexport function clearEmpty(node) {\n    while (!isVisible(node)) {\n        const toRemove = node;\n        node = node.parentNode;\n        toRemove.remove();\n    }\n    return node;\n}\n\nexport function setTagName(el, newTagName) {\n    if (el.tagName === newTagName) {\n        return el;\n    }\n    var n = document.createElement(newTagName);\n    var attr = el.attributes;\n    for (var i = 0, len = attr.length; i < len; ++i) {\n        n.setAttribute(attr[i].name, attr[i].value);\n    }\n    while (el.firstChild) {\n        n.append(el.firstChild);\n    }\n    const closestLi = el.closest('li');\n    if (el.tagName === 'LI' && newTagName !== 'p') {\n        el.append(n);\n    } else if (closestLi && newTagName === 'p') {\n        closestLi.replaceChildren(...n.childNodes);\n    } else {\n        el.parentNode.replaceChild(n, el);\n    }\n    return n;\n}\n/**\n * Moves the given subset of nodes of a source element to the given destination.\n * If the source element is left empty it is removed. This ensures the moved\n * content and its destination surroundings are restored (@see restoreState) to\n * the way there were.\n *\n * It also reposition at the right position on the left of the moved nodes.\n *\n * @param {HTMLElement} destinationEl\n * @param {number} destinationOffset\n * @param {HTMLElement} sourceEl\n * @param {number} [startIndex=0]\n * @param {number} [endIndex=sourceEl.childNodes.length]\n * @returns {Array.<HTMLElement, number} The position at the left of the moved\n *     nodes after the move was done (and where the cursor was returned).\n */\nexport function moveNodes(\n    destinationEl,\n    destinationOffset,\n    sourceEl,\n    startIndex = 0,\n    endIndex = sourceEl.childNodes.length,\n) {\n    if (selfClosingElementTags.includes(destinationEl.nodeName)) {\n        throw new Error(`moveNodes: Invalid destination element ${destinationEl.nodeName}`);\n    }\n\n    const nodes = [];\n    for (let i = startIndex; i < endIndex; i++) {\n        nodes.push(sourceEl.childNodes[i]);\n    }\n\n    if (nodes.length) {\n        const restoreDestination = prepareUpdate(destinationEl, destinationOffset);\n        const restoreMoved = prepareUpdate(\n            ...leftPos(sourceEl.childNodes[startIndex]),\n            ...rightPos(sourceEl.childNodes[endIndex - 1]),\n        );\n        const fragment = document.createDocumentFragment();\n        nodes.forEach(node => fragment.appendChild(node));\n        const posRightNode = destinationEl.childNodes[destinationOffset];\n        if (posRightNode) {\n            destinationEl.insertBefore(fragment, posRightNode);\n        } else {\n            destinationEl.appendChild(fragment);\n        }\n        restoreDestination();\n        restoreMoved();\n    }\n\n    if (!nodeSize(sourceEl)) {\n        const restoreOrigin = prepareUpdate(...boundariesOut(sourceEl));\n        sourceEl.remove();\n        restoreOrigin();\n    }\n\n    // Return cursor position, but don't change it\n    const firstNode = nodes.find(node => !!node.parentNode);\n    return firstNode ? leftPos(firstNode) : [destinationEl, destinationOffset];\n}\n\n//------------------------------------------------------------------------------\n// Prepare / Save / Restore state utilities\n//------------------------------------------------------------------------------\n\nconst prepareUpdateLockedEditables = new Set();\n/**\n * Any editor command is applied to a selection (collapsed or not). After the\n * command, the content type on the selection boundaries, in both direction,\n * should be preserved (some whitespace should disappear as went from collapsed\n * to non collapsed, or converted to &nbsp; as went from non collapsed to\n * collapsed, there also <br> to remove/duplicate, etc).\n *\n * This function returns a callback which allows to do that after the command\n * has been done.\n *\n * Note: the method has been made generic enough to work with non-collapsed\n * selection but can be used for an unique cursor position.\n *\n * @param {HTMLElement} el\n * @param {number} offset\n * @param {...(HTMLElement|number)} args - argument 1 and 2 can be repeated for\n *     multiple preparations with only one restore callback returned. Note: in\n *     that case, the positions should be given in the document node order.\n * @param {Object} [options]\n * @param {boolean} [options.allowReenter = true] - if false, all calls to\n *     prepareUpdate before this one gets restored will be ignored.\n * @param {string} [options.label = <random 6 character string>]\n * @param {boolean} [options.debug = false] - if true, adds nicely formatted\n *     console logs to help with debugging.\n * @returns {function}\n */\nexport function prepareUpdate(...args) {\n    const closestRoot = args.length && ancestors(args[0]).find(ancestor => ancestor.oid === 'root');\n    const isPrepareUpdateLocked = closestRoot && prepareUpdateLockedEditables.has(closestRoot);\n    const hash = (Math.random() + 1).toString(36).substring(7);\n    const options = {\n        allowReenter: true,\n        label: hash,\n        debug: false,\n        ...(args.length && args[args.length - 1] instanceof Object ? args.pop() : {}),\n    };\n    if (options.debug) {\n        console.log(\n            '%cPreparing%c update: ' + options.label +\n            (options.label === hash ? '' : ` (${hash})`) +\n            '%c' + (isPrepareUpdateLocked ? ' LOCKED' : ''),\n            'color: cyan;',\n            'color: white;',\n            'color: red; font-weight: bold;',\n        );\n    }\n    if (isPrepareUpdateLocked) {\n        return () => {\n            if (options.debug) {\n                console.log(\n                    '%cRestoring%c update: ' + options.label +\n                    (options.label === hash ? '' : ` (${hash})`) +\n                    '%c LOCKED',\n                    'color: lightgreen;',\n                    'color: white;',\n                    'color: red; font-weight: bold;',\n                );\n            }\n        };\n    }\n    if (!options.allowReenter && closestRoot) {\n        prepareUpdateLockedEditables.add(closestRoot);\n    }\n    const positions = [...args];\n\n    // Check the state in each direction starting from each position.\n    const restoreData = [];\n    let el, offset;\n    while (positions.length) {\n        // Note: important to get the positions in reverse order to restore\n        // right side before left side.\n        offset = positions.pop();\n        el = positions.pop();\n        const left = getState(el, offset, DIRECTIONS.LEFT);\n        const right = getState(el, offset, DIRECTIONS.RIGHT, left.cType);\n        if (options.debug) {\n            const editable = el && closestElement(el, '.odoo-editor-editable');\n            const oldEditableHTML = editable && editable.innerHTML.replaceAll(' ', '_').replaceAll('\\u200B', 'ZWS') || '';\n            left.oldEditableHTML = oldEditableHTML;\n            right.oldEditableHTML = oldEditableHTML;\n        }\n        restoreData.push(left, right);\n    }\n\n    // Create the callback that will be able to restore the state in each\n    // direction wherever the node in the opposite direction has landed.\n    return function restoreStates() {\n        if (options.debug) {\n            console.log(\n                '%cRestoring%c update: ' + options.label +\n                (options.label === hash ? '' : ` (${hash})`),\n                'color: lightgreen;',\n                'color: white;',\n            );\n        }\n        for (const data of restoreData) {\n            restoreState(data, options.debug);\n        }\n        if (!options.allowReenter && closestRoot) {\n            prepareUpdateLockedEditables.delete(closestRoot);\n        }\n    };\n}\n/**\n * Retrieves the \"state\" from a given position looking at the given direction.\n * The \"state\" is the type of content. The functions also returns the first\n * meaninful node looking in the opposite direction = the first node we trust\n * will not disappear if a command is played in the given direction.\n *\n * Note: only work for in-between nodes positions. If the position is inside a\n * text node, first split it @see splitTextNode.\n *\n * @param {HTMLElement} el\n * @param {number} offset\n * @param {number} direction @see DIRECTIONS.LEFT @see DIRECTIONS.RIGHT\n * @param {CTYPES} leftCType\n * @returns {Object}\n */\nexport function getState(el, offset, direction, leftCType) {\n    const leftDOMPath = leftLeafOnlyNotBlockPath;\n    const rightDOMPath = rightLeafOnlyNotBlockPath;\n\n    let domPath;\n    let inverseDOMPath;\n    let expr;\n    const reasons = [];\n    if (direction === DIRECTIONS.LEFT) {\n        domPath = leftDOMPath(el, offset, reasons);\n        inverseDOMPath = rightDOMPath(el, offset);\n        expr = /[^\\S\\u00A0]$/;\n    } else {\n        domPath = rightDOMPath(el, offset, reasons);\n        inverseDOMPath = leftDOMPath(el, offset);\n        expr = /^[^\\S\\u00A0]/;\n    }\n\n    // TODO I think sometimes, the node we have to consider as the\n    // anchor point to restore the state is not the first one of the inverse\n    // path (like for example, empty text nodes that may disappear\n    // after the command so we would not want to get those ones).\n    const boundaryNode = inverseDOMPath.next().value;\n\n    // We only traverse through deep inline nodes. If we cannot find a\n    // meanfingful state between them, that means we hit a block.\n    let cType = undefined;\n\n    // Traverse the DOM in the given direction to check what type of content\n    // there is.\n    let lastSpace = null;\n    for (const node of domPath) {\n        if (node.nodeType === Node.TEXT_NODE) {\n            const value = node.nodeValue;\n            // If we hit a text node, the state depends on the path direction:\n            // any space encountered backwards is a visible space if we hit\n            // visible content afterwards. If going forward, spaces are only\n            // visible if we have content backwards.\n            if (direction === DIRECTIONS.LEFT) {\n                if (isVisibleStr(value)) {\n                    if (lastSpace) {\n                        cType = CTYPES.SPACE;\n                    } else {\n                        const rightLeaf = rightLeafOnlyNotBlockPath(node).next().value;\n                        const hasContentRight = rightLeaf && !rightLeaf.textContent.startsWith(' ');\n                        cType = !hasContentRight && node.textContent.endsWith(' ') ? CTYPES.SPACE : CTYPES.CONTENT;\n                    }\n                    break;\n                }\n                if (value.length) {\n                    lastSpace = node;\n                }\n            } else {\n                leftCType = leftCType || getState(el, offset, DIRECTIONS.LEFT).cType;\n                if (expr.test(value)) {\n                    const leftLeaf = leftLeafOnlyNotBlockPath(node).next().value;\n                    const hasContentLeft = leftLeaf && !leftLeaf.textContent.endsWith(' ');\n                    const rct = isVisibleStr(value)\n                        ? CTYPES.CONTENT\n                        : getState(...rightPos(node), DIRECTIONS.RIGHT).cType;\n                    cType =\n                        leftCType & CTYPES.CONTENT && rct & (CTYPES.CONTENT | CTYPES.BR) && !hasContentLeft\n                            ? CTYPES.SPACE\n                            : rct;\n                    break;\n                }\n                if (isVisibleStr(value)) {\n                    cType = CTYPES.CONTENT;\n                    break;\n                }\n            }\n        } else if (node.nodeName === 'BR') {\n            cType = CTYPES.BR;\n            break;\n        } else if (isVisible(node)) {\n            // E.g. an image\n            cType = CTYPES.CONTENT;\n            break;\n        }\n    }\n\n    if (cType === undefined) {\n        cType = reasons.includes(PATH_END_REASONS.BLOCK_HIT)\n            ? CTYPES.BLOCK_OUTSIDE\n            : CTYPES.BLOCK_INSIDE;\n    }\n\n    return {\n        node: boundaryNode,\n        direction: direction,\n        cType: cType, // Short for contentType\n    };\n}\nconst priorityRestoreStateRules = [\n    // Each entry is a list of two objects, with each key being optional (the\n    // more key-value pairs, the bigger the priority).\n    // {direction: ..., cType1: ..., cType2: ...}\n    // ->\n    // {spaceVisibility: (false|true), brVisibility: (false|true)}\n    [\n        // Replace a space by &nbsp; when it was not collapsed before and now is\n        // collapsed (one-letter word removal for example).\n        { cType1: CTYPES.CONTENT, cType2: CTYPES.SPACE | CTGROUPS.BLOCK },\n        { spaceVisibility: true },\n    ],\n    [\n        // Replace a space by &nbsp; when it was content before and now it is\n        // a BR.\n        { direction: DIRECTIONS.LEFT, cType1: CTGROUPS.INLINE, cType2: CTGROUPS.BR },\n        { spaceVisibility: true },\n    ],\n    [\n        // Replace a space by &nbsp; when it was content before and now it is\n        // a BR (removal of last character before a BR for example).\n        { direction: DIRECTIONS.RIGHT, cType1: CTGROUPS.CONTENT, cType2: CTGROUPS.BR },\n        { spaceVisibility: true },\n    ],\n    [\n        // Replace a space by &nbsp; when it was visible thanks to a BR which\n        // is now gone.\n        { direction: DIRECTIONS.RIGHT, cType1: CTGROUPS.BR, cType2: CTYPES.SPACE | CTGROUPS.BLOCK },\n        { spaceVisibility: true },\n    ],\n    [\n        // Remove all collapsed spaces when a space is removed.\n        { cType1: CTYPES.SPACE },\n        { spaceVisibility: false },\n    ],\n    [\n        // Remove spaces once the preceeding BR is removed\n        { direction: DIRECTIONS.LEFT, cType1: CTGROUPS.BR },\n        { spaceVisibility: false },\n    ],\n    [\n        // Remove space before block once content is put after it (otherwise it\n        // would become visible).\n        { cType1: CTGROUPS.BLOCK, cType2: CTGROUPS.INLINE | CTGROUPS.BR },\n        { spaceVisibility: false },\n    ],\n    [\n        // Duplicate a BR once the content afterwards disappears\n        { direction: DIRECTIONS.RIGHT, cType1: CTGROUPS.INLINE, cType2: CTGROUPS.BLOCK },\n        { brVisibility: true },\n    ],\n    [\n        // Remove a BR at the end of a block once inline content is put after\n        // it (otherwise it would act as a line break).\n        {\n            direction: DIRECTIONS.RIGHT,\n            cType1: CTGROUPS.BLOCK,\n            cType2: CTGROUPS.INLINE | CTGROUPS.BR,\n        },\n        { brVisibility: false },\n    ],\n    [\n        // Remove a BR once the BR that preceeds it is now replaced by\n        // content (or if it was a BR at the start of a block which now is\n        // a trailing BR).\n        {\n            direction: DIRECTIONS.LEFT,\n            cType1: CTGROUPS.BR | CTGROUPS.BLOCK,\n            cType2: CTGROUPS.INLINE,\n        },\n        { brVisibility: false, extraBRRemovalCondition: brNode => isFakeLineBreak(brNode) },\n    ],\n];\nfunction restoreStateRuleHashCode(direction, cType1, cType2) {\n    return `${direction}-${cType1}-${cType2}`;\n}\nconst allRestoreStateRules = (function () {\n    const map = new Map();\n\n    const keys = ['direction', 'cType1', 'cType2'];\n    for (const direction of Object.values(DIRECTIONS)) {\n        for (const cType1 of Object.values(CTYPES)) {\n            for (const cType2 of Object.values(CTYPES)) {\n                const rule = { direction: direction, cType1: cType1, cType2: cType2 };\n\n                // Search for the rules which match whatever their priority\n                const matchedRules = [];\n                for (const entry of priorityRestoreStateRules) {\n                    let priority = 0;\n                    for (const key of keys) {\n                        const entryKeyValue = entry[0][key];\n                        if (entryKeyValue !== undefined) {\n                            if (\n                                typeof entryKeyValue === 'boolean'\n                                    ? rule[key] === entryKeyValue\n                                    : rule[key] & entryKeyValue\n                            ) {\n                                priority++;\n                            } else {\n                                priority = -1;\n                                break;\n                            }\n                        }\n                    }\n                    if (priority >= 0) {\n                        matchedRules.push([priority, entry[1]]);\n                    }\n                }\n\n                // Create the final rule by merging found rules by order of\n                // priority\n                const finalRule = {};\n                for (let p = 0; p <= keys.length; p++) {\n                    for (const entry of matchedRules) {\n                        if (entry[0] === p) {\n                            Object.assign(finalRule, entry[1]);\n                        }\n                    }\n                }\n\n                // Create an unique identifier for the set of values\n                // direction - state 1 - state2 to add the rule in the map\n                const hashCode = restoreStateRuleHashCode(direction, cType1, cType2);\n                map.set(hashCode, finalRule);\n            }\n        }\n    }\n\n    return map;\n})();\n/**\n * Restores the given state starting before the given while looking in the given\n * direction.\n *\n * @param {Object} prevStateData @see getState\n * @param {boolean} debug=false - if true, adds nicely formatted\n *     console logs to help with debugging.\n * @returns {Object|undefined} the rule that was applied to restore the state,\n *     if any, for testing purposes.\n */\nexport function restoreState(prevStateData, debug=false) {\n    const { node, direction, cType: cType1, oldEditableHTML } = prevStateData;\n    if (!node || !node.parentNode) {\n        // FIXME sometimes we want to restore the state starting from a node\n        // which has been removed by another restoreState call... Not sure if\n        // it is a problem or not, to investigate.\n        return;\n    }\n    const [el, offset] = direction === DIRECTIONS.LEFT ? leftPos(node) : rightPos(node);\n    const { cType: cType2 } = getState(el, offset, direction);\n\n    /**\n     * Knowing the old state data and the new state data, we know if we have to\n     * do something or not, and what to do.\n     */\n    const ruleHashCode = restoreStateRuleHashCode(direction, cType1, cType2);\n    const rule = allRestoreStateRules.get(ruleHashCode);\n    if (debug) {\n        const editable = closestElement(node, '.odoo-editor-editable');\n        console.log(\n            '%c' + node.textContent.replaceAll(' ', '_').replaceAll('\\u200B', 'ZWS') + '\\n' +\n            '%c' + (direction === DIRECTIONS.LEFT ? 'left' : 'right') + '\\n' +\n            '%c' + ctypeToString(cType1) + '\\n' +\n            '%c' + ctypeToString(cType2) + '\\n' +\n            '%c' + 'BEFORE: ' + (oldEditableHTML || '(unavailable)') + '\\n' +\n            '%c' + 'AFTER:  ' + (editable ? editable.innerHTML.replaceAll(' ', '_').replaceAll('\\u200B', 'ZWS') : '(unavailable)') + '\\n',\n            'color: white; display: block; width: 100%;',\n            'color: ' + (direction === DIRECTIONS.LEFT ? 'magenta' : 'lightgreen') + '; display: block; width: 100%;',\n            'color: pink; display: block; width: 100%;',\n            'color: lightblue; display: block; width: 100%;',\n            'color: white; display: block; width: 100%;',\n            'color: white; display: block; width: 100%;',\n            rule,\n        );\n    }\n    if (Object.values(rule).filter(x => x !== undefined).length) {\n        const inverseDirection = direction === DIRECTIONS.LEFT ? DIRECTIONS.RIGHT : DIRECTIONS.LEFT;\n        enforceWhitespace(el, offset, inverseDirection, rule);\n    }\n    return rule;\n}\n/**\n * Enforces the whitespace and BR visibility in the given direction starting\n * from the given position.\n *\n * @param {HTMLElement} el\n * @param {number} offset\n * @param {number} direction @see DIRECTIONS.LEFT @see DIRECTIONS.RIGHT\n * @param {Object} rule\n * @param {boolean} [rule.spaceVisibility]\n * @param {boolean} [rule.brVisibility]\n */\nexport function enforceWhitespace(el, offset, direction, rule) {\n    let domPath;\n    let expr;\n    if (direction === DIRECTIONS.LEFT) {\n        domPath = leftLeafOnlyNotBlockPath(el, offset);\n        expr = /[^\\S\\u00A0]+$/;\n    } else {\n        domPath = rightLeafOnlyNotBlockPath(el, offset);\n        expr = /^[^\\S\\u00A0]+/;\n    }\n\n    const invisibleSpaceTextNodes = [];\n    let foundVisibleSpaceTextNode = null;\n    for (const node of domPath) {\n        if (node.nodeName === 'BR') {\n            if (rule.brVisibility === undefined) {\n                break;\n            }\n            if (rule.brVisibility) {\n                node.before(document.createElement('br'));\n            } else {\n                if (!rule.extraBRRemovalCondition || rule.extraBRRemovalCondition(node)) {\n                    node.remove();\n                }\n            }\n            break;\n        } else if (node.nodeType === Node.TEXT_NODE && !isInPre(node)) {\n            if (expr.test(node.nodeValue)) {\n                // If we hit spaces going in the direction, either they are in a\n                // visible text node and we have to change the visibility of\n                // those spaces, or it is in an invisible text node. In that\n                // last case, we either remove the spaces if there are spaces in\n                // a visible text node going further in the direction or we\n                // change the visiblity or those spaces.\n                if (isVisibleStr(node)) {\n                    foundVisibleSpaceTextNode = node;\n                    break;\n                } else {\n                    invisibleSpaceTextNodes.push(node);\n                }\n            } else if (isVisibleStr(node)) {\n                break;\n            }\n        } else {\n            break;\n        }\n    }\n\n    if (rule.spaceVisibility === undefined) {\n        return;\n    }\n    if (!rule.spaceVisibility) {\n        for (const node of invisibleSpaceTextNodes) {\n            // Empty and not remove to not mess with offset-based positions in\n            // commands implementation, also remove non-block empty parents.\n            node.nodeValue = '';\n            const ancestorPath = closestPath(node.parentNode);\n            let toRemove = null;\n            for (const pNode of ancestorPath) {\n                if (toRemove) {\n                    toRemove.remove();\n                }\n                if (pNode.childNodes.length === 1 && !isBlock(pNode)) {\n                    pNode.after(node);\n                    toRemove = pNode;\n                } else {\n                    break;\n                }\n            }\n        }\n    }\n    const spaceNode = foundVisibleSpaceTextNode || invisibleSpaceTextNodes[0];\n    if (spaceNode) {\n        let spaceVisibility = rule.spaceVisibility;\n        // In case we are asked to replace the space by a &nbsp;, disobey and\n        // do the opposite if that space is currently not visible\n        // TODO I'd like this to not be needed, it feels wrong...\n        if (\n            spaceVisibility &&\n            !foundVisibleSpaceTextNode &&\n            getState(...rightPos(spaceNode), DIRECTIONS.RIGHT).cType & CTGROUPS.BLOCK\n        ) {\n            spaceVisibility = false;\n        }\n        spaceNode.nodeValue = spaceNode.nodeValue.replace(expr, spaceVisibility ? '\\u00A0' : '');\n    }\n}\n\nexport function rgbToHex(rgb = '') {\n    return (\n        '#' +\n        (rgb.match(/\\d{1,3}/g) || [])\n            .map(x => {\n                x = parseInt(x).toString(16);\n                return x.length === 1 ? '0' + x : x;\n            })\n            .join('')\n    );\n}\n\nexport function getRangePosition(el, document, options = {}) {\n    const selection = document.getSelection();\n    if (!selection.isCollapsed || !selection.rangeCount) return;\n    const range = selection.getRangeAt(0);\n\n    const marginRight = options.marginRight || 20;\n    const marginBottom = options.marginBottom || 20;\n    const marginTop = options.marginTop || 10;\n    const marginLeft = options.marginLeft || 10;\n\n    let offset;\n    if (range.endOffset - 1 > 0) {\n        const clonedRange = range.cloneRange();\n        clonedRange.setStart(range.endContainer, range.endOffset - 1);\n        clonedRange.setEnd(range.endContainer, range.endOffset);\n        const rect = clonedRange.getBoundingClientRect();\n        offset = { height: rect.height, left: rect.left + rect.width, top: rect.top };\n        clonedRange.detach();\n    }\n\n    if (!offset || offset.heigh === 0) {\n        const clonedRange = range.cloneRange();\n        const shadowCaret = document.createTextNode('|');\n        clonedRange.insertNode(shadowCaret);\n        clonedRange.selectNode(shadowCaret);\n        const rect = clonedRange.getBoundingClientRect();\n        offset = { height: rect.height, left: rect.left, top: rect.top };\n        shadowCaret.remove();\n        clonedRange.detach();\n    }\n\n    const leftMove = Math.max(0, offset.left + el.offsetWidth + marginRight - window.innerWidth);\n    if (leftMove && offset.left - leftMove > marginLeft) {\n        offset.left -= leftMove;\n    } else if (offset.left - leftMove < marginLeft) {\n        offset.left = marginLeft;\n    }\n\n    if (options.getContextFromParentRect) {\n        const parentContextRect = options.getContextFromParentRect();\n        offset.left += parentContextRect.left;\n        offset.top += parentContextRect.top;\n    }\n\n    if (\n        offset.top - marginTop + offset.height + el.offsetHeight > window.innerHeight &&\n        offset.top - el.offsetHeight - marginBottom > 0\n    ) {\n        offset.top -= el.offsetHeight;\n    } else {\n        offset.top += offset.height;\n    }\n\n    if (offset) {\n        offset.top += window.scrollY;\n        offset.left += window.scrollX;\n    }\n\n    return offset;\n}\n\nexport const isNotEditableNode = node =>\n    node.getAttribute &&\n    node.getAttribute('contenteditable') &&\n    node.getAttribute('contenteditable').toLowerCase() === 'false';\n\nexport const leftLeafFirstPath = createDOMPathGenerator(DIRECTIONS.LEFT);\nexport const leftLeafOnlyNotBlockPath = createDOMPathGenerator(DIRECTIONS.LEFT, {\n    leafOnly: true,\n    stopTraverseFunction: isBlock,\n    stopFunction: isBlock,\n});\nexport const leftLeafOnlyInScopeNotBlockNoEditablePath = createDOMPathGenerator(DIRECTIONS.LEFT, {\n    leafOnly: true,\n    inScope: true,\n    stopTraverseFunction: node => isNotEditableNode(node) || isBlock(node),\n    stopFunction: node => isNotEditableNode(node) || isBlock(node),\n});\n\nexport const rightLeafOnlyNotBlockPath = createDOMPathGenerator(DIRECTIONS.RIGHT, {\n    leafOnly: true,\n    stopTraverseFunction: isBlock,\n    stopFunction: isBlock,\n});\n\nexport const rightLeafOnlyPathNotBlockNotEditablePath = createDOMPathGenerator(DIRECTIONS.RIGHT, {\n    leafOnly: true,\n});\nexport const rightLeafOnlyInScopeNotBlockPath = createDOMPathGenerator(DIRECTIONS.RIGHT, {\n    leafOnly: true,\n    inScope: true,\n    stopTraverseFunction: isBlock,\n    stopFunction: isBlock,\n});\nexport const rightLeafOnlyNotBlockNotEditablePath = createDOMPathGenerator(DIRECTIONS.RIGHT, {\n    leafOnly: true,\n    stopTraverseFunction: node => isNotEditableNode(node) || isBlock(node),\n    stopFunction: node => isBlock(node) && !isNotEditableNode(node),\n});\n//------------------------------------------------------------------------------\n// Miscelaneous\n//------------------------------------------------------------------------------\nexport function peek(arr) {\n    return arr[arr.length - 1];\n}\n/**\n * Check user OS \n * @returns {boolean} \n */\nexport function isMacOS() {\n    return window.navigator.userAgent.includes('Mac');\n}\n\n/**\n * Remove zero-width spaces from the provided node and its descendants.\n *\n * @param {Node} node\n */\nexport function cleanZWS(node) {\n    [node, ...descendants(node)]\n        .filter(node => node.nodeType === Node.TEXT_NODE)\n        .forEach(node => node.nodeValue = node.nodeValue.replace(/\\u200B/g, ''));\n}\n", "odoo.define(\"website_sale.tour_utils\", function (require) {\n    \"use strict\";\n    \n    const core = require(\"web.core\");\n    const _t = core._t;\n\n\n    function goToCart(quantity = 1, position = \"bottom\") {\n        return {\n            content: _t(\"Go to cart\"),\n            trigger: `a:has(.my_cart_quantity:containsExact(${quantity}))`,\n            position: position,\n            run: \"click\",\n        };\n    }\n\n    return {\n        goToCart,\n    };\n});\n", "odoo.define(\"website_sale.tour_shop\", function (require) {\n    \"use strict\";\n\n    const {_t} = require(\"web.core\");\n    const {Markup} = require('web.utils');\n\n    // return the steps, used for backend and frontend\n\n    return [{\n        trigger: \"body:has(#o_new_content_menu_choices.o_hidden) #new-content-menu > a\",\n        content: _t(\"Let's create your first product.\"),\n        extra_trigger: \".js_sale\",\n        consumeVisibleOnly: true,\n        position: \"bottom\",\n    }, {\n        trigger: \"a[data-action=new_product]\",\n        content: Markup(_t(\"Select <b>New Product</b> to create it and manage its properties to boost your sales.\")),\n        position: \"bottom\",\n    }, {\n        trigger: \".modal-dialog #editor_new_product input[type=text]\",\n        content: _t(\"Enter a name for your new product\"),\n        position: \"left\",\n    }, {\n        trigger: \".modal-footer button.btn-primary.btn-continue\",\n        content: Markup(_t(\"Click on <em>Continue</em> to create the product.\")),\n        position: \"right\",\n    }, {\n        trigger: \".product_price .oe_currency_value:visible\",\n        extra_trigger: \".editor_enable\",\n        content: _t(\"Edit the price of this product by clicking on the amount.\"),\n        position: \"bottom\",\n        run: \"text 1.99\",\n    }, {\n        trigger: \"#wrap img.product_detail_img\",\n        extra_trigger: \".product_price .o_dirty .oe_currency_value:not(:containsExact(1.00))\",\n        content: _t(\"Double click here to set an image describing your product.\"),\n        position: \"top\",\n        run: function (actions) {\n            actions.dblclick();\n        },\n    }, {\n        trigger: \".o_select_media_dialog .o_upload_media_button\",\n        content: _t(\"Upload a file from your local library.\"),\n        position: \"bottom\",\n        run: function (actions) {\n            actions.auto(\".modal-footer .btn-secondary\");\n        },\n        auto: true,\n    }, {\n        trigger: \"button.o_we_add_snippet_btn\",\n        auto: true,\n    }, {\n        trigger: \"#snippet_structure .oe_snippet:eq(3) .oe_snippet_thumbnail\",\n        extra_trigger: \"body:not(.modal-open)\",\n        content: _t(\"Drag this website block and drop it in your page.\"),\n        position: \"bottom\",\n        run: \"drag_and_drop\",\n    }, {\n        trigger: \"button[data-action=save]\",\n        content: Markup(_t(\"Once you click on <b>Save</b>, your product is updated.\")),\n        position: \"bottom\",\n    }, {\n        trigger: \".js_publish_management .js_publish_btn .css_publish\",\n        extra_trigger: \"body:not(.editor_enable)\",\n        content: _t(\"Click on this button so your customers can see it.\"),\n        position: \"bottom\",\n    }, {\n        trigger: \".o_main_navbar .o_menu_toggle, #oe_applications .dropdown-toggle\",\n        content: _t(\"Let's now take a look at your administration dashboard to get your eCommerce website ready in no time.\"),\n        position: \"bottom\",\n    }, { // backend\n        trigger: '.o_apps > a[data-menu-xmlid=\"website.menu_website_configuration\"], #oe_main_menu_navbar a[data-menu-xmlid=\"website.menu_website_configuration\"]',\n        content: _t(\"Open your website app here.\"),\n        extra_trigger: \".o_apps,#oe_applications\",\n        position: \"bottom\",\n        timeout: 30000, // ~ 10 secondes to be redirected, due to slow assets generation\n    }];\n});\n"], "file": "/web/assets/4191-4b72cbb/web.assets_common.js", "sourceRoot": "../../../"}