Skip to Content

In my latest blog post I explained how to create a Custom Control from 0 to hero.

In all of these examples I always needed to wrap an external library inside a custom control. At first I always copied the latest master version of the library inside my source code and pack it with grunt-openui5.

But I was not satisfied at all. BowerJS and npm exists for a reason, they are a package manager that allow you to easily sync with a specific version of a library and upgrade it with just a command.

That’s why I tried to push grunt-openui5 (kudos to Matthias Oßwal for the huge help) to it’s limit and share with you my work. In this example we will see everything I’ve learned to create “openui5-flatpickr a stunning DatePicker for your SAPUI5 app”.

Configure NPM to install flatpickr.

{
  "name": "openui5-flatpickr",
  "version": "0.0.1",
  "description": "An openui5 custom control to use flatpickr (https://github.com/chmln/flatpickr)",
  "main": "index.js",
  "repository": {
    "type": "git",
    "url": "https://github.com/StErMi/openui5-flatpickr"
  },
  "keywords": [
    "datepicker",
    "openui5",
    "sapui5",
    "javascript"
  ],
  "author": {
    "name": "Emanuele Ricci",
    "email": "stermi@gmail.com"
  },
  "license": "Apache-2.0",
  "scripts": {
    "test": "echo \"Error: no test specified. Please add some.\" && exit 1",
    "postinstall": "bower install",
    "start": "grunt"
  },
  "devDependencies": {
    "bower": "^1.8.0",
    "grunt": "^1.0.1",
    "grunt-contrib-clean": "^1.0.0",
    "grunt-contrib-connect": "^1.0.2",
    "grunt-contrib-copy": "^1.0.0",
    "grunt-contrib-jshint": "^1.1.0",
    "grunt-contrib-uglify": "^2.2.0",
    "grunt-contrib-watch": "^1.0.0",
    "grunt-eslint": "^19.0.0",
    "grunt-openui5": "^0.11.0",
    "flatpickr": "^3.0.6"
  }
}

In our case we just have to add (to the other dependencies needed to develop and package the custom library) flatpickr version 3.0.6 (the latest one from the master repository)

Flatpickr will be downloaded and installed inside /node_modules/flatpickr/dist. In particular we are interested in

  • /node_modules/flatpickr/dist/flatpickr.min.js
  • /node_modules/flatpickr/dist/flatpickr.min.css

Include flatpickr.min.js in your OpenUI5 project

“./3dparty/flatpickr” is the relative path of the flatpickr.js file that will be included inside our library-preload.js file.

Include flatpickr.min.css in your OpenUI5 project

Flatpickr include also it’s own css file to customize and render the DatePicker. This was the trickiest part for me.

All your themes must be defined inside your library root package inside the subfolder themes. In our case we just defined the base theme (used by all others and merged with them).

Here’s the content inside our /themes/base/library.source.less

/*!
 * ${copyright}
 */

@import (less) "../../../../../flatpickr/dist/flatpickr.min.css";

../../../../../flatpickr/dist/flatpickr.min.css is the relative path to the css file inside our node_modules folder

Pack it all together via grunt-openui5

module.exports = function(grunt) {

	grunt.initConfig({
		dir: {
			src: 'src',
			dest: 'dist',
			demo: 'test/demo',
			src_flatpickr: 'node_modules/flatpickr/dist',
			bower_components: 'bower_components',
			node_modules: 'node_modules',
			css: 'it/designfuture/flatpickr/themes/',
			css_base: 'it/designfuture/flatpickr/themes/base/library.source.less',
			css_belize: 'it/designfuture/flatpickr/themes/sap_belize/library.source.less',
			sap_bluecrystal: 'it/designfuture/flatpickr/themes/sap_bluecrystal/library.source.less'
		},

		copy: {
			main: {
				expand: true,
				cwd: '<%= dir.dest %>/',
				src: ['**'],
				dest: '<%= dir.demo %>/thirdparty/',
			},
		},

		clean: {
			dist: '<%= dir.dest %>/**'
		},

		eslint: {
            options: {
                configFile: './.eslintrc'
            },

            demo: ['<%= dir.demo %>']
        },

		connect: {
			options: {
				port: 8080,
				hostname: '*'
			},
			src: {},
			dist: {}
		},

		openui5_connect: {
			options: {
				resources: [
					'<%= dir.bower_components %>/openui5-sap.ui.core/resources',
					'<%= dir.bower_components %>/openui5-sap.m/resources',
					'<%= dir.bower_components %>/openui5-sap.ui.layout/resources',
					'<%= dir.bower_components %>/openui5-themelib_sap_belize/resources',
				],
				testresources: [
					'<%= dir.bower_components %>/openui5-sap.ui.core/test-resources',
					'<%= dir.bower_components %>/openui5-sap.m/test-resources',
					'<%= dir.bower_components %>/openui5-sap.ui.layout/test-resources',
					'<%= dir.bower_components %>/openui5-themelib_sap_belize/test-resources'
				],
			},
			src: {
				options: {
					appresources: '<%= dir.demo %>'
				}
			},
			dist: {
				options: {
					appresources: '<%= dir.demo %>'
				}
			}
		},

		openui5_preload: {
		    library: {
		        options: {
		            resources: [
		                { cwd: '<%= dir.src %>' },
		                { cwd: '<%= dir.src_flatpickr %>', src: 'flatpickr.js', prefix: 'it/designfuture/flatpickr/3rdparty' }
		            ],
		            dest: '<%= dir.dest %>',
		            compatVersion: '1.44',
		            compress: false
		        },
		        libraries: 'it/designfuture/flatpickr'
		    }
		},

		openui5_theme: {
			library: {
				files: [
					{
						expand: true,
						cwd: '<%= dir.src %>',
						src: '**/themes/*/library.source.less',
						dest: '<%= dir.dest %>'
					}
				],
				options: {
					rootPaths: [
						'<%= dir.src %>',
						'<%= dir.node_modules %>'
					],
					library: {
						name: 'it.designfuture.flatpickr'
					}
				}
			}
		}
	});

	// These publins provide necessary tasks
	grunt.loadNpmTasks('grunt-contrib-connect');
	grunt.loadNpmTasks('grunt-contrib-clean');
	grunt.loadNpmTasks('grunt-contrib-copy');
	grunt.loadNpmTasks('grunt-openui5');
	grunt.loadNpmTasks('grunt-eslint');
    grunt.loadNpmTasks("grunt-contrib-watch");

	// Server task
	grunt.registerTask('serve', function(target) {
		grunt.task.run('openui5_connect:' + (target || 'src') + ':keepalive');
	});

	// Linting task
	grunt.registerTask('lint', ['eslint']);

	// Build task
	grunt.registerTask('build_theme', ['clean', 'openui5_theme']);

	// Build task
	grunt.registerTask('build', ['clean','openui5_theme', 'openui5_preload', 'copy']);

	// Default task
	grunt.registerTask('default', [
		'clean',
		'build',
		'serve'
	]);

};

openui5_theme

Builds a theme and creates the following files in the dest directory of the specified less file:

  • library.css (regular css)
  • library-RTL.css (mirrored css for right-to-left support)
  • library-parameters.json (key-value map of all global less variables)

We’re going to take a better look at some options used in our Gruntfile.js task.

rootPaths: Root paths to use for import directives. It is useful if less files are located in separate folders but referenced as they would all be in one.

In our case we have two different rootPaths:

  • src
  • node_modules

The node_modules rootPaths allow us to resolve the relative import path that we have defined inside our /themes/base/library.source.less

files: tells the task where you theme files are located. ‘**/themes/*/library.source.less’ allow you to have multiple theme (base, sap_belize, sap_bluecrystal, etc…)

openui5_preload

openui5_preload is the task that allow you to pack all your code inside the library-preload.js file

resources: Resources/files that should be used as source for preload files

  • cwd: Base/root directory for finding resources.
  • prefix: Directory namespace prefix that should be prepended to all found paths. This is useful if the source folder structure is not the same as the module namespace.
  • src: Glob pattern(s) for finding relevant resources insidecwd. If set, the default patterns will be replaced.

In our case we only had 2 resource entity, one for our main src folder (where the library source code is located) and one (more interesting) to include in the library-preload.js the flatpickr source code located inside the node_modules folder:

{ cwd: ‘ node_modules/flatpickr/dist’, src: ‘flatpickr.js’, prefix: ‘it/designfuture/flatpickr/3rdparty’ }

NB: if you take a good look, the prefix has the same path of the resource we included in our FlatDatePicker.js. That’s the trick I was talking about 😉

Grunt build: the output

When, in your terminal, type

grunt build

grunt will execute the following sub tasks (in order):

  • clean: clean the distribution folder of the packed custom library
  • openui5_theme: collect the custom library theme/css
  • openui5_preload: pack theme and library code all toghether
  • copy: copy the packed library inside our demo app (maybe I’ll move this sub task inside another task named grunt build-demo)

Below you can see the library-preload.js generated by the openui5_preload subtask.

jQuery.sap.registerPreloadedModules({
	"version": "2.0",
	"name": "it.designfuture.flatpickr.library-preload",
	"modules": {
		"it/designfuture/flatpickr/FlatDatePicker.js": "/*!\r\n * ${copyright}\r\n */\r\n\r\n// Provides control it.designfuture.flatpickr.FlatDatePicker\r\nsap.ui.define([\r\n\t\t'jquery.sap.global',\r\n\t\t'sap/m/InputBase',\r\n\t\t'./3rdparty/flatpickr',\r\n\t\t'./library'\r\n\t], function(jQuery, InputBase, flatpickr, library) {\r\n\t\"use strict\";\r\n\r\n\t/**\r\n\t * Constructor for a new FlatDatePicker.\r\n\t *\r\n\t * @param {string} [sId] id for the new control, generated automatically if no id is given \r\n\t * @param {object} [mSettings] initial settings for the new control\r\n\t *\r\n\t * @class\r\n\t * FlatDatePicker TODO ADD HERE A DESCRIPTION\r\n\t * @extends sap.m.InputBase\r\n\t * @version ${version}\r\n\t *\r\n\t * @constructor\r\n\t * @public\r\n\t * @since 1.40\r\n\t * @name it.designfuture.flatpickr.FlatDatePicker\r\n\t */\r\n\r\n\tvar FlatDatePicker = InputBase.extend(\"it.designfuture.flatpickr.FlatDatePicker\", /** @lends it.designfuture.flatpickr.FlatDatePicker prototype */ { \r\n\t\t\r\n\t\t__flatPickr: undefined,\r\n\t\t\r\n\t\tmetadata : {\r\n\t\t\tlibrary: 'it.designfuture.flatpickr',\r\n\t\t\tproperties : {\r\n\t\t\t\t\r\n\t\t\t\t/**\r\n\t\t\t\t * Exactly the same as date format, but for the altInput field\r\n\t\t\t\t */\r\n\t\t\t\taltFormat : {type : \"string\", group : \"Appearance\", defaultValue : \"F j, Y\"},\r\n\t\t\t\t\r\n\t\t\t\t/**\r\n\t\t\t\t * Show the user a readable date (as per altFormat), but return something totally different to the server.\r\n\t\t\t\t */\r\n\t\t\t\taltInput : {type : \"boolean\", group : \"Appearance\", defaultValue : false},\r\n\t\t\t\t\r\n\t\t\t\t/**\r\n\t\t\t\t * This class will be added to the input element created by the altInput option.  \r\n\t\t\t\t * Note that altInput already inherits classes from the original input.\r\n\t\t\t\t */\r\n\t\t\t\taltInputClass : {type : \"string\", group : \"Appearance\", defaultValue : \"\"},\r\n\t\t\t\t\r\n\t\t\t\t/**\r\n\t\t\t\t * Allows the user to enter a date directly input the input field. By default, direct entry is disabled.\r\n\t\t\t\t */\r\n\t\t\t\tallowInput : {type : \"boolean\", group : \"Appearance\", defaultValue : false},\r\n\t\t\t\t\r\n\t\t\t\t/**\r\n\t\t\t\t * Allows the user to enter a date directly input the input field. By default, direct entry is disabled.\r\n\t\t\t\t */\r\n\t\t\t\t//appendTo : {type : \"boolean\", group : \"Appearance\", defaultValue : false},\r\n\t\t\t\t\r\n\t\t\t\t/**\r\n\t\t\t\t * Whether clicking on the input should open the picker. \r\n\t\t\t\t * You could disable this if you wish to open the calendar manually with.open()\r\n\t\t\t\t */\r\n\t\t\t\tclickOpens : {type : \"boolean\", group : \"Appearance\", defaultValue : true},\r\n\t\t\t\t\r\n\t\t\t\t/**\r\n\t\t\t\t * A string of characters which are used to define how the date will be displayed in the input box. \r\n\t\t\t\t * The supported characters are defined in the table below.\r\n\t\t\t\t */\r\n\t\t\t\tdateFormat : {type : \"string\", group : \"Appearance\", defaultValue : \"Y-m-d\"},\r\n\t\t\t\t\r\n\t\t\t\t/**\r\n\t\t\t\t * Sets the initial selected date(s).\r\n\t\t\t\t * If you're using mode: \"multiple\" or a range calendar supply an Array of Date objects or an Array of date strings which follow your dateFormat.\r\n\t\t\t\t * Otherwise, you can supply a single Date object or a date string.\r\n\t\t\t\t */\r\n\t\t\t\tdateValue : {type : \"object\", group : \"Appearance\", defaultValue : null, bindable: \"bindable\"},\r\n\t\t\t\t\r\n\t\t\t\t/**\r\n\t\t\t\t * Initial value of the hour element.\r\n\t\t\t\t */\r\n\t\t\t\thourValue : {type : \"object\", group : \"Appearance\", defaultValue : 12, bindable: \"bindable\"},\r\n\t\t\t\t\r\n\t\t\t\t/**\r\n\t\t\t\t * Initial value of the minute element.\r\n\t\t\t\t */\r\n\t\t\t\tminuteValue : {type : \"object\", group : \"Appearance\", defaultValue : 0, bindable: \"bindable\"},\r\n\t\t\t\t\r\n\t\t\t\t/**\r\n\t\t\t\t * Arrays of dates object to be disabled\r\n\t\t\t\t */\r\n\t\t\t\tdisabledDates : {type : \"object[]\", group : \"Appearance\", defaultValue : [], bindable: \"bindable\"},\r\n\r\n\t\t\t\t/**\r\n\t\t\t\t * Set disableMobile to true to always use the non-native picker.\r\n\t\t\t\t * By default, Flatpickr utilizes native datetime widgets unless certain options (e.g. disable) are used.\r\n\t\t\t\t */\r\n\t\t\t\tdisableMobile : {type : \"boolean\", group : \"Appearance\", defaultValue : false},\r\n\t\t\t\t\r\n\t\t\t\t/**\r\n\t\t\t\t * Arrays of dates object to be enabled\r\n\t\t\t\t */\r\n\t\t\t\tenabledDates : {type : \"object[]\", group : \"Appearance\", defaultValue : [], bindable: \"bindable\"},\r\n\t\t\t\t\r\n\t\t\t\t/**\r\n\t\t\t\t * Enables time picker\r\n\t\t\t\t */\r\n\t\t\t\tenableTime : {type : \"boolean\", group : \"Appearance\", defaultValue : false},\r\n\t\t\t\t\r\n\t\t\t\t/**\r\n\t\t\t\t * Enables seconds in the time picker.\r\n\t\t\t\t */\r\n\t\t\t\tenableSeconds : {type : \"boolean\", group : \"Appearance\", defaultValue : false},\r\n\t\t\t\t\r\n\t\t\t\t/**\r\n\t\t\t\t * Adjusts the step for the hour input (incl. scrolling)\r\n\t\t\t\t */\r\n\t\t\t\thourIncrement : {type : \"int\", group : \"Appearance\", defaultValue : 1},\r\n\t\t\t\t\r\n\t\t\t\t/**\r\n\t\t\t\t * Displays the calendar inline\r\n\t\t\t\t */\r\n\t\t\t\tinline : {type : \"boolean\", group : \"Appearance\", defaultValue : false},\r\n\t\t\t\t\r\n\t\t\t\t/**\r\n\t\t\t\t * The maximum date that a user can pick to (inclusive).\r\n\t\t\t\t */\r\n\t\t\t\tmaxDate : {type : \"object\", group : \"Appearance\", defaultValue : null},\r\n\t\t\t\t\r\n\t\t\t\t/**\r\n\t\t\t\t * The minimum date that a user can start picking from (inclusive).\r\n\t\t\t\t */\r\n\t\t\t\tminDate : {type : \"object\", group : \"Appearance\", defaultValue : null},\r\n\t\t\t\t\r\n\t\t\t\t/**\r\n\t\t\t\t * Adjusts the step for the minute input (incl. scrolling)\r\n\t\t\t\t */\r\n\t\t\t\tminuteIncrement : {type : \"int\", group : \"Appearance\", defaultValue : 5},\r\n\t\t\t\t\r\n\t\t\t\t/**\r\n\t\t\t\t * \"single\", \"multiple\", or \"range\"\r\n\t\t\t\t */\r\n\t\t\t\tmode : {type : \"string\", group : \"Appearance\", defaultValue : \"single\"},\r\n\t\t\t\t\r\n\t\t\t\t/**\r\n\t\t\t\t * Hides the day selection in calendar. \r\n\t\t\t\t * Use it along with enableTime to create a time picker.\r\n\t\t\t\t */\r\n\t\t\t\tnoCalendar : {type : \"boolean\", group : \"Appearance\", defaultValue : false},\r\n\t\t\t\t\r\n\t\t\t\t/**\r\n\t\t\t\t * \tShow the month using the shorthand version (ie, Sep instead of September).\r\n\t\t\t\t */\r\n\t\t\t\tshorthandCurrentMonth : {type : \"boolean\", group : \"Appearance\", defaultValue : false},\r\n\t\t\t\t\r\n\t\t\t\t/**\r\n\t\t\t\t * Position the calendar inside the wrapper and next to the input element. \r\n\t\t\t\t * (Leave false unless you know what you're doing.)\r\n\t\t\t\t */\r\n\t\t\t\tstatic : {type : \"boolean\", group : \"Appearance\", defaultValue : false},\r\n\t\t\t\t\r\n\t\t\t\t/**\r\n\t\t\t\t * Displays time picker in 24 hour mode without AM/PM selection when enabled.\r\n\t\t\t\t */\r\n\t\t\t\ttime_24hr : {type : \"boolean\", group : \"Appearance\", defaultValue : false},\r\n\t\t\t\t\r\n\t\t\t\t/**\r\n\t\t\t\t * Enables display of week numbers in calendar.\r\n\t\t\t\t */\r\n\t\t\t\tweekNumbers : {type : \"boolean\", group : \"Appearance\", defaultValue : false},\r\n\t\t\t},\r\n\t\t\taggregations: {},\r\n\t\t\tevents: {\r\n\t\t\t\t\r\n\t\t\t\t/**\r\n\t\t\t\t * onChange gets triggered when the user selects a date, or changes the time on a selected date\r\n\t\t\t\t */\r\n\t\t\t\tonChange: {\r\n\t\t\t\t\tparameters: {\r\n\t\t\t\t\t\t/**\r\n\t\t\t\t\t\t * An array of Date objects selected by the user. When there are no dates selected, the array is empty.\r\n\t\t\t\t\t\t */\r\n\t\t\t\t\t\tselectedDates: { type: \"object[]\" },\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t/**\r\n\t\t\t\t\t\t * String representation of the latest selected Date object by the user. The string is formatted as per the dateFormat option\r\n\t\t\t\t\t\t */\r\n\t\t\t\t\t\tdateStr: { type: \"string\" },\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t/**\r\n\t\t\t\t\t\t * The Flatpickr object, containing various methods and properties\r\n\t\t\t\t\t\t */\r\n\t\t\t\t\t\tinstance: { type: \"object\" }\r\n\t\t\t\t\t}\r\n\t\t\t\t},\r\n\t\t\t\t\r\n\t\t\t\t/**\r\n\t\t\t\t * onOpen gets triggered when the calendar is opened\r\n\t\t\t\t */\r\n\t\t\t\tonOpen: {\r\n\t\t\t\t\tparameters: {\r\n\t\t\t\t\t\t/**\r\n\t\t\t\t\t\t * An array of Date objects selected by the user. When there are no dates selected, the array is empty.\r\n\t\t\t\t\t\t */\r\n\t\t\t\t\t\tselectedDates: { type: \"object[]\" },\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t/**\r\n\t\t\t\t\t\t * String representation of the latest selected Date object by the user. The string is formatted as per the dateFormat option\r\n\t\t\t\t\t\t */\r\n\t\t\t\t\t\tdateStr: { type: \"string\" },\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t/**\r\n\t\t\t\t\t\t * The Flatpickr object, containing various methods and properties\r\n\t\t\t\t\t\t */\r\n\t\t\t\t\t\tinstance: { type: \"object\" }\r\n\t\t\t\t\t}\r\n\t\t\t\t},\r\n\t\t\t\t\r\n\t\t\t\t/**\r\n\t\t\t\t * onClose gets triggered when the calendar is closed\r\n\t\t\t\t */\r\n\t\t\t\tonClose: {\r\n\t\t\t\t\tparameters: {\r\n\t\t\t\t\t\t/**\r\n\t\t\t\t\t\t * An array of Date objects selected by the user. When there are no dates selected, the array is empty.\r\n\t\t\t\t\t\t */\r\n\t\t\t\t\t\tselectedDates: { type: \"object[]\" },\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t/**\r\n\t\t\t\t\t\t * String representation of the latest selected Date object by the user. The string is formatted as per the dateFormat option\r\n\t\t\t\t\t\t */\r\n\t\t\t\t\t\tdateStr: { type: \"string\" },\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t/**\r\n\t\t\t\t\t\t * The Flatpickr object, containing various methods and properties\r\n\t\t\t\t\t\t */\r\n\t\t\t\t\t\tinstance: { type: \"object\" }\r\n\t\t\t\t\t}\r\n\t\t\t\t},\r\n\t\t\t\t\r\n\t\t\t\t/**\r\n\t\t\t\t * onMonthChange gets triggered when the month is changed, either by the user or programmatically\r\n\t\t\t\t */\r\n\t\t\t\tonMonthChange: {\r\n\t\t\t\t\tparameters: {\r\n\t\t\t\t\t\t/**\r\n\t\t\t\t\t\t * An array of Date objects selected by the user. When there are no dates selected, the array is empty.\r\n\t\t\t\t\t\t */\r\n\t\t\t\t\t\tselectedDates: { type: \"object[]\" },\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t/**\r\n\t\t\t\t\t\t * String representation of the latest selected Date object by the user. The string is formatted as per the dateFormat option\r\n\t\t\t\t\t\t */\r\n\t\t\t\t\t\tdateStr: { type: \"string\" },\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t/**\r\n\t\t\t\t\t\t * The Flatpickr object, containing various methods and properties\r\n\t\t\t\t\t\t */\r\n\t\t\t\t\t\tinstance: { type: \"object\" }\r\n\t\t\t\t\t}\r\n\t\t\t\t},\r\n\t\t\t\t\r\n\t\t\t\t/**\r\n\t\t\t\t * onMonthChange gets triggered when the year is changed, either by the user or programmatically\r\n\t\t\t\t */\r\n\t\t\t\tonYearChange: {\r\n\t\t\t\t\tparameters: {\r\n\t\t\t\t\t\t/**\r\n\t\t\t\t\t\t * An array of Date objects selected by the user. When there are no dates selected, the array is empty.\r\n\t\t\t\t\t\t */\r\n\t\t\t\t\t\tselectedDates: { type: \"object[]\" },\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t/**\r\n\t\t\t\t\t\t * String representation of the latest selected Date object by the user. The string is formatted as per the dateFormat option\r\n\t\t\t\t\t\t */\r\n\t\t\t\t\t\tdateStr: { type: \"string\" },\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t/**\r\n\t\t\t\t\t\t * The Flatpickr object, containing various methods and properties\r\n\t\t\t\t\t\t */\r\n\t\t\t\t\t\tinstance: { type: \"object\" }\r\n\t\t\t\t\t}\r\n\t\t\t\t},\r\n\t\t\t\t\r\n\t\t\t\t/**\r\n\t\t\t\t * onReady gets triggered once the calendar is in a ready state.\r\n\t\t\t\t */\r\n\t\t\t\tonReady: {\r\n\t\t\t\t\tparameters: {\r\n\t\t\t\t\t\t/**\r\n\t\t\t\t\t\t * An array of Date objects selected by the user. When there are no dates selected, the array is empty.\r\n\t\t\t\t\t\t */\r\n\t\t\t\t\t\tselectedDates: { type: \"object[]\" },\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t/**\r\n\t\t\t\t\t\t * String representation of the latest selected Date object by the user. The string is formatted as per the dateFormat option\r\n\t\t\t\t\t\t */\r\n\t\t\t\t\t\tdateStr: { type: \"string\" },\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t/**\r\n\t\t\t\t\t\t * The Flatpickr object, containing various methods and properties\r\n\t\t\t\t\t\t */\r\n\t\t\t\t\t\tinstance: { type: \"object\" }\r\n\t\t\t\t\t}\r\n\t\t\t\t},\r\n\t\t\t\t\r\n\t\t\t\t/**\r\n\t\t\t\t * onValueUpdate gets triggered when the input value is updated with a new date string\r\n\t\t\t\t */\r\n\t\t\t\tonValueUpdate: {\r\n\t\t\t\t\tparameters: {\r\n\t\t\t\t\t\t/**\r\n\t\t\t\t\t\t * An array of Date objects selected by the user. When there are no dates selected, the array is empty.\r\n\t\t\t\t\t\t */\r\n\t\t\t\t\t\tselectedDates: { type: \"object[]\" },\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t/**\r\n\t\t\t\t\t\t * String representation of the latest selected Date object by the user. The string is formatted as per the dateFormat option\r\n\t\t\t\t\t\t */\r\n\t\t\t\t\t\tdateStr: { type: \"string\" },\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t/**\r\n\t\t\t\t\t\t * The Flatpickr object, containing various methods and properties\r\n\t\t\t\t\t\t */\r\n\t\t\t\t\t\tinstance: { type: \"object\" }\r\n\t\t\t\t\t}\r\n\t\t\t\t},\r\n\t\t\t\t\r\n\t\t\t\t/**\r\n\t\t\t\t * Take full control of every date cell with the onDayCreate() hook\r\n\t\t\t\t */\r\n\t\t\t\tonDayCreate: {\r\n\t\t\t\t\tparameters: {\r\n\t\t\t\t\t\t/**\r\n\t\t\t\t\t\t * An array of Date objects selected by the user. When there are no dates selected, the array is empty.\r\n\t\t\t\t\t\t */\r\n\t\t\t\t\t\tselectedDates: { type: \"object[]\" },\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t/**\r\n\t\t\t\t\t\t * String representation of the latest selected Date object by the user. The string is formatted as per the dateFormat option\r\n\t\t\t\t\t\t */\r\n\t\t\t\t\t\tdateStr: { type: \"string\" },\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t/**\r\n\t\t\t\t\t\t * The Flatpickr object, containing various methods and properties\r\n\t\t\t\t\t\t */\r\n\t\t\t\t\t\tinstance: { type: \"object\" }\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t}\r\n\t\t}, \r\n\t\t\r\n\t\tinit: function() {\r\n\t\t\t//\tInit all the things!\r\n\t\t},\r\n\t\t\r\n\t\tonAfterRendering: function() {\r\n\t\t\tvar that = this;\r\n\t\t\tthis.__flatPickr = $(\"#\"+this.getId()+\".flatpickrCustomControl\").flatpickr({\r\n\t\t\t    altFormat: this.getAltFormat(),\r\n\t\t\t    altInput: this.getAltInput(),\r\n\t\t\t    altInputClass: this.getAltInputClass(),\r\n\t\t\t    allowInput: this.getAllowInput(),\r\n\t\t\t    clickOpens: this.getClickOpens(),\r\n\t\t\t    dateFormat: this.getDateFormat(),\r\n\t\t\t    defaultDate: this.getDateValue(),\r\n\t\t\t    defaultHour: this.getHourValue(),\r\n\t\t\t    defaultMinute: this.getMinuteValue(),\r\n\t\t\t    disable: this.getDisabledDates(),\r\n\t\t\t\tdisableMobile: this.getDisableMobile(),\r\n\t\t\t    enable: this.getEnabledDates(),\r\n\t\t\t    enableTime: this.getEnableTime(),\r\n\t\t\t    enableSeconds: this.getEnableSeconds(),\r\n\t\t\t    hourIncrement: this.getHourIncrement(),\r\n\t\t\t    inline: this.getInline(),\r\n\t\t\t    maxDate: this.getMaxDate(),\r\n\t\t\t    minDate: this.getMinDate(),\r\n\t\t\t    minuteIncrement: this.getMinuteIncrement(),\r\n\t\t\t    mode: this.getMode(),\r\n\t\t\t    noCalendar: this.getNoCalendar(),\r\n\t\t\t    shorthandCurrentMonth: this.getShorthandCurrentMonth(),\r\n\t\t\t    static: this.getStatic(),\r\n\t\t\t    time_24hr: this.getTime_24hr(),\r\n\t\t\t    weekNumbers: this.getWeekNumbers(),\r\n\t\t\t    wrap: true, // force wrap to true\r\n\t\t\t    \r\n\t\t\t    // defining events callback\r\n\t\t\t    onChange: function(selectedDates, dateStr, instance) {\r\n\t\t\t\t\tthat.setProperty(\"dateValue\", selectedDates, true);\r\n\t\t\t\t\tthat.fireOnChange({selectedDates: selectedDates, dateStr: dateStr, instance: instance});\r\n\t\t\t\t},\r\n\t\t\t    onOpen: function(selectedDates, dateStr, instance) {\r\n\t\t\t\t\tthat.fireOnOpen({selectedDates: selectedDates, dateStr: dateStr, instance: instance});\r\n\t\t\t\t},\r\n\t\t\t    onClose: function(selectedDates, dateStr, instance) {\r\n\t\t\t\t\tthat.fireOnClose({selectedDates: selectedDates, dateStr: dateStr, instance: instance});\r\n\t\t\t\t},\r\n\t\t\t    onMonthChange: function(selectedDates, dateStr, instance) {\r\n\t\t\t\t\tthat.fireOnMonthChange({selectedDates: selectedDates, dateStr: dateStr, instance: instance});\r\n\t\t\t\t},\r\n\t\t\t    onYearChange: function(selectedDates, dateStr, instance) {\r\n\t\t\t\t\tthat.fireOnYearChange({selectedDates: selectedDates, dateStr: dateStr, instance: instance});\r\n\t\t\t\t},\r\n\t\t\t    onReady: function(selectedDates, dateStr, instance) {\r\n\t\t\t\t\tthat.fireOnReady({selectedDates: selectedDates, dateStr: dateStr, instance: instance});\r\n\t\t\t\t},\r\n\t\t\t    onValueUpdate: function(selectedDates, dateStr, instance) {\r\n\t\t\t\t\tthat.fireOnValueUpdate({selectedDates: selectedDates, dateStr: dateStr, instance: instance});\r\n\t\t\t\t},\r\n\t\t\t    onDayCreate: function(selectedDates, dateStr, instance) {\r\n\t\t\t\t\tthat.fireOnDayCreate({selectedDates: selectedDates, dateStr: dateStr, instance: instance});\r\n\t\t\t\t}\r\n\t\t\t});\r\n\t\t},\r\n\t\t\r\n\t\t////////////////////////////////////////////////////\r\n\t\t//\tFASTPICKR METHODS\r\n\t\t////////////////////////////////////////////////////\r\n\t\t\r\n\t\t/*\r\n\t\t* Resets the selected dates (if any) and clears the input.\r\n\t\t* @public\r\n\t\t*/\r\n\t\tclearDatePicker: function() {\r\n\t\t\tif( this.__flatPickr ) {\r\n\t\t\t\tthis.__flatPickr.clear();\r\n\t\t\t}\r\n\t\t},\r\n\t\t\r\n\t\t/*\r\n\t\t* Closes the calendar.\r\n\t\t* @public\r\n\t\t*/\r\n\t\tcloseDatePicker: function() {\r\n\t\t\tif( this.__flatPickr ) {\r\n\t\t\t\tthis.__flatPickr.close();\r\n\t\t\t}\r\n\t\t},\r\n\t\t\r\n\t\t/*\r\n\t\t* Destroys the Flatpickr instance, cleans up - removes event listeners, restores inputs, etc.\r\n\t\t* @public\r\n\t\t*/\r\n\t\tdestroyDatePicker: function() {\r\n\t\t\tif( this.__flatPickr ) {\r\n\t\t\t\tthis.__flatPickr.destroy();\r\n\t\t\t}\r\n\t\t},\r\n\t\t\r\n\t\t/*\r\n\t\t* Return a formatted date\r\n\t\t* @public\r\n\t\t* @param {string} formatStr Formatting tokens string\r\n\t\t* @param {string} dateObj Date to be formatted\r\n\t\t* @returns {string} A string representation of dateObj,  formatted as per formatStr\r\n\t\t*/\r\n\t\tformatDate: function(formatStr, dateObj) {\r\n\t\t\tif( this.__flatPickr ) {\r\n\t\t\t\treturn this.__flatPickr.formatDate(formatStr, dateObj);\r\n\t\t\t}\r\n\t\t\treturn null;\r\n\t\t},\r\n\t\t\r\n\t\t\r\n\t\t/*\r\n\t\t* Sets the calendar view to the year and month ofdate, which can be a date string, a Date, or nothing\r\n\t\t* If date is undefined, the view is set to the latest selected date, the minDate, or today’s date\r\n\t\t* @public\r\n\t\t* @param {Date} date Date to jump to\r\n\t\t*/\r\n\t\tjumpToDate: function(date) {\r\n\t\t\tif( this.__flatPickr ) {\r\n\t\t\t\tthis.__flatPickr.jumpToDate(date);\r\n\t\t\t}\r\n\t\t},\r\n\t\t\r\n\t\t/*\r\n\t\t* Shows/opens the calendar.\r\n\t\t* @public\r\n\t\t*/\r\n\t\topenDatePicker: function() {\r\n\t\t\tif( this.__flatPickr ) {\r\n\t\t\t\tthis.__flatPickr.open();\r\n\t\t\t}\r\n\t\t},\r\n\t\t\r\n\t\t/*\r\n\t\t* Parses a date string or a timestamp, and returns a Date.\r\n\t\t* @public\r\n\t\t* @param {object} date String or timestamp to be parsed\r\n\t\t* @returns {Date} Parsed date\r\n\t\t*/\r\n\t\tparseDate: function(date) {\r\n\t\t\tif( this.__flatPickr ) {\r\n\t\t\t\tthis.__flatPickr.parseDate();\r\n\t\t\t}\r\n\t\t},\r\n\t\t\r\n\t\t/*\r\n\t\t* Redraws the calendar. Shouldn’t be necessary in most cases\r\n\t\t* @public\r\n\t\t*/\r\n\t\tredrawDatePicker: function() {\r\n\t\t\tif( this.__flatPickr ) {\r\n\t\t\t\tthis.__flatPickr.redraw();\r\n\t\t\t}\r\n\t\t},\r\n\t\t\r\n\t\t/*\r\n\t\t* Sets the current selected date(s) todate, which can be a date string, a Date, or an Array of the Dates.\r\n\t\t* Optionally, pass true as the second argument to force any onChange events to fire\r\n\t\t* @public\r\n\t\t* @param {object} string, Date or an Array of the Dates\r\n\t\t* @param {boolean} triggerChange If true will force any onChange events to fire\r\n\t\t*/\r\n\t\tsetDate: function(date, triggerChange) {\r\n\t\t\tthis.__flatPickr.setDate(date, triggerChange);\r\n\t\t},\r\n\t\t\r\n\t\t/*\r\n\t\t* Shows/opens the calendar if its closed, hides/closes it otherwise\r\n\t\t* @public\r\n\t\t*/\r\n\t\ttoggleDatePicker: function() {\r\n\t\t\tthis.__flatPickr.toggle();\r\n\t\t},\r\n\t\t\r\n\t\t////////////////////////////////////////////////////\r\n\t\t//\tEVENTS HANDLING\r\n\t\t////////////////////////////////////////////////////\r\n\t\t\r\n\t\tonChange: function(selectedDates, dateStr, instance) {\r\n\t\t\tthis.fireOnChange({selectedDates: selectedDates, dateStr: dateStr, instance: instance});\r\n\t\t},\r\n\t\t\r\n\t\tonOpen: function(selectedDates, dateStr, instance) {\r\n\t\t\tthis.fireOnOpen({selectedDates: selectedDates, dateStr: dateStr, instance: instance});\r\n\t\t},\r\n\t\t\r\n\t\tonClose: function(selectedDates, dateStr, instance) {\r\n\t\t\tthis.fireOnClose({selectedDates: selectedDates, dateStr: dateStr, instance: instance});\r\n\t\t},\r\n\t\t\r\n\t\tonMonthChange: function(selectedDates, dateStr, instance) {\r\n\t\t\tthis.fireOnMonthChange({selectedDates: selectedDates, dateStr: dateStr, instance: instance});\r\n\t\t},\r\n\t\t\r\n\t\tonYearChange: function(selectedDates, dateStr, instance) {\r\n\t\t\tthis.fireOnYearChange({selectedDates: selectedDates, dateStr: dateStr, instance: instance});\r\n\t\t},\r\n\t\t\r\n\t\tonReady: function(selectedDates, dateStr, instance) {\r\n\t\t\tthis.fireOnReady({selectedDates: selectedDates, dateStr: dateStr, instance: instance});\r\n\t\t},\r\n\t\t\r\n\t\tonValueUpdate: function(selectedDates, dateStr, instance) {\r\n\t\t\tthis.fireOnValueUpdate({selectedDates: selectedDates, dateStr: dateStr, instance: instance});\r\n\t\t},\r\n\t\t\r\n\t\tonDayCreate: function(selectedDates, dateStr, instance) {\r\n\t\t\tthis.fireOnDayCreate({selectedDates: selectedDates, dateStr: dateStr, instance: instance});\r\n\t\t},\r\n\t\t\r\n\t\t////////////////////////////////////////////////////\r\n\t\t//\tGETTER & SETTER FOR FLAT PICKER PROPERTIES\r\n\t\t////////////////////////////////////////////////////\r\n\r\n\t\tgetSelectedDates: function() { \r\n\t\t\tif( this.__flatPickr ) {\r\n\t\t\t\treturn this.__flatPickr.selectedDates;\r\n\t\t\t}\r\n\t\t\treturn null;\r\n\t\t}, \r\n\t\t\r\n\t\tsetAltFormat: function(value) {\r\n\t\t\tif( this.__flatPickr ) {\r\n\t\t\t\tthis.__flatPickr.set(\"altFormat\", value);\r\n\t\t\t}\r\n\t\t\tthis.setProperty(\"altFormat\", value, false);\r\n\t\t\treturn this;\r\n\t\t},\r\n\t\t\r\n\t\tsetAltInput: function(value) {\r\n\t\t\tif( this.__flatPickr ) {\r\n\t\t\t\tthis.__flatPickr.set(\"altInput\", value);\r\n\t\t\t}\r\n\t\t\tthis.setProperty(\"altInput\", value, false);\r\n\t\t\treturn this;\r\n\t\t},\r\n\t\t\r\n\t\tsetAltInputClass: function(value) {\r\n\t\t\tif( this.__flatPickr ) {\r\n\t\t\t\tthis.__flatPickr.set(\"altInputClass\", value);\r\n\t\t\t}\r\n\t\t\tthis.setProperty(\"altInputClass\", value, false);\r\n\t\t\treturn this;\r\n\t\t},\r\n\t\t\r\n\t\tsetAllowInput: function(value) {\r\n\t\t\tif( this.__flatPickr ) {\r\n\t\t\t\tthis.__flatPickr.set(\"allowInput\", value);\r\n\t\t\t}\r\n\t\t\tthis.setProperty(\"allowInput\", value, false);\r\n\t\t\treturn this;\r\n\t\t},\r\n\t\t\r\n\t\tsetClickOpens: function(value) {\r\n\t\t\tif( this.__flatPickr ) {\r\n\t\t\t\tthis.__flatPickr.set(\"clickOpens\", value);\r\n\t\t\t}\r\n\t\t\tthis.setProperty(\"clickOpens\", value, false);\r\n\t\t\treturn this;\r\n\t\t},\r\n\t\t\r\n\t\tsetDateFormat: function(value) {\r\n\t\t\tif( this.__flatPickr ) {\r\n\t\t\t\tthis.__flatPickr.set(\"dateFormat\", value);\r\n\t\t\t}\r\n\t\t\tthis.setProperty(\"dateFormat\", value, false);\r\n\t\t\treturn this;\r\n\t\t},\r\n\t\t\r\n\t\tsetDateValue: function(value) {\r\n\t\t\tif( this.__flatPickr ) {\r\n\t\t\t\tthis.__flatPickr.set(\"defaultDate\", value);\r\n\t\t\t}\r\n\t\t\tthis.setProperty(\"dateValue\", value, false);\r\n\t\t\treturn this;\r\n\t\t},\r\n\t\t\r\n\t\tsetHourValue: function(value) {\r\n\t\t\tif( this.__flatPickr ) {\r\n\t\t\t\tthis.__flatPickr.set(\"defaultHour\", value);\r\n\t\t\t}\r\n\t\t\tthis.setProperty(\"hourValue\", value, false);\r\n\t\t\treturn this;\r\n\t\t},\r\n\t\t\r\n\t\tsetMinuteValue: function(value) {\r\n\t\t\tif( this.__flatPickr ) {\r\n\t\t\t\tthis.__flatPickr.set(\"defaultMinute\", value);\r\n\t\t\t}\r\n\t\t\tthis.setProperty(\"minuteValue\", value, false);\r\n\t\t\treturn this;\r\n\t\t},\r\n\t\t\r\n\t\tsetDisabledDates: function(value) {\r\n\t\t\tif( this.__flatPickr ) {\r\n\t\t\t\tthis.__flatPickr.set(\"disable\", value);\r\n\t\t\t}\r\n\t\t\tthis.setProperty(\"disabledDates\", value, false);\r\n\t\t\treturn this;\r\n\t\t},\r\n\t\t\r\n\t\tsetDisableMobile: function(value) {\r\n\t\t\tif( this.__flatPickr ) {\r\n\t\t\t\tthis.__flatPickr.set(\"disableMobile\", value);\r\n\t\t\t}\r\n\t\t\tthis.setProperty(\"disableMobile\", value, false);\r\n\t\t\treturn this;\r\n\t\t},\r\n\t\t\r\n\t\tsetEnabledDates: function(value) {\r\n\t\t\tif( this.__flatPickr ) {\r\n\t\t\t\tthis.__flatPickr.set(\"enable\", value);\r\n\t\t\t}\r\n\t\t\tthis.setProperty(\"enabledDates\", value, false);\r\n\t\t\treturn this;\r\n\t\t},\r\n\t\t\r\n\t\tsetEnableTime: function(value) {\r\n\t\t\tif( this.__flatPickr ) {\r\n\t\t\t\tthis.__flatPickr.set(\"enableTime\", value);\r\n\t\t\t}\r\n\t\t\tthis.setProperty(\"enableTime\", value, false);\r\n\t\t\treturn this;\r\n\t\t},\r\n\t\t\r\n\t\tsetEnableSeconds: function(value) {\r\n\t\t\tif( this.__flatPickr ) {\r\n\t\t\t\tthis.__flatPickr.set(\"enableSeconds\", value);\r\n\t\t\t}\r\n\t\t\tthis.setProperty(\"enableSeconds\", value, false);\r\n\t\t\treturn this;\r\n\t\t},\r\n\t\t\r\n\t\tsetHourIncrement: function(value) {\r\n\t\t\tif( this.__flatPickr ) {\r\n\t\t\t\tthis.__flatPickr.set(\"hourIncrement\", value);\r\n\t\t\t}\r\n\t\t\tthis.setProperty(\"hourIncrement\", value, false);\r\n\t\t\treturn this;\r\n\t\t},\r\n\t\t\r\n\t\tsetInline: function(value) {\r\n\t\t\tif( this.__flatPickr ) {\r\n\t\t\t\tthis.__flatPickr.set(\"inline\", value);\r\n\t\t\t}\r\n\t\t\tthis.setProperty(\"inline\", value, false);\r\n\t\t\treturn this;\r\n\t\t},\r\n\t\t\r\n\t\tsetMaxDate: function(value) {\r\n\t\t\tif( this.__flatPickr ) {\r\n\t\t\t\tthis.__flatPickr.set(\"maxDate\", value);\r\n\t\t\t}\r\n\t\t\tthis.setProperty(\"maxDate\", value, false);\r\n\t\t\treturn this;\r\n\t\t},\r\n\t\t\r\n\t\tsetMinDate: function(value) {\r\n\t\t\tif( this.__flatPickr ) {\r\n\t\t\t\tthis.__flatPickr.set(\"minDate\", value);\r\n\t\t\t}\r\n\t\t\tthis.setProperty(\"minDate\", value, false);\r\n\t\t\treturn this;\r\n\t\t},\r\n\t\t\r\n\t\tsetMinuteIncrement: function(value) {\r\n\t\t\tif( this.__flatPickr ) {\r\n\t\t\t\tthis.__flatPickr.set(\"minuteIncrement\", value);\r\n\t\t\t}\r\n\t\t\tthis.setProperty(\"minuteIncrement\", value, false);\r\n\t\t\treturn this;\r\n\t\t},\r\n\t\t\r\n\t\tsetMode: function(value) {\r\n\t\t\tif( this.__flatPickr ) {\r\n\t\t\t\tthis.__flatPickr.set(\"mode\", value);\r\n\t\t\t}\r\n\t\t\tthis.setProperty(\"mode\", value, false);\r\n\t\t\treturn this;\r\n\t\t},\r\n\t\t\r\n\t\tsetNoCalendar: function(value) {\r\n\t\t\tif( this.__flatPickr ) {\r\n\t\t\t\tthis.__flatPickr.set(\"noCalendar\", value);\r\n\t\t\t}\r\n\t\t\tthis.setProperty(\"noCalendar\", value, false);\r\n\t\t\treturn this;\r\n\t\t},\r\n\t\t\r\n\t\tsetShorthandCurrentMonth: function(value) {\r\n\t\t\tif( this.__flatPickr ) {\r\n\t\t\t\tthis.__flatPickr.set(\"shorthandCurrentMonth\", value);\r\n\t\t\t}\r\n\t\t\tthis.setProperty(\"shorthandCurrentMonth\", value, false);\r\n\t\t\treturn this;\r\n\t\t},\r\n\t\t\r\n\t\tsetStatic: function(value) {\r\n\t\t\tif( this.__flatPickr ) {\r\n\t\t\t\tthis.__flatPickr.set(\"static\", value);\r\n\t\t\t}\r\n\t\t\tthis.setProperty(\"static\", value, false);\r\n\t\t\treturn this;\r\n\t\t},\r\n\t\t\r\n\t\tsetTime_24hr: function(value) {\r\n\t\t\tif( this.__flatPickr ) {\r\n\t\t\t\tthis.__flatPickr.set(\"time_24hr\", value);\r\n\t\t\t}\r\n\t\t\tthis.setProperty(\"time_24hr\", value, false);\r\n\t\t\treturn this;\r\n\t\t},\r\n\t\t\r\n\t\tsetWeekNumbers: function(value) {\r\n\t\t\tif( this.__flatPickr ) {\r\n\t\t\t\tthis.__flatPickr.set(\"weekNumbers\", value);\r\n\t\t\t}\r\n\t\t\tthis.setProperty(\"weekNumbers\", value, false);\r\n\t\t\treturn this;\r\n\t\t}\r\n\t\t\r\n\t});\r\n\t\r\n\t/*\r\n\t* Override the exit method to free local resources and destroy \r\n\t* Optionally, pass true as the second argument to force any onChange events to fire\r\n\t* @public\r\n\t*/\t\r\n\tFlatDatePicker.prototype.exit = function() {\r\n\t\tInputBase.prototype.exit.apply(this, arguments);\r\n\t\tif (this.__flatPickr) {\r\n\t\t\tif (this.__flatPickr.isOpen) {\r\n\t\t\t\tthis.closeDatePicker();\r\n\t\t\t}\r\n\t\t\tthis.destroyDatePicker();\r\n\t\t}\r\n\t\tthis.__flatPickr = undefined;\r\n\t};\r\n\t\r\n\treturn FlatDatePicker;\r\n\r\n}, /* bExport= */ true);",
		"it/designfuture/flatpickr/FlatDatePickerRenderer.js": "/*!\r\n * ${copyright}\r\n */\r\n\r\nsap.ui.define(['jquery.sap.global', 'sap/m/DatePickerRenderer'],\r\n\tfunction(jQuery, DatePickerRenderer) {\r\n\t\"use strict\";\r\n\r\n\t/**\r\n\t * FlatDatePicker renderer.\r\n\t * @static\r\n\t * @namespace\r\n\t */\r\n\tvar FlatDatePickerRenderer = DatePickerRenderer.extend(\"it.designfuture.flatpickr.FlatDatePickerRenderer\");\r\n\t\r\n\t/**\r\n\t * Add the custom class to render the Date Picker, using the provided {@link sap.ui.core.RenderManager}.\r\n\t *\r\n\t * @param {sap.ui.core.RenderManager} oRm The RenderManager that can be used for writing to the render output buffer.\r\n\t * @param {sap.ui.core.Control} oControl An object representation of the control that should be rendered.\r\n\t */\r\n\tFlatDatePickerRenderer.addOuterClasses = function(oRm, oControl) {\r\n\t\toRm.addClass(\"flatpickrCustomControl\");\r\n\t};\r\n\t\r\n\t/**\r\n\t * Overrided to add data-input custom data\r\n\t *\r\n\t * @param {sap.ui.core.RenderManager} oRm The RenderManager that can be used for writing to the render output buffer.\r\n\t * @param {sap.ui.core.Control} oControl An object representation of the control that should be rendered.\r\n\t */\r\n\tFlatDatePickerRenderer.writeInnerAttributes = function(oRm, oDP) {\r\n\t\toRm.write(\" data-input \");\r\n\t};\r\n\t\r\n\t/**\r\n\t * Overrided to add data-toggle custom data\r\n\t *\r\n\t * @param {sap.ui.core.RenderManager} oRm the RenderManager that can be used for writing to the render output buffer\r\n\t * @param {sap.m.DatePicker} oDP an object representation of the control that should be rendered\r\n\t */\r\n\tFlatDatePickerRenderer.writeInnerContent = function(oRm, oDP) {\r\n\r\n\t\tif (oDP.getEnabled() && oDP.getEditable()) {\r\n\t\t\tvar aClasses = [\"sapMInputValHelpInner\"];\r\n\t\t\tvar mAttributes = {};\r\n\r\n\t\t\tmAttributes[\"id\"] = oDP.getId() + \"-icon\";\r\n\t\t\tmAttributes[\"tabindex\"] = \"-1\"; // to get focus events on it, needed for popup autoclose handling\r\n\t\t\toRm.write('<div class=\"sapMInputValHelp\" data-toggle>');\r\n\t\t\toRm.writeIcon(\"sap-icon://appointment-2\", aClasses, mAttributes);\r\n\t\t\toRm.write(\"</div>\");\r\n\t\t}\r\n\r\n\t\t// invisible span with description for keyboard navigation\r\n\t\tvar rb = sap.ui.getCore().getLibraryResourceBundle(\"sap.ui.unified\");\r\n\t\t\t// ResourceBundle always returns the key if the text is not found\r\n\t\t// ResourceBundle always returns the key if the text is not found\r\n\t\tvar sText = rb.getText(\"DATEPICKER_DATE_TYPE\");\r\n\r\n\t\tvar sTooltip = sap.ui.core.ValueStateSupport.enrichTooltip(oDP, oDP.getTooltip_AsString());\r\n\t\tif (sTooltip) {\r\n\t\t\t// add tooltip to description because it is not read by JAWS from title-attribute if a label is assigned\r\n\t\t\tsText = sText + \". \" + sTooltip;\r\n\t\t}\r\n\t\toRm.write('<SPAN id=\"' + oDP.getId() + '-Descr\" style=\"visibility: hidden; display: none;\">');\r\n\t\toRm.writeEscaped(sText);\r\n\t\toRm.write('</SPAN>');\r\n\r\n\t};\r\n\r\n\treturn FlatDatePickerRenderer;\r\n\r\n}, /* bExport= */ true);",
		"it/designfuture/flatpickr/library.js": "/*!\r\n * ${copyright}\r\n */\r\n\r\n/**\r\n * Initialization Code and shared classes of library it.designfuture.flatpickr.\r\n */\r\nsap.ui.define([\r\n\t'jquery.sap.global', \r\n\t'sap/ui/core/library' // library dependency\r\n\t],  function(jQuery, library) {\r\n\r\n\t\t\"use strict\";\r\n\r\n\t\t/**\r\n\t\t * Suite controls library.\r\n\t\t *\r\n\t\t * @namespace\r\n\t\t * @name it.designfuture.flatpickr\r\n\t\t * @author Emanuele Ricci <stermi@gmail.com>\r\n\t\t * @version ${version}\r\n\t\t * @public\r\n\t\t */\r\n\r\n\r\n\t\t// delegate further initialization of this library to the Core\r\n\t\tsap.ui.getCore().initLibrary({\r\n\t\t\tname : \"it.designfuture.flatpickr\",\r\n\t\t\tversion: \"${version}\",\r\n\t\t\tdependencies : [\"sap.ui.core\", \"sap.m\"],\r\n\t\t\ttypes: [],\r\n\t\t\tinterfaces: [],\r\n\t\t\tcontrols: [ \r\n\t\t\t\t\"it.designfuture.flatpickr.FlatDatePicker\"\r\n\t\t\t],\r\n\t\t\telements: []\r\n\t\t});\r\n\r\n\t\treturn it.designfuture.flatpickr;\r\n\r\n}, /* bExport= */ false);",
		"it/designfuture/flatpickr/3rdparty/flatpickr.js": "var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };\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\n/*! flatpickr v3.0.6, @license MIT */\nfunction FlatpickrInstance(element, config) {\n\tvar self = this;\n\n\tself._ = {};\n\tself._.afterDayAnim = afterDayAnim;\n\tself._bind = bind;\n\tself._compareDates = compareDates;\n\tself._setHoursFromDate = setHoursFromDate;\n\tself.changeMonth = changeMonth;\n\tself.changeYear = changeYear;\n\tself.clear = clear;\n\tself.close = close;\n\tself._createElement = createElement;\n\tself.destroy = destroy;\n\tself.isEnabled = isEnabled;\n\tself.jumpToDate = jumpToDate;\n\tself.open = open;\n\tself.redraw = redraw;\n\tself.set = set;\n\tself.setDate = setDate;\n\tself.toggle = toggle;\n\n\tfunction init() {\n\t\tself.element = self.input = element;\n\t\tself.instanceConfig = config || {};\n\t\tself.parseDate = FlatpickrInstance.prototype.parseDate.bind(self);\n\t\tself.formatDate = FlatpickrInstance.prototype.formatDate.bind(self);\n\n\t\tsetupFormats();\n\t\tparseConfig();\n\t\tsetupLocale();\n\t\tsetupInputs();\n\t\tsetupDates();\n\t\tsetupHelperFunctions();\n\n\t\tself.isOpen = false;\n\n\t\tself.isMobile = !self.config.disableMobile && !self.config.inline && self.config.mode === \"single\" && !self.config.disable.length && !self.config.enable.length && !self.config.weekNumbers && /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);\n\n\t\tif (!self.isMobile) build();\n\n\t\tbindEvents();\n\n\t\tif (self.selectedDates.length || self.config.noCalendar) {\n\t\t\tif (self.config.enableTime) {\n\t\t\t\tsetHoursFromDate(self.config.noCalendar ? self.latestSelectedDateObj || self.config.minDate : null);\n\t\t\t}\n\t\t\tupdateValue();\n\t\t}\n\n\t\tself.showTimeInput = self.selectedDates.length > 0 || self.config.noCalendar;\n\n\t\tif (self.config.weekNumbers) {\n\t\t\tself.calendarContainer.style.width = self.daysContainer.offsetWidth + self.weekWrapper.offsetWidth + \"px\";\n\t\t}\n\n\t\tif (!self.isMobile) positionCalendar();\n\n\t\ttriggerEvent(\"Ready\");\n\t}\n\n\t/**\n  * Binds a function to the current flatpickr instance\n  * @param {Function} fn the function\n  * @return {Function} the function bound to the instance\n  */\n\tfunction bindToInstance(fn) {\n\t\treturn fn.bind(self);\n\t}\n\n\t/**\n  * The handler for all events targeting the time inputs\n  * @param {Event} e the event - \"input\", \"wheel\", \"increment\", etc\n  */\n\tfunction updateTime(e) {\n\t\tif (self.config.noCalendar && !self.selectedDates.length)\n\t\t\t// picking time only\n\t\t\tself.selectedDates = [self.now];\n\n\t\ttimeWrapper(e);\n\n\t\tif (!self.selectedDates.length) return;\n\n\t\tif (!self.minDateHasTime || e.type !== \"input\" || e.target.value.length >= 2) {\n\t\t\tsetHoursFromInputs();\n\t\t\tupdateValue();\n\t\t} else {\n\t\t\tsetTimeout(function () {\n\t\t\t\tsetHoursFromInputs();\n\t\t\t\tupdateValue();\n\t\t\t}, 1000);\n\t\t}\n\t}\n\n\t/**\n  * Syncs the selected date object time with user's time input\n  */\n\tfunction setHoursFromInputs() {\n\t\tif (!self.config.enableTime) return;\n\n\t\tvar hours = (parseInt(self.hourElement.value, 10) || 0) % (self.amPM ? 12 : 24),\n\t\t    minutes = (parseInt(self.minuteElement.value, 10) || 0) % 60,\n\t\t    seconds = self.config.enableSeconds ? (parseInt(self.secondElement.value, 10) || 0) % 60 : 0;\n\n\t\tif (self.amPM !== undefined) hours = hours % 12 + 12 * (self.amPM.textContent === \"PM\");\n\n\t\tif (self.minDateHasTime && compareDates(self.latestSelectedDateObj, self.config.minDate) === 0) {\n\n\t\t\thours = Math.max(hours, self.config.minDate.getHours());\n\t\t\tif (hours === self.config.minDate.getHours()) minutes = Math.max(minutes, self.config.minDate.getMinutes());\n\t\t}\n\n\t\tif (self.maxDateHasTime && compareDates(self.latestSelectedDateObj, self.config.maxDate) === 0) {\n\t\t\thours = Math.min(hours, self.config.maxDate.getHours());\n\t\t\tif (hours === self.config.maxDate.getHours()) minutes = Math.min(minutes, self.config.maxDate.getMinutes());\n\t\t}\n\n\t\tsetHours(hours, minutes, seconds);\n\t}\n\n\t/**\n  * Syncs time input values with a date\n  * @param {Date} dateObj the date to sync with\n  */\n\tfunction setHoursFromDate(dateObj) {\n\t\tvar date = dateObj || self.latestSelectedDateObj;\n\n\t\tif (date) setHours(date.getHours(), date.getMinutes(), date.getSeconds());\n\t}\n\n\t/**\n  * Sets the hours, minutes, and optionally seconds\n  * of the latest selected date object and the\n  * corresponding time inputs\n  * @param {Number} hours the hour. whether its military\n  *                 or am-pm gets inferred from config\n  * @param {Number} minutes the minutes\n  * @param {Number} seconds the seconds (optional)\n  */\n\tfunction setHours(hours, minutes, seconds) {\n\t\tif (self.selectedDates.length) {\n\t\t\tself.latestSelectedDateObj.setHours(hours % 24, minutes, seconds || 0, 0);\n\t\t}\n\n\t\tif (!self.config.enableTime || self.isMobile) return;\n\n\t\tself.hourElement.value = self.pad(!self.config.time_24hr ? (12 + hours) % 12 + 12 * (hours % 12 === 0) : hours);\n\n\t\tself.minuteElement.value = self.pad(minutes);\n\n\t\tif (!self.config.time_24hr) self.amPM.textContent = hours >= 12 ? \"PM\" : \"AM\";\n\n\t\tif (self.config.enableSeconds === true) self.secondElement.value = self.pad(seconds);\n\t}\n\n\t/**\n  * Handles the year input and incrementing events\n  * @param {Event} event the keyup or increment event\n  */\n\tfunction onYearInput(event) {\n\t\tvar year = event.target.value;\n\t\tif (event.delta) year = (parseInt(year) + event.delta).toString();\n\n\t\tif (year.length === 4 || event.key === \"Enter\") {\n\t\t\tself.currentYearElement.blur();\n\t\t\tif (!/[^\\d]/.test(year)) changeYear(year);\n\t\t}\n\t}\n\n\t/**\n  * Essentially addEventListener + tracking\n  * @param {Element} element the element to addEventListener to\n  * @param {String} event the event name\n  * @param {Function} handler the event handler\n  */\n\tfunction bind(element, event, handler) {\n\t\tif (event instanceof Array) return event.forEach(function (ev) {\n\t\t\treturn bind(element, ev, handler);\n\t\t});\n\n\t\tif (element instanceof Array) return element.forEach(function (el) {\n\t\t\treturn bind(el, event, handler);\n\t\t});\n\n\t\telement.addEventListener(event, handler);\n\t\tself._handlers.push({ element: element, event: event, handler: handler });\n\t}\n\n\t/**\n  * A mousedown handler which mimics click.\n  * Minimizes latency, since we don't need to wait for mouseup in most cases.\n  * Also, avoids handling right clicks.\n  *\n  * @param {Function} handler the event handler\n  */\n\tfunction onClick(handler) {\n\t\treturn function (evt) {\n\t\t\treturn evt.which === 1 && handler(evt);\n\t\t};\n\t}\n\n\t/**\n  * Adds all the necessary event listeners\n  */\n\tfunction bindEvents() {\n\t\tself._handlers = [];\n\t\tself._animationLoop = [];\n\t\tif (self.config.wrap) {\n\t\t\t[\"open\", \"close\", \"toggle\", \"clear\"].forEach(function (evt) {\n\t\t\t\tArray.prototype.forEach.call(self.element.querySelectorAll(\"[data-\" + evt + \"]\"), function (el) {\n\t\t\t\t\treturn bind(el, \"mousedown\", onClick(self[evt]));\n\t\t\t\t});\n\t\t\t});\n\t\t}\n\n\t\tif (self.isMobile) return setupMobile();\n\n\t\tself.debouncedResize = debounce(onResize, 50);\n\t\tself.triggerChange = function () {\n\t\t\ttriggerEvent(\"Change\");\n\t\t};\n\t\tself.debouncedChange = debounce(self.triggerChange, 300);\n\n\t\tif (self.config.mode === \"range\" && self.daysContainer) bind(self.daysContainer, \"mouseover\", function (e) {\n\t\t\treturn onMouseOver(e.target);\n\t\t});\n\n\t\tbind(window.document.body, \"keydown\", onKeyDown);\n\n\t\tif (!self.config.static) bind(self._input, \"keydown\", onKeyDown);\n\n\t\tif (!self.config.inline && !self.config.static) bind(window, \"resize\", self.debouncedResize);\n\n\t\tif (window.ontouchstart !== undefined) bind(window.document, \"touchstart\", documentClick);\n\n\t\tbind(window.document, \"mousedown\", onClick(documentClick));\n\t\tbind(self._input, \"blur\", documentClick);\n\n\t\tif (self.config.clickOpens === true) {\n\t\t\tbind(self._input, \"focus\", self.open);\n\t\t\tbind(self._input, \"mousedown\", onClick(self.open));\n\t\t}\n\n\t\tif (!self.config.noCalendar) {\n\t\t\tself.monthNav.addEventListener(\"wheel\", function (e) {\n\t\t\t\treturn e.preventDefault();\n\t\t\t});\n\t\t\tbind(self.monthNav, \"wheel\", debounce(onMonthNavScroll, 10));\n\t\t\tbind(self.monthNav, \"mousedown\", onClick(onMonthNavClick));\n\n\t\t\tbind(self.monthNav, [\"keyup\", \"increment\"], onYearInput);\n\t\t\tbind(self.daysContainer, \"mousedown\", onClick(selectDate));\n\n\t\t\tif (self.config.animate) {\n\t\t\t\tbind(self.daysContainer, [\"webkitAnimationEnd\", \"animationend\"], animateDays);\n\t\t\t\tbind(self.monthNav, [\"webkitAnimationEnd\", \"animationend\"], animateMonths);\n\t\t\t}\n\t\t}\n\n\t\tif (self.config.enableTime) {\n\t\t\tvar selText = function selText(e) {\n\t\t\t\treturn e.target.select();\n\t\t\t};\n\t\t\tbind(self.timeContainer, [\"wheel\", \"input\", \"increment\"], updateTime);\n\t\t\tbind(self.timeContainer, \"mousedown\", onClick(timeIncrement));\n\n\t\t\tbind(self.timeContainer, [\"wheel\", \"increment\"], self.debouncedChange);\n\t\t\tbind(self.timeContainer, \"input\", self.triggerChange);\n\n\t\t\tbind([self.hourElement, self.minuteElement], \"focus\", selText);\n\n\t\t\tif (self.secondElement !== undefined) bind(self.secondElement, \"focus\", function () {\n\t\t\t\treturn self.secondElement.select();\n\t\t\t});\n\n\t\t\tif (self.amPM !== undefined) {\n\t\t\t\tbind(self.amPM, \"mousedown\", onClick(function (e) {\n\t\t\t\t\tupdateTime(e);\n\t\t\t\t\tself.triggerChange(e);\n\t\t\t\t}));\n\t\t\t}\n\t\t}\n\t}\n\n\tfunction processPostDayAnimation() {\n\t\tfor (var i = self._animationLoop.length; i--;) {\n\t\t\tself._animationLoop[i]();\n\t\t\tself._animationLoop.splice(i, 1);\n\t\t}\n\t}\n\n\t/**\n  * Removes the day container that slided out of view\n  * @param {Event} e the animation event\n  */\n\tfunction animateDays(e) {\n\t\tif (self.daysContainer.childNodes.length > 1) {\n\t\t\tswitch (e.animationName) {\n\t\t\t\tcase \"fpSlideLeft\":\n\t\t\t\t\tself.daysContainer.lastChild.classList.remove(\"slideLeftNew\");\n\t\t\t\t\tself.daysContainer.removeChild(self.daysContainer.firstChild);\n\t\t\t\t\tself.days = self.daysContainer.firstChild;\n\t\t\t\t\tprocessPostDayAnimation();\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase \"fpSlideRight\":\n\t\t\t\t\tself.daysContainer.firstChild.classList.remove(\"slideRightNew\");\n\t\t\t\t\tself.daysContainer.removeChild(self.daysContainer.lastChild);\n\t\t\t\t\tself.days = self.daysContainer.firstChild;\n\t\t\t\t\tprocessPostDayAnimation();\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n  * Removes the month element that animated out of view\n  * @param {Event} e the animation event\n  */\n\tfunction animateMonths(e) {\n\t\tswitch (e.animationName) {\n\t\t\tcase \"fpSlideLeftNew\":\n\t\t\tcase \"fpSlideRightNew\":\n\t\t\t\tself.navigationCurrentMonth.classList.remove(\"slideLeftNew\");\n\t\t\t\tself.navigationCurrentMonth.classList.remove(\"slideRightNew\");\n\t\t\t\tvar nav = self.navigationCurrentMonth;\n\n\t\t\t\twhile (nav.nextSibling && /curr/.test(nav.nextSibling.className)) {\n\t\t\t\t\tself.monthNav.removeChild(nav.nextSibling);\n\t\t\t\t}while (nav.previousSibling && /curr/.test(nav.previousSibling.className)) {\n\t\t\t\t\tself.monthNav.removeChild(nav.previousSibling);\n\t\t\t\t}self.oldCurMonth = null;\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t/**\n  * Set the calendar view to a particular date.\n  * @param {Date} jumpDate the date to set the view to\n  */\n\tfunction jumpToDate(jumpDate) {\n\t\tjumpDate = jumpDate ? self.parseDate(jumpDate) : self.latestSelectedDateObj || (self.config.minDate > self.now ? self.config.minDate : self.config.maxDate && self.config.maxDate < self.now ? self.config.maxDate : self.now);\n\n\t\ttry {\n\t\t\tself.currentYear = jumpDate.getFullYear();\n\t\t\tself.currentMonth = jumpDate.getMonth();\n\t\t} catch (e) {\n\t\t\t/* istanbul ignore next */\n\t\t\tconsole.error(e.stack);\n\t\t\t/* istanbul ignore next */\n\t\t\tconsole.warn(\"Invalid date supplied: \" + jumpDate);\n\t\t}\n\n\t\tself.redraw();\n\t}\n\n\t/**\n  * The up/down arrow handler for time inputs\n  * @param {Event} e the click event\n  */\n\tfunction timeIncrement(e) {\n\t\tif (~e.target.className.indexOf(\"arrow\")) incrementNumInput(e, e.target.classList.contains(\"arrowUp\") ? 1 : -1);\n\t}\n\n\t/**\n  * Increments/decrements the value of input associ-\n  * ated with the up/down arrow by dispatching an\n  * \"increment\" event on the input.\n  *\n  * @param {Event} e the click event\n  * @param {Number} delta the diff (usually 1 or -1)\n  * @param {Element} inputElem the input element\n  */\n\tfunction incrementNumInput(e, delta, inputElem) {\n\t\tvar input = inputElem || e.target.parentNode.childNodes[0];\n\t\tvar event = createEvent(\"increment\");\n\t\tevent.delta = delta;\n\t\tinput.dispatchEvent(event);\n\t}\n\n\tfunction createNumberInput(inputClassName) {\n\t\tvar wrapper = createElement(\"div\", \"numInputWrapper\"),\n\t\t    numInput = createElement(\"input\", \"numInput \" + inputClassName),\n\t\t    arrowUp = createElement(\"span\", \"arrowUp\"),\n\t\t    arrowDown = createElement(\"span\", \"arrowDown\");\n\n\t\tnumInput.type = \"text\";\n\t\tnumInput.pattern = \"\\\\d*\";\n\n\t\twrapper.appendChild(numInput);\n\t\twrapper.appendChild(arrowUp);\n\t\twrapper.appendChild(arrowDown);\n\n\t\treturn wrapper;\n\t}\n\n\tfunction build() {\n\t\tvar fragment = window.document.createDocumentFragment();\n\t\tself.calendarContainer = createElement(\"div\", \"flatpickr-calendar\");\n\t\tself.calendarContainer.tabIndex = -1;\n\n\t\tif (!self.config.noCalendar) {\n\t\t\tfragment.appendChild(buildMonthNav());\n\t\t\tself.innerContainer = createElement(\"div\", \"flatpickr-innerContainer\");\n\n\t\t\tif (self.config.weekNumbers) self.innerContainer.appendChild(buildWeeks());\n\n\t\t\tself.rContainer = createElement(\"div\", \"flatpickr-rContainer\");\n\t\t\tself.rContainer.appendChild(buildWeekdays());\n\n\t\t\tif (!self.daysContainer) {\n\t\t\t\tself.daysContainer = createElement(\"div\", \"flatpickr-days\");\n\t\t\t\tself.daysContainer.tabIndex = -1;\n\t\t\t}\n\n\t\t\tbuildDays();\n\t\t\tself.rContainer.appendChild(self.daysContainer);\n\n\t\t\tself.innerContainer.appendChild(self.rContainer);\n\t\t\tfragment.appendChild(self.innerContainer);\n\t\t}\n\n\t\tif (self.config.enableTime) fragment.appendChild(buildTime());\n\n\t\ttoggleClass(self.calendarContainer, \"rangeMode\", self.config.mode === \"range\");\n\t\ttoggleClass(self.calendarContainer, \"animate\", self.config.animate);\n\n\t\tself.calendarContainer.appendChild(fragment);\n\n\t\tvar customAppend = self.config.appendTo && self.config.appendTo.nodeType;\n\n\t\tif (self.config.inline || self.config.static) {\n\t\t\tself.calendarContainer.classList.add(self.config.inline ? \"inline\" : \"static\");\n\n\t\t\tif (self.config.inline && !customAppend) {\n\t\t\t\treturn self.element.parentNode.insertBefore(self.calendarContainer, self._input.nextSibling);\n\t\t\t}\n\n\t\t\tif (self.config.static) {\n\t\t\t\tvar wrapper = createElement(\"div\", \"flatpickr-wrapper\");\n\t\t\t\tself.element.parentNode.insertBefore(wrapper, self.element);\n\t\t\t\twrapper.appendChild(self.element);\n\n\t\t\t\tif (self.altInput) wrapper.appendChild(self.altInput);\n\n\t\t\t\twrapper.appendChild(self.calendarContainer);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t(customAppend ? self.config.appendTo : window.document.body).appendChild(self.calendarContainer);\n\t}\n\n\tfunction createDay(className, date, dayNumber, i) {\n\t\tvar dateIsEnabled = isEnabled(date, true),\n\t\t    dayElement = createElement(\"span\", \"flatpickr-day \" + className, date.getDate());\n\n\t\tdayElement.dateObj = date;\n\t\tdayElement.$i = i;\n\t\tdayElement.setAttribute(\"aria-label\", self.formatDate(date, self.config.ariaDateFormat));\n\n\t\tif (compareDates(date, self.now) === 0) {\n\t\t\tself.todayDateElem = dayElement;\n\t\t\tdayElement.classList.add(\"today\");\n\t\t}\n\n\t\tif (dateIsEnabled) {\n\t\t\tdayElement.tabIndex = -1;\n\t\t\tif (isDateSelected(date)) {\n\t\t\t\tdayElement.classList.add(\"selected\");\n\t\t\t\tself.selectedDateElem = dayElement;\n\t\t\t\tif (self.config.mode === \"range\") {\n\t\t\t\t\ttoggleClass(dayElement, \"startRange\", compareDates(date, self.selectedDates[0]) === 0);\n\n\t\t\t\t\ttoggleClass(dayElement, \"endRange\", compareDates(date, self.selectedDates[1]) === 0);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tdayElement.classList.add(\"disabled\");\n\t\t\tif (self.selectedDates[0] && date > self.minRangeDate && date < self.selectedDates[0]) self.minRangeDate = date;else if (self.selectedDates[0] && date < self.maxRangeDate && date > self.selectedDates[0]) self.maxRangeDate = date;\n\t\t}\n\n\t\tif (self.config.mode === \"range\") {\n\t\t\tif (isDateInRange(date) && !isDateSelected(date)) dayElement.classList.add(\"inRange\");\n\n\t\t\tif (self.selectedDates.length === 1 && (date < self.minRangeDate || date > self.maxRangeDate)) dayElement.classList.add(\"notAllowed\");\n\t\t}\n\n\t\tif (self.config.weekNumbers && className !== \"prevMonthDay\" && dayNumber % 7 === 1) {\n\t\t\tself.weekNumbers.insertAdjacentHTML(\"beforeend\", \"<span class='disabled flatpickr-day'>\" + self.config.getWeek(date) + \"</span>\");\n\t\t}\n\n\t\ttriggerEvent(\"DayCreate\", dayElement);\n\n\t\treturn dayElement;\n\t}\n\n\tfunction focusOnDay(currentIndex, offset) {\n\t\tvar newIndex = currentIndex + offset || 0,\n\t\t    targetNode = currentIndex !== undefined ? self.days.childNodes[newIndex] : self.selectedDateElem || self.todayDateElem || self.days.childNodes[0],\n\t\t    focus = function focus() {\n\t\t\ttargetNode = targetNode || self.days.childNodes[newIndex];\n\t\t\ttargetNode.focus();\n\n\t\t\tif (self.config.mode === \"range\") onMouseOver(targetNode);\n\t\t};\n\n\t\tif (targetNode === undefined && offset !== 0) {\n\t\t\tif (offset > 0) {\n\t\t\t\tself.changeMonth(1);\n\t\t\t\tnewIndex = newIndex % 42;\n\t\t\t} else if (offset < 0) {\n\t\t\t\tself.changeMonth(-1);\n\t\t\t\tnewIndex += 42;\n\t\t\t}\n\n\t\t\treturn afterDayAnim(focus);\n\t\t}\n\n\t\tfocus();\n\t}\n\n\tfunction afterDayAnim(fn) {\n\t\tif (self.config.animate === true) return self._animationLoop.push(fn);\n\t\tfn();\n\t}\n\n\tfunction buildDays(delta) {\n\t\tvar firstOfMonth = (new Date(self.currentYear, self.currentMonth, 1).getDay() - self.l10n.firstDayOfWeek + 7) % 7,\n\t\t    isRangeMode = self.config.mode === \"range\";\n\n\t\tself.prevMonthDays = self.utils.getDaysinMonth((self.currentMonth - 1 + 12) % 12);\n\t\tself.selectedDateElem = undefined;\n\t\tself.todayDateElem = undefined;\n\n\t\tvar daysInMonth = self.utils.getDaysinMonth(),\n\t\t    days = window.document.createDocumentFragment();\n\n\t\tvar dayNumber = self.prevMonthDays + 1 - firstOfMonth,\n\t\t    dayIndex = 0;\n\n\t\tif (self.config.weekNumbers && self.weekNumbers.firstChild) self.weekNumbers.textContent = \"\";\n\n\t\tif (isRangeMode) {\n\t\t\t// const dateLimits = self.config.enable.length || self.config.disable.length || self.config.mixDate || self.config.maxDate;\n\t\t\tself.minRangeDate = new Date(self.currentYear, self.currentMonth - 1, dayNumber);\n\t\t\tself.maxRangeDate = new Date(self.currentYear, self.currentMonth + 1, (42 - firstOfMonth) % daysInMonth);\n\t\t}\n\n\t\t// prepend days from the ending of previous month\n\t\tfor (; dayNumber <= self.prevMonthDays; dayNumber++, dayIndex++) {\n\t\t\tdays.appendChild(createDay(\"prevMonthDay\", new Date(self.currentYear, self.currentMonth - 1, dayNumber), dayNumber, dayIndex));\n\t\t}\n\n\t\t// Start at 1 since there is no 0th day\n\t\tfor (dayNumber = 1; dayNumber <= daysInMonth; dayNumber++, dayIndex++) {\n\t\t\tdays.appendChild(createDay(\"\", new Date(self.currentYear, self.currentMonth, dayNumber), dayNumber, dayIndex));\n\t\t}\n\n\t\t// append days from the next month\n\t\tfor (var dayNum = daysInMonth + 1; dayNum <= 42 - firstOfMonth; dayNum++, dayIndex++) {\n\t\t\tdays.appendChild(createDay(\"nextMonthDay\", new Date(self.currentYear, self.currentMonth + 1, dayNum % daysInMonth), dayNum, dayIndex));\n\t\t}\n\n\t\tif (isRangeMode && self.selectedDates.length === 1 && days.childNodes[0]) {\n\t\t\tself._hidePrevMonthArrow = self._hidePrevMonthArrow || self.minRangeDate > days.childNodes[0].dateObj;\n\n\t\t\tself._hideNextMonthArrow = self._hideNextMonthArrow || self.maxRangeDate < new Date(self.currentYear, self.currentMonth + 1, 1);\n\t\t} else updateNavigationCurrentMonth();\n\n\t\tvar dayContainer = createElement(\"div\", \"dayContainer\");\n\t\tdayContainer.appendChild(days);\n\n\t\tif (!self.config.animate || delta === undefined) clearNode(self.daysContainer);else {\n\t\t\twhile (self.daysContainer.childNodes.length > 1) {\n\t\t\t\tself.daysContainer.removeChild(self.daysContainer.firstChild);\n\t\t\t}\n\t\t}\n\n\t\tif (delta >= 0) self.daysContainer.appendChild(dayContainer);else self.daysContainer.insertBefore(dayContainer, self.daysContainer.firstChild);\n\n\t\tself.days = self.daysContainer.firstChild;\n\t\treturn self.daysContainer;\n\t}\n\n\tfunction clearNode(node) {\n\t\twhile (node.firstChild) {\n\t\t\tnode.removeChild(node.firstChild);\n\t\t}\n\t}\n\n\tfunction buildMonthNav() {\n\t\tvar monthNavFragment = window.document.createDocumentFragment();\n\t\tself.monthNav = createElement(\"div\", \"flatpickr-month\");\n\n\t\tself.prevMonthNav = createElement(\"span\", \"flatpickr-prev-month\");\n\t\tself.prevMonthNav.innerHTML = self.config.prevArrow;\n\n\t\tself.currentMonthElement = createElement(\"span\", \"cur-month\");\n\t\tself.currentMonthElement.title = self.l10n.scrollTitle;\n\n\t\tvar yearInput = createNumberInput(\"cur-year\");\n\t\tself.currentYearElement = yearInput.childNodes[0];\n\t\tself.currentYearElement.title = self.l10n.scrollTitle;\n\n\t\tif (self.config.minDate) self.currentYearElement.min = self.config.minDate.getFullYear();\n\n\t\tif (self.config.maxDate) {\n\t\t\tself.currentYearElement.max = self.config.maxDate.getFullYear();\n\n\t\t\tself.currentYearElement.disabled = self.config.minDate && self.config.minDate.getFullYear() === self.config.maxDate.getFullYear();\n\t\t}\n\n\t\tself.nextMonthNav = createElement(\"span\", \"flatpickr-next-month\");\n\t\tself.nextMonthNav.innerHTML = self.config.nextArrow;\n\n\t\tself.navigationCurrentMonth = createElement(\"span\", \"flatpickr-current-month\");\n\t\tself.navigationCurrentMonth.appendChild(self.currentMonthElement);\n\t\tself.navigationCurrentMonth.appendChild(yearInput);\n\n\t\tmonthNavFragment.appendChild(self.prevMonthNav);\n\t\tmonthNavFragment.appendChild(self.navigationCurrentMonth);\n\t\tmonthNavFragment.appendChild(self.nextMonthNav);\n\t\tself.monthNav.appendChild(monthNavFragment);\n\n\t\tObject.defineProperty(self, \"_hidePrevMonthArrow\", {\n\t\t\tget: function get() {\n\t\t\t\treturn this.__hidePrevMonthArrow;\n\t\t\t},\n\t\t\tset: function set(bool) {\n\t\t\t\tif (this.__hidePrevMonthArrow !== bool) self.prevMonthNav.style.display = bool ? \"none\" : \"block\";\n\t\t\t\tthis.__hidePrevMonthArrow = bool;\n\t\t\t}\n\t\t});\n\n\t\tObject.defineProperty(self, \"_hideNextMonthArrow\", {\n\t\t\tget: function get() {\n\t\t\t\treturn this.__hideNextMonthArrow;\n\t\t\t},\n\t\t\tset: function set(bool) {\n\t\t\t\tif (this.__hideNextMonthArrow !== bool) self.nextMonthNav.style.display = bool ? \"none\" : \"block\";\n\t\t\t\tthis.__hideNextMonthArrow = bool;\n\t\t\t}\n\t\t});\n\n\t\tupdateNavigationCurrentMonth();\n\n\t\treturn self.monthNav;\n\t}\n\n\tfunction buildTime() {\n\t\tself.calendarContainer.classList.add(\"hasTime\");\n\t\tif (self.config.noCalendar) self.calendarContainer.classList.add(\"noCalendar\");\n\t\tself.timeContainer = createElement(\"div\", \"flatpickr-time\");\n\t\tself.timeContainer.tabIndex = -1;\n\t\tvar separator = createElement(\"span\", \"flatpickr-time-separator\", \":\");\n\n\t\tvar hourInput = createNumberInput(\"flatpickr-hour\");\n\t\tself.hourElement = hourInput.childNodes[0];\n\n\t\tvar minuteInput = createNumberInput(\"flatpickr-minute\");\n\t\tself.minuteElement = minuteInput.childNodes[0];\n\n\t\tself.hourElement.tabIndex = self.minuteElement.tabIndex = -1;\n\n\t\tself.hourElement.value = self.pad(self.latestSelectedDateObj ? self.latestSelectedDateObj.getHours() : self.config.defaultHour);\n\n\t\tself.minuteElement.value = self.pad(self.latestSelectedDateObj ? self.latestSelectedDateObj.getMinutes() : self.config.defaultMinute);\n\n\t\tself.hourElement.step = self.config.hourIncrement;\n\t\tself.minuteElement.step = self.config.minuteIncrement;\n\n\t\tself.hourElement.min = self.config.time_24hr ? 0 : 1;\n\t\tself.hourElement.max = self.config.time_24hr ? 23 : 12;\n\n\t\tself.minuteElement.min = 0;\n\t\tself.minuteElement.max = 59;\n\n\t\tself.hourElement.title = self.minuteElement.title = self.l10n.scrollTitle;\n\n\t\tself.timeContainer.appendChild(hourInput);\n\t\tself.timeContainer.appendChild(separator);\n\t\tself.timeContainer.appendChild(minuteInput);\n\n\t\tif (self.config.time_24hr) self.timeContainer.classList.add(\"time24hr\");\n\n\t\tif (self.config.enableSeconds) {\n\t\t\tself.timeContainer.classList.add(\"hasSeconds\");\n\n\t\t\tvar secondInput = createNumberInput(\"flatpickr-second\");\n\t\t\tself.secondElement = secondInput.childNodes[0];\n\n\t\t\tself.secondElement.value = self.latestSelectedDateObj ? self.pad(self.latestSelectedDateObj.getSeconds()) : \"00\";\n\n\t\t\tself.secondElement.step = self.minuteElement.step;\n\t\t\tself.secondElement.min = self.minuteElement.min;\n\t\t\tself.secondElement.max = self.minuteElement.max;\n\n\t\t\tself.timeContainer.appendChild(createElement(\"span\", \"flatpickr-time-separator\", \":\"));\n\t\t\tself.timeContainer.appendChild(secondInput);\n\t\t}\n\n\t\tif (!self.config.time_24hr) {\n\t\t\t// add self.amPM if appropriate\n\t\t\tself.amPM = createElement(\"span\", \"flatpickr-am-pm\", [\"AM\", \"PM\"][self.hourElement.value > 11 | 0]);\n\t\t\tself.amPM.title = self.l10n.toggleTitle;\n\t\t\tself.amPM.tabIndex = -1;\n\t\t\tself.timeContainer.appendChild(self.amPM);\n\t\t}\n\n\t\treturn self.timeContainer;\n\t}\n\n\tfunction buildWeekdays() {\n\t\tif (!self.weekdayContainer) self.weekdayContainer = createElement(\"div\", \"flatpickr-weekdays\");\n\n\t\tvar firstDayOfWeek = self.l10n.firstDayOfWeek;\n\t\tvar weekdays = self.l10n.weekdays.shorthand.slice();\n\n\t\tif (firstDayOfWeek > 0 && firstDayOfWeek < weekdays.length) {\n\t\t\tweekdays = [].concat(weekdays.splice(firstDayOfWeek, weekdays.length), weekdays.splice(0, firstDayOfWeek));\n\t\t}\n\n\t\tself.weekdayContainer.innerHTML = \"\\n\\t\\t<span class=flatpickr-weekday>\\n\\t\\t\\t\" + weekdays.join(\"</span><span class=flatpickr-weekday>\") + \"\\n\\t\\t</span>\\n\\t\\t\";\n\n\t\treturn self.weekdayContainer;\n\t}\n\n\t/* istanbul ignore next */\n\tfunction buildWeeks() {\n\t\tself.calendarContainer.classList.add(\"hasWeeks\");\n\t\tself.weekWrapper = createElement(\"div\", \"flatpickr-weekwrapper\");\n\t\tself.weekWrapper.appendChild(createElement(\"span\", \"flatpickr-weekday\", self.l10n.weekAbbreviation));\n\t\tself.weekNumbers = createElement(\"div\", \"flatpickr-weeks\");\n\t\tself.weekWrapper.appendChild(self.weekNumbers);\n\n\t\treturn self.weekWrapper;\n\t}\n\n\tfunction changeMonth(value, is_offset, animate) {\n\t\tis_offset = is_offset === undefined || is_offset;\n\t\tvar delta = is_offset ? value : value - self.currentMonth;\n\t\tvar skipAnimations = !self.config.animate || animate === false;\n\n\t\tif (delta < 0 && self._hidePrevMonthArrow || delta > 0 && self._hideNextMonthArrow) return;\n\n\t\tself.currentMonth += delta;\n\n\t\tif (self.currentMonth < 0 || self.currentMonth > 11) {\n\t\t\tself.currentYear += self.currentMonth > 11 ? 1 : -1;\n\t\t\tself.currentMonth = (self.currentMonth + 12) % 12;\n\n\t\t\ttriggerEvent(\"YearChange\");\n\t\t}\n\n\t\tbuildDays(!skipAnimations ? delta : undefined);\n\n\t\tif (skipAnimations) {\n\t\t\ttriggerEvent(\"MonthChange\");\n\t\t\treturn updateNavigationCurrentMonth();\n\t\t}\n\n\t\t// remove possible remnants from clicking too fast\n\t\tvar nav = self.navigationCurrentMonth;\n\t\tif (delta < 0) {\n\t\t\twhile (nav.nextSibling && /curr/.test(nav.nextSibling.className)) {\n\t\t\t\tself.monthNav.removeChild(nav.nextSibling);\n\t\t\t}\n\t\t} else if (delta > 0) {\n\t\t\twhile (nav.previousSibling && /curr/.test(nav.previousSibling.className)) {\n\t\t\t\tself.monthNav.removeChild(nav.previousSibling);\n\t\t\t}\n\t\t}\n\n\t\tself.oldCurMonth = self.navigationCurrentMonth;\n\n\t\tself.navigationCurrentMonth = self.monthNav.insertBefore(self.oldCurMonth.cloneNode(true), delta > 0 ? self.oldCurMonth.nextSibling : self.oldCurMonth);\n\n\t\tif (delta > 0) {\n\t\t\tself.daysContainer.firstChild.classList.add(\"slideLeft\");\n\t\t\tself.daysContainer.lastChild.classList.add(\"slideLeftNew\");\n\n\t\t\tself.oldCurMonth.classList.add(\"slideLeft\");\n\t\t\tself.navigationCurrentMonth.classList.add(\"slideLeftNew\");\n\t\t} else if (delta < 0) {\n\t\t\tself.daysContainer.firstChild.classList.add(\"slideRightNew\");\n\t\t\tself.daysContainer.lastChild.classList.add(\"slideRight\");\n\n\t\t\tself.oldCurMonth.classList.add(\"slideRight\");\n\t\t\tself.navigationCurrentMonth.classList.add(\"slideRightNew\");\n\t\t}\n\n\t\tself.currentMonthElement = self.navigationCurrentMonth.firstChild;\n\t\tself.currentYearElement = self.navigationCurrentMonth.lastChild.childNodes[0];\n\n\t\tupdateNavigationCurrentMonth();\n\t\tself.oldCurMonth.firstChild.textContent = self.utils.monthToStr(self.currentMonth - delta);\n\n\t\ttriggerEvent(\"MonthChange\");\n\n\t\tif (document.activeElement && document.activeElement.$i) {\n\t\t\tvar index = document.activeElement.$i;\n\t\t\tafterDayAnim(function () {\n\t\t\t\tfocusOnDay(index, 0);\n\t\t\t});\n\t\t}\n\t}\n\n\tfunction clear(triggerChangeEvent) {\n\t\tself.input.value = \"\";\n\n\t\tif (self.altInput) self.altInput.value = \"\";\n\n\t\tif (self.mobileInput) self.mobileInput.value = \"\";\n\n\t\tself.selectedDates = [];\n\t\tself.latestSelectedDateObj = undefined;\n\t\tself.showTimeInput = false;\n\n\t\tself.redraw();\n\n\t\tif (triggerChangeEvent !== false)\n\t\t\t// triggerChangeEvent is true (default) or an Event\n\t\t\ttriggerEvent(\"Change\");\n\t}\n\n\tfunction close() {\n\t\tself.isOpen = false;\n\n\t\tif (!self.isMobile) {\n\t\t\tself.calendarContainer.classList.remove(\"open\");\n\t\t\tself._input.classList.remove(\"active\");\n\t\t}\n\n\t\ttriggerEvent(\"Close\");\n\t}\n\n\tfunction destroy() {\n\t\tif (self.config !== undefined) triggerEvent(\"Destroy\");\n\n\t\tfor (var i = self._handlers.length; i--;) {\n\t\t\tvar h = self._handlers[i];\n\t\t\th.element.removeEventListener(h.event, h.handler);\n\t\t}\n\n\t\tself._handlers = [];\n\n\t\tif (self.mobileInput) {\n\t\t\tif (self.mobileInput.parentNode) self.mobileInput.parentNode.removeChild(self.mobileInput);\n\t\t\tself.mobileInput = null;\n\t\t} else if (self.calendarContainer && self.calendarContainer.parentNode) self.calendarContainer.parentNode.removeChild(self.calendarContainer);\n\n\t\tif (self.altInput) {\n\t\t\tself.input.type = \"text\";\n\t\t\tif (self.altInput.parentNode) self.altInput.parentNode.removeChild(self.altInput);\n\t\t\tdelete self.altInput;\n\t\t}\n\n\t\tif (self.input) {\n\t\t\tself.input.type = self.input._type;\n\t\t\tself.input.classList.remove(\"flatpickr-input\");\n\t\t\tself.input.removeAttribute(\"readonly\");\n\t\t\tself.input.value = \"\";\n\t\t}\n\n\t\t[\"_showTimeInput\", \"latestSelectedDateObj\", \"_hideNextMonthArrow\", \"_hidePrevMonthArrow\", \"__hideNextMonthArrow\", \"__hidePrevMonthArrow\", \"isMobile\", \"isOpen\", \"selectedDateElem\", \"minDateHasTime\", \"maxDateHasTime\", \"days\", \"daysContainer\", \"_input\", \"_positionElement\", \"innerContainer\", \"rContainer\", \"monthNav\", \"todayDateElem\", \"calendarContainer\", \"weekdayContainer\", \"prevMonthNav\", \"nextMonthNav\", \"currentMonthElement\", \"currentYearElement\", \"navigationCurrentMonth\", \"selectedDateElem\", \"config\"].forEach(function (k) {\n\t\t\treturn delete self[k];\n\t\t});\n\t}\n\n\tfunction isCalendarElem(elem) {\n\t\tif (self.config.appendTo && self.config.appendTo.contains(elem)) return true;\n\n\t\treturn self.calendarContainer.contains(elem);\n\t}\n\n\tfunction documentClick(e) {\n\t\tif (self.isOpen && !self.config.inline) {\n\t\t\tvar isCalendarElement = isCalendarElem(e.target);\n\t\t\tvar isInput = e.target === self.input || e.target === self.altInput || self.element.contains(e.target) ||\n\t\t\t// web components\n\t\t\te.path && e.path.indexOf && (~e.path.indexOf(self.input) || ~e.path.indexOf(self.altInput));\n\n\t\t\tvar lostFocus = e.type === \"blur\" ? isInput && e.relatedTarget && !isCalendarElem(e.relatedTarget) : !isInput && !isCalendarElement;\n\n\t\t\tif (lostFocus && self.config.ignoredFocusElements.indexOf(e.target) === -1) {\n\t\t\t\tself.close();\n\n\t\t\t\tif (self.config.mode === \"range\" && self.selectedDates.length === 1) {\n\t\t\t\t\tself.clear(false);\n\t\t\t\t\tself.redraw();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tfunction changeYear(newYear) {\n\t\tif (!newYear || self.currentYearElement.min && newYear < self.currentYearElement.min || self.currentYearElement.max && newYear > self.currentYearElement.max) return;\n\n\t\tvar newYearNum = parseInt(newYear, 10),\n\t\t    isNewYear = self.currentYear !== newYearNum;\n\n\t\tself.currentYear = newYearNum || self.currentYear;\n\n\t\tif (self.config.maxDate && self.currentYear === self.config.maxDate.getFullYear()) {\n\t\t\tself.currentMonth = Math.min(self.config.maxDate.getMonth(), self.currentMonth);\n\t\t} else if (self.config.minDate && self.currentYear === self.config.minDate.getFullYear()) {\n\t\t\tself.currentMonth = Math.max(self.config.minDate.getMonth(), self.currentMonth);\n\t\t}\n\n\t\tif (isNewYear) {\n\t\t\tself.redraw();\n\t\t\ttriggerEvent(\"YearChange\");\n\t\t}\n\t}\n\n\tfunction isEnabled(date, timeless) {\n\t\tif (self.config.minDate && compareDates(date, self.config.minDate, timeless !== undefined ? timeless : !self.minDateHasTime) < 0 || self.config.maxDate && compareDates(date, self.config.maxDate, timeless !== undefined ? timeless : !self.maxDateHasTime) > 0) return false;\n\n\t\tif (!self.config.enable.length && !self.config.disable.length) return true;\n\n\t\tvar dateToCheck = self.parseDate(date, null, true); // timeless\n\n\t\tvar bool = self.config.enable.length > 0,\n\t\t    array = bool ? self.config.enable : self.config.disable;\n\n\t\tfor (var i = 0, d; i < array.length; i++) {\n\t\t\td = array[i];\n\n\t\t\tif (d instanceof Function && d(dateToCheck)) // disabled by function\n\t\t\t\treturn bool;else if (d instanceof Date && d.getTime() === dateToCheck.getTime())\n\t\t\t\t// disabled by date\n\t\t\t\treturn bool;else if (typeof d === \"string\" && self.parseDate(d, null, true).getTime() === dateToCheck.getTime())\n\t\t\t\t// disabled by date string\n\t\t\t\treturn bool;else if ( // disabled by range\n\t\t\t(typeof d === \"undefined\" ? \"undefined\" : _typeof(d)) === \"object\" && d.from && d.to && dateToCheck >= d.from && dateToCheck <= d.to) return bool;\n\t\t}\n\n\t\treturn !bool;\n\t}\n\n\tfunction onKeyDown(e) {\n\t\tvar isInput = e.target === self._input;\n\t\tvar calendarElem = isCalendarElem(e.target);\n\t\tvar allowInput = self.config.allowInput;\n\t\tvar allowKeydown = self.isOpen && (!allowInput || !isInput);\n\t\tvar allowInlineKeydown = self.config.inline && isInput && !allowInput;\n\n\t\tif (e.key === \"Enter\" && allowInput && isInput) {\n\t\t\tself.setDate(self._input.value, true, e.target === self.altInput ? self.config.altFormat : self.config.dateFormat);\n\t\t\treturn e.target.blur();\n\t\t} else if (calendarElem || allowKeydown || allowInlineKeydown) {\n\t\t\tvar isTimeObj = self.timeContainer && self.timeContainer.contains(e.target);\n\t\t\tswitch (e.key) {\n\t\t\t\tcase \"Enter\":\n\t\t\t\t\tif (isTimeObj) updateValue();else selectDate(e);\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase \"Escape\":\n\t\t\t\t\t// escape\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\tself.close();\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase \"ArrowLeft\":\n\t\t\t\tcase \"ArrowRight\":\n\t\t\t\t\tif (!isTimeObj) {\n\t\t\t\t\t\te.preventDefault();\n\n\t\t\t\t\t\tif (self.daysContainer) {\n\t\t\t\t\t\t\tvar _delta = e.key === \"ArrowRight\" ? 1 : -1;\n\n\t\t\t\t\t\t\tif (!e.ctrlKey) focusOnDay(e.target.$i, _delta);else changeMonth(_delta, true);\n\t\t\t\t\t\t} else if (self.config.enableTime && !isTimeObj) self.hourElement.focus();\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase \"ArrowUp\":\n\t\t\t\tcase \"ArrowDown\":\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\tvar delta = e.key === \"ArrowDown\" ? 1 : -1;\n\n\t\t\t\t\tif (self.daysContainer) {\n\t\t\t\t\t\tif (e.ctrlKey) {\n\t\t\t\t\t\t\tchangeYear(self.currentYear - delta);\n\t\t\t\t\t\t\tfocusOnDay(e.target.$i, 0);\n\t\t\t\t\t\t} else if (!isTimeObj) focusOnDay(e.target.$i, delta * 7);\n\t\t\t\t\t} else if (self.config.enableTime) {\n\t\t\t\t\t\tif (!isTimeObj) self.hourElement.focus();\n\t\t\t\t\t\tupdateTime(e);\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase \"Tab\":\n\t\t\t\t\tif (e.target === self.hourElement) {\n\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\tself.minuteElement.select();\n\t\t\t\t\t} else if (e.target === self.minuteElement && (self.secondElement || self.amPM)) {\n\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\t(self.secondElement || self.amPM).focus();\n\t\t\t\t\t} else if (e.target === self.secondElement) {\n\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\tself.amPM.focus();\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase \"a\":\n\t\t\t\t\tif (e.target === self.amPM) {\n\t\t\t\t\t\tself.amPM.textContent = \"AM\";\n\t\t\t\t\t\tsetHoursFromInputs();\n\t\t\t\t\t\tupdateValue();\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase \"p\":\n\t\t\t\t\tif (e.target === self.amPM) {\n\t\t\t\t\t\tself.amPM.textContent = \"PM\";\n\t\t\t\t\t\tsetHoursFromInputs();\n\t\t\t\t\t\tupdateValue();\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\n\t\t\t}\n\n\t\t\ttriggerEvent(\"KeyDown\", e);\n\t\t}\n\t}\n\n\tfunction onMouseOver(elem) {\n\t\tif (self.selectedDates.length !== 1 || !elem.classList.contains(\"flatpickr-day\")) return;\n\n\t\tvar hoverDate = elem.dateObj,\n\t\t    initialDate = self.parseDate(self.selectedDates[0], null, true),\n\t\t    rangeStartDate = Math.min(hoverDate.getTime(), self.selectedDates[0].getTime()),\n\t\t    rangeEndDate = Math.max(hoverDate.getTime(), self.selectedDates[0].getTime()),\n\t\t    containsDisabled = false;\n\n\t\tfor (var t = rangeStartDate; t < rangeEndDate; t += self.utils.duration.DAY) {\n\t\t\tif (!isEnabled(new Date(t))) {\n\t\t\t\tcontainsDisabled = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tvar _loop = function _loop(timestamp, i) {\n\t\t\tvar outOfRange = timestamp < self.minRangeDate.getTime() || timestamp > self.maxRangeDate.getTime(),\n\t\t\t    dayElem = self.days.childNodes[i];\n\n\t\t\tif (outOfRange) {\n\t\t\t\tself.days.childNodes[i].classList.add(\"notAllowed\");\n\t\t\t\t[\"inRange\", \"startRange\", \"endRange\"].forEach(function (c) {\n\t\t\t\t\tdayElem.classList.remove(c);\n\t\t\t\t});\n\t\t\t\treturn \"continue\";\n\t\t\t} else if (containsDisabled && !outOfRange) return \"continue\";\n\n\t\t\t[\"startRange\", \"inRange\", \"endRange\", \"notAllowed\"].forEach(function (c) {\n\t\t\t\tdayElem.classList.remove(c);\n\t\t\t});\n\n\t\t\tvar minRangeDate = Math.max(self.minRangeDate.getTime(), rangeStartDate),\n\t\t\t    maxRangeDate = Math.min(self.maxRangeDate.getTime(), rangeEndDate);\n\n\t\t\telem.classList.add(hoverDate < self.selectedDates[0] ? \"startRange\" : \"endRange\");\n\n\t\t\tif (initialDate < hoverDate && timestamp === initialDate.getTime()) dayElem.classList.add(\"startRange\");else if (initialDate > hoverDate && timestamp === initialDate.getTime()) dayElem.classList.add(\"endRange\");\n\n\t\t\tif (timestamp >= minRangeDate && timestamp <= maxRangeDate) dayElem.classList.add(\"inRange\");\n\t\t};\n\n\t\tfor (var timestamp = self.days.childNodes[0].dateObj.getTime(), i = 0; i < 42; i++, timestamp += self.utils.duration.DAY) {\n\t\t\tvar _ret = _loop(timestamp, i);\n\n\t\t\tif (_ret === \"continue\") continue;\n\t\t}\n\t}\n\n\tfunction onResize() {\n\t\tif (self.isOpen && !self.config.static && !self.config.inline) positionCalendar();\n\t}\n\n\tfunction open(e, positionElement) {\n\t\tif (self.isMobile) {\n\t\t\tif (e) {\n\t\t\t\te.preventDefault();\n\t\t\t\te.target.blur();\n\t\t\t}\n\n\t\t\tsetTimeout(function () {\n\t\t\t\tself.mobileInput.click();\n\t\t\t}, 0);\n\n\t\t\ttriggerEvent(\"Open\");\n\t\t\treturn;\n\t\t}\n\n\t\tif (self.isOpen || self._input.disabled || self.config.inline) return;\n\n\t\tself.isOpen = true;\n\t\tself.calendarContainer.classList.add(\"open\");\n\t\tpositionCalendar(positionElement);\n\t\tself._input.classList.add(\"active\");\n\n\t\ttriggerEvent(\"Open\");\n\t}\n\n\tfunction minMaxDateSetter(type) {\n\t\treturn function (date) {\n\t\t\tvar dateObj = self.config[\"_\" + type + \"Date\"] = self.parseDate(date);\n\n\t\t\tvar inverseDateObj = self.config[\"_\" + (type === \"min\" ? \"max\" : \"min\") + \"Date\"];\n\t\t\tvar isValidDate = date && dateObj instanceof Date;\n\n\t\t\tif (isValidDate) {\n\t\t\t\tself[type + \"DateHasTime\"] = dateObj.getHours() || dateObj.getMinutes() || dateObj.getSeconds();\n\t\t\t}\n\n\t\t\tif (self.selectedDates) {\n\t\t\t\tself.selectedDates = self.selectedDates.filter(function (d) {\n\t\t\t\t\treturn isEnabled(d);\n\t\t\t\t});\n\t\t\t\tif (!self.selectedDates.length && type === \"min\") setHoursFromDate(dateObj);\n\t\t\t\tupdateValue();\n\t\t\t}\n\n\t\t\tif (self.daysContainer) {\n\t\t\t\tredraw();\n\n\t\t\t\tif (isValidDate) self.currentYearElement[type] = dateObj.getFullYear();else self.currentYearElement.removeAttribute(type);\n\n\t\t\t\tself.currentYearElement.disabled = inverseDateObj && dateObj && inverseDateObj.getFullYear() === dateObj.getFullYear();\n\t\t\t}\n\t\t};\n\t}\n\n\tfunction parseConfig() {\n\t\tvar boolOpts = [\"wrap\", \"weekNumbers\", \"allowInput\", \"clickOpens\", \"time_24hr\", \"enableTime\", \"noCalendar\", \"altInput\", \"shorthandCurrentMonth\", \"inline\", \"static\", \"enableSeconds\", \"disableMobile\"];\n\n\t\tvar hooks = [\"onChange\", \"onClose\", \"onDayCreate\", \"onDestroy\", \"onKeyDown\", \"onMonthChange\", \"onOpen\", \"onParseConfig\", \"onReady\", \"onValueUpdate\", \"onYearChange\"];\n\n\t\tself.config = Object.create(flatpickr.defaultConfig);\n\n\t\tvar userConfig = _extends({}, self.instanceConfig, JSON.parse(JSON.stringify(self.element.dataset || {})));\n\n\t\tself.config.parseDate = userConfig.parseDate;\n\t\tself.config.formatDate = userConfig.formatDate;\n\n\t\tObject.defineProperty(self.config, \"enable\", {\n\t\t\tget: function get() {\n\t\t\t\treturn self.config._enable || [];\n\t\t\t},\n\t\t\tset: function set(dates) {\n\t\t\t\treturn self.config._enable = parseDateRules(dates);\n\t\t\t}\n\t\t});\n\n\t\tObject.defineProperty(self.config, \"disable\", {\n\t\t\tget: function get() {\n\t\t\t\treturn self.config._disable || [];\n\t\t\t},\n\t\t\tset: function set(dates) {\n\t\t\t\treturn self.config._disable = parseDateRules(dates);\n\t\t\t}\n\t\t});\n\n\t\t_extends(self.config, userConfig);\n\n\t\tif (!userConfig.dateFormat && userConfig.enableTime) {\n\t\t\tself.config.dateFormat = self.config.noCalendar ? \"H:i\" + (self.config.enableSeconds ? \":S\" : \"\") : flatpickr.defaultConfig.dateFormat + \" H:i\" + (self.config.enableSeconds ? \":S\" : \"\");\n\t\t}\n\n\t\tif (userConfig.altInput && userConfig.enableTime && !userConfig.altFormat) {\n\t\t\tself.config.altFormat = self.config.noCalendar ? \"h:i\" + (self.config.enableSeconds ? \":S K\" : \" K\") : flatpickr.defaultConfig.altFormat + (\" h:i\" + (self.config.enableSeconds ? \":S\" : \"\") + \" K\");\n\t\t}\n\n\t\tObject.defineProperty(self.config, \"minDate\", {\n\t\t\tget: function get() {\n\t\t\t\treturn this._minDate;\n\t\t\t},\n\t\t\tset: minMaxDateSetter(\"min\")\n\t\t});\n\n\t\tObject.defineProperty(self.config, \"maxDate\", {\n\t\t\tget: function get() {\n\t\t\t\treturn this._maxDate;\n\t\t\t},\n\t\t\tset: minMaxDateSetter(\"max\")\n\t\t});\n\n\t\tself.config.minDate = userConfig.minDate;\n\t\tself.config.maxDate = userConfig.maxDate;\n\n\t\tfor (var i = 0; i < boolOpts.length; i++) {\n\t\t\tself.config[boolOpts[i]] = self.config[boolOpts[i]] === true || self.config[boolOpts[i]] === \"true\";\n\t\t}for (var _i = hooks.length; _i--;) {\n\t\t\tif (self.config[hooks[_i]] !== undefined) {\n\t\t\t\tself.config[hooks[_i]] = arrayify(self.config[hooks[_i]] || []).map(bindToInstance);\n\t\t\t}\n\t\t}\n\n\t\tfor (var _i2 = 0; _i2 < self.config.plugins.length; _i2++) {\n\t\t\tvar pluginConf = self.config.plugins[_i2](self) || {};\n\t\t\tfor (var key in pluginConf) {\n\n\t\t\t\tif (self.config[key] instanceof Array || ~hooks.indexOf(key)) {\n\t\t\t\t\tself.config[key] = arrayify(pluginConf[key]).map(bindToInstance).concat(self.config[key]);\n\t\t\t\t} else if (typeof userConfig[key] === \"undefined\") self.config[key] = pluginConf[key];\n\t\t\t}\n\t\t}\n\n\t\ttriggerEvent(\"ParseConfig\");\n\t}\n\n\tfunction setupLocale() {\n\t\tif (_typeof(self.config.locale) !== \"object\" && typeof flatpickr.l10ns[self.config.locale] === \"undefined\") console.warn(\"flatpickr: invalid locale \" + self.config.locale);\n\n\t\tself.l10n = _extends(Object.create(flatpickr.l10ns.default), _typeof(self.config.locale) === \"object\" ? self.config.locale : self.config.locale !== \"default\" ? flatpickr.l10ns[self.config.locale] || {} : {});\n\t}\n\n\tfunction positionCalendar() {\n\t\tvar positionElement = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : self._positionElement;\n\n\t\tif (self.calendarContainer === undefined) return;\n\n\t\tvar calendarHeight = self.calendarContainer.offsetHeight,\n\t\t    calendarWidth = self.calendarContainer.offsetWidth,\n\t\t    configPos = self.config.position,\n\t\t    inputBounds = positionElement.getBoundingClientRect(),\n\t\t    distanceFromBottom = window.innerHeight - inputBounds.bottom,\n\t\t    showOnTop = configPos === \"above\" || configPos !== \"below\" && distanceFromBottom < calendarHeight && inputBounds.top > calendarHeight;\n\n\t\tvar top = window.pageYOffset + inputBounds.top + (!showOnTop ? positionElement.offsetHeight + 2 : -calendarHeight - 2);\n\n\t\ttoggleClass(self.calendarContainer, \"arrowTop\", !showOnTop);\n\t\ttoggleClass(self.calendarContainer, \"arrowBottom\", showOnTop);\n\n\t\tif (self.config.inline) return;\n\n\t\tvar left = window.pageXOffset + inputBounds.left;\n\t\tvar right = window.document.body.offsetWidth - inputBounds.right;\n\t\tvar rightMost = left + calendarWidth > window.document.body.offsetWidth;\n\n\t\ttoggleClass(self.calendarContainer, \"rightMost\", rightMost);\n\n\t\tif (self.config.static) return;\n\n\t\tself.calendarContainer.style.top = top + \"px\";\n\n\t\tif (!rightMost) {\n\t\t\tself.calendarContainer.style.left = left + \"px\";\n\t\t\tself.calendarContainer.style.right = \"auto\";\n\t\t} else {\n\t\t\tself.calendarContainer.style.left = \"auto\";\n\t\t\tself.calendarContainer.style.right = right + \"px\";\n\t\t}\n\t}\n\n\tfunction redraw() {\n\t\tif (self.config.noCalendar || self.isMobile) return;\n\n\t\tbuildWeekdays();\n\t\tupdateNavigationCurrentMonth();\n\t\tbuildDays();\n\t}\n\n\tfunction selectDate(e) {\n\t\te.preventDefault();\n\t\te.stopPropagation();\n\n\t\tif (!e.target.classList.contains(\"flatpickr-day\") || e.target.classList.contains(\"disabled\") || e.target.classList.contains(\"notAllowed\")) return;\n\n\t\tvar selectedDate = self.latestSelectedDateObj = new Date(e.target.dateObj.getTime());\n\n\t\tvar shouldChangeMonth = selectedDate.getMonth() !== self.currentMonth && self.config.mode !== \"range\";\n\n\t\tself.selectedDateElem = e.target;\n\n\t\tif (self.config.mode === \"single\") self.selectedDates = [selectedDate];else if (self.config.mode === \"multiple\") {\n\t\t\tvar selectedIndex = isDateSelected(selectedDate);\n\t\t\tif (selectedIndex) self.selectedDates.splice(selectedIndex, 1);else self.selectedDates.push(selectedDate);\n\t\t} else if (self.config.mode === \"range\") {\n\t\t\tif (self.selectedDates.length === 2) self.clear();\n\n\t\t\tself.selectedDates.push(selectedDate);\n\n\t\t\t// unless selecting same date twice, sort ascendingly\n\t\t\tif (compareDates(selectedDate, self.selectedDates[0], true) !== 0) self.selectedDates.sort(function (a, b) {\n\t\t\t\treturn a.getTime() - b.getTime();\n\t\t\t});\n\t\t}\n\n\t\tsetHoursFromInputs();\n\n\t\tif (shouldChangeMonth) {\n\t\t\tvar isNewYear = self.currentYear !== selectedDate.getFullYear();\n\t\t\tself.currentYear = selectedDate.getFullYear();\n\t\t\tself.currentMonth = selectedDate.getMonth();\n\n\t\t\tif (isNewYear) triggerEvent(\"YearChange\");\n\n\t\t\ttriggerEvent(\"MonthChange\");\n\t\t}\n\n\t\tbuildDays();\n\n\t\tif (self.minDateHasTime && self.config.enableTime && compareDates(selectedDate, self.config.minDate) === 0) setHoursFromDate(self.config.minDate);\n\n\t\tupdateValue();\n\n\t\tif (self.config.enableTime) setTimeout(function () {\n\t\t\treturn self.showTimeInput = true;\n\t\t}, 50);\n\n\t\tif (self.config.mode === \"range\") {\n\t\t\tif (self.selectedDates.length === 1) {\n\t\t\t\tonMouseOver(e.target);\n\n\t\t\t\tself._hidePrevMonthArrow = self._hidePrevMonthArrow || self.minRangeDate > self.days.childNodes[0].dateObj;\n\n\t\t\t\tself._hideNextMonthArrow = self._hideNextMonthArrow || self.maxRangeDate < new Date(self.currentYear, self.currentMonth + 1, 1);\n\t\t\t} else updateNavigationCurrentMonth();\n\t\t}\n\n\t\ttriggerEvent(\"Change\");\n\n\t\t// maintain focus\n\t\tif (!shouldChangeMonth) focusOnDay(e.target.$i, 0);else afterDayAnim(function () {\n\t\t\treturn self.selectedDateElem.focus();\n\t\t});\n\n\t\tif (self.config.enableTime) setTimeout(function () {\n\t\t\treturn self.hourElement.select();\n\t\t}, 451);\n\n\t\tif (self.config.closeOnSelect) {\n\t\t\tvar single = self.config.mode === \"single\" && !self.config.enableTime;\n\t\t\tvar range = self.config.mode === \"range\" && self.selectedDates.length === 2 && !self.config.enableTime;\n\n\t\t\tif (single || range) self.close();\n\t\t}\n\t}\n\n\tfunction set(option, value) {\n\t\tself.config[option] = value;\n\t\tself.redraw();\n\t\tjumpToDate();\n\t}\n\n\tfunction setSelectedDate(inputDate, format) {\n\t\tif (inputDate instanceof Array) self.selectedDates = inputDate.map(function (d) {\n\t\t\treturn self.parseDate(d, format);\n\t\t});else if (inputDate instanceof Date || !isNaN(inputDate)) self.selectedDates = [self.parseDate(inputDate, format)];else if (inputDate && inputDate.substring) {\n\t\t\tswitch (self.config.mode) {\n\t\t\t\tcase \"single\":\n\t\t\t\t\tself.selectedDates = [self.parseDate(inputDate, format)];\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase \"multiple\":\n\t\t\t\t\tself.selectedDates = inputDate.split(\"; \").map(function (date) {\n\t\t\t\t\t\treturn self.parseDate(date, format);\n\t\t\t\t\t});\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase \"range\":\n\t\t\t\t\tself.selectedDates = inputDate.split(self.l10n.rangeSeparator).map(function (date) {\n\t\t\t\t\t\treturn self.parseDate(date, format);\n\t\t\t\t\t});\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tself.selectedDates = self.selectedDates.filter(function (d) {\n\t\t\treturn d instanceof Date && isEnabled(d, false);\n\t\t});\n\n\t\tself.selectedDates.sort(function (a, b) {\n\t\t\treturn a.getTime() - b.getTime();\n\t\t});\n\t}\n\n\tfunction setDate(date, triggerChange, format) {\n\t\tif (date !== 0 && !date) return self.clear(triggerChange);\n\n\t\tsetSelectedDate(date, format);\n\n\t\tself.showTimeInput = self.selectedDates.length > 0;\n\t\tself.latestSelectedDateObj = self.selectedDates[0];\n\n\t\tself.redraw();\n\t\tjumpToDate();\n\n\t\tsetHoursFromDate();\n\t\tupdateValue(triggerChange);\n\n\t\tif (triggerChange) triggerEvent(\"Change\");\n\t}\n\n\tfunction parseDateRules(arr) {\n\t\tfor (var i = arr.length; i--;) {\n\t\t\tif (typeof arr[i] === \"string\" || +arr[i]) arr[i] = self.parseDate(arr[i], null, true);else if (arr[i] && arr[i].from && arr[i].to) {\n\t\t\t\tarr[i].from = self.parseDate(arr[i].from);\n\t\t\t\tarr[i].to = self.parseDate(arr[i].to);\n\t\t\t}\n\t\t}\n\n\t\treturn arr.filter(function (x) {\n\t\t\treturn x;\n\t\t}); // remove falsy values\n\t}\n\n\tfunction setupDates() {\n\t\tself.selectedDates = [];\n\t\tself.now = new Date();\n\n\t\tvar preloadedDate = self.config.defaultDate || self.input.value;\n\t\tif (preloadedDate) setSelectedDate(preloadedDate, self.config.dateFormat);\n\n\t\tvar initialDate = self.selectedDates.length ? self.selectedDates[0] : self.config.minDate && self.config.minDate.getTime() > self.now ? self.config.minDate : self.config.maxDate && self.config.maxDate.getTime() < self.now ? self.config.maxDate : self.now;\n\n\t\tself.currentYear = initialDate.getFullYear();\n\t\tself.currentMonth = initialDate.getMonth();\n\n\t\tif (self.selectedDates.length) self.latestSelectedDateObj = self.selectedDates[0];\n\n\t\tself.minDateHasTime = self.config.minDate && (self.config.minDate.getHours() || self.config.minDate.getMinutes() || self.config.minDate.getSeconds());\n\n\t\tself.maxDateHasTime = self.config.maxDate && (self.config.maxDate.getHours() || self.config.maxDate.getMinutes() || self.config.maxDate.getSeconds());\n\n\t\tObject.defineProperty(self, \"latestSelectedDateObj\", {\n\t\t\tget: function get() {\n\t\t\t\treturn self._selectedDateObj || self.selectedDates[self.selectedDates.length - 1];\n\t\t\t},\n\t\t\tset: function set(date) {\n\t\t\t\tself._selectedDateObj = date;\n\t\t\t}\n\t\t});\n\n\t\tif (!self.isMobile) {\n\t\t\tObject.defineProperty(self, \"showTimeInput\", {\n\t\t\t\tget: function get() {\n\t\t\t\t\treturn self._showTimeInput;\n\t\t\t\t},\n\t\t\t\tset: function set(bool) {\n\t\t\t\t\tself._showTimeInput = bool;\n\t\t\t\t\tif (self.calendarContainer) toggleClass(self.calendarContainer, \"showTimeInput\", bool);\n\t\t\t\t\tpositionCalendar();\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\n\tfunction setupHelperFunctions() {\n\t\tself.utils = {\n\t\t\tduration: {\n\t\t\t\tDAY: 86400000\n\t\t\t},\n\t\t\tgetDaysinMonth: function getDaysinMonth(month, yr) {\n\t\t\t\tmonth = typeof month === \"undefined\" ? self.currentMonth : month;\n\n\t\t\t\tyr = typeof yr === \"undefined\" ? self.currentYear : yr;\n\n\t\t\t\tif (month === 1 && (yr % 4 === 0 && yr % 100 !== 0 || yr % 400 === 0)) return 29;\n\n\t\t\t\treturn self.l10n.daysInMonth[month];\n\t\t\t},\n\t\t\tmonthToStr: function monthToStr(monthNumber, shorthand) {\n\t\t\t\tshorthand = typeof shorthand === \"undefined\" ? self.config.shorthandCurrentMonth : shorthand;\n\n\t\t\t\treturn self.l10n.months[(shorthand ? \"short\" : \"long\") + \"hand\"][monthNumber];\n\t\t\t}\n\t\t};\n\t}\n\n\t/* istanbul ignore next */\n\tfunction setupFormats() {\n\t\tself.formats = Object.create(FlatpickrInstance.prototype.formats);\n\t\t[\"D\", \"F\", \"J\", \"M\", \"W\", \"l\"].forEach(function (f) {\n\t\t\tself.formats[f] = FlatpickrInstance.prototype.formats[f].bind(self);\n\t\t});\n\n\t\tself.revFormat.F = FlatpickrInstance.prototype.revFormat.F.bind(self);\n\t\tself.revFormat.M = FlatpickrInstance.prototype.revFormat.M.bind(self);\n\t}\n\n\tfunction setupInputs() {\n\t\tself.input = self.config.wrap ? self.element.querySelector(\"[data-input]\") : self.element;\n\n\t\t/* istanbul ignore next */\n\t\tif (!self.input) return console.warn(\"Error: invalid input element specified\", self.input);\n\n\t\tself.input._type = self.input.type;\n\t\tself.input.type = \"text\";\n\n\t\tself.input.classList.add(\"flatpickr-input\");\n\t\tself._input = self.input;\n\n\t\tif (self.config.altInput) {\n\t\t\t// replicate self.element\n\t\t\tself.altInput = createElement(self.input.nodeName, self.input.className + \" \" + self.config.altInputClass);\n\t\t\tself._input = self.altInput;\n\t\t\tself.altInput.placeholder = self.input.placeholder;\n\t\t\tself.altInput.disabled = self.input.disabled;\n\t\t\tself.altInput.required = self.input.required;\n\t\t\tself.altInput.type = \"text\";\n\t\t\tself.input.type = \"hidden\";\n\n\t\t\tif (!self.config.static && self.input.parentNode) self.input.parentNode.insertBefore(self.altInput, self.input.nextSibling);\n\t\t}\n\n\t\tif (!self.config.allowInput) self._input.setAttribute(\"readonly\", \"readonly\");\n\n\t\tself._positionElement = self.config.positionElement || self._input;\n\t}\n\n\tfunction setupMobile() {\n\t\tvar inputType = self.config.enableTime ? self.config.noCalendar ? \"time\" : \"datetime-local\" : \"date\";\n\n\t\tself.mobileInput = createElement(\"input\", self.input.className + \" flatpickr-mobile\");\n\t\tself.mobileInput.step = \"any\";\n\t\tself.mobileInput.tabIndex = 1;\n\t\tself.mobileInput.type = inputType;\n\t\tself.mobileInput.disabled = self.input.disabled;\n\t\tself.mobileInput.placeholder = self.input.placeholder;\n\n\t\tself.mobileFormatStr = inputType === \"datetime-local\" ? \"Y-m-d\\\\TH:i:S\" : inputType === \"date\" ? \"Y-m-d\" : \"H:i:S\";\n\n\t\tif (self.selectedDates.length) {\n\t\t\tself.mobileInput.defaultValue = self.mobileInput.value = self.formatDate(self.selectedDates[0], self.mobileFormatStr);\n\t\t}\n\n\t\tif (self.config.minDate) self.mobileInput.min = self.formatDate(self.config.minDate, \"Y-m-d\");\n\n\t\tif (self.config.maxDate) self.mobileInput.max = self.formatDate(self.config.maxDate, \"Y-m-d\");\n\n\t\tself.input.type = \"hidden\";\n\t\tif (self.config.altInput) self.altInput.type = \"hidden\";\n\n\t\ttry {\n\t\t\tself.input.parentNode.insertBefore(self.mobileInput, self.input.nextSibling);\n\t\t} catch (e) {\n\t\t\t//\n\t\t}\n\n\t\tself.mobileInput.addEventListener(\"change\", function (e) {\n\t\t\tself.setDate(e.target.value, false, self.mobileFormatStr);\n\t\t\ttriggerEvent(\"Change\");\n\t\t\ttriggerEvent(\"Close\");\n\t\t});\n\t}\n\n\tfunction toggle() {\n\t\tif (self.isOpen) return self.close();\n\t\tself.open();\n\t}\n\n\tfunction triggerEvent(event, data) {\n\t\tvar hooks = self.config[\"on\" + event];\n\n\t\tif (hooks !== undefined && hooks.length > 0) {\n\t\t\tfor (var i = 0; hooks[i] && i < hooks.length; i++) {\n\t\t\t\thooks[i](self.selectedDates, self.input.value, self, data);\n\t\t\t}\n\t\t}\n\n\t\tif (event === \"Change\") {\n\t\t\tself.input.dispatchEvent(createEvent(\"change\"));\n\n\t\t\t// many front-end frameworks bind to the input event\n\t\t\tself.input.dispatchEvent(createEvent(\"input\"));\n\t\t}\n\t}\n\n\t/**\n  * Creates an Event, normalized across browsers\n  * @param {String} name the event name, e.g. \"click\"\n  * @return {Event} the created event\n  */\n\tfunction createEvent(name) {\n\t\tif (self._supportsEvents) return new Event(name, { bubbles: true });\n\n\t\tself._[name + \"Event\"] = document.createEvent(\"Event\");\n\t\tself._[name + \"Event\"].initEvent(name, true, true);\n\t\treturn self._[name + \"Event\"];\n\t}\n\n\tfunction isDateSelected(date) {\n\t\tfor (var i = 0; i < self.selectedDates.length; i++) {\n\t\t\tif (compareDates(self.selectedDates[i], date) === 0) return \"\" + i;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tfunction isDateInRange(date) {\n\t\tif (self.config.mode !== \"range\" || self.selectedDates.length < 2) return false;\n\t\treturn compareDates(date, self.selectedDates[0]) >= 0 && compareDates(date, self.selectedDates[1]) <= 0;\n\t}\n\n\tfunction updateNavigationCurrentMonth() {\n\t\tif (self.config.noCalendar || self.isMobile || !self.monthNav) return;\n\n\t\tself.currentMonthElement.textContent = self.utils.monthToStr(self.currentMonth) + \" \";\n\t\tself.currentYearElement.value = self.currentYear;\n\n\t\tself._hidePrevMonthArrow = self.config.minDate && (self.currentYear === self.config.minDate.getFullYear() ? self.currentMonth <= self.config.minDate.getMonth() : self.currentYear < self.config.minDate.getFullYear());\n\n\t\tself._hideNextMonthArrow = self.config.maxDate && (self.currentYear === self.config.maxDate.getFullYear() ? self.currentMonth + 1 > self.config.maxDate.getMonth() : self.currentYear > self.config.maxDate.getFullYear());\n\t}\n\n\t/**\n  * Updates the values of inputs associated with the calendar\n  * @return {void}\n  */\n\tfunction updateValue(triggerChange) {\n\t\tif (!self.selectedDates.length) return self.clear(triggerChange);\n\n\t\tif (self.isMobile) {\n\t\t\tself.mobileInput.value = self.selectedDates.length ? self.formatDate(self.latestSelectedDateObj, self.mobileFormatStr) : \"\";\n\t\t}\n\n\t\tvar joinChar = self.config.mode !== \"range\" ? \"; \" : self.l10n.rangeSeparator;\n\n\t\tself.input.value = self.selectedDates.map(function (dObj) {\n\t\t\treturn self.formatDate(dObj, self.config.dateFormat);\n\t\t}).join(joinChar);\n\n\t\tif (self.config.altInput) {\n\t\t\tself.altInput.value = self.selectedDates.map(function (dObj) {\n\t\t\t\treturn self.formatDate(dObj, self.config.altFormat);\n\t\t\t}).join(joinChar);\n\t\t}\n\n\t\tif (triggerChange !== false) triggerEvent(\"ValueUpdate\");\n\t}\n\n\tfunction mouseDelta(e) {\n\t\treturn Math.max(-1, Math.min(1, e.wheelDelta || -e.deltaY));\n\t}\n\n\tfunction onMonthNavScroll(e) {\n\t\te.preventDefault();\n\t\tvar isYear = self.currentYearElement.parentNode.contains(e.target);\n\n\t\tif (e.target === self.currentMonthElement || isYear) {\n\n\t\t\tvar delta = mouseDelta(e);\n\n\t\t\tif (isYear) {\n\t\t\t\tchangeYear(self.currentYear + delta);\n\t\t\t\te.target.value = self.currentYear;\n\t\t\t} else self.changeMonth(delta, true, false);\n\t\t}\n\t}\n\n\tfunction onMonthNavClick(e) {\n\t\tvar isPrevMonth = self.prevMonthNav.contains(e.target);\n\t\tvar isNextMonth = self.nextMonthNav.contains(e.target);\n\n\t\tif (isPrevMonth || isNextMonth) changeMonth(isPrevMonth ? -1 : 1);else if (e.target === self.currentYearElement) {\n\t\t\te.preventDefault();\n\t\t\tself.currentYearElement.select();\n\t\t} else if (e.target.className === \"arrowUp\") self.changeYear(self.currentYear + 1);else if (e.target.className === \"arrowDown\") self.changeYear(self.currentYear - 1);\n\t}\n\n\t/**\n  * Creates an HTMLElement with given tag, class, and textual content\n  * @param {String} tag the HTML tag\n  * @param {String} className the new element's class name\n  * @param {String} content The new element's text content\n  * @return {HTMLElement} the created HTML element\n  */\n\tfunction createElement(tag, className, content) {\n\t\tvar e = window.document.createElement(tag);\n\t\tclassName = className || \"\";\n\t\tcontent = content || \"\";\n\n\t\te.className = className;\n\n\t\tif (content !== undefined) e.textContent = content;\n\n\t\treturn e;\n\t}\n\n\tfunction arrayify(obj) {\n\t\tif (obj instanceof Array) return obj;\n\t\treturn [obj];\n\t}\n\n\tfunction toggleClass(elem, className, bool) {\n\t\tif (bool) return elem.classList.add(className);\n\t\telem.classList.remove(className);\n\t}\n\n\t/* istanbul ignore next */\n\tfunction debounce(func, wait, immediate) {\n\t\tvar timeout = void 0;\n\t\treturn function () {\n\t\t\tvar context = this,\n\t\t\t    args = arguments;\n\t\t\tclearTimeout(timeout);\n\t\t\ttimeout = setTimeout(function () {\n\t\t\t\ttimeout = null;\n\t\t\t\tif (!immediate) func.apply(context, args);\n\t\t\t}, wait);\n\t\t\tif (immediate && !timeout) func.apply(context, args);\n\t\t};\n\t}\n\n\t/**\n  * Compute the difference in dates, measured in ms\n  * @param {Date} date1\n  * @param {Date} date2\n  * @param {Boolean} timeless whether to reset times of both dates to 00:00\n  * @return {Number} the difference in ms\n  */\n\tfunction compareDates(date1, date2, timeless) {\n\t\tif (!(date1 instanceof Date) || !(date2 instanceof Date)) return false;\n\n\t\tif (timeless !== false) {\n\t\t\treturn new Date(date1.getTime()).setHours(0, 0, 0, 0) - new Date(date2.getTime()).setHours(0, 0, 0, 0);\n\t\t}\n\n\t\treturn date1.getTime() - date2.getTime();\n\t}\n\n\tfunction timeWrapper(e) {\n\t\te.preventDefault();\n\n\t\tvar isKeyDown = e.type === \"keydown\",\n\t\t    isWheel = e.type === \"wheel\",\n\t\t    isIncrement = e.type === \"increment\",\n\t\t    input = e.target;\n\n\t\tif (self.amPM && e.target === self.amPM) return e.target.textContent = [\"AM\", \"PM\"][e.target.textContent === \"AM\" | 0];\n\n\t\tvar min = Number(input.min),\n\t\t    max = Number(input.max),\n\t\t    step = Number(input.step),\n\t\t    curValue = parseInt(input.value, 10),\n\t\t    delta = e.delta || (!isKeyDown ? Math.max(-1, Math.min(1, e.wheelDelta || -e.deltaY)) || 0 : e.which === 38 ? 1 : -1);\n\n\t\tvar newValue = curValue + step * delta;\n\n\t\tif (typeof input.value !== \"undefined\" && input.value.length === 2) {\n\t\t\tvar isHourElem = input === self.hourElement,\n\t\t\t    isMinuteElem = input === self.minuteElement;\n\n\t\t\tif (newValue < min) {\n\t\t\t\tnewValue = max + newValue + !isHourElem + (isHourElem && !self.amPM);\n\n\t\t\t\tif (isMinuteElem) incrementNumInput(null, -1, self.hourElement);\n\t\t\t} else if (newValue > max) {\n\t\t\t\tnewValue = input === self.hourElement ? newValue - max - !self.amPM : min;\n\n\t\t\t\tif (isMinuteElem) incrementNumInput(null, 1, self.hourElement);\n\t\t\t}\n\n\t\t\tif (self.amPM && isHourElem && (step === 1 ? newValue + curValue === 23 : Math.abs(newValue - curValue) > step)) self.amPM.textContent = self.amPM.textContent === \"PM\" ? \"AM\" : \"PM\";\n\n\t\t\tinput.value = self.pad(newValue);\n\t\t}\n\t}\n\n\tinit();\n\treturn self;\n}\n\nFlatpickrInstance.prototype = {\n\tformats: {\n\t\t// get the date in UTC\n\t\tZ: function Z(date) {\n\t\t\treturn date.toISOString();\n\t\t},\n\n\t\t// weekday name, short, e.g. Thu\n\t\tD: function D(date) {\n\t\t\treturn this.l10n.weekdays.shorthand[this.formats.w(date)];\n\t\t},\n\n\t\t// full month name e.g. January\n\t\tF: function F(date) {\n\t\t\treturn this.utils.monthToStr(this.formats.n(date) - 1, false);\n\t\t},\n\n\t\t// padded hour 1-12\n\t\tG: function G(date) {\n\t\t\treturn FlatpickrInstance.prototype.pad(FlatpickrInstance.prototype.formats.h(date));\n\t\t},\n\n\t\t// hours with leading zero e.g. 03\n\t\tH: function H(date) {\n\t\t\treturn FlatpickrInstance.prototype.pad(date.getHours());\n\t\t},\n\n\t\t// day (1-30) with ordinal suffix e.g. 1st, 2nd\n\t\tJ: function J(date) {\n\t\t\treturn date.getDate() + this.l10n.ordinal(date.getDate());\n\t\t},\n\n\t\t// AM/PM\n\t\tK: function K(date) {\n\t\t\treturn date.getHours() > 11 ? \"PM\" : \"AM\";\n\t\t},\n\n\t\t// shorthand month e.g. Jan, Sep, Oct, etc\n\t\tM: function M(date) {\n\t\t\treturn this.utils.monthToStr(date.getMonth(), true);\n\t\t},\n\n\t\t// seconds 00-59\n\t\tS: function S(date) {\n\t\t\treturn FlatpickrInstance.prototype.pad(date.getSeconds());\n\t\t},\n\n\t\t// unix timestamp\n\t\tU: function U(date) {\n\t\t\treturn date.getTime() / 1000;\n\t\t},\n\n\t\tW: function W(date) {\n\t\t\treturn this.config.getWeek(date);\n\t\t},\n\n\t\t// full year e.g. 2016\n\t\tY: function Y(date) {\n\t\t\treturn date.getFullYear();\n\t\t},\n\n\t\t// day in month, padded (01-30)\n\t\td: function d(date) {\n\t\t\treturn FlatpickrInstance.prototype.pad(date.getDate());\n\t\t},\n\n\t\t// hour from 1-12 (am/pm)\n\t\th: function h(date) {\n\t\t\treturn date.getHours() % 12 ? date.getHours() % 12 : 12;\n\t\t},\n\n\t\t// minutes, padded with leading zero e.g. 09\n\t\ti: function i(date) {\n\t\t\treturn FlatpickrInstance.prototype.pad(date.getMinutes());\n\t\t},\n\n\t\t// day in month (1-30)\n\t\tj: function j(date) {\n\t\t\treturn date.getDate();\n\t\t},\n\n\t\t// weekday name, full, e.g. Thursday\n\t\tl: function l(date) {\n\t\t\treturn this.l10n.weekdays.longhand[date.getDay()];\n\t\t},\n\n\t\t// padded month number (01-12)\n\t\tm: function m(date) {\n\t\t\treturn FlatpickrInstance.prototype.pad(date.getMonth() + 1);\n\t\t},\n\n\t\t// the month number (1-12)\n\t\tn: function n(date) {\n\t\t\treturn date.getMonth() + 1;\n\t\t},\n\n\t\t// seconds 0-59\n\t\ts: function s(date) {\n\t\t\treturn date.getSeconds();\n\t\t},\n\n\t\t// number of the day of the week\n\t\tw: function w(date) {\n\t\t\treturn date.getDay();\n\t\t},\n\n\t\t// last two digits of year e.g. 16 for 2016\n\t\ty: function y(date) {\n\t\t\treturn String(date.getFullYear()).substring(2);\n\t\t}\n\t},\n\n\t/**\n  * Formats a given Date object into a string based on supplied format\n  * @param {Date} dateObj the date object\n  * @param {String} frmt a string composed of formatting tokens e.g. \"Y-m-d\"\n  * @return {String} The textual representation of the date e.g. 2017-02-03\n  */\n\tformatDate: function formatDate(dateObj, frmt) {\n\t\tvar _this = this;\n\n\t\tif (this.config !== undefined && this.config.formatDate !== undefined) return this.config.formatDate(dateObj, frmt);\n\n\t\treturn frmt.split(\"\").map(function (c, i, arr) {\n\t\t\treturn _this.formats[c] && arr[i - 1] !== \"\\\\\" ? _this.formats[c](dateObj) : c !== \"\\\\\" ? c : \"\";\n\t\t}).join(\"\");\n\t},\n\n\n\trevFormat: {\n\t\tD: function D() {},\n\t\tF: function F(dateObj, monthName) {\n\t\t\tdateObj.setMonth(this.l10n.months.longhand.indexOf(monthName));\n\t\t},\n\t\tG: function G(dateObj, hour) {\n\t\t\tdateObj.setHours(parseFloat(hour));\n\t\t},\n\t\tH: function H(dateObj, hour) {\n\t\t\tdateObj.setHours(parseFloat(hour));\n\t\t},\n\t\tJ: function J(dateObj, day) {\n\t\t\tdateObj.setDate(parseFloat(day));\n\t\t},\n\t\tK: function K(dateObj, amPM) {\n\t\t\tvar hours = dateObj.getHours();\n\n\t\t\tif (hours !== 12) dateObj.setHours(hours % 12 + 12 * /pm/i.test(amPM));\n\t\t},\n\t\tM: function M(dateObj, shortMonth) {\n\t\t\tdateObj.setMonth(this.l10n.months.shorthand.indexOf(shortMonth));\n\t\t},\n\t\tS: function S(dateObj, seconds) {\n\t\t\tdateObj.setSeconds(seconds);\n\t\t},\n\t\tU: function U(dateObj, unixSeconds) {\n\t\t\treturn new Date(parseFloat(unixSeconds) * 1000);\n\t\t},\n\n\t\tW: function W(dateObj, weekNumber) {\n\t\t\tweekNumber = parseInt(weekNumber);\n\t\t\treturn new Date(dateObj.getFullYear(), 0, 2 + (weekNumber - 1) * 7, 0, 0, 0, 0, 0);\n\t\t},\n\t\tY: function Y(dateObj, year) {\n\t\t\tdateObj.setFullYear(year);\n\t\t},\n\t\tZ: function Z(dateObj, ISODate) {\n\t\t\treturn new Date(ISODate);\n\t\t},\n\n\t\td: function d(dateObj, day) {\n\t\t\tdateObj.setDate(parseFloat(day));\n\t\t},\n\t\th: function h(dateObj, hour) {\n\t\t\tdateObj.setHours(parseFloat(hour));\n\t\t},\n\t\ti: function i(dateObj, minutes) {\n\t\t\tdateObj.setMinutes(parseFloat(minutes));\n\t\t},\n\t\tj: function j(dateObj, day) {\n\t\t\tdateObj.setDate(parseFloat(day));\n\t\t},\n\t\tl: function l() {},\n\t\tm: function m(dateObj, month) {\n\t\t\tdateObj.setMonth(parseFloat(month) - 1);\n\t\t},\n\t\tn: function n(dateObj, month) {\n\t\t\tdateObj.setMonth(parseFloat(month) - 1);\n\t\t},\n\t\ts: function s(dateObj, seconds) {\n\t\t\tdateObj.setSeconds(parseFloat(seconds));\n\t\t},\n\t\tw: function w() {},\n\t\ty: function y(dateObj, year) {\n\t\t\tdateObj.setFullYear(2000 + parseFloat(year));\n\t\t}\n\t},\n\n\ttokenRegex: {\n\t\tD: \"(\\\\w+)\",\n\t\tF: \"(\\\\w+)\",\n\t\tG: \"(\\\\d\\\\d|\\\\d)\",\n\t\tH: \"(\\\\d\\\\d|\\\\d)\",\n\t\tJ: \"(\\\\d\\\\d|\\\\d)\\\\w+\",\n\t\tK: \"(am|AM|Am|aM|pm|PM|Pm|pM)\",\n\t\tM: \"(\\\\w+)\",\n\t\tS: \"(\\\\d\\\\d|\\\\d)\",\n\t\tU: \"(.+)\",\n\t\tW: \"(\\\\d\\\\d|\\\\d)\",\n\t\tY: \"(\\\\d{4})\",\n\t\tZ: \"(.+)\",\n\t\td: \"(\\\\d\\\\d|\\\\d)\",\n\t\th: \"(\\\\d\\\\d|\\\\d)\",\n\t\ti: \"(\\\\d\\\\d|\\\\d)\",\n\t\tj: \"(\\\\d\\\\d|\\\\d)\",\n\t\tl: \"(\\\\w+)\",\n\t\tm: \"(\\\\d\\\\d|\\\\d)\",\n\t\tn: \"(\\\\d\\\\d|\\\\d)\",\n\t\ts: \"(\\\\d\\\\d|\\\\d)\",\n\t\tw: \"(\\\\d\\\\d|\\\\d)\",\n\t\ty: \"(\\\\d{2})\"\n\t},\n\n\tpad: function pad(number) {\n\t\treturn (\"0\" + number).slice(-2);\n\t},\n\n\t/**\n  * Parses a date(+time) string into a Date object\n  * @param {String} date the date string, e.g. 2017-02-03 14:45\n  * @param {String} givenFormat the date format, e.g. Y-m-d H:i\n  * @param {Boolean} timeless whether to reset the time of Date object\n  * @return {Date} the parsed Date object\n  */\n\tparseDate: function parseDate(date, givenFormat, timeless) {\n\t\tif (date !== 0 && !date) return null;\n\n\t\tvar date_orig = date;\n\n\t\tif (date instanceof Date) date = new Date(date.getTime()); // create a copy\n\n\t\telse if (date.toFixed !== undefined) // timestamp\n\t\t\t\tdate = new Date(date);else {\n\t\t\t\t// date string\n\t\t\t\tvar format = givenFormat || (this.config || flatpickr.defaultConfig).dateFormat;\n\t\t\t\tdate = String(date).trim();\n\n\t\t\t\tif (date === \"today\") {\n\t\t\t\t\tdate = new Date();\n\t\t\t\t\ttimeless = true;\n\t\t\t\t} else if (/Z$/.test(date) || /GMT$/.test(date)) // datestrings w/ timezone\n\t\t\t\t\tdate = new Date(date);else if (this.config && this.config.parseDate) date = this.config.parseDate(date, format);else {\n\t\t\t\t\tvar parsedDate = !this.config || !this.config.noCalendar ? new Date(new Date().getFullYear(), 0, 1, 0, 0, 0, 0) : new Date(new Date().setHours(0, 0, 0, 0));\n\n\t\t\t\t\tvar matched = void 0;\n\n\t\t\t\t\tfor (var i = 0, matchIndex = 0, regexStr = \"\"; i < format.length; i++) {\n\t\t\t\t\t\tvar token = format[i];\n\t\t\t\t\t\tvar isBackSlash = token === \"\\\\\";\n\t\t\t\t\t\tvar escaped = format[i - 1] === \"\\\\\" || isBackSlash;\n\n\t\t\t\t\t\tif (this.tokenRegex[token] && !escaped) {\n\t\t\t\t\t\t\tregexStr += this.tokenRegex[token];\n\t\t\t\t\t\t\tvar match = new RegExp(regexStr).exec(date);\n\t\t\t\t\t\t\tif (match && (matched = true)) {\n\t\t\t\t\t\t\t\tparsedDate = this.revFormat[token](parsedDate, match[++matchIndex]) || parsedDate;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if (!isBackSlash) regexStr += \".\"; // don't really care\n\t\t\t\t\t}\n\n\t\t\t\t\tdate = matched ? parsedDate : null;\n\t\t\t\t}\n\t\t\t}\n\n\t\t/* istanbul ignore next */\n\t\tif (!(date instanceof Date)) {\n\t\t\tconsole.warn(\"flatpickr: invalid date \" + date_orig);\n\t\t\tconsole.info(this.element);\n\t\t\treturn null;\n\t\t}\n\n\t\tif (timeless === true) date.setHours(0, 0, 0, 0);\n\n\t\treturn date;\n\t}\n};\n\n/* istanbul ignore next */\nfunction _flatpickr(nodeList, config) {\n\tvar nodes = Array.prototype.slice.call(nodeList); // static list\n\tvar instances = [];\n\tfor (var i = 0; i < nodes.length; i++) {\n\t\ttry {\n\t\t\tif (nodes[i].getAttribute(\"data-fp-omit\") !== null) continue;\n\n\t\t\tif (nodes[i]._flatpickr) {\n\t\t\t\tnodes[i]._flatpickr.destroy();\n\t\t\t\tnodes[i]._flatpickr = null;\n\t\t\t}\n\n\t\t\tnodes[i]._flatpickr = new FlatpickrInstance(nodes[i], config || {});\n\t\t\tinstances.push(nodes[i]._flatpickr);\n\t\t} catch (e) {\n\t\t\tconsole.warn(e, e.stack);\n\t\t}\n\t}\n\n\treturn instances.length === 1 ? instances[0] : instances;\n}\n\n/* istanbul ignore next */\nif (typeof HTMLElement !== \"undefined\") {\n\t// browser env\n\tHTMLCollection.prototype.flatpickr = NodeList.prototype.flatpickr = function (config) {\n\t\treturn _flatpickr(this, config);\n\t};\n\n\tHTMLElement.prototype.flatpickr = function (config) {\n\t\treturn _flatpickr([this], config);\n\t};\n}\n\n/* istanbul ignore next */\nfunction flatpickr(selector, config) {\n\tif (selector instanceof NodeList) return _flatpickr(selector, config);else if (!(selector instanceof HTMLElement)) return _flatpickr(window.document.querySelectorAll(selector), config);\n\n\treturn _flatpickr([selector], config);\n}\n\n/* istanbul ignore next */\nflatpickr.defaultConfig = FlatpickrInstance.defaultConfig = {\n\tmode: \"single\",\n\n\tposition: \"auto\",\n\n\tanimate: window.navigator.userAgent.indexOf(\"MSIE\") === -1,\n\n\t// wrap: see https://chmln.github.io/flatpickr/examples/#flatpickr-external-elements\n\twrap: false,\n\n\t// enables week numbers\n\tweekNumbers: false,\n\n\t// allow manual datetime input\n\tallowInput: false,\n\n\t/*\n \tclicking on input opens the date(time)picker.\n \tdisable if you wish to open the calendar manually with .open()\n */\n\tclickOpens: true,\n\n\t/*\n \tcloses calendar after date selection,\n \tunless 'mode' is 'multiple' or enableTime is true\n */\n\tcloseOnSelect: true,\n\n\t// display time picker in 24 hour mode\n\ttime_24hr: false,\n\n\t// enables the time picker functionality\n\tenableTime: false,\n\n\t// noCalendar: true will hide the calendar. use for a time picker along w/ enableTime\n\tnoCalendar: false,\n\n\t// more date format chars at https://chmln.github.io/flatpickr/#dateformat\n\tdateFormat: \"Y-m-d\",\n\n\t// date format used in aria-label for days\n\tariaDateFormat: \"F j, Y\",\n\n\t// altInput - see https://chmln.github.io/flatpickr/#altinput\n\taltInput: false,\n\n\t// the created altInput element will have this class.\n\taltInputClass: \"form-control input\",\n\n\t// same as dateFormat, but for altInput\n\taltFormat: \"F j, Y\", // defaults to e.g. June 10, 2016\n\n\t// defaultDate - either a datestring or a date object. used for datetimepicker\"s initial value\n\tdefaultDate: null,\n\n\t// the minimum date that user can pick (inclusive)\n\tminDate: null,\n\n\t// the maximum date that user can pick (inclusive)\n\tmaxDate: null,\n\n\t// dateparser that transforms a given string to a date object\n\tparseDate: null,\n\n\t// dateformatter that transforms a given date object to a string, according to passed format\n\tformatDate: null,\n\n\tgetWeek: function getWeek(givenDate) {\n\t\tvar date = new Date(givenDate.getTime());\n\t\tvar onejan = new Date(date.getFullYear(), 0, 1);\n\t\treturn Math.ceil(((date - onejan) / 86400000 + onejan.getDay() + 1) / 7);\n\t},\n\n\n\t// see https://chmln.github.io/flatpickr/#disable\n\tenable: [],\n\n\t// see https://chmln.github.io/flatpickr/#disable\n\tdisable: [],\n\n\t// display the short version of month names - e.g. Sep instead of September\n\tshorthandCurrentMonth: false,\n\n\t// displays calendar inline. see https://chmln.github.io/flatpickr/#inline-calendar\n\tinline: false,\n\n\t// position calendar inside wrapper and next to the input element\n\t// leave at false unless you know what you\"re doing\n\t\"static\": false,\n\n\t// DOM node to append the calendar to in *static* mode\n\tappendTo: null,\n\n\t// code for previous/next icons. this is where you put your custom icon code e.g. fontawesome\n\tprevArrow: \"<svg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' viewBox='0 0 17 17'><g></g><path d='M5.207 8.471l7.146 7.147-0.707 0.707-7.853-7.854 7.854-7.853 0.707 0.707-7.147 7.146z' /></svg>\",\n\tnextArrow: \"<svg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' viewBox='0 0 17 17'><g></g><path d='M13.207 8.472l-7.854 7.854-0.707-0.707 7.146-7.146-7.146-7.148 0.707-0.707 7.854 7.854z' /></svg>\",\n\n\t// enables seconds in the time picker\n\tenableSeconds: false,\n\n\t// step size used when scrolling/incrementing the hour element\n\thourIncrement: 1,\n\n\t// step size used when scrolling/incrementing the minute element\n\tminuteIncrement: 5,\n\n\t// initial value in the hour element\n\tdefaultHour: 12,\n\n\t// initial value in the minute element\n\tdefaultMinute: 0,\n\n\t// disable native mobile datetime input support\n\tdisableMobile: false,\n\n\t// default locale\n\tlocale: \"default\",\n\n\tplugins: [],\n\n\tignoredFocusElements: [],\n\n\t// called every time calendar is closed\n\tonClose: undefined, // function (dateObj, dateStr) {}\n\n\t// onChange callback when user selects a date or time\n\tonChange: undefined, // function (dateObj, dateStr) {}\n\n\t// called for every day element\n\tonDayCreate: undefined,\n\n\t// called every time the month is changed\n\tonMonthChange: undefined,\n\n\t// called every time calendar is opened\n\tonOpen: undefined, // function (dateObj, dateStr) {}\n\n\t// called after the configuration has been parsed\n\tonParseConfig: undefined,\n\n\t// called after calendar is ready\n\tonReady: undefined, // function (dateObj, dateStr) {}\n\n\t// called after input value updated\n\tonValueUpdate: undefined,\n\n\t// called every time the year is changed\n\tonYearChange: undefined,\n\n\tonKeyDown: undefined,\n\n\tonDestroy: undefined\n};\n\n/* istanbul ignore next */\nflatpickr.l10ns = {\n\ten: {\n\t\tweekdays: {\n\t\t\tshorthand: [\"Sun\", \"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\", \"Sat\"],\n\t\t\tlonghand: [\"Sunday\", \"Monday\", \"Tuesday\", \"Wednesday\", \"Thursday\", \"Friday\", \"Saturday\"]\n\t\t},\n\t\tmonths: {\n\t\t\tshorthand: [\"Jan\", \"Feb\", \"Mar\", \"Apr\", \"May\", \"Jun\", \"Jul\", \"Aug\", \"Sep\", \"Oct\", \"Nov\", \"Dec\"],\n\t\t\tlonghand: [\"January\", \"February\", \"March\", \"April\", \"May\", \"June\", \"July\", \"August\", \"September\", \"October\", \"November\", \"December\"]\n\t\t},\n\t\tdaysInMonth: [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31],\n\t\tfirstDayOfWeek: 0,\n\t\tordinal: function ordinal(nth) {\n\t\t\tvar s = nth % 100;\n\t\t\tif (s > 3 && s < 21) return \"th\";\n\t\t\tswitch (s % 10) {\n\t\t\t\tcase 1:\n\t\t\t\t\treturn \"st\";\n\t\t\t\tcase 2:\n\t\t\t\t\treturn \"nd\";\n\t\t\t\tcase 3:\n\t\t\t\t\treturn \"rd\";\n\t\t\t\tdefault:\n\t\t\t\t\treturn \"th\";\n\t\t\t}\n\t\t},\n\t\trangeSeparator: \" to \",\n\t\tweekAbbreviation: \"Wk\",\n\t\tscrollTitle: \"Scroll to increment\",\n\t\ttoggleTitle: \"Click to toggle\"\n\t}\n};\n\nflatpickr.l10ns.default = Object.create(flatpickr.l10ns.en);\nflatpickr.localize = function (l10n) {\n\treturn _extends(flatpickr.l10ns.default, l10n || {});\n};\nflatpickr.setDefaults = function (config) {\n\treturn _extends(flatpickr.defaultConfig, config || {});\n};\n\n/* istanbul ignore next */\nif (typeof jQuery !== \"undefined\") {\n\tjQuery.fn.flatpickr = function (config) {\n\t\treturn _flatpickr(this, config);\n\t};\n}\n\nDate.prototype.fp_incr = function (days) {\n\treturn new Date(this.getFullYear(), this.getMonth(), this.getDate() + parseInt(days, 10));\n};\n\nif (typeof module !== \"undefined\") module.exports = flatpickr;"
	}
});

 

And here’s the result of our openui5_theme subtask: for each of our openui5 theme we have 3 different compressed files.

 

That’s all folks!

Hope you have enjoyed this tutorial. As usual feel free to give me some feedback to improve it!

To report this post you need to login first.

Be the first to leave a comment

You must be Logged on to comment or reply to a post.

Leave a Reply