diff --git a/assets/air-datepicker/css/datepicker.css b/assets/air-datepicker/css/datepicker.css
new file mode 100644
index 0000000..a803fda
--- /dev/null
+++ b/assets/air-datepicker/css/datepicker.css
@@ -0,0 +1,622 @@
+.datepicker--cell-day.-other-month-, .datepicker--cell-year.-other-decade- {
+ color: #dedede; }
+ .datepicker--cell-day.-other-month-:hover, .datepicker--cell-year.-other-decade-:hover {
+ color: #c5c5c5; }
+ .-disabled-.-focus-.datepicker--cell-day.-other-month-, .-disabled-.-focus-.datepicker--cell-year.-other-decade- {
+ color: #dedede; }
+ .-selected-.datepicker--cell-day.-other-month-, .-selected-.datepicker--cell-year.-other-decade- {
+ color: #fff;
+ background: #a2ddf6; }
+ .-selected-.-focus-.datepicker--cell-day.-other-month-, .-selected-.-focus-.datepicker--cell-year.-other-decade- {
+ background: #8ad5f4; }
+ .-in-range-.datepicker--cell-day.-other-month-, .-in-range-.datepicker--cell-year.-other-decade- {
+ background-color: rgba(92, 196, 239, 0.1);
+ color: #cccccc; }
+ .-in-range-.-focus-.datepicker--cell-day.-other-month-, .-in-range-.-focus-.datepicker--cell-year.-other-decade- {
+ background-color: rgba(92, 196, 239, 0.2); }
+ .datepicker--cell-day.-other-month-:empty, .datepicker--cell-year.-other-decade-:empty {
+ background: none;
+ border: none; }
+
+/* -------------------------------------------------
+ Datepicker cells
+ ------------------------------------------------- */
+.datepicker--cells {
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-flex-wrap: wrap;
+ -ms-flex-wrap: wrap;
+ flex-wrap: wrap; }
+
+.datepicker--cell {
+ border-radius: 4px;
+ box-sizing: border-box;
+ cursor: pointer;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ position: relative;
+ -webkit-align-items: center;
+ -ms-flex-align: center;
+ align-items: center;
+ -webkit-justify-content: center;
+ -ms-flex-pack: center;
+ justify-content: center;
+ height: 32px;
+ z-index: 1; }
+ .datepicker--cell.-focus- {
+ background: #f0f0f0; }
+ .datepicker--cell.-current- {
+ color: #4EB5E6; }
+ .datepicker--cell.-current-.-focus- {
+ color: #4a4a4a; }
+ .datepicker--cell.-current-.-in-range- {
+ color: #4EB5E6; }
+ .datepicker--cell.-in-range- {
+ background: rgba(92, 196, 239, 0.1);
+ color: #4a4a4a;
+ border-radius: 0; }
+ .datepicker--cell.-in-range-.-focus- {
+ background-color: rgba(92, 196, 239, 0.2); }
+ .datepicker--cell.-disabled- {
+ cursor: default;
+ color: #aeaeae; }
+ .datepicker--cell.-disabled-.-focus- {
+ color: #aeaeae; }
+ .datepicker--cell.-disabled-.-in-range- {
+ color: #a1a1a1; }
+ .datepicker--cell.-disabled-.-current-.-focus- {
+ color: #aeaeae; }
+ .datepicker--cell.-range-from- {
+ border: 1px solid rgba(92, 196, 239, 0.5);
+ background-color: rgba(92, 196, 239, 0.1);
+ border-radius: 4px 0 0 4px; }
+ .datepicker--cell.-range-to- {
+ border: 1px solid rgba(92, 196, 239, 0.5);
+ background-color: rgba(92, 196, 239, 0.1);
+ border-radius: 0 4px 4px 0; }
+ .datepicker--cell.-range-from-.-range-to- {
+ border-radius: 4px; }
+ .datepicker--cell.-selected- {
+ color: #fff;
+ border: none;
+ background: #5cc4ef; }
+ .datepicker--cell.-selected-.-current- {
+ color: #fff;
+ background: #5cc4ef; }
+ .datepicker--cell.-selected-.-focus- {
+ background: #45bced; }
+ .datepicker--cell:empty {
+ cursor: default; }
+
+.datepicker--days-names {
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-flex-wrap: wrap;
+ -ms-flex-wrap: wrap;
+ flex-wrap: wrap;
+ margin: 8px 0 3px; }
+
+.datepicker--day-name {
+ color: #FF9A19;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-align-items: center;
+ -ms-flex-align: center;
+ align-items: center;
+ -webkit-justify-content: center;
+ -ms-flex-pack: center;
+ justify-content: center;
+ -webkit-flex: 1;
+ -ms-flex: 1;
+ flex: 1;
+ text-align: center;
+ text-transform: uppercase;
+ font-size: .8em; }
+
+.datepicker--cell-day {
+ width: 14.28571%; }
+
+.datepicker--cells-months {
+ height: 170px; }
+
+.datepicker--cell-month {
+ width: 33.33%;
+ height: 25%; }
+
+.datepicker--years {
+ height: 170px; }
+
+.datepicker--cells-years {
+ height: 170px; }
+
+.datepicker--cell-year {
+ width: 25%;
+ height: 33.33%; }
+
+.datepicker--cell-day.-other-month-, .datepicker--cell-year.-other-decade- {
+ color: #dedede; }
+ .datepicker--cell-day.-other-month-:hover, .datepicker--cell-year.-other-decade-:hover {
+ color: #c5c5c5; }
+ .-disabled-.-focus-.datepicker--cell-day.-other-month-, .-disabled-.-focus-.datepicker--cell-year.-other-decade- {
+ color: #dedede; }
+ .-selected-.datepicker--cell-day.-other-month-, .-selected-.datepicker--cell-year.-other-decade- {
+ color: #fff;
+ background: #a2ddf6; }
+ .-selected-.-focus-.datepicker--cell-day.-other-month-, .-selected-.-focus-.datepicker--cell-year.-other-decade- {
+ background: #8ad5f4; }
+ .-in-range-.datepicker--cell-day.-other-month-, .-in-range-.datepicker--cell-year.-other-decade- {
+ background-color: rgba(92, 196, 239, 0.1);
+ color: #cccccc; }
+ .-in-range-.-focus-.datepicker--cell-day.-other-month-, .-in-range-.-focus-.datepicker--cell-year.-other-decade- {
+ background-color: rgba(92, 196, 239, 0.2); }
+ .datepicker--cell-day.-other-month-:empty, .datepicker--cell-year.-other-decade-:empty {
+ background: none;
+ border: none; }
+
+/* -------------------------------------------------
+ Datepicker
+ ------------------------------------------------- */
+.datepickers-container {
+ position: absolute;
+ left: 0;
+ top: 0; }
+ @media print {
+ .datepickers-container {
+ display: none; } }
+
+.datepicker {
+ background: #fff;
+ border: 1px solid #dbdbdb;
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
+ border-radius: 4px;
+ box-sizing: content-box;
+ font-family: Tahoma, sans-serif;
+ font-size: 14px;
+ color: #4a4a4a;
+ width: 250px;
+ position: absolute;
+ left: -100000px;
+ opacity: 0;
+ transition: opacity 0.3s ease, left 0s 0.3s, -webkit-transform 0.3s ease;
+ transition: opacity 0.3s ease, transform 0.3s ease, left 0s 0.3s;
+ transition: opacity 0.3s ease, transform 0.3s ease, left 0s 0.3s, -webkit-transform 0.3s ease;
+ z-index: 100; }
+ .datepicker.-from-top- {
+ -webkit-transform: translateY(-8px);
+ transform: translateY(-8px); }
+ .datepicker.-from-right- {
+ -webkit-transform: translateX(8px);
+ transform: translateX(8px); }
+ .datepicker.-from-bottom- {
+ -webkit-transform: translateY(8px);
+ transform: translateY(8px); }
+ .datepicker.-from-left- {
+ -webkit-transform: translateX(-8px);
+ transform: translateX(-8px); }
+ .datepicker.active {
+ opacity: 1;
+ -webkit-transform: translate(0);
+ transform: translate(0);
+ transition: opacity 0.3s ease, left 0s 0s, -webkit-transform 0.3s ease;
+ transition: opacity 0.3s ease, transform 0.3s ease, left 0s 0s;
+ transition: opacity 0.3s ease, transform 0.3s ease, left 0s 0s, -webkit-transform 0.3s ease; }
+
+.datepicker-inline .datepicker {
+ border-color: #d7d7d7;
+ box-shadow: none;
+ position: static;
+ left: auto;
+ right: auto;
+ opacity: 1;
+ -webkit-transform: none;
+ transform: none; }
+
+.datepicker-inline .datepicker--pointer {
+ display: none; }
+
+.datepicker--content {
+ box-sizing: content-box;
+ padding: 4px; }
+ .-only-timepicker- .datepicker--content {
+ display: none; }
+
+.datepicker--pointer {
+ position: absolute;
+ background: #fff;
+ border-top: 1px solid #dbdbdb;
+ border-right: 1px solid #dbdbdb;
+ width: 10px;
+ height: 10px;
+ z-index: -1; }
+ .-top-left- .datepicker--pointer, .-top-center- .datepicker--pointer, .-top-right- .datepicker--pointer {
+ top: calc(100% - 4px);
+ -webkit-transform: rotate(135deg);
+ transform: rotate(135deg); }
+ .-right-top- .datepicker--pointer, .-right-center- .datepicker--pointer, .-right-bottom- .datepicker--pointer {
+ right: calc(100% - 4px);
+ -webkit-transform: rotate(225deg);
+ transform: rotate(225deg); }
+ .-bottom-left- .datepicker--pointer, .-bottom-center- .datepicker--pointer, .-bottom-right- .datepicker--pointer {
+ bottom: calc(100% - 4px);
+ -webkit-transform: rotate(315deg);
+ transform: rotate(315deg); }
+ .-left-top- .datepicker--pointer, .-left-center- .datepicker--pointer, .-left-bottom- .datepicker--pointer {
+ left: calc(100% - 4px);
+ -webkit-transform: rotate(45deg);
+ transform: rotate(45deg); }
+ .-top-left- .datepicker--pointer, .-bottom-left- .datepicker--pointer {
+ left: 10px; }
+ .-top-right- .datepicker--pointer, .-bottom-right- .datepicker--pointer {
+ right: 10px; }
+ .-top-center- .datepicker--pointer, .-bottom-center- .datepicker--pointer {
+ left: calc(50% - 10px / 2); }
+ .-left-top- .datepicker--pointer, .-right-top- .datepicker--pointer {
+ top: 10px; }
+ .-left-bottom- .datepicker--pointer, .-right-bottom- .datepicker--pointer {
+ bottom: 10px; }
+ .-left-center- .datepicker--pointer, .-right-center- .datepicker--pointer {
+ top: calc(50% - 10px / 2); }
+
+.datepicker--body {
+ display: none; }
+ .datepicker--body.active {
+ display: block; }
+
+.datepicker--cell-day.-other-month-, .datepicker--cell-year.-other-decade- {
+ color: #dedede; }
+ .datepicker--cell-day.-other-month-:hover, .datepicker--cell-year.-other-decade-:hover {
+ color: #c5c5c5; }
+ .-disabled-.-focus-.datepicker--cell-day.-other-month-, .-disabled-.-focus-.datepicker--cell-year.-other-decade- {
+ color: #dedede; }
+ .-selected-.datepicker--cell-day.-other-month-, .-selected-.datepicker--cell-year.-other-decade- {
+ color: #fff;
+ background: #a2ddf6; }
+ .-selected-.-focus-.datepicker--cell-day.-other-month-, .-selected-.-focus-.datepicker--cell-year.-other-decade- {
+ background: #8ad5f4; }
+ .-in-range-.datepicker--cell-day.-other-month-, .-in-range-.datepicker--cell-year.-other-decade- {
+ background-color: rgba(92, 196, 239, 0.1);
+ color: #cccccc; }
+ .-in-range-.-focus-.datepicker--cell-day.-other-month-, .-in-range-.-focus-.datepicker--cell-year.-other-decade- {
+ background-color: rgba(92, 196, 239, 0.2); }
+ .datepicker--cell-day.-other-month-:empty, .datepicker--cell-year.-other-decade-:empty {
+ background: none;
+ border: none; }
+
+/* -------------------------------------------------
+ Navigation
+ ------------------------------------------------- */
+.datepicker--nav {
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-justify-content: space-between;
+ -ms-flex-pack: justify;
+ justify-content: space-between;
+ border-bottom: 1px solid #efefef;
+ min-height: 32px;
+ padding: 4px; }
+ .-only-timepicker- .datepicker--nav {
+ display: none; }
+
+.datepicker--nav-title,
+.datepicker--nav-action {
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ cursor: pointer;
+ -webkit-align-items: center;
+ -ms-flex-align: center;
+ align-items: center;
+ -webkit-justify-content: center;
+ -ms-flex-pack: center;
+ justify-content: center; }
+
+.datepicker--nav-action {
+ width: 32px;
+ border-radius: 4px;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none; }
+ .datepicker--nav-action:hover {
+ background: #f0f0f0; }
+ .datepicker--nav-action.-disabled- {
+ visibility: hidden; }
+ .datepicker--nav-action svg {
+ width: 32px;
+ height: 32px; }
+ .datepicker--nav-action path {
+ fill: none;
+ stroke: #9c9c9c;
+ stroke-width: 2px; }
+
+.datepicker--nav-title {
+ border-radius: 4px;
+ padding: 0 8px; }
+ .datepicker--nav-title i {
+ font-style: normal;
+ color: #9c9c9c;
+ margin-left: 5px; }
+ .datepicker--nav-title:hover {
+ background: #f0f0f0; }
+ .datepicker--nav-title.-disabled- {
+ cursor: default;
+ background: none; }
+
+.datepicker--buttons {
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ padding: 4px;
+ border-top: 1px solid #efefef; }
+
+.datepicker--button {
+ color: #4EB5E6;
+ cursor: pointer;
+ border-radius: 4px;
+ -webkit-flex: 1;
+ -ms-flex: 1;
+ flex: 1;
+ display: -webkit-inline-flex;
+ display: -ms-inline-flexbox;
+ display: inline-flex;
+ -webkit-justify-content: center;
+ -ms-flex-pack: center;
+ justify-content: center;
+ -webkit-align-items: center;
+ -ms-flex-align: center;
+ align-items: center;
+ height: 32px; }
+ .datepicker--button:hover {
+ color: #4a4a4a;
+ background: #f0f0f0; }
+
+.datepicker--cell-day.-other-month-, .datepicker--cell-year.-other-decade- {
+ color: #dedede; }
+ .datepicker--cell-day.-other-month-:hover, .datepicker--cell-year.-other-decade-:hover {
+ color: #c5c5c5; }
+ .-disabled-.-focus-.datepicker--cell-day.-other-month-, .-disabled-.-focus-.datepicker--cell-year.-other-decade- {
+ color: #dedede; }
+ .-selected-.datepicker--cell-day.-other-month-, .-selected-.datepicker--cell-year.-other-decade- {
+ color: #fff;
+ background: #a2ddf6; }
+ .-selected-.-focus-.datepicker--cell-day.-other-month-, .-selected-.-focus-.datepicker--cell-year.-other-decade- {
+ background: #8ad5f4; }
+ .-in-range-.datepicker--cell-day.-other-month-, .-in-range-.datepicker--cell-year.-other-decade- {
+ background-color: rgba(92, 196, 239, 0.1);
+ color: #cccccc; }
+ .-in-range-.-focus-.datepicker--cell-day.-other-month-, .-in-range-.-focus-.datepicker--cell-year.-other-decade- {
+ background-color: rgba(92, 196, 239, 0.2); }
+ .datepicker--cell-day.-other-month-:empty, .datepicker--cell-year.-other-decade-:empty {
+ background: none;
+ border: none; }
+
+/* -------------------------------------------------
+ Timepicker
+ ------------------------------------------------- */
+.datepicker--time {
+ border-top: 1px solid #efefef;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-align-items: center;
+ -ms-flex-align: center;
+ align-items: center;
+ padding: 4px;
+ position: relative; }
+ .datepicker--time.-am-pm- .datepicker--time-sliders {
+ -webkit-flex: 0 1 138px;
+ -ms-flex: 0 1 138px;
+ flex: 0 1 138px;
+ max-width: 138px; }
+ .-only-timepicker- .datepicker--time {
+ border-top: none; }
+
+.datepicker--time-sliders {
+ -webkit-flex: 0 1 153px;
+ -ms-flex: 0 1 153px;
+ flex: 0 1 153px;
+ margin-right: 10px;
+ max-width: 153px; }
+
+.datepicker--time-label {
+ display: none;
+ font-size: 12px; }
+
+.datepicker--time-current {
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-align-items: center;
+ -ms-flex-align: center;
+ align-items: center;
+ -webkit-flex: 1;
+ -ms-flex: 1;
+ flex: 1;
+ font-size: 14px;
+ text-align: center;
+ margin: 0 0 0 10px; }
+
+.datepicker--time-current-colon {
+ margin: 0 2px 3px;
+ line-height: 1; }
+
+.datepicker--time-current-hours,
+.datepicker--time-current-minutes {
+ line-height: 1;
+ font-size: 19px;
+ font-family: "Century Gothic", CenturyGothic, AppleGothic, sans-serif;
+ position: relative;
+ z-index: 1; }
+ .datepicker--time-current-hours:after,
+ .datepicker--time-current-minutes:after {
+ content: '';
+ background: #f0f0f0;
+ border-radius: 4px;
+ position: absolute;
+ left: -2px;
+ top: -3px;
+ right: -2px;
+ bottom: -2px;
+ z-index: -1;
+ opacity: 0; }
+ .datepicker--time-current-hours.-focus-:after,
+ .datepicker--time-current-minutes.-focus-:after {
+ opacity: 1; }
+
+.datepicker--time-current-ampm {
+ text-transform: uppercase;
+ -webkit-align-self: flex-end;
+ -ms-flex-item-align: end;
+ align-self: flex-end;
+ color: #9c9c9c;
+ margin-left: 6px;
+ font-size: 11px;
+ margin-bottom: 1px; }
+
+.datepicker--time-row {
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-align-items: center;
+ -ms-flex-align: center;
+ align-items: center;
+ font-size: 11px;
+ height: 17px;
+ background: linear-gradient(to right, #dedede, #dedede) left 50%/100% 1px no-repeat; }
+ .datepicker--time-row:first-child {
+ margin-bottom: 4px; }
+ .datepicker--time-row input[type='range'] {
+ background: none;
+ cursor: pointer;
+ -webkit-flex: 1;
+ -ms-flex: 1;
+ flex: 1;
+ height: 100%;
+ padding: 0;
+ margin: 0;
+ -webkit-appearance: none; }
+ .datepicker--time-row input[type='range']::-webkit-slider-thumb {
+ -webkit-appearance: none; }
+ .datepicker--time-row input[type='range']::-ms-tooltip {
+ display: none; }
+ .datepicker--time-row input[type='range']:hover::-webkit-slider-thumb {
+ border-color: #b8b8b8; }
+ .datepicker--time-row input[type='range']:hover::-moz-range-thumb {
+ border-color: #b8b8b8; }
+ .datepicker--time-row input[type='range']:hover::-ms-thumb {
+ border-color: #b8b8b8; }
+ .datepicker--time-row input[type='range']:focus {
+ outline: none; }
+ .datepicker--time-row input[type='range']:focus::-webkit-slider-thumb {
+ background: #5cc4ef;
+ border-color: #5cc4ef; }
+ .datepicker--time-row input[type='range']:focus::-moz-range-thumb {
+ background: #5cc4ef;
+ border-color: #5cc4ef; }
+ .datepicker--time-row input[type='range']:focus::-ms-thumb {
+ background: #5cc4ef;
+ border-color: #5cc4ef; }
+ .datepicker--time-row input[type='range']::-webkit-slider-thumb {
+ box-sizing: border-box;
+ height: 12px;
+ width: 12px;
+ border-radius: 3px;
+ border: 1px solid #dedede;
+ background: #fff;
+ cursor: pointer;
+ transition: background .2s; }
+ .datepicker--time-row input[type='range']::-moz-range-thumb {
+ box-sizing: border-box;
+ height: 12px;
+ width: 12px;
+ border-radius: 3px;
+ border: 1px solid #dedede;
+ background: #fff;
+ cursor: pointer;
+ transition: background .2s; }
+ .datepicker--time-row input[type='range']::-ms-thumb {
+ box-sizing: border-box;
+ height: 12px;
+ width: 12px;
+ border-radius: 3px;
+ border: 1px solid #dedede;
+ background: #fff;
+ cursor: pointer;
+ transition: background .2s; }
+ .datepicker--time-row input[type='range']::-webkit-slider-thumb {
+ margin-top: -6px; }
+ .datepicker--time-row input[type='range']::-webkit-slider-runnable-track {
+ border: none;
+ height: 1px;
+ cursor: pointer;
+ color: transparent;
+ background: transparent; }
+ .datepicker--time-row input[type='range']::-moz-range-track {
+ border: none;
+ height: 1px;
+ cursor: pointer;
+ color: transparent;
+ background: transparent; }
+ .datepicker--time-row input[type='range']::-ms-track {
+ border: none;
+ height: 1px;
+ cursor: pointer;
+ color: transparent;
+ background: transparent; }
+ .datepicker--time-row input[type='range']::-ms-fill-lower {
+ background: transparent; }
+ .datepicker--time-row input[type='range']::-ms-fill-upper {
+ background: transparent; }
+ .datepicker--time-row span {
+ padding: 0 12px; }
+
+.datepicker--time-icon {
+ color: #9c9c9c;
+ border: 1px solid;
+ border-radius: 50%;
+ font-size: 16px;
+ position: relative;
+ margin: 0 5px -1px 0;
+ width: 1em;
+ height: 1em; }
+ .datepicker--time-icon:after, .datepicker--time-icon:before {
+ content: '';
+ background: currentColor;
+ position: absolute; }
+ .datepicker--time-icon:after {
+ height: .4em;
+ width: 1px;
+ left: calc(50% - 1px);
+ top: calc(50% + 1px);
+ -webkit-transform: translateY(-100%);
+ transform: translateY(-100%); }
+ .datepicker--time-icon:before {
+ width: .4em;
+ height: 1px;
+ top: calc(50% + 1px);
+ left: calc(50% - 1px); }
+
+.datepicker--cell-day.-other-month-, .datepicker--cell-year.-other-decade- {
+ color: #dedede; }
+ .datepicker--cell-day.-other-month-:hover, .datepicker--cell-year.-other-decade-:hover {
+ color: #c5c5c5; }
+ .-disabled-.-focus-.datepicker--cell-day.-other-month-, .-disabled-.-focus-.datepicker--cell-year.-other-decade- {
+ color: #dedede; }
+ .-selected-.datepicker--cell-day.-other-month-, .-selected-.datepicker--cell-year.-other-decade- {
+ color: #fff;
+ background: #a2ddf6; }
+ .-selected-.-focus-.datepicker--cell-day.-other-month-, .-selected-.-focus-.datepicker--cell-year.-other-decade- {
+ background: #8ad5f4; }
+ .-in-range-.datepicker--cell-day.-other-month-, .-in-range-.datepicker--cell-year.-other-decade- {
+ background-color: rgba(92, 196, 239, 0.1);
+ color: #cccccc; }
+ .-in-range-.-focus-.datepicker--cell-day.-other-month-, .-in-range-.-focus-.datepicker--cell-year.-other-decade- {
+ background-color: rgba(92, 196, 239, 0.2); }
+ .datepicker--cell-day.-other-month-:empty, .datepicker--cell-year.-other-decade-:empty {
+ background: none;
+ border: none; }
diff --git a/assets/air-datepicker/css/datepicker.min.css b/assets/air-datepicker/css/datepicker.min.css
new file mode 100644
index 0000000..bc3cd6c
--- /dev/null
+++ b/assets/air-datepicker/css/datepicker.min.css
@@ -0,0 +1 @@
+.datepicker--cells{display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.datepicker--cell{border-radius:4px;box-sizing:border-box;cursor:pointer;display:-webkit-flex;display:-ms-flexbox;display:flex;position:relative;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;height:32px;z-index:1}.datepicker--cell.-focus-{background:#f0f0f0}.datepicker--cell.-current-{color:#4EB5E6}.datepicker--cell.-current-.-focus-{color:#4a4a4a}.datepicker--cell.-current-.-in-range-{color:#4EB5E6}.datepicker--cell.-in-range-{background:rgba(92,196,239,.1);color:#4a4a4a;border-radius:0}.datepicker--cell.-in-range-.-focus-{background-color:rgba(92,196,239,.2)}.datepicker--cell.-disabled-{cursor:default;color:#aeaeae}.datepicker--cell.-disabled-.-focus-{color:#aeaeae}.datepicker--cell.-disabled-.-in-range-{color:#a1a1a1}.datepicker--cell.-disabled-.-current-.-focus-{color:#aeaeae}.datepicker--cell.-range-from-{border:1px solid rgba(92,196,239,.5);background-color:rgba(92,196,239,.1);border-radius:4px 0 0 4px}.datepicker--cell.-range-to-{border:1px solid rgba(92,196,239,.5);background-color:rgba(92,196,239,.1);border-radius:0 4px 4px 0}.datepicker--cell.-selected-,.datepicker--cell.-selected-.-current-{color:#fff;background:#5cc4ef}.datepicker--cell.-range-from-.-range-to-{border-radius:4px}.datepicker--cell.-selected-{border:none}.datepicker--cell.-selected-.-focus-{background:#45bced}.datepicker--cell:empty{cursor:default}.datepicker--days-names{display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;margin:8px 0 3px}.datepicker--day-name{color:#FF9A19;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;-webkit-flex:1;-ms-flex:1;flex:1;text-align:center;text-transform:uppercase;font-size:.8em}.-only-timepicker- .datepicker--content,.datepicker--body,.datepicker-inline .datepicker--pointer{display:none}.datepicker--cell-day{width:14.28571%}.datepicker--cells-months{height:170px}.datepicker--cell-month{width:33.33%;height:25%}.datepicker--cells-years,.datepicker--years{height:170px}.datepicker--cell-year{width:25%;height:33.33%}.datepickers-container{position:absolute;left:0;top:0}@media print{.datepickers-container{display:none}}.datepicker{background:#fff;border:1px solid #dbdbdb;box-shadow:0 4px 12px rgba(0,0,0,.15);border-radius:4px;box-sizing:content-box;font-family:Tahoma,sans-serif;font-size:14px;color:#4a4a4a;width:250px;position:absolute;left:-100000px;opacity:0;transition:opacity .3s ease,left 0s .3s,-webkit-transform .3s ease;transition:opacity .3s ease,transform .3s ease,left 0s .3s;transition:opacity .3s ease,transform .3s ease,left 0s .3s,-webkit-transform .3s ease;z-index:100}.datepicker.-from-top-{-webkit-transform:translateY(-8px);transform:translateY(-8px)}.datepicker.-from-right-{-webkit-transform:translateX(8px);transform:translateX(8px)}.datepicker.-from-bottom-{-webkit-transform:translateY(8px);transform:translateY(8px)}.datepicker.-from-left-{-webkit-transform:translateX(-8px);transform:translateX(-8px)}.datepicker.active{opacity:1;-webkit-transform:translate(0);transform:translate(0);transition:opacity .3s ease,left 0s 0s,-webkit-transform .3s ease;transition:opacity .3s ease,transform .3s ease,left 0s 0s;transition:opacity .3s ease,transform .3s ease,left 0s 0s,-webkit-transform .3s ease}.datepicker-inline .datepicker{border-color:#d7d7d7;box-shadow:none;position:static;left:auto;right:auto;opacity:1;-webkit-transform:none;transform:none}.datepicker--content{box-sizing:content-box;padding:4px}.datepicker--pointer{position:absolute;background:#fff;border-top:1px solid #dbdbdb;border-right:1px solid #dbdbdb;width:10px;height:10px;z-index:-1}.datepicker--nav-action:hover,.datepicker--nav-title:hover{background:#f0f0f0}.-top-center- .datepicker--pointer,.-top-left- .datepicker--pointer,.-top-right- .datepicker--pointer{top:calc(100% - 4px);-webkit-transform:rotate(135deg);transform:rotate(135deg)}.-right-bottom- .datepicker--pointer,.-right-center- .datepicker--pointer,.-right-top- .datepicker--pointer{right:calc(100% - 4px);-webkit-transform:rotate(225deg);transform:rotate(225deg)}.-bottom-center- .datepicker--pointer,.-bottom-left- .datepicker--pointer,.-bottom-right- .datepicker--pointer{bottom:calc(100% - 4px);-webkit-transform:rotate(315deg);transform:rotate(315deg)}.-left-bottom- .datepicker--pointer,.-left-center- .datepicker--pointer,.-left-top- .datepicker--pointer{left:calc(100% - 4px);-webkit-transform:rotate(45deg);transform:rotate(45deg)}.-bottom-left- .datepicker--pointer,.-top-left- .datepicker--pointer{left:10px}.-bottom-right- .datepicker--pointer,.-top-right- .datepicker--pointer{right:10px}.-bottom-center- .datepicker--pointer,.-top-center- .datepicker--pointer{left:calc(50% - 10px / 2)}.-left-top- .datepicker--pointer,.-right-top- .datepicker--pointer{top:10px}.-left-bottom- .datepicker--pointer,.-right-bottom- .datepicker--pointer{bottom:10px}.-left-center- .datepicker--pointer,.-right-center- .datepicker--pointer{top:calc(50% - 10px / 2)}.datepicker--body.active{display:block}.datepicker--nav{display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between;border-bottom:1px solid #efefef;min-height:32px;padding:4px}.-only-timepicker- .datepicker--nav{display:none}.datepicker--nav-action,.datepicker--nav-title{display:-webkit-flex;display:-ms-flexbox;display:flex;cursor:pointer;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center}.datepicker--nav-action{width:32px;border-radius:4px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.datepicker--nav-action.-disabled-{visibility:hidden}.datepicker--nav-action svg{width:32px;height:32px}.datepicker--nav-action path{fill:none;stroke:#9c9c9c;stroke-width:2px}.datepicker--nav-title{border-radius:4px;padding:0 8px}.datepicker--buttons,.datepicker--time{border-top:1px solid #efefef;padding:4px}.datepicker--nav-title i{font-style:normal;color:#9c9c9c;margin-left:5px}.datepicker--nav-title.-disabled-{cursor:default;background:0 0}.datepicker--buttons{display:-webkit-flex;display:-ms-flexbox;display:flex}.datepicker--button{color:#4EB5E6;cursor:pointer;border-radius:4px;-webkit-flex:1;-ms-flex:1;flex:1;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;height:32px}.datepicker--button:hover{color:#4a4a4a;background:#f0f0f0}.datepicker--time{display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-ms-flex-align:center;align-items:center;position:relative}.datepicker--time.-am-pm- .datepicker--time-sliders{-webkit-flex:0 1 138px;-ms-flex:0 1 138px;flex:0 1 138px;max-width:138px}.-only-timepicker- .datepicker--time{border-top:none}.datepicker--time-sliders{-webkit-flex:0 1 153px;-ms-flex:0 1 153px;flex:0 1 153px;margin-right:10px;max-width:153px}.datepicker--time-label{display:none;font-size:12px}.datepicker--time-current{display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-flex:1;-ms-flex:1;flex:1;font-size:14px;text-align:center;margin:0 0 0 10px}.datepicker--time-current-colon{margin:0 2px 3px;line-height:1}.datepicker--time-current-hours,.datepicker--time-current-minutes{line-height:1;font-size:19px;font-family:"Century Gothic",CenturyGothic,AppleGothic,sans-serif;position:relative;z-index:1}.datepicker--time-current-hours:after,.datepicker--time-current-minutes:after{content:'';background:#f0f0f0;border-radius:4px;position:absolute;left:-2px;top:-3px;right:-2px;bottom:-2px;z-index:-1;opacity:0}.datepicker--time-current-hours.-focus-:after,.datepicker--time-current-minutes.-focus-:after{opacity:1}.datepicker--time-current-ampm{text-transform:uppercase;-webkit-align-self:flex-end;-ms-flex-item-align:end;align-self:flex-end;color:#9c9c9c;margin-left:6px;font-size:11px;margin-bottom:1px}.datepicker--time-row{display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-ms-flex-align:center;align-items:center;font-size:11px;height:17px;background:linear-gradient(to right,#dedede,#dedede) left 50%/100% 1px no-repeat}.datepicker--time-row:first-child{margin-bottom:4px}.datepicker--time-row input[type=range]{background:0 0;cursor:pointer;-webkit-flex:1;-ms-flex:1;flex:1;height:100%;padding:0;margin:0;-webkit-appearance:none}.datepicker--time-row input[type=range]::-ms-tooltip{display:none}.datepicker--time-row input[type=range]:hover::-webkit-slider-thumb{border-color:#b8b8b8}.datepicker--time-row input[type=range]:hover::-moz-range-thumb{border-color:#b8b8b8}.datepicker--time-row input[type=range]:hover::-ms-thumb{border-color:#b8b8b8}.datepicker--time-row input[type=range]:focus{outline:0}.datepicker--time-row input[type=range]:focus::-webkit-slider-thumb{background:#5cc4ef;border-color:#5cc4ef}.datepicker--time-row input[type=range]:focus::-moz-range-thumb{background:#5cc4ef;border-color:#5cc4ef}.datepicker--time-row input[type=range]:focus::-ms-thumb{background:#5cc4ef;border-color:#5cc4ef}.datepicker--time-row input[type=range]::-webkit-slider-thumb{-webkit-appearance:none;box-sizing:border-box;height:12px;width:12px;border-radius:3px;border:1px solid #dedede;background:#fff;cursor:pointer;transition:background .2s;margin-top:-6px}.datepicker--time-row input[type=range]::-moz-range-thumb{box-sizing:border-box;height:12px;width:12px;border-radius:3px;border:1px solid #dedede;background:#fff;cursor:pointer;transition:background .2s}.datepicker--time-row input[type=range]::-ms-thumb{box-sizing:border-box;height:12px;width:12px;border-radius:3px;border:1px solid #dedede;background:#fff;cursor:pointer;transition:background .2s}.datepicker--time-row input[type=range]::-webkit-slider-runnable-track{border:none;height:1px;cursor:pointer;color:transparent;background:0 0}.datepicker--time-row input[type=range]::-moz-range-track{border:none;height:1px;cursor:pointer;color:transparent;background:0 0}.datepicker--time-row input[type=range]::-ms-track{border:none;height:1px;cursor:pointer;color:transparent;background:0 0}.datepicker--time-row input[type=range]::-ms-fill-lower{background:0 0}.datepicker--time-row input[type=range]::-ms-fill-upper{background:0 0}.datepicker--time-row span{padding:0 12px}.datepicker--time-icon{color:#9c9c9c;border:1px solid;border-radius:50%;font-size:16px;position:relative;margin:0 5px -1px 0;width:1em;height:1em}.datepicker--time-icon:after,.datepicker--time-icon:before{content:'';background:currentColor;position:absolute}.datepicker--time-icon:after{height:.4em;width:1px;left:calc(50% - 1px);top:calc(50% + 1px);-webkit-transform:translateY(-100%);transform:translateY(-100%)}.datepicker--time-icon:before{width:.4em;height:1px;top:calc(50% + 1px);left:calc(50% - 1px)}.datepicker--cell-day.-other-month-,.datepicker--cell-year.-other-decade-{color:#dedede}.datepicker--cell-day.-other-month-:hover,.datepicker--cell-year.-other-decade-:hover{color:#c5c5c5}.-disabled-.-focus-.datepicker--cell-day.-other-month-,.-disabled-.-focus-.datepicker--cell-year.-other-decade-{color:#dedede}.-selected-.datepicker--cell-day.-other-month-,.-selected-.datepicker--cell-year.-other-decade-{color:#fff;background:#a2ddf6}.-selected-.-focus-.datepicker--cell-day.-other-month-,.-selected-.-focus-.datepicker--cell-year.-other-decade-{background:#8ad5f4}.-in-range-.datepicker--cell-day.-other-month-,.-in-range-.datepicker--cell-year.-other-decade-{background-color:rgba(92,196,239,.1);color:#ccc}.-in-range-.-focus-.datepicker--cell-day.-other-month-,.-in-range-.-focus-.datepicker--cell-year.-other-decade-{background-color:rgba(92,196,239,.2)}.datepicker--cell-day.-other-month-:empty,.datepicker--cell-year.-other-decade-:empty{background:0 0;border:none}
\ No newline at end of file
diff --git a/assets/air-datepicker/js/datepicker.js b/assets/air-datepicker/js/datepicker.js
new file mode 100644
index 0000000..ad69b4f
--- /dev/null
+++ b/assets/air-datepicker/js/datepicker.js
@@ -0,0 +1,2236 @@
+;(function (window, $, undefined) { ;(function () {
+ var VERSION = '2.2.3',
+ pluginName = 'datepicker',
+ autoInitSelector = '.datepicker-here',
+ $body, $datepickersContainer,
+ containerBuilt = false,
+ baseTemplate = '' +
+ '
');
+
+ if(this.el.nodeName == 'INPUT') {
+ if (!this.opts.inline) {
+ $appendTarget = $datepickersContainer;
+ } else {
+ $appendTarget = $inline.insertAfter(this.$el)
+ }
+ } else {
+ $appendTarget = $inline.appendTo(this.$el)
+ }
+
+ this.$datepicker = $(baseTemplate).appendTo($appendTarget);
+ this.$content = $('.datepicker--content', this.$datepicker);
+ this.$nav = $('.datepicker--nav', this.$datepicker);
+ },
+
+ _triggerOnChange: function () {
+ if (!this.selectedDates.length) {
+ // Prevent from triggering multiple onSelect callback with same argument (empty string) in IE10-11
+ if (this._prevOnSelectValue === '') return;
+ this._prevOnSelectValue = '';
+ return this.opts.onSelect('', '', this);
+ }
+
+ var selectedDates = this.selectedDates,
+ parsedSelected = datepicker.getParsedDate(selectedDates[0]),
+ formattedDates,
+ _this = this,
+ dates = new Date(
+ parsedSelected.year,
+ parsedSelected.month,
+ parsedSelected.date,
+ parsedSelected.hours,
+ parsedSelected.minutes
+ );
+
+ formattedDates = selectedDates.map(function (date) {
+ return _this.formatDate(_this.loc.dateFormat, date)
+ }).join(this.opts.multipleDatesSeparator);
+
+ // Create new dates array, to separate it from original selectedDates
+ if (this.opts.multipleDates || this.opts.range) {
+ dates = selectedDates.map(function(date) {
+ var parsedDate = datepicker.getParsedDate(date);
+ return new Date(
+ parsedDate.year,
+ parsedDate.month,
+ parsedDate.date,
+ parsedDate.hours,
+ parsedDate.minutes
+ );
+ })
+ }
+
+ this._prevOnSelectValue = formattedDates;
+ this.opts.onSelect(formattedDates, dates, this);
+ },
+
+ next: function () {
+ var d = this.parsedDate,
+ o = this.opts;
+ switch (this.view) {
+ case 'days':
+ this.date = new Date(d.year, d.month + 1, 1);
+ if (o.onChangeMonth) o.onChangeMonth(this.parsedDate.month, this.parsedDate.year);
+ break;
+ case 'months':
+ this.date = new Date(d.year + 1, d.month, 1);
+ if (o.onChangeYear) o.onChangeYear(this.parsedDate.year);
+ break;
+ case 'years':
+ this.date = new Date(d.year + 10, 0, 1);
+ if (o.onChangeDecade) o.onChangeDecade(this.curDecade);
+ break;
+ }
+ },
+
+ prev: function () {
+ var d = this.parsedDate,
+ o = this.opts;
+ switch (this.view) {
+ case 'days':
+ this.date = new Date(d.year, d.month - 1, 1);
+ if (o.onChangeMonth) o.onChangeMonth(this.parsedDate.month, this.parsedDate.year);
+ break;
+ case 'months':
+ this.date = new Date(d.year - 1, d.month, 1);
+ if (o.onChangeYear) o.onChangeYear(this.parsedDate.year);
+ break;
+ case 'years':
+ this.date = new Date(d.year - 10, 0, 1);
+ if (o.onChangeDecade) o.onChangeDecade(this.curDecade);
+ break;
+ }
+ },
+
+ formatDate: function (string, date) {
+ date = date || this.date;
+ var result = string,
+ boundary = this._getWordBoundaryRegExp,
+ locale = this.loc,
+ leadingZero = datepicker.getLeadingZeroNum,
+ decade = datepicker.getDecade(date),
+ d = datepicker.getParsedDate(date),
+ fullHours = d.fullHours,
+ hours = d.hours,
+ ampm = string.match(boundary('aa')) || string.match(boundary('AA')),
+ dayPeriod = 'am',
+ replacer = this._replacer,
+ validHours;
+
+ if (this.opts.timepicker && this.timepicker && ampm) {
+ validHours = this.timepicker._getValidHoursFromDate(date, ampm);
+ fullHours = leadingZero(validHours.hours);
+ hours = validHours.hours;
+ dayPeriod = validHours.dayPeriod;
+ }
+
+ switch (true) {
+ case /@/.test(result):
+ result = result.replace(/@/, date.getTime());
+ case /aa/.test(result):
+ result = replacer(result, boundary('aa'), dayPeriod);
+ case /AA/.test(result):
+ result = replacer(result, boundary('AA'), dayPeriod.toUpperCase());
+ case /dd/.test(result):
+ result = replacer(result, boundary('dd'), d.fullDate);
+ case /d/.test(result):
+ result = replacer(result, boundary('d'), d.date);
+ case /DD/.test(result):
+ result = replacer(result, boundary('DD'), locale.days[d.day]);
+ case /D/.test(result):
+ result = replacer(result, boundary('D'), locale.daysShort[d.day]);
+ case /mm/.test(result):
+ result = replacer(result, boundary('mm'), d.fullMonth);
+ case /m/.test(result):
+ result = replacer(result, boundary('m'), d.month + 1);
+ case /MM/.test(result):
+ result = replacer(result, boundary('MM'), this.loc.months[d.month]);
+ case /M/.test(result):
+ result = replacer(result, boundary('M'), locale.monthsShort[d.month]);
+ case /ii/.test(result):
+ result = replacer(result, boundary('ii'), d.fullMinutes);
+ case /i/.test(result):
+ result = replacer(result, boundary('i'), d.minutes);
+ case /hh/.test(result):
+ result = replacer(result, boundary('hh'), fullHours);
+ case /h/.test(result):
+ result = replacer(result, boundary('h'), hours);
+ case /yyyy/.test(result):
+ result = replacer(result, boundary('yyyy'), d.year);
+ case /yyyy1/.test(result):
+ result = replacer(result, boundary('yyyy1'), decade[0]);
+ case /yyyy2/.test(result):
+ result = replacer(result, boundary('yyyy2'), decade[1]);
+ case /yy/.test(result):
+ result = replacer(result, boundary('yy'), d.year.toString().slice(-2));
+ }
+
+ return result;
+ },
+
+ _replacer: function (str, reg, data) {
+ return str.replace(reg, function (match, p1,p2,p3) {
+ return p1 + data + p3;
+ })
+ },
+
+ _getWordBoundaryRegExp: function (sign) {
+ var symbols = '\\s|\\.|-|/|\\\\|,|\\$|\\!|\\?|:|;';
+
+ return new RegExp('(^|>|' + symbols + ')(' + sign + ')($|<|' + symbols + ')', 'g');
+ },
+
+
+ selectDate: function (date) {
+ var _this = this,
+ opts = _this.opts,
+ d = _this.parsedDate,
+ selectedDates = _this.selectedDates,
+ len = selectedDates.length,
+ newDate = '';
+
+ if (Array.isArray(date)) {
+ date.forEach(function (d) {
+ _this.selectDate(d)
+ });
+ return;
+ }
+
+ if (!(date instanceof Date)) return;
+
+ this.lastSelectedDate = date;
+
+ // Set new time values from Date
+ if (this.timepicker) {
+ this.timepicker._setTime(date);
+ }
+
+ // On this step timepicker will set valid values in it's instance
+ _this._trigger('selectDate', date);
+
+ // Set correct time values after timepicker's validation
+ // Prevent from setting hours or minutes which values are lesser then `min` value or
+ // greater then `max` value
+ if (this.timepicker) {
+ date.setHours(this.timepicker.hours);
+ date.setMinutes(this.timepicker.minutes)
+ }
+
+ if (_this.view == 'days') {
+ if (date.getMonth() != d.month && opts.moveToOtherMonthsOnSelect) {
+ newDate = new Date(date.getFullYear(), date.getMonth(), 1);
+ }
+ }
+
+ if (_this.view == 'years') {
+ if (date.getFullYear() != d.year && opts.moveToOtherYearsOnSelect) {
+ newDate = new Date(date.getFullYear(), 0, 1);
+ }
+ }
+
+ if (newDate) {
+ _this.silent = true;
+ _this.date = newDate;
+ _this.silent = false;
+ _this.nav._render()
+ }
+
+ if (opts.multipleDates && !opts.range) { // Set priority to range functionality
+ if (len === opts.multipleDates) return;
+ if (!_this._isSelected(date)) {
+ _this.selectedDates.push(date);
+ }
+ } else if (opts.range) {
+ if (len == 2) {
+ _this.selectedDates = [date];
+ _this.minRange = date;
+ _this.maxRange = '';
+ } else if (len == 1) {
+ _this.selectedDates.push(date);
+ if (!_this.maxRange){
+ _this.maxRange = date;
+ } else {
+ _this.minRange = date;
+ }
+ // Swap dates if they were selected via dp.selectDate() and second date was smaller then first
+ if (datepicker.bigger(_this.maxRange, _this.minRange)) {
+ _this.maxRange = _this.minRange;
+ _this.minRange = date;
+ }
+ _this.selectedDates = [_this.minRange, _this.maxRange]
+
+ } else {
+ _this.selectedDates = [date];
+ _this.minRange = date;
+ }
+ } else {
+ _this.selectedDates = [date];
+ }
+
+ _this._setInputValue();
+
+ if (opts.onSelect) {
+ _this._triggerOnChange();
+ }
+
+ if (opts.autoClose && !this.timepickerIsActive) {
+ if (!opts.multipleDates && !opts.range) {
+ _this.hide();
+ } else if (opts.range && _this.selectedDates.length == 2) {
+ _this.hide();
+ }
+ }
+
+ _this.views[this.currentView]._render()
+ },
+
+ removeDate: function (date) {
+ var selected = this.selectedDates,
+ _this = this;
+
+ if (!(date instanceof Date)) return;
+
+ return selected.some(function (curDate, i) {
+ if (datepicker.isSame(curDate, date)) {
+ selected.splice(i, 1);
+
+ if (!_this.selectedDates.length) {
+ _this.minRange = '';
+ _this.maxRange = '';
+ _this.lastSelectedDate = '';
+ } else {
+ _this.lastSelectedDate = _this.selectedDates[_this.selectedDates.length - 1];
+ }
+
+ _this.views[_this.currentView]._render();
+ _this._setInputValue();
+
+ if (_this.opts.onSelect) {
+ _this._triggerOnChange();
+ }
+
+ return true
+ }
+ })
+ },
+
+ today: function () {
+ this.silent = true;
+ this.view = this.opts.minView;
+ this.silent = false;
+ this.date = new Date();
+
+ if (this.opts.todayButton instanceof Date) {
+ this.selectDate(this.opts.todayButton)
+ }
+ },
+
+ clear: function () {
+ this.selectedDates = [];
+ this.minRange = '';
+ this.maxRange = '';
+ this.views[this.currentView]._render();
+ this._setInputValue();
+ if (this.opts.onSelect) {
+ this._triggerOnChange()
+ }
+ },
+
+ /**
+ * Updates datepicker options
+ * @param {String|Object} param - parameter's name to update. If object then it will extend current options
+ * @param {String|Number|Object} [value] - new param value
+ */
+ update: function (param, value) {
+ var len = arguments.length,
+ lastSelectedDate = this.lastSelectedDate;
+
+ if (len == 2) {
+ this.opts[param] = value;
+ } else if (len == 1 && typeof param == 'object') {
+ this.opts = $.extend(true, this.opts, param)
+ }
+
+ this._createShortCuts();
+ this._syncWithMinMaxDates();
+ this._defineLocale(this.opts.language);
+ this.nav._addButtonsIfNeed();
+ if (!this.opts.onlyTimepicker) this.nav._render();
+ this.views[this.currentView]._render();
+
+ if (this.elIsInput && !this.opts.inline) {
+ this._setPositionClasses(this.opts.position);
+ if (this.visible) {
+ this.setPosition(this.opts.position)
+ }
+ }
+
+ if (this.opts.classes) {
+ this.$datepicker.addClass(this.opts.classes)
+ }
+
+ if (this.opts.onlyTimepicker) {
+ this.$datepicker.addClass('-only-timepicker-');
+ }
+
+ if (this.opts.timepicker) {
+ if (lastSelectedDate) this.timepicker._handleDate(lastSelectedDate);
+ this.timepicker._updateRanges();
+ this.timepicker._updateCurrentTime();
+ // Change hours and minutes if it's values have been changed through min/max hours/minutes
+ if (lastSelectedDate) {
+ lastSelectedDate.setHours(this.timepicker.hours);
+ lastSelectedDate.setMinutes(this.timepicker.minutes);
+ }
+ }
+
+ this._setInputValue();
+
+ return this;
+ },
+
+ _syncWithMinMaxDates: function () {
+ var curTime = this.date.getTime();
+ this.silent = true;
+ if (this.minTime > curTime) {
+ this.date = this.minDate;
+ }
+
+ if (this.maxTime < curTime) {
+ this.date = this.maxDate;
+ }
+ this.silent = false;
+ },
+
+ _isSelected: function (checkDate, cellType) {
+ var res = false;
+ this.selectedDates.some(function (date) {
+ if (datepicker.isSame(date, checkDate, cellType)) {
+ res = date;
+ return true;
+ }
+ });
+ return res;
+ },
+
+ _setInputValue: function () {
+ var _this = this,
+ opts = _this.opts,
+ format = _this.loc.dateFormat,
+ altFormat = opts.altFieldDateFormat,
+ value = _this.selectedDates.map(function (date) {
+ return _this.formatDate(format, date)
+ }),
+ altValues;
+
+ if (opts.altField && _this.$altField.length) {
+ altValues = this.selectedDates.map(function (date) {
+ return _this.formatDate(altFormat, date)
+ });
+ altValues = altValues.join(this.opts.multipleDatesSeparator);
+ this.$altField.val(altValues);
+ }
+
+ value = value.join(this.opts.multipleDatesSeparator);
+
+ this.$el.val(value)
+ },
+
+ /**
+ * Check if date is between minDate and maxDate
+ * @param date {object} - date object
+ * @param type {string} - cell type
+ * @returns {boolean}
+ * @private
+ */
+ _isInRange: function (date, type) {
+ var time = date.getTime(),
+ d = datepicker.getParsedDate(date),
+ min = datepicker.getParsedDate(this.minDate),
+ max = datepicker.getParsedDate(this.maxDate),
+ dMinTime = new Date(d.year, d.month, min.date).getTime(),
+ dMaxTime = new Date(d.year, d.month, max.date).getTime(),
+ types = {
+ day: time >= this.minTime && time <= this.maxTime,
+ month: dMinTime >= this.minTime && dMaxTime <= this.maxTime,
+ year: d.year >= min.year && d.year <= max.year
+ };
+ return type ? types[type] : types.day
+ },
+
+ _getDimensions: function ($el) {
+ var offset = $el.offset();
+
+ return {
+ width: $el.outerWidth(),
+ height: $el.outerHeight(),
+ left: offset.left,
+ top: offset.top
+ }
+ },
+
+ _getDateFromCell: function (cell) {
+ var curDate = this.parsedDate,
+ year = cell.data('year') || curDate.year,
+ month = cell.data('month') == undefined ? curDate.month : cell.data('month'),
+ date = cell.data('date') || 1;
+
+ return new Date(year, month, date);
+ },
+
+ _setPositionClasses: function (pos) {
+ pos = pos.split(' ');
+ var main = pos[0],
+ sec = pos[1],
+ classes = 'datepicker -' + main + '-' + sec + '- -from-' + main + '-';
+
+ if (this.visible) classes += ' active';
+
+ this.$datepicker
+ .removeAttr('class')
+ .addClass(classes);
+ },
+
+ setPosition: function (position) {
+ position = position || this.opts.position;
+
+ var dims = this._getDimensions(this.$el),
+ selfDims = this._getDimensions(this.$datepicker),
+ pos = position.split(' '),
+ top, left,
+ offset = this.opts.offset,
+ main = pos[0],
+ secondary = pos[1];
+
+ switch (main) {
+ case 'top':
+ top = dims.top - selfDims.height - offset;
+ break;
+ case 'right':
+ left = dims.left + dims.width + offset;
+ break;
+ case 'bottom':
+ top = dims.top + dims.height + offset;
+ break;
+ case 'left':
+ left = dims.left - selfDims.width - offset;
+ break;
+ }
+
+ switch(secondary) {
+ case 'top':
+ top = dims.top;
+ break;
+ case 'right':
+ left = dims.left + dims.width - selfDims.width;
+ break;
+ case 'bottom':
+ top = dims.top + dims.height - selfDims.height;
+ break;
+ case 'left':
+ left = dims.left;
+ break;
+ case 'center':
+ if (/left|right/.test(main)) {
+ top = dims.top + dims.height/2 - selfDims.height/2;
+ } else {
+ left = dims.left + dims.width/2 - selfDims.width/2;
+ }
+ }
+
+ this.$datepicker
+ .css({
+ left: left,
+ top: top
+ })
+ },
+
+ show: function () {
+ var onShow = this.opts.onShow;
+
+ this.setPosition(this.opts.position);
+ this.$datepicker.addClass('active');
+ this.visible = true;
+
+ if (onShow) {
+ this._bindVisionEvents(onShow)
+ }
+ },
+
+ hide: function () {
+ var onHide = this.opts.onHide;
+
+ this.$datepicker
+ .removeClass('active')
+ .css({
+ left: '-100000px'
+ });
+
+ this.focused = '';
+ this.keys = [];
+
+ this.inFocus = false;
+ this.visible = false;
+ this.$el.blur();
+
+ if (onHide) {
+ this._bindVisionEvents(onHide)
+ }
+ },
+
+ down: function (date) {
+ this._changeView(date, 'down');
+ },
+
+ up: function (date) {
+ this._changeView(date, 'up');
+ },
+
+ _bindVisionEvents: function (event) {
+ this.$datepicker.off('transitionend.dp');
+ event(this, false);
+ this.$datepicker.one('transitionend.dp', event.bind(this, this, true))
+ },
+
+ _changeView: function (date, dir) {
+ date = date || this.focused || this.date;
+
+ var nextView = dir == 'up' ? this.viewIndex + 1 : this.viewIndex - 1;
+ if (nextView > 2) nextView = 2;
+ if (nextView < 0) nextView = 0;
+
+ this.silent = true;
+ this.date = new Date(date.getFullYear(), date.getMonth(), 1);
+ this.silent = false;
+ this.view = this.viewIndexes[nextView];
+
+ },
+
+ _handleHotKey: function (key) {
+ var date = datepicker.getParsedDate(this._getFocusedDate()),
+ focusedParsed,
+ o = this.opts,
+ newDate,
+ totalDaysInNextMonth,
+ monthChanged = false,
+ yearChanged = false,
+ decadeChanged = false,
+ y = date.year,
+ m = date.month,
+ d = date.date;
+
+ switch (key) {
+ case 'ctrlRight':
+ case 'ctrlUp':
+ m += 1;
+ monthChanged = true;
+ break;
+ case 'ctrlLeft':
+ case 'ctrlDown':
+ m -= 1;
+ monthChanged = true;
+ break;
+ case 'shiftRight':
+ case 'shiftUp':
+ yearChanged = true;
+ y += 1;
+ break;
+ case 'shiftLeft':
+ case 'shiftDown':
+ yearChanged = true;
+ y -= 1;
+ break;
+ case 'altRight':
+ case 'altUp':
+ decadeChanged = true;
+ y += 10;
+ break;
+ case 'altLeft':
+ case 'altDown':
+ decadeChanged = true;
+ y -= 10;
+ break;
+ case 'ctrlShiftUp':
+ this.up();
+ break;
+ }
+
+ totalDaysInNextMonth = datepicker.getDaysCount(new Date(y,m));
+ newDate = new Date(y,m,d);
+
+ // If next month has less days than current, set date to total days in that month
+ if (totalDaysInNextMonth < d) d = totalDaysInNextMonth;
+
+ // Check if newDate is in valid range
+ if (newDate.getTime() < this.minTime) {
+ newDate = this.minDate;
+ } else if (newDate.getTime() > this.maxTime) {
+ newDate = this.maxDate;
+ }
+
+ this.focused = newDate;
+
+ focusedParsed = datepicker.getParsedDate(newDate);
+ if (monthChanged && o.onChangeMonth) {
+ o.onChangeMonth(focusedParsed.month, focusedParsed.year)
+ }
+ if (yearChanged && o.onChangeYear) {
+ o.onChangeYear(focusedParsed.year)
+ }
+ if (decadeChanged && o.onChangeDecade) {
+ o.onChangeDecade(this.curDecade)
+ }
+ },
+
+ _registerKey: function (key) {
+ var exists = this.keys.some(function (curKey) {
+ return curKey == key;
+ });
+
+ if (!exists) {
+ this.keys.push(key)
+ }
+ },
+
+ _unRegisterKey: function (key) {
+ var index = this.keys.indexOf(key);
+
+ this.keys.splice(index, 1);
+ },
+
+ _isHotKeyPressed: function () {
+ var currentHotKey,
+ found = false,
+ _this = this,
+ pressedKeys = this.keys.sort();
+
+ for (var hotKey in hotKeys) {
+ currentHotKey = hotKeys[hotKey];
+ if (pressedKeys.length != currentHotKey.length) continue;
+
+ if (currentHotKey.every(function (key, i) { return key == pressedKeys[i]})) {
+ _this._trigger('hotKey', hotKey);
+ found = true;
+ }
+ }
+
+ return found;
+ },
+
+ _trigger: function (event, args) {
+ this.$el.trigger(event, args)
+ },
+
+ _focusNextCell: function (keyCode, type) {
+ type = type || this.cellType;
+
+ var date = datepicker.getParsedDate(this._getFocusedDate()),
+ y = date.year,
+ m = date.month,
+ d = date.date;
+
+ if (this._isHotKeyPressed()){
+ return;
+ }
+
+ switch(keyCode) {
+ case 37: // left
+ type == 'day' ? (d -= 1) : '';
+ type == 'month' ? (m -= 1) : '';
+ type == 'year' ? (y -= 1) : '';
+ break;
+ case 38: // up
+ type == 'day' ? (d -= 7) : '';
+ type == 'month' ? (m -= 3) : '';
+ type == 'year' ? (y -= 4) : '';
+ break;
+ case 39: // right
+ type == 'day' ? (d += 1) : '';
+ type == 'month' ? (m += 1) : '';
+ type == 'year' ? (y += 1) : '';
+ break;
+ case 40: // down
+ type == 'day' ? (d += 7) : '';
+ type == 'month' ? (m += 3) : '';
+ type == 'year' ? (y += 4) : '';
+ break;
+ }
+
+ var nd = new Date(y,m,d);
+ if (nd.getTime() < this.minTime) {
+ nd = this.minDate;
+ } else if (nd.getTime() > this.maxTime) {
+ nd = this.maxDate;
+ }
+
+ this.focused = nd;
+
+ },
+
+ _getFocusedDate: function () {
+ var focused = this.focused || this.selectedDates[this.selectedDates.length - 1],
+ d = this.parsedDate;
+
+ if (!focused) {
+ switch (this.view) {
+ case 'days':
+ focused = new Date(d.year, d.month, new Date().getDate());
+ break;
+ case 'months':
+ focused = new Date(d.year, d.month, 1);
+ break;
+ case 'years':
+ focused = new Date(d.year, 0, 1);
+ break;
+ }
+ }
+
+ return focused;
+ },
+
+ _getCell: function (date, type) {
+ type = type || this.cellType;
+
+ var d = datepicker.getParsedDate(date),
+ selector = '.datepicker--cell[data-year="' + d.year + '"]',
+ $cell;
+
+ switch (type) {
+ case 'month':
+ selector = '[data-month="' + d.month + '"]';
+ break;
+ case 'day':
+ selector += '[data-month="' + d.month + '"][data-date="' + d.date + '"]';
+ break;
+ }
+ $cell = this.views[this.currentView].$el.find(selector);
+
+ return $cell.length ? $cell : $('');
+ },
+
+ destroy: function () {
+ var _this = this;
+ _this.$el
+ .off('.adp')
+ .data('datepicker', '');
+
+ _this.selectedDates = [];
+ _this.focused = '';
+ _this.views = {};
+ _this.keys = [];
+ _this.minRange = '';
+ _this.maxRange = '';
+
+ if (_this.opts.inline || !_this.elIsInput) {
+ _this.$datepicker.closest('.datepicker-inline').remove();
+ } else {
+ _this.$datepicker.remove();
+ }
+ },
+
+ _handleAlreadySelectedDates: function (alreadySelected, selectedDate) {
+ if (this.opts.range) {
+ if (!this.opts.toggleSelected) {
+ // Add possibility to select same date when range is true
+ if (this.selectedDates.length != 2) {
+ this._trigger('clickCell', selectedDate);
+ }
+ } else {
+ this.removeDate(selectedDate);
+ }
+ } else if (this.opts.toggleSelected){
+ this.removeDate(selectedDate);
+ }
+
+ // Change last selected date to be able to change time when clicking on this cell
+ if (!this.opts.toggleSelected) {
+ this.lastSelectedDate = alreadySelected;
+ if (this.opts.timepicker) {
+ this.timepicker._setTime(alreadySelected);
+ this.timepicker.update();
+ }
+ }
+ },
+
+ _onShowEvent: function (e) {
+ if (!this.visible) {
+ this.show();
+ }
+ },
+
+ _onBlur: function () {
+ if (!this.inFocus && this.visible) {
+ this.hide();
+ }
+ },
+
+ _onMouseDownDatepicker: function (e) {
+ this.inFocus = true;
+ },
+
+ _onMouseUpDatepicker: function (e) {
+ this.inFocus = false;
+ e.originalEvent.inFocus = true;
+ if (!e.originalEvent.timepickerFocus) this.$el.focus();
+ },
+
+ _onKeyUpGeneral: function (e) {
+ var val = this.$el.val();
+
+ if (!val) {
+ this.clear();
+ }
+ },
+
+ _onResize: function () {
+ if (this.visible) {
+ this.setPosition();
+ }
+ },
+
+ _onMouseUpBody: function (e) {
+ if (e.originalEvent.inFocus) return;
+
+ if (this.visible && !this.inFocus) {
+ this.hide();
+ }
+ },
+
+ _onMouseUpEl: function (e) {
+ e.originalEvent.inFocus = true;
+ setTimeout(this._onKeyUpGeneral.bind(this),4);
+ },
+
+ _onKeyDown: function (e) {
+ var code = e.which;
+ this._registerKey(code);
+
+ // Arrows
+ if (code >= 37 && code <= 40) {
+ e.preventDefault();
+ this._focusNextCell(code);
+ }
+
+ // Enter
+ if (code == 13) {
+ if (this.focused) {
+ if (this._getCell(this.focused).hasClass('-disabled-')) return;
+ if (this.view != this.opts.minView) {
+ this.down()
+ } else {
+ var alreadySelected = this._isSelected(this.focused, this.cellType);
+
+ if (!alreadySelected) {
+ if (this.timepicker) {
+ this.focused.setHours(this.timepicker.hours);
+ this.focused.setMinutes(this.timepicker.minutes);
+ }
+ this.selectDate(this.focused);
+ return;
+ }
+ this._handleAlreadySelectedDates(alreadySelected, this.focused)
+ }
+ }
+ }
+
+ // Esc
+ if (code == 27) {
+ this.hide();
+ }
+ },
+
+ _onKeyUp: function (e) {
+ var code = e.which;
+ this._unRegisterKey(code);
+ },
+
+ _onHotKey: function (e, hotKey) {
+ this._handleHotKey(hotKey);
+ },
+
+ _onMouseEnterCell: function (e) {
+ var $cell = $(e.target).closest('.datepicker--cell'),
+ date = this._getDateFromCell($cell);
+
+ // Prevent from unnecessary rendering and setting new currentDate
+ this.silent = true;
+
+ if (this.focused) {
+ this.focused = ''
+ }
+
+ $cell.addClass('-focus-');
+
+ this.focused = date;
+ this.silent = false;
+
+ if (this.opts.range && this.selectedDates.length == 1) {
+ this.minRange = this.selectedDates[0];
+ this.maxRange = '';
+ if (datepicker.less(this.minRange, this.focused)) {
+ this.maxRange = this.minRange;
+ this.minRange = '';
+ }
+ this.views[this.currentView]._update();
+ }
+ },
+
+ _onMouseLeaveCell: function (e) {
+ var $cell = $(e.target).closest('.datepicker--cell');
+
+ $cell.removeClass('-focus-');
+
+ this.silent = true;
+ this.focused = '';
+ this.silent = false;
+ },
+
+ _onTimeChange: function (e, h, m) {
+ var date = new Date(),
+ selectedDates = this.selectedDates,
+ selected = false;
+
+ if (selectedDates.length) {
+ selected = true;
+ date = this.lastSelectedDate;
+ }
+
+ date.setHours(h);
+ date.setMinutes(m);
+
+ if (!selected && !this._getCell(date).hasClass('-disabled-')) {
+ this.selectDate(date);
+ } else {
+ this._setInputValue();
+ if (this.opts.onSelect) {
+ this._triggerOnChange();
+ }
+ }
+ },
+
+ _onClickCell: function (e, date) {
+ if (this.timepicker) {
+ date.setHours(this.timepicker.hours);
+ date.setMinutes(this.timepicker.minutes);
+ }
+ this.selectDate(date);
+ },
+
+ set focused(val) {
+ if (!val && this.focused) {
+ var $cell = this._getCell(this.focused);
+
+ if ($cell.length) {
+ $cell.removeClass('-focus-')
+ }
+ }
+ this._focused = val;
+ if (this.opts.range && this.selectedDates.length == 1) {
+ this.minRange = this.selectedDates[0];
+ this.maxRange = '';
+ if (datepicker.less(this.minRange, this._focused)) {
+ this.maxRange = this.minRange;
+ this.minRange = '';
+ }
+ }
+ if (this.silent) return;
+ this.date = val;
+ },
+
+ get focused() {
+ return this._focused;
+ },
+
+ get parsedDate() {
+ return datepicker.getParsedDate(this.date);
+ },
+
+ set date (val) {
+ if (!(val instanceof Date)) return;
+
+ this.currentDate = val;
+
+ if (this.inited && !this.silent) {
+ this.views[this.view]._render();
+ this.nav._render();
+ if (this.visible && this.elIsInput) {
+ this.setPosition();
+ }
+ }
+ return val;
+ },
+
+ get date () {
+ return this.currentDate
+ },
+
+ set view (val) {
+ this.viewIndex = this.viewIndexes.indexOf(val);
+
+ if (this.viewIndex < 0) {
+ return;
+ }
+
+ this.prevView = this.currentView;
+ this.currentView = val;
+
+ if (this.inited) {
+ if (!this.views[val]) {
+ this.views[val] = new $.fn.datepicker.Body(this, val, this.opts)
+ } else {
+ this.views[val]._render();
+ }
+
+ this.views[this.prevView].hide();
+ this.views[val].show();
+ this.nav._render();
+
+ if (this.opts.onChangeView) {
+ this.opts.onChangeView(val)
+ }
+ if (this.elIsInput && this.visible) this.setPosition();
+ }
+
+ return val
+ },
+
+ get view() {
+ return this.currentView;
+ },
+
+ get cellType() {
+ return this.view.substring(0, this.view.length - 1)
+ },
+
+ get minTime() {
+ var min = datepicker.getParsedDate(this.minDate);
+ return new Date(min.year, min.month, min.date).getTime()
+ },
+
+ get maxTime() {
+ var max = datepicker.getParsedDate(this.maxDate);
+ return new Date(max.year, max.month, max.date).getTime()
+ },
+
+ get curDecade() {
+ return datepicker.getDecade(this.date)
+ }
+ };
+
+ // Utils
+ // -------------------------------------------------
+
+ datepicker.getDaysCount = function (date) {
+ return new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate();
+ };
+
+ datepicker.getParsedDate = function (date) {
+ return {
+ year: date.getFullYear(),
+ month: date.getMonth(),
+ fullMonth: (date.getMonth() + 1) < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1, // One based
+ date: date.getDate(),
+ fullDate: date.getDate() < 10 ? '0' + date.getDate() : date.getDate(),
+ day: date.getDay(),
+ hours: date.getHours(),
+ fullHours: date.getHours() < 10 ? '0' + date.getHours() : date.getHours() ,
+ minutes: date.getMinutes(),
+ fullMinutes: date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes()
+ }
+ };
+
+ datepicker.getDecade = function (date) {
+ var firstYear = Math.floor(date.getFullYear() / 10) * 10;
+
+ return [firstYear, firstYear + 9];
+ };
+
+ datepicker.template = function (str, data) {
+ return str.replace(/#\{([\w]+)\}/g, function (source, match) {
+ if (data[match] || data[match] === 0) {
+ return data[match]
+ }
+ });
+ };
+
+ datepicker.isSame = function (date1, date2, type) {
+ if (!date1 || !date2) return false;
+ var d1 = datepicker.getParsedDate(date1),
+ d2 = datepicker.getParsedDate(date2),
+ _type = type ? type : 'day',
+
+ conditions = {
+ day: d1.date == d2.date && d1.month == d2.month && d1.year == d2.year,
+ month: d1.month == d2.month && d1.year == d2.year,
+ year: d1.year == d2.year
+ };
+
+ return conditions[_type];
+ };
+
+ datepicker.less = function (dateCompareTo, date, type) {
+ if (!dateCompareTo || !date) return false;
+ return date.getTime() < dateCompareTo.getTime();
+ };
+
+ datepicker.bigger = function (dateCompareTo, date, type) {
+ if (!dateCompareTo || !date) return false;
+ return date.getTime() > dateCompareTo.getTime();
+ };
+
+ datepicker.getLeadingZeroNum = function (num) {
+ return parseInt(num) < 10 ? '0' + num : num;
+ };
+
+ /**
+ * Returns copy of date with hours and minutes equals to 0
+ * @param date {Date}
+ */
+ datepicker.resetTime = function (date) {
+ if (typeof date != 'object') return;
+ date = datepicker.getParsedDate(date);
+ return new Date(date.year, date.month, date.date)
+ };
+
+ $.fn.datepicker = function ( options ) {
+ return this.each(function () {
+ if (!$.data(this, pluginName)) {
+ $.data(this, pluginName,
+ new Datepicker( this, options ));
+ } else {
+ var _this = $.data(this, pluginName);
+
+ _this.opts = $.extend(true, _this.opts, options);
+ _this.update();
+ }
+ });
+ };
+
+ $.fn.datepicker.Constructor = Datepicker;
+
+ $.fn.datepicker.language = {
+ ru: {
+ days: ['Воскресенье', 'Понедельник', 'Вторник', 'Среда', 'Четверг', 'Пятница', 'Суббота'],
+ daysShort: ['Вос','Пон','Вто','Сре','Чет','Пят','Суб'],
+ daysMin: ['Вс','Пн','Вт','Ср','Чт','Пт','Сб'],
+ months: ['Январь', 'Февраль', 'Март', 'Апрель', 'Май', 'Июнь', 'Июль', 'Август', 'Сентябрь', 'Октябрь', 'Ноябрь', 'Декабрь'],
+ monthsShort: ['Янв', 'Фев', 'Мар', 'Апр', 'Май', 'Июн', 'Июл', 'Авг', 'Сен', 'Окт', 'Ноя', 'Дек'],
+ today: 'Сегодня',
+ clear: 'Очистить',
+ dateFormat: 'dd.mm.yyyy',
+ timeFormat: 'hh:ii',
+ firstDay: 1
+ }
+ };
+
+ $(function () {
+ $(autoInitSelector).datepicker();
+ })
+
+})();
+
+;(function () {
+ var templates = {
+ days:'' +
+ '
',
+ months: '' +
+ '
',
+ years: '' +
+ '
'
+ },
+ datepicker = $.fn.datepicker,
+ dp = datepicker.Constructor;
+
+ datepicker.Body = function (d, type, opts) {
+ this.d = d;
+ this.type = type;
+ this.opts = opts;
+ this.$el = $('');
+
+ if (this.opts.onlyTimepicker) return;
+ this.init();
+ };
+
+ datepicker.Body.prototype = {
+ init: function () {
+ this._buildBaseHtml();
+ this._render();
+
+ this._bindEvents();
+ },
+
+ _bindEvents: function () {
+ this.$el.on('click', '.datepicker--cell', $.proxy(this._onClickCell, this));
+ },
+
+ _buildBaseHtml: function () {
+ this.$el = $(templates[this.type]).appendTo(this.d.$content);
+ this.$names = $('.datepicker--days-names', this.$el);
+ this.$cells = $('.datepicker--cells', this.$el);
+ },
+
+ _getDayNamesHtml: function (firstDay, curDay, html, i) {
+ curDay = curDay != undefined ? curDay : firstDay;
+ html = html ? html : '';
+ i = i != undefined ? i : 0;
+
+ if (i > 7) return html;
+ if (curDay == 7) return this._getDayNamesHtml(firstDay, 0, html, ++i);
+
+ html += '
' + this.d.loc.daysMin[curDay] + '
';
+
+ return this._getDayNamesHtml(firstDay, ++curDay, html, ++i);
+ },
+
+ _getCellContents: function (date, type) {
+ var classes = "datepicker--cell datepicker--cell-" + type,
+ currentDate = new Date(),
+ parent = this.d,
+ minRange = dp.resetTime(parent.minRange),
+ maxRange = dp.resetTime(parent.maxRange),
+ opts = parent.opts,
+ d = dp.getParsedDate(date),
+ render = {},
+ html = d.date;
+
+ switch (type) {
+ case 'day':
+ if (parent.isWeekend(d.day)) classes += " -weekend-";
+ if (d.month != this.d.parsedDate.month) {
+ classes += " -other-month-";
+ if (!opts.selectOtherMonths) {
+ classes += " -disabled-";
+ }
+ if (!opts.showOtherMonths) html = '';
+ }
+ break;
+ case 'month':
+ html = parent.loc[parent.opts.monthsField][d.month];
+ break;
+ case 'year':
+ var decade = parent.curDecade;
+ html = d.year;
+ if (d.year < decade[0] || d.year > decade[1]) {
+ classes += ' -other-decade-';
+ if (!opts.selectOtherYears) {
+ classes += " -disabled-";
+ }
+ if (!opts.showOtherYears) html = '';
+ }
+ break;
+ }
+
+ if (opts.onRenderCell) {
+ render = opts.onRenderCell(date, type) || {};
+ html = render.html ? render.html : html;
+ classes += render.classes ? ' ' + render.classes : '';
+ }
+
+ if (opts.range) {
+ if (dp.isSame(minRange, date, type)) classes += ' -range-from-';
+ if (dp.isSame(maxRange, date, type)) classes += ' -range-to-';
+
+ if (parent.selectedDates.length == 1 && parent.focused) {
+ if (
+ (dp.bigger(minRange, date) && dp.less(parent.focused, date)) ||
+ (dp.less(maxRange, date) && dp.bigger(parent.focused, date)))
+ {
+ classes += ' -in-range-'
+ }
+
+ if (dp.less(maxRange, date) && dp.isSame(parent.focused, date)) {
+ classes += ' -range-from-'
+ }
+ if (dp.bigger(minRange, date) && dp.isSame(parent.focused, date)) {
+ classes += ' -range-to-'
+ }
+
+ } else if (parent.selectedDates.length == 2) {
+ if (dp.bigger(minRange, date) && dp.less(maxRange, date)) {
+ classes += ' -in-range-'
+ }
+ }
+ }
+
+
+ if (dp.isSame(currentDate, date, type)) classes += ' -current-';
+ if (parent.focused && dp.isSame(date, parent.focused, type)) classes += ' -focus-';
+ if (parent._isSelected(date, type)) classes += ' -selected-';
+ if (!parent._isInRange(date, type) || render.disabled) classes += ' -disabled-';
+
+ return {
+ html: html,
+ classes: classes
+ }
+ },
+
+ /**
+ * Calculates days number to render. Generates days html and returns it.
+ * @param {object} date - Date object
+ * @returns {string}
+ * @private
+ */
+ _getDaysHtml: function (date) {
+ var totalMonthDays = dp.getDaysCount(date),
+ firstMonthDay = new Date(date.getFullYear(), date.getMonth(), 1).getDay(),
+ lastMonthDay = new Date(date.getFullYear(), date.getMonth(), totalMonthDays).getDay(),
+ daysFromPevMonth = firstMonthDay - this.d.loc.firstDay,
+ daysFromNextMonth = 6 - lastMonthDay + this.d.loc.firstDay;
+
+ daysFromPevMonth = daysFromPevMonth < 0 ? daysFromPevMonth + 7 : daysFromPevMonth;
+ daysFromNextMonth = daysFromNextMonth > 6 ? daysFromNextMonth - 7 : daysFromNextMonth;
+
+ var startDayIndex = -daysFromPevMonth + 1,
+ m, y,
+ html = '';
+
+ for (var i = startDayIndex, max = totalMonthDays + daysFromNextMonth; i <= max; i++) {
+ y = date.getFullYear();
+ m = date.getMonth();
+
+ html += this._getDayHtml(new Date(y, m, i))
+ }
+
+ return html;
+ },
+
+ _getDayHtml: function (date) {
+ var content = this._getCellContents(date, 'day');
+
+ return '
' + content.html + '
';
+ },
+
+ /**
+ * Generates months html
+ * @param {object} date - date instance
+ * @returns {string}
+ * @private
+ */
+ _getMonthsHtml: function (date) {
+ var html = '',
+ d = dp.getParsedDate(date),
+ i = 0;
+
+ while(i < 12) {
+ html += this._getMonthHtml(new Date(d.year, i));
+ i++
+ }
+
+ return html;
+ },
+
+ _getMonthHtml: function (date) {
+ var content = this._getCellContents(date, 'month');
+
+ return '
' + content.html + '
'
+ },
+
+ _getYearsHtml: function (date) {
+ var d = dp.getParsedDate(date),
+ decade = dp.getDecade(date),
+ firstYear = decade[0] - 1,
+ html = '',
+ i = firstYear;
+
+ for (i; i <= decade[1] + 1; i++) {
+ html += this._getYearHtml(new Date(i , 0));
+ }
+
+ return html;
+ },
+
+ _getYearHtml: function (date) {
+ var content = this._getCellContents(date, 'year');
+
+ return '
' + content.html + '
'
+ },
+
+ _renderTypes: {
+ days: function () {
+ var dayNames = this._getDayNamesHtml(this.d.loc.firstDay),
+ days = this._getDaysHtml(this.d.currentDate);
+
+ this.$cells.html(days);
+ this.$names.html(dayNames)
+ },
+ months: function () {
+ var html = this._getMonthsHtml(this.d.currentDate);
+
+ this.$cells.html(html)
+ },
+ years: function () {
+ var html = this._getYearsHtml(this.d.currentDate);
+
+ this.$cells.html(html)
+ }
+ },
+
+ _render: function () {
+ if (this.opts.onlyTimepicker) return;
+ this._renderTypes[this.type].bind(this)();
+ },
+
+ _update: function () {
+ var $cells = $('.datepicker--cell', this.$cells),
+ _this = this,
+ classes,
+ $cell,
+ date;
+ $cells.each(function (cell, i) {
+ $cell = $(this);
+ date = _this.d._getDateFromCell($(this));
+ classes = _this._getCellContents(date, _this.d.cellType);
+ $cell.attr('class',classes.classes)
+ });
+ },
+
+ show: function () {
+ if (this.opts.onlyTimepicker) return;
+ this.$el.addClass('active');
+ this.acitve = true;
+ },
+
+ hide: function () {
+ this.$el.removeClass('active');
+ this.active = false;
+ },
+
+ // Events
+ // -------------------------------------------------
+
+ _handleClick: function (el) {
+ var date = el.data('date') || 1,
+ month = el.data('month') || 0,
+ year = el.data('year') || this.d.parsedDate.year,
+ dp = this.d;
+ // Change view if min view does not reach yet
+ if (dp.view != this.opts.minView) {
+ dp.down(new Date(year, month, date));
+ return;
+ }
+ // Select date if min view is reached
+ var selectedDate = new Date(year, month, date),
+ alreadySelected = this.d._isSelected(selectedDate, this.d.cellType);
+
+ if (!alreadySelected) {
+ dp._trigger('clickCell', selectedDate);
+ return;
+ }
+
+ dp._handleAlreadySelectedDates.bind(dp, alreadySelected, selectedDate)();
+
+ },
+
+ _onClickCell: function (e) {
+ var $el = $(e.target).closest('.datepicker--cell');
+
+ if ($el.hasClass('-disabled-')) return;
+
+ this._handleClick.bind(this)($el);
+ }
+ };
+})();
+
+;(function () {
+ var template = '' +
+ '
#{prevHtml}
' +
+ '
#{title}
' +
+ '
#{nextHtml}
',
+ buttonsContainerTemplate = '
',
+ button = '
#{label}',
+ datepicker = $.fn.datepicker,
+ dp = datepicker.Constructor;
+
+ datepicker.Navigation = function (d, opts) {
+ this.d = d;
+ this.opts = opts;
+
+ this.$buttonsContainer = '';
+
+ this.init();
+ };
+
+ datepicker.Navigation.prototype = {
+ init: function () {
+ this._buildBaseHtml();
+ this._bindEvents();
+ },
+
+ _bindEvents: function () {
+ this.d.$nav.on('click', '.datepicker--nav-action', $.proxy(this._onClickNavButton, this));
+ this.d.$nav.on('click', '.datepicker--nav-title', $.proxy(this._onClickNavTitle, this));
+ this.d.$datepicker.on('click', '.datepicker--button', $.proxy(this._onClickNavButton, this));
+ },
+
+ _buildBaseHtml: function () {
+ if (!this.opts.onlyTimepicker) {
+ this._render();
+ }
+ this._addButtonsIfNeed();
+ },
+
+ _addButtonsIfNeed: function () {
+ if (this.opts.todayButton) {
+ this._addButton('today')
+ }
+ if (this.opts.clearButton) {
+ this._addButton('clear')
+ }
+ },
+
+ _render: function () {
+ var title = this._getTitle(this.d.currentDate),
+ html = dp.template(template, $.extend({title: title}, this.opts));
+ this.d.$nav.html(html);
+ if (this.d.view == 'years') {
+ $('.datepicker--nav-title', this.d.$nav).addClass('-disabled-');
+ }
+ this.setNavStatus();
+ },
+
+ _getTitle: function (date) {
+ return this.d.formatDate(this.opts.navTitles[this.d.view], date)
+ },
+
+ _addButton: function (type) {
+ if (!this.$buttonsContainer.length) {
+ this._addButtonsContainer();
+ }
+
+ var data = {
+ action: type,
+ label: this.d.loc[type]
+ },
+ html = dp.template(button, data);
+
+ if ($('[data-action=' + type + ']', this.$buttonsContainer).length) return;
+ this.$buttonsContainer.append(html);
+ },
+
+ _addButtonsContainer: function () {
+ this.d.$datepicker.append(buttonsContainerTemplate);
+ this.$buttonsContainer = $('.datepicker--buttons', this.d.$datepicker);
+ },
+
+ setNavStatus: function () {
+ if (!(this.opts.minDate || this.opts.maxDate) || !this.opts.disableNavWhenOutOfRange) return;
+
+ var date = this.d.parsedDate,
+ m = date.month,
+ y = date.year,
+ d = date.date;
+
+ switch (this.d.view) {
+ case 'days':
+ if (!this.d._isInRange(new Date(y, m-1, 1), 'month')) {
+ this._disableNav('prev')
+ }
+ if (!this.d._isInRange(new Date(y, m+1, 1), 'month')) {
+ this._disableNav('next')
+ }
+ break;
+ case 'months':
+ if (!this.d._isInRange(new Date(y-1, m, d), 'year')) {
+ this._disableNav('prev')
+ }
+ if (!this.d._isInRange(new Date(y+1, m, d), 'year')) {
+ this._disableNav('next')
+ }
+ break;
+ case 'years':
+ var decade = dp.getDecade(this.d.date);
+ if (!this.d._isInRange(new Date(decade[0] - 1, 0, 1), 'year')) {
+ this._disableNav('prev')
+ }
+ if (!this.d._isInRange(new Date(decade[1] + 1, 0, 1), 'year')) {
+ this._disableNav('next')
+ }
+ break;
+ }
+ },
+
+ _disableNav: function (nav) {
+ $('[data-action="' + nav + '"]', this.d.$nav).addClass('-disabled-')
+ },
+
+ _activateNav: function (nav) {
+ $('[data-action="' + nav + '"]', this.d.$nav).removeClass('-disabled-')
+ },
+
+ _onClickNavButton: function (e) {
+ var $el = $(e.target).closest('[data-action]'),
+ action = $el.data('action');
+
+ this.d[action]();
+ },
+
+ _onClickNavTitle: function (e) {
+ if ($(e.target).hasClass('-disabled-')) return;
+
+ if (this.d.view == 'days') {
+ return this.d.view = 'months'
+ }
+
+ this.d.view = 'years';
+ }
+ }
+
+})();
+
+;(function () {
+ var template = '
' +
+ '
' +
+ ' #{hourVisible}' +
+ ' :' +
+ ' #{minValue}' +
+ '
' +
+ '
' +
+ '
',
+ datepicker = $.fn.datepicker,
+ dp = datepicker.Constructor;
+
+ datepicker.Timepicker = function (inst, opts) {
+ this.d = inst;
+ this.opts = opts;
+
+ this.init();
+ };
+
+ datepicker.Timepicker.prototype = {
+ init: function () {
+ var input = 'input';
+ this._setTime(this.d.date);
+ this._buildHTML();
+
+ if (navigator.userAgent.match(/trident/gi)) {
+ input = 'change';
+ }
+
+ this.d.$el.on('selectDate', this._onSelectDate.bind(this));
+ this.$ranges.on(input, this._onChangeRange.bind(this));
+ this.$ranges.on('mouseup', this._onMouseUpRange.bind(this));
+ this.$ranges.on('mousemove focus ', this._onMouseEnterRange.bind(this));
+ this.$ranges.on('mouseout blur', this._onMouseOutRange.bind(this));
+ },
+
+ _setTime: function (date) {
+ var _date = dp.getParsedDate(date);
+
+ this._handleDate(date);
+ this.hours = _date.hours < this.minHours ? this.minHours : _date.hours;
+ this.minutes = _date.minutes < this.minMinutes ? this.minMinutes : _date.minutes;
+ },
+
+ /**
+ * Sets minHours and minMinutes from date (usually it's a minDate)
+ * Also changes minMinutes if current hours are bigger then @date hours
+ * @param date {Date}
+ * @private
+ */
+ _setMinTimeFromDate: function (date) {
+ this.minHours = date.getHours();
+ this.minMinutes = date.getMinutes();
+
+ // If, for example, min hours are 10, and current hours are 12,
+ // update minMinutes to default value, to be able to choose whole range of values
+ if (this.d.lastSelectedDate) {
+ if (this.d.lastSelectedDate.getHours() > date.getHours()) {
+ this.minMinutes = this.opts.minMinutes;
+ }
+ }
+ },
+
+ _setMaxTimeFromDate: function (date) {
+ this.maxHours = date.getHours();
+ this.maxMinutes = date.getMinutes();
+
+ if (this.d.lastSelectedDate) {
+ if (this.d.lastSelectedDate.getHours() < date.getHours()) {
+ this.maxMinutes = this.opts.maxMinutes;
+ }
+ }
+ },
+
+ _setDefaultMinMaxTime: function () {
+ var maxHours = 23,
+ maxMinutes = 59,
+ opts = this.opts;
+
+ this.minHours = opts.minHours < 0 || opts.minHours > maxHours ? 0 : opts.minHours;
+ this.minMinutes = opts.minMinutes < 0 || opts.minMinutes > maxMinutes ? 0 : opts.minMinutes;
+ this.maxHours = opts.maxHours < 0 || opts.maxHours > maxHours ? maxHours : opts.maxHours;
+ this.maxMinutes = opts.maxMinutes < 0 || opts.maxMinutes > maxMinutes ? maxMinutes : opts.maxMinutes;
+ },
+
+ /**
+ * Looks for min/max hours/minutes and if current values
+ * are out of range sets valid values.
+ * @private
+ */
+ _validateHoursMinutes: function (date) {
+ if (this.hours < this.minHours) {
+ this.hours = this.minHours;
+ } else if (this.hours > this.maxHours) {
+ this.hours = this.maxHours;
+ }
+
+ if (this.minutes < this.minMinutes) {
+ this.minutes = this.minMinutes;
+ } else if (this.minutes > this.maxMinutes) {
+ this.minutes = this.maxMinutes;
+ }
+ },
+
+ _buildHTML: function () {
+ var lz = dp.getLeadingZeroNum,
+ data = {
+ hourMin: this.minHours,
+ hourMax: lz(this.maxHours),
+ hourStep: this.opts.hoursStep,
+ hourValue: this.hours,
+ hourVisible: lz(this.displayHours),
+ minMin: this.minMinutes,
+ minMax: lz(this.maxMinutes),
+ minStep: this.opts.minutesStep,
+ minValue: lz(this.minutes)
+ },
+ _template = dp.template(template, data);
+
+ this.$timepicker = $(_template).appendTo(this.d.$datepicker);
+ this.$ranges = $('[type="range"]', this.$timepicker);
+ this.$hours = $('[name="hours"]', this.$timepicker);
+ this.$minutes = $('[name="minutes"]', this.$timepicker);
+ this.$hoursText = $('.datepicker--time-current-hours', this.$timepicker);
+ this.$minutesText = $('.datepicker--time-current-minutes', this.$timepicker);
+
+ if (this.d.ampm) {
+ this.$ampm = $('
')
+ .appendTo($('.datepicker--time-current', this.$timepicker))
+ .html(this.dayPeriod);
+
+ this.$timepicker.addClass('-am-pm-');
+ }
+ },
+
+ _updateCurrentTime: function () {
+ var h = dp.getLeadingZeroNum(this.displayHours),
+ m = dp.getLeadingZeroNum(this.minutes);
+
+ this.$hoursText.html(h);
+ this.$minutesText.html(m);
+
+ if (this.d.ampm) {
+ this.$ampm.html(this.dayPeriod);
+ }
+ },
+
+ _updateRanges: function () {
+ this.$hours.attr({
+ min: this.minHours,
+ max: this.maxHours
+ }).val(this.hours);
+
+ this.$minutes.attr({
+ min: this.minMinutes,
+ max: this.maxMinutes
+ }).val(this.minutes)
+ },
+
+ /**
+ * Sets minHours, minMinutes etc. from date. If date is not passed, than sets
+ * values from options
+ * @param [date] {object} - Date object, to get values from
+ * @private
+ */
+ _handleDate: function (date) {
+ this._setDefaultMinMaxTime();
+ if (date) {
+ if (dp.isSame(date, this.d.opts.minDate)) {
+ this._setMinTimeFromDate(this.d.opts.minDate);
+ } else if (dp.isSame(date, this.d.opts.maxDate)) {
+ this._setMaxTimeFromDate(this.d.opts.maxDate);
+ }
+ }
+
+ this._validateHoursMinutes(date);
+ },
+
+ update: function () {
+ this._updateRanges();
+ this._updateCurrentTime();
+ },
+
+ /**
+ * Calculates valid hour value to display in text input and datepicker's body.
+ * @param date {Date|Number} - date or hours
+ * @param [ampm] {Boolean} - 12 hours mode
+ * @returns {{hours: *, dayPeriod: string}}
+ * @private
+ */
+ _getValidHoursFromDate: function (date, ampm) {
+ var d = date,
+ hours = date;
+
+ if (date instanceof Date) {
+ d = dp.getParsedDate(date);
+ hours = d.hours;
+ }
+
+ var _ampm = ampm || this.d.ampm,
+ dayPeriod = 'am';
+
+ if (_ampm) {
+ switch(true) {
+ case hours == 0:
+ hours = 12;
+ break;
+ case hours == 12:
+ dayPeriod = 'pm';
+ break;
+ case hours > 11:
+ hours = hours - 12;
+ dayPeriod = 'pm';
+ break;
+ default:
+ break;
+ }
+ }
+
+ return {
+ hours: hours,
+ dayPeriod: dayPeriod
+ }
+ },
+
+ set hours (val) {
+ this._hours = val;
+
+ var displayHours = this._getValidHoursFromDate(val);
+
+ this.displayHours = displayHours.hours;
+ this.dayPeriod = displayHours.dayPeriod;
+ },
+
+ get hours() {
+ return this._hours;
+ },
+
+ // Events
+ // -------------------------------------------------
+
+ _onChangeRange: function (e) {
+ var $target = $(e.target),
+ name = $target.attr('name');
+
+ this.d.timepickerIsActive = true;
+
+ this[name] = $target.val();
+ this._updateCurrentTime();
+ this.d._trigger('timeChange', [this.hours, this.minutes]);
+
+ this._handleDate(this.d.lastSelectedDate);
+ this.update()
+ },
+
+ _onSelectDate: function (e, data) {
+ this._handleDate(data);
+ this.update();
+ },
+
+ _onMouseEnterRange: function (e) {
+ var name = $(e.target).attr('name');
+ $('.datepicker--time-current-' + name, this.$timepicker).addClass('-focus-');
+ },
+
+ _onMouseOutRange: function (e) {
+ var name = $(e.target).attr('name');
+ if (this.d.inFocus) return; // Prevent removing focus when mouse out of range slider
+ $('.datepicker--time-current-' + name, this.$timepicker).removeClass('-focus-');
+ },
+
+ _onMouseUpRange: function (e) {
+ this.d.timepickerIsActive = false;
+ }
+ };
+})();
+ })(window, jQuery);
\ No newline at end of file
diff --git a/assets/air-datepicker/js/datepicker.min.js b/assets/air-datepicker/js/datepicker.min.js
new file mode 100644
index 0000000..31537f1
--- /dev/null
+++ b/assets/air-datepicker/js/datepicker.min.js
@@ -0,0 +1,2 @@
+!function(t,e,i){!function(){var s,a,n,h="2.2.3",o="datepicker",r=".datepicker-here",c=!1,d='',l={classes:"",inline:!1,language:"ru",startDate:new Date,firstDay:"",weekends:[6,0],dateFormat:"",altField:"",altFieldDateFormat:"@",toggleSelected:!0,keyboardNav:!0,position:"bottom left",offset:12,view:"days",minView:"days",showOtherMonths:!0,selectOtherMonths:!0,moveToOtherMonthsOnSelect:!0,showOtherYears:!0,selectOtherYears:!0,moveToOtherYearsOnSelect:!0,minDate:"",maxDate:"",disableNavWhenOutOfRange:!0,multipleDates:!1,multipleDatesSeparator:",",range:!1,todayButton:!1,clearButton:!1,showEvent:"focus",autoClose:!1,monthsField:"monthsShort",prevHtml:'',nextHtml:'',navTitles:{days:"MM, yyyy",months:"yyyy",years:"yyyy1 - yyyy2"},timepicker:!1,onlyTimepicker:!1,dateTimeSeparator:" ",timeFormat:"",minHours:0,maxHours:24,minMinutes:0,maxMinutes:59,hoursStep:1,minutesStep:1,onSelect:"",onShow:"",onHide:"",onChangeMonth:"",onChangeYear:"",onChangeDecade:"",onChangeView:"",onRenderCell:""},u={ctrlRight:[17,39],ctrlUp:[17,38],ctrlLeft:[17,37],ctrlDown:[17,40],shiftRight:[16,39],shiftUp:[16,38],shiftLeft:[16,37],shiftDown:[16,40],altUp:[18,38],altRight:[18,39],altLeft:[18,37],altDown:[18,40],ctrlShiftUp:[16,17,38]},m=function(t,a){this.el=t,this.$el=e(t),this.opts=e.extend(!0,{},l,a,this.$el.data()),s==i&&(s=e("body")),this.opts.startDate||(this.opts.startDate=new Date),"INPUT"==this.el.nodeName&&(this.elIsInput=!0),this.opts.altField&&(this.$altField="string"==typeof this.opts.altField?e(this.opts.altField):this.opts.altField),this.inited=!1,this.visible=!1,this.silent=!1,this.currentDate=this.opts.startDate,this.currentView=this.opts.view,this._createShortCuts(),this.selectedDates=[],this.views={},this.keys=[],this.minRange="",this.maxRange="",this._prevOnSelectValue="",this.init()};n=m,n.prototype={VERSION:h,viewIndexes:["days","months","years"],init:function(){c||this.opts.inline||!this.elIsInput||this._buildDatepickersContainer(),this._buildBaseHtml(),this._defineLocale(this.opts.language),this._syncWithMinMaxDates(),this.elIsInput&&(this.opts.inline||(this._setPositionClasses(this.opts.position),this._bindEvents()),this.opts.keyboardNav&&!this.opts.onlyTimepicker&&this._bindKeyboardEvents(),this.$datepicker.on("mousedown",this._onMouseDownDatepicker.bind(this)),this.$datepicker.on("mouseup",this._onMouseUpDatepicker.bind(this))),this.opts.classes&&this.$datepicker.addClass(this.opts.classes),this.opts.timepicker&&(this.timepicker=new e.fn.datepicker.Timepicker(this,this.opts),this._bindTimepickerEvents()),this.opts.onlyTimepicker&&this.$datepicker.addClass("-only-timepicker-"),this.views[this.currentView]=new e.fn.datepicker.Body(this,this.currentView,this.opts),this.views[this.currentView].show(),this.nav=new e.fn.datepicker.Navigation(this,this.opts),this.view=this.currentView,this.$el.on("clickCell.adp",this._onClickCell.bind(this)),this.$datepicker.on("mouseenter",".datepicker--cell",this._onMouseEnterCell.bind(this)),this.$datepicker.on("mouseleave",".datepicker--cell",this._onMouseLeaveCell.bind(this)),this.inited=!0},_createShortCuts:function(){this.minDate=this.opts.minDate?this.opts.minDate:new Date(-86399999136e5),this.maxDate=this.opts.maxDate?this.opts.maxDate:new Date(86399999136e5)},_bindEvents:function(){this.$el.on(this.opts.showEvent+".adp",this._onShowEvent.bind(this)),this.$el.on("mouseup.adp",this._onMouseUpEl.bind(this)),this.$el.on("blur.adp",this._onBlur.bind(this)),this.$el.on("keyup.adp",this._onKeyUpGeneral.bind(this)),e(t).on("resize.adp",this._onResize.bind(this)),e("body").on("mouseup.adp",this._onMouseUpBody.bind(this))},_bindKeyboardEvents:function(){this.$el.on("keydown.adp",this._onKeyDown.bind(this)),this.$el.on("keyup.adp",this._onKeyUp.bind(this)),this.$el.on("hotKey.adp",this._onHotKey.bind(this))},_bindTimepickerEvents:function(){this.$el.on("timeChange.adp",this._onTimeChange.bind(this))},isWeekend:function(t){return-1!==this.opts.weekends.indexOf(t)},_defineLocale:function(t){"string"==typeof t?(this.loc=e.fn.datepicker.language[t],this.loc||(console.warn("Can't find language \""+t+'" in Datepicker.language, will use "ru" instead'),this.loc=e.extend(!0,{},e.fn.datepicker.language.ru)),this.loc=e.extend(!0,{},e.fn.datepicker.language.ru,e.fn.datepicker.language[t])):this.loc=e.extend(!0,{},e.fn.datepicker.language.ru,t),this.opts.dateFormat&&(this.loc.dateFormat=this.opts.dateFormat),this.opts.timeFormat&&(this.loc.timeFormat=this.opts.timeFormat),""!==this.opts.firstDay&&(this.loc.firstDay=this.opts.firstDay),this.opts.timepicker&&(this.loc.dateFormat=[this.loc.dateFormat,this.loc.timeFormat].join(this.opts.dateTimeSeparator)),this.opts.onlyTimepicker&&(this.loc.dateFormat=this.loc.timeFormat);var i=this._getWordBoundaryRegExp;(this.loc.timeFormat.match(i("aa"))||this.loc.timeFormat.match(i("AA")))&&(this.ampm=!0)},_buildDatepickersContainer:function(){c=!0,s.append(''),a=e("#datepickers-container")},_buildBaseHtml:function(){var t,i=e('');t="INPUT"==this.el.nodeName?this.opts.inline?i.insertAfter(this.$el):a:i.appendTo(this.$el),this.$datepicker=e(d).appendTo(t),this.$content=e(".datepicker--content",this.$datepicker),this.$nav=e(".datepicker--nav",this.$datepicker)},_triggerOnChange:function(){if(!this.selectedDates.length){if(""===this._prevOnSelectValue)return;return this._prevOnSelectValue="",this.opts.onSelect("","",this)}var t,e=this.selectedDates,i=n.getParsedDate(e[0]),s=this,a=new Date(i.year,i.month,i.date,i.hours,i.minutes);t=e.map(function(t){return s.formatDate(s.loc.dateFormat,t)}).join(this.opts.multipleDatesSeparator),(this.opts.multipleDates||this.opts.range)&&(a=e.map(function(t){var e=n.getParsedDate(t);return new Date(e.year,e.month,e.date,e.hours,e.minutes)})),this._prevOnSelectValue=t,this.opts.onSelect(t,a,this)},next:function(){var t=this.parsedDate,e=this.opts;switch(this.view){case"days":this.date=new Date(t.year,t.month+1,1),e.onChangeMonth&&e.onChangeMonth(this.parsedDate.month,this.parsedDate.year);break;case"months":this.date=new Date(t.year+1,t.month,1),e.onChangeYear&&e.onChangeYear(this.parsedDate.year);break;case"years":this.date=new Date(t.year+10,0,1),e.onChangeDecade&&e.onChangeDecade(this.curDecade)}},prev:function(){var t=this.parsedDate,e=this.opts;switch(this.view){case"days":this.date=new Date(t.year,t.month-1,1),e.onChangeMonth&&e.onChangeMonth(this.parsedDate.month,this.parsedDate.year);break;case"months":this.date=new Date(t.year-1,t.month,1),e.onChangeYear&&e.onChangeYear(this.parsedDate.year);break;case"years":this.date=new Date(t.year-10,0,1),e.onChangeDecade&&e.onChangeDecade(this.curDecade)}},formatDate:function(t,e){e=e||this.date;var i,s=t,a=this._getWordBoundaryRegExp,h=this.loc,o=n.getLeadingZeroNum,r=n.getDecade(e),c=n.getParsedDate(e),d=c.fullHours,l=c.hours,u=t.match(a("aa"))||t.match(a("AA")),m="am",p=this._replacer;switch(this.opts.timepicker&&this.timepicker&&u&&(i=this.timepicker._getValidHoursFromDate(e,u),d=o(i.hours),l=i.hours,m=i.dayPeriod),!0){case/@/.test(s):s=s.replace(/@/,e.getTime());case/aa/.test(s):s=p(s,a("aa"),m);case/AA/.test(s):s=p(s,a("AA"),m.toUpperCase());case/dd/.test(s):s=p(s,a("dd"),c.fullDate);case/d/.test(s):s=p(s,a("d"),c.date);case/DD/.test(s):s=p(s,a("DD"),h.days[c.day]);case/D/.test(s):s=p(s,a("D"),h.daysShort[c.day]);case/mm/.test(s):s=p(s,a("mm"),c.fullMonth);case/m/.test(s):s=p(s,a("m"),c.month+1);case/MM/.test(s):s=p(s,a("MM"),this.loc.months[c.month]);case/M/.test(s):s=p(s,a("M"),h.monthsShort[c.month]);case/ii/.test(s):s=p(s,a("ii"),c.fullMinutes);case/i/.test(s):s=p(s,a("i"),c.minutes);case/hh/.test(s):s=p(s,a("hh"),d);case/h/.test(s):s=p(s,a("h"),l);case/yyyy/.test(s):s=p(s,a("yyyy"),c.year);case/yyyy1/.test(s):s=p(s,a("yyyy1"),r[0]);case/yyyy2/.test(s):s=p(s,a("yyyy2"),r[1]);case/yy/.test(s):s=p(s,a("yy"),c.year.toString().slice(-2))}return s},_replacer:function(t,e,i){return t.replace(e,function(t,e,s,a){return e+i+a})},_getWordBoundaryRegExp:function(t){var e="\\s|\\.|-|/|\\\\|,|\\$|\\!|\\?|:|;";return new RegExp("(^|>|"+e+")("+t+")($|<|"+e+")","g")},selectDate:function(t){var e=this,i=e.opts,s=e.parsedDate,a=e.selectedDates,h=a.length,o="";if(Array.isArray(t))return void t.forEach(function(t){e.selectDate(t)});if(t instanceof Date){if(this.lastSelectedDate=t,this.timepicker&&this.timepicker._setTime(t),e._trigger("selectDate",t),this.timepicker&&(t.setHours(this.timepicker.hours),t.setMinutes(this.timepicker.minutes)),"days"==e.view&&t.getMonth()!=s.month&&i.moveToOtherMonthsOnSelect&&(o=new Date(t.getFullYear(),t.getMonth(),1)),"years"==e.view&&t.getFullYear()!=s.year&&i.moveToOtherYearsOnSelect&&(o=new Date(t.getFullYear(),0,1)),o&&(e.silent=!0,e.date=o,e.silent=!1,e.nav._render()),i.multipleDates&&!i.range){if(h===i.multipleDates)return;e._isSelected(t)||e.selectedDates.push(t)}else i.range?2==h?(e.selectedDates=[t],e.minRange=t,e.maxRange=""):1==h?(e.selectedDates.push(t),e.maxRange?e.minRange=t:e.maxRange=t,n.bigger(e.maxRange,e.minRange)&&(e.maxRange=e.minRange,e.minRange=t),e.selectedDates=[e.minRange,e.maxRange]):(e.selectedDates=[t],e.minRange=t):e.selectedDates=[t];e._setInputValue(),i.onSelect&&e._triggerOnChange(),i.autoClose&&!this.timepickerIsActive&&(i.multipleDates||i.range?i.range&&2==e.selectedDates.length&&e.hide():e.hide()),e.views[this.currentView]._render()}},removeDate:function(t){var e=this.selectedDates,i=this;if(t instanceof Date)return e.some(function(s,a){return n.isSame(s,t)?(e.splice(a,1),i.selectedDates.length?i.lastSelectedDate=i.selectedDates[i.selectedDates.length-1]:(i.minRange="",i.maxRange="",i.lastSelectedDate=""),i.views[i.currentView]._render(),i._setInputValue(),i.opts.onSelect&&i._triggerOnChange(),!0):void 0})},today:function(){this.silent=!0,this.view=this.opts.minView,this.silent=!1,this.date=new Date,this.opts.todayButton instanceof Date&&this.selectDate(this.opts.todayButton)},clear:function(){this.selectedDates=[],this.minRange="",this.maxRange="",this.views[this.currentView]._render(),this._setInputValue(),this.opts.onSelect&&this._triggerOnChange()},update:function(t,i){var s=arguments.length,a=this.lastSelectedDate;return 2==s?this.opts[t]=i:1==s&&"object"==typeof t&&(this.opts=e.extend(!0,this.opts,t)),this._createShortCuts(),this._syncWithMinMaxDates(),this._defineLocale(this.opts.language),this.nav._addButtonsIfNeed(),this.opts.onlyTimepicker||this.nav._render(),this.views[this.currentView]._render(),this.elIsInput&&!this.opts.inline&&(this._setPositionClasses(this.opts.position),this.visible&&this.setPosition(this.opts.position)),this.opts.classes&&this.$datepicker.addClass(this.opts.classes),this.opts.onlyTimepicker&&this.$datepicker.addClass("-only-timepicker-"),this.opts.timepicker&&(a&&this.timepicker._handleDate(a),this.timepicker._updateRanges(),this.timepicker._updateCurrentTime(),a&&(a.setHours(this.timepicker.hours),a.setMinutes(this.timepicker.minutes))),this._setInputValue(),this},_syncWithMinMaxDates:function(){var t=this.date.getTime();this.silent=!0,this.minTime>t&&(this.date=this.minDate),this.maxTime
=this.minTime&&i<=this.maxTime,month:o>=this.minTime&&r<=this.maxTime,year:s.year>=a.year&&s.year<=h.year};return e?c[e]:c.day},_getDimensions:function(t){var e=t.offset();return{width:t.outerWidth(),height:t.outerHeight(),left:e.left,top:e.top}},_getDateFromCell:function(t){var e=this.parsedDate,s=t.data("year")||e.year,a=t.data("month")==i?e.month:t.data("month"),n=t.data("date")||1;return new Date(s,a,n)},_setPositionClasses:function(t){t=t.split(" ");var e=t[0],i=t[1],s="datepicker -"+e+"-"+i+"- -from-"+e+"-";this.visible&&(s+=" active"),this.$datepicker.removeAttr("class").addClass(s)},setPosition:function(t){t=t||this.opts.position;var e,i,s=this._getDimensions(this.$el),a=this._getDimensions(this.$datepicker),n=t.split(" "),h=this.opts.offset,o=n[0],r=n[1];switch(o){case"top":e=s.top-a.height-h;break;case"right":i=s.left+s.width+h;break;case"bottom":e=s.top+s.height+h;break;case"left":i=s.left-a.width-h}switch(r){case"top":e=s.top;break;case"right":i=s.left+s.width-a.width;break;case"bottom":e=s.top+s.height-a.height;break;case"left":i=s.left;break;case"center":/left|right/.test(o)?e=s.top+s.height/2-a.height/2:i=s.left+s.width/2-a.width/2}this.$datepicker.css({left:i,top:e})},show:function(){var t=this.opts.onShow;this.setPosition(this.opts.position),this.$datepicker.addClass("active"),this.visible=!0,t&&this._bindVisionEvents(t)},hide:function(){var t=this.opts.onHide;this.$datepicker.removeClass("active").css({left:"-100000px"}),this.focused="",this.keys=[],this.inFocus=!1,this.visible=!1,this.$el.blur(),t&&this._bindVisionEvents(t)},down:function(t){this._changeView(t,"down")},up:function(t){this._changeView(t,"up")},_bindVisionEvents:function(t){this.$datepicker.off("transitionend.dp"),t(this,!1),this.$datepicker.one("transitionend.dp",t.bind(this,this,!0))},_changeView:function(t,e){t=t||this.focused||this.date;var i="up"==e?this.viewIndex+1:this.viewIndex-1;i>2&&(i=2),0>i&&(i=0),this.silent=!0,this.date=new Date(t.getFullYear(),t.getMonth(),1),this.silent=!1,this.view=this.viewIndexes[i]},_handleHotKey:function(t){var e,i,s,a=n.getParsedDate(this._getFocusedDate()),h=this.opts,o=!1,r=!1,c=!1,d=a.year,l=a.month,u=a.date;switch(t){case"ctrlRight":case"ctrlUp":l+=1,o=!0;break;case"ctrlLeft":case"ctrlDown":l-=1,o=!0;break;case"shiftRight":case"shiftUp":r=!0,d+=1;break;case"shiftLeft":case"shiftDown":r=!0,d-=1;break;case"altRight":case"altUp":c=!0,d+=10;break;case"altLeft":case"altDown":c=!0,d-=10;break;case"ctrlShiftUp":this.up()}s=n.getDaysCount(new Date(d,l)),i=new Date(d,l,u),u>s&&(u=s),i.getTime()this.maxTime&&(i=this.maxDate),this.focused=i,e=n.getParsedDate(i),o&&h.onChangeMonth&&h.onChangeMonth(e.month,e.year),r&&h.onChangeYear&&h.onChangeYear(e.year),c&&h.onChangeDecade&&h.onChangeDecade(this.curDecade)},_registerKey:function(t){var e=this.keys.some(function(e){return e==t});e||this.keys.push(t)},_unRegisterKey:function(t){var e=this.keys.indexOf(t);this.keys.splice(e,1)},_isHotKeyPressed:function(){var t,e=!1,i=this,s=this.keys.sort();for(var a in u)t=u[a],s.length==t.length&&t.every(function(t,e){return t==s[e]})&&(i._trigger("hotKey",a),e=!0);return e},_trigger:function(t,e){this.$el.trigger(t,e)},_focusNextCell:function(t,e){e=e||this.cellType;var i=n.getParsedDate(this._getFocusedDate()),s=i.year,a=i.month,h=i.date;if(!this._isHotKeyPressed()){switch(t){case 37:"day"==e?h-=1:"","month"==e?a-=1:"","year"==e?s-=1:"";break;case 38:"day"==e?h-=7:"","month"==e?a-=3:"","year"==e?s-=4:"";break;case 39:"day"==e?h+=1:"","month"==e?a+=1:"","year"==e?s+=1:"";break;case 40:"day"==e?h+=7:"","month"==e?a+=3:"","year"==e?s+=4:""}var o=new Date(s,a,h);o.getTime()this.maxTime&&(o=this.maxDate),this.focused=o}},_getFocusedDate:function(){var t=this.focused||this.selectedDates[this.selectedDates.length-1],e=this.parsedDate;if(!t)switch(this.view){case"days":t=new Date(e.year,e.month,(new Date).getDate());break;case"months":t=new Date(e.year,e.month,1);break;case"years":t=new Date(e.year,0,1)}return t},_getCell:function(t,i){i=i||this.cellType;var s,a=n.getParsedDate(t),h='.datepicker--cell[data-year="'+a.year+'"]';switch(i){case"month":h='[data-month="'+a.month+'"]';break;case"day":h+='[data-month="'+a.month+'"][data-date="'+a.date+'"]'}return s=this.views[this.currentView].$el.find(h),s.length?s:e("")},destroy:function(){var t=this;t.$el.off(".adp").data("datepicker",""),t.selectedDates=[],t.focused="",t.views={},t.keys=[],t.minRange="",t.maxRange="",t.opts.inline||!t.elIsInput?t.$datepicker.closest(".datepicker-inline").remove():t.$datepicker.remove()},_handleAlreadySelectedDates:function(t,e){this.opts.range?this.opts.toggleSelected?this.removeDate(e):2!=this.selectedDates.length&&this._trigger("clickCell",e):this.opts.toggleSelected&&this.removeDate(e),this.opts.toggleSelected||(this.lastSelectedDate=t,this.opts.timepicker&&(this.timepicker._setTime(t),this.timepicker.update()))},_onShowEvent:function(t){this.visible||this.show()},_onBlur:function(){!this.inFocus&&this.visible&&this.hide()},_onMouseDownDatepicker:function(t){this.inFocus=!0},_onMouseUpDatepicker:function(t){this.inFocus=!1,t.originalEvent.inFocus=!0,t.originalEvent.timepickerFocus||this.$el.focus()},_onKeyUpGeneral:function(t){var e=this.$el.val();e||this.clear()},_onResize:function(){this.visible&&this.setPosition()},_onMouseUpBody:function(t){t.originalEvent.inFocus||this.visible&&!this.inFocus&&this.hide()},_onMouseUpEl:function(t){t.originalEvent.inFocus=!0,setTimeout(this._onKeyUpGeneral.bind(this),4)},_onKeyDown:function(t){var e=t.which;if(this._registerKey(e),e>=37&&40>=e&&(t.preventDefault(),this._focusNextCell(e)),13==e&&this.focused){if(this._getCell(this.focused).hasClass("-disabled-"))return;if(this.view!=this.opts.minView)this.down();else{var i=this._isSelected(this.focused,this.cellType);if(!i)return this.timepicker&&(this.focused.setHours(this.timepicker.hours),this.focused.setMinutes(this.timepicker.minutes)),void this.selectDate(this.focused);this._handleAlreadySelectedDates(i,this.focused)}}27==e&&this.hide()},_onKeyUp:function(t){var e=t.which;this._unRegisterKey(e)},_onHotKey:function(t,e){this._handleHotKey(e)},_onMouseEnterCell:function(t){var i=e(t.target).closest(".datepicker--cell"),s=this._getDateFromCell(i);this.silent=!0,this.focused&&(this.focused=""),i.addClass("-focus-"),this.focused=s,this.silent=!1,this.opts.range&&1==this.selectedDates.length&&(this.minRange=this.selectedDates[0],this.maxRange="",n.less(this.minRange,this.focused)&&(this.maxRange=this.minRange,this.minRange=""),this.views[this.currentView]._update())},_onMouseLeaveCell:function(t){var i=e(t.target).closest(".datepicker--cell");i.removeClass("-focus-"),this.silent=!0,this.focused="",this.silent=!1},_onTimeChange:function(t,e,i){var s=new Date,a=this.selectedDates,n=!1;a.length&&(n=!0,s=this.lastSelectedDate),s.setHours(e),s.setMinutes(i),n||this._getCell(s).hasClass("-disabled-")?(this._setInputValue(),this.opts.onSelect&&this._triggerOnChange()):this.selectDate(s)},_onClickCell:function(t,e){this.timepicker&&(e.setHours(this.timepicker.hours),e.setMinutes(this.timepicker.minutes)),this.selectDate(e)},set focused(t){if(!t&&this.focused){var e=this._getCell(this.focused);e.length&&e.removeClass("-focus-")}this._focused=t,this.opts.range&&1==this.selectedDates.length&&(this.minRange=this.selectedDates[0],this.maxRange="",n.less(this.minRange,this._focused)&&(this.maxRange=this.minRange,this.minRange="")),this.silent||(this.date=t)},get focused(){return this._focused},get parsedDate(){return n.getParsedDate(this.date)},set date(t){return t instanceof Date?(this.currentDate=t,this.inited&&!this.silent&&(this.views[this.view]._render(),this.nav._render(),this.visible&&this.elIsInput&&this.setPosition()),t):void 0},get date(){return this.currentDate},set view(t){return this.viewIndex=this.viewIndexes.indexOf(t),this.viewIndex<0?void 0:(this.prevView=this.currentView,this.currentView=t,this.inited&&(this.views[t]?this.views[t]._render():this.views[t]=new e.fn.datepicker.Body(this,t,this.opts),this.views[this.prevView].hide(),this.views[t].show(),this.nav._render(),this.opts.onChangeView&&this.opts.onChangeView(t),this.elIsInput&&this.visible&&this.setPosition()),t)},get view(){return this.currentView},get cellType(){return this.view.substring(0,this.view.length-1)},get minTime(){var t=n.getParsedDate(this.minDate);return new Date(t.year,t.month,t.date).getTime()},get maxTime(){var t=n.getParsedDate(this.maxDate);return new Date(t.year,t.month,t.date).getTime()},get curDecade(){return n.getDecade(this.date)}},n.getDaysCount=function(t){return new Date(t.getFullYear(),t.getMonth()+1,0).getDate()},n.getParsedDate=function(t){return{year:t.getFullYear(),month:t.getMonth(),fullMonth:t.getMonth()+1<10?"0"+(t.getMonth()+1):t.getMonth()+1,date:t.getDate(),fullDate:t.getDate()<10?"0"+t.getDate():t.getDate(),day:t.getDay(),hours:t.getHours(),fullHours:t.getHours()<10?"0"+t.getHours():t.getHours(),minutes:t.getMinutes(),fullMinutes:t.getMinutes()<10?"0"+t.getMinutes():t.getMinutes()}},n.getDecade=function(t){var e=10*Math.floor(t.getFullYear()/10);return[e,e+9]},n.template=function(t,e){return t.replace(/#\{([\w]+)\}/g,function(t,i){return e[i]||0===e[i]?e[i]:void 0})},n.isSame=function(t,e,i){if(!t||!e)return!1;var s=n.getParsedDate(t),a=n.getParsedDate(e),h=i?i:"day",o={day:s.date==a.date&&s.month==a.month&&s.year==a.year,month:s.month==a.month&&s.year==a.year,year:s.year==a.year};return o[h]},n.less=function(t,e,i){return t&&e?e.getTime()t.getTime():!1},n.getLeadingZeroNum=function(t){return parseInt(t)<10?"0"+t:t},n.resetTime=function(t){return"object"==typeof t?(t=n.getParsedDate(t),new Date(t.year,t.month,t.date)):void 0},e.fn.datepicker=function(t){return this.each(function(){if(e.data(this,o)){var i=e.data(this,o);i.opts=e.extend(!0,i.opts,t),i.update()}else e.data(this,o,new m(this,t))})},e.fn.datepicker.Constructor=m,e.fn.datepicker.language={ru:{days:["Воскресенье","Понедельник","Вторник","Среда","Четверг","Пятница","Суббота"],daysShort:["Вос","Пон","Вто","Сре","Чет","Пят","Суб"],daysMin:["Вс","Пн","Вт","Ср","Чт","Пт","Сб"],months:["Январь","Февраль","Март","Апрель","Май","Июнь","Июль","Август","Сентябрь","Октябрь","Ноябрь","Декабрь"],monthsShort:["Янв","Фев","Мар","Апр","Май","Июн","Июл","Авг","Сен","Окт","Ноя","Дек"],today:"Сегодня",clear:"Очистить",dateFormat:"dd.mm.yyyy",timeFormat:"hh:ii",firstDay:1}},e(function(){e(r).datepicker()})}(),function(){var t={days:'',months:'',years:''},s=e.fn.datepicker,a=s.Constructor;s.Body=function(t,i,s){this.d=t,this.type=i,this.opts=s,this.$el=e(""),this.opts.onlyTimepicker||this.init()},s.Body.prototype={init:function(){this._buildBaseHtml(),this._render(),this._bindEvents()},_bindEvents:function(){this.$el.on("click",".datepicker--cell",e.proxy(this._onClickCell,this))},_buildBaseHtml:function(){this.$el=e(t[this.type]).appendTo(this.d.$content),this.$names=e(".datepicker--days-names",this.$el),this.$cells=e(".datepicker--cells",this.$el)},_getDayNamesHtml:function(t,e,s,a){return e=e!=i?e:t,s=s?s:"",a=a!=i?a:0,a>7?s:7==e?this._getDayNamesHtml(t,0,s,++a):(s+=''+this.d.loc.daysMin[e]+"
",this._getDayNamesHtml(t,++e,s,++a))},_getCellContents:function(t,e){var i="datepicker--cell datepicker--cell-"+e,s=new Date,n=this.d,h=a.resetTime(n.minRange),o=a.resetTime(n.maxRange),r=n.opts,c=a.getParsedDate(t),d={},l=c.date;switch(e){case"day":n.isWeekend(c.day)&&(i+=" -weekend-"),c.month!=this.d.parsedDate.month&&(i+=" -other-month-",r.selectOtherMonths||(i+=" -disabled-"),r.showOtherMonths||(l=""));break;case"month":l=n.loc[n.opts.monthsField][c.month];break;case"year":var u=n.curDecade;l=c.year,(c.yearu[1])&&(i+=" -other-decade-",r.selectOtherYears||(i+=" -disabled-"),r.showOtherYears||(l=""))}return r.onRenderCell&&(d=r.onRenderCell(t,e)||{},l=d.html?d.html:l,i+=d.classes?" "+d.classes:""),r.range&&(a.isSame(h,t,e)&&(i+=" -range-from-"),a.isSame(o,t,e)&&(i+=" -range-to-"),1==n.selectedDates.length&&n.focused?((a.bigger(h,t)&&a.less(n.focused,t)||a.less(o,t)&&a.bigger(n.focused,t))&&(i+=" -in-range-"),a.less(o,t)&&a.isSame(n.focused,t)&&(i+=" -range-from-"),a.bigger(h,t)&&a.isSame(n.focused,t)&&(i+=" -range-to-")):2==n.selectedDates.length&&a.bigger(h,t)&&a.less(o,t)&&(i+=" -in-range-")),a.isSame(s,t,e)&&(i+=" -current-"),n.focused&&a.isSame(t,n.focused,e)&&(i+=" -focus-"),n._isSelected(t,e)&&(i+=" -selected-"),(!n._isInRange(t,e)||d.disabled)&&(i+=" -disabled-"),{html:l,classes:i}},_getDaysHtml:function(t){var e=a.getDaysCount(t),i=new Date(t.getFullYear(),t.getMonth(),1).getDay(),s=new Date(t.getFullYear(),t.getMonth(),e).getDay(),n=i-this.d.loc.firstDay,h=6-s+this.d.loc.firstDay;n=0>n?n+7:n,h=h>6?h-7:h;for(var o,r,c=-n+1,d="",l=c,u=e+h;u>=l;l++)r=t.getFullYear(),o=t.getMonth(),d+=this._getDayHtml(new Date(r,o,l));return d},_getDayHtml:function(t){var e=this._getCellContents(t,"day");return''+e.html+"
"},_getMonthsHtml:function(t){for(var e="",i=a.getParsedDate(t),s=0;12>s;)e+=this._getMonthHtml(new Date(i.year,s)),s++;return e},_getMonthHtml:function(t){var e=this._getCellContents(t,"month");return''+e.html+"
"},_getYearsHtml:function(t){var e=(a.getParsedDate(t),a.getDecade(t)),i=e[0]-1,s="",n=i;for(n;n<=e[1]+1;n++)s+=this._getYearHtml(new Date(n,0));return s},_getYearHtml:function(t){var e=this._getCellContents(t,"year");return''+e.html+"
"},_renderTypes:{days:function(){var t=this._getDayNamesHtml(this.d.loc.firstDay),e=this._getDaysHtml(this.d.currentDate);this.$cells.html(e),this.$names.html(t)},months:function(){var t=this._getMonthsHtml(this.d.currentDate);this.$cells.html(t)},years:function(){var t=this._getYearsHtml(this.d.currentDate);this.$cells.html(t)}},_render:function(){this.opts.onlyTimepicker||this._renderTypes[this.type].bind(this)()},_update:function(){var t,i,s,a=e(".datepicker--cell",this.$cells),n=this;a.each(function(a,h){i=e(this),s=n.d._getDateFromCell(e(this)),t=n._getCellContents(s,n.d.cellType),i.attr("class",t.classes)})},show:function(){this.opts.onlyTimepicker||(this.$el.addClass("active"),this.acitve=!0)},hide:function(){this.$el.removeClass("active"),this.active=!1},_handleClick:function(t){var e=t.data("date")||1,i=t.data("month")||0,s=t.data("year")||this.d.parsedDate.year,a=this.d;if(a.view!=this.opts.minView)return void a.down(new Date(s,i,e));var n=new Date(s,i,e),h=this.d._isSelected(n,this.d.cellType);return h?void a._handleAlreadySelectedDates.bind(a,h,n)():void a._trigger("clickCell",n)},_onClickCell:function(t){var i=e(t.target).closest(".datepicker--cell");i.hasClass("-disabled-")||this._handleClick.bind(this)(i)}}}(),function(){var t='#{prevHtml}
#{title}
#{nextHtml}
',i='',s='#{label}',a=e.fn.datepicker,n=a.Constructor;a.Navigation=function(t,e){this.d=t,this.opts=e,this.$buttonsContainer="",this.init()},a.Navigation.prototype={init:function(){this._buildBaseHtml(),this._bindEvents()},_bindEvents:function(){this.d.$nav.on("click",".datepicker--nav-action",e.proxy(this._onClickNavButton,this)),this.d.$nav.on("click",".datepicker--nav-title",e.proxy(this._onClickNavTitle,this)),this.d.$datepicker.on("click",".datepicker--button",e.proxy(this._onClickNavButton,this))},_buildBaseHtml:function(){this.opts.onlyTimepicker||this._render(),this._addButtonsIfNeed()},_addButtonsIfNeed:function(){this.opts.todayButton&&this._addButton("today"),this.opts.clearButton&&this._addButton("clear")},_render:function(){var i=this._getTitle(this.d.currentDate),s=n.template(t,e.extend({title:i},this.opts));this.d.$nav.html(s),"years"==this.d.view&&e(".datepicker--nav-title",this.d.$nav).addClass("-disabled-"),this.setNavStatus()},_getTitle:function(t){return this.d.formatDate(this.opts.navTitles[this.d.view],t)},_addButton:function(t){this.$buttonsContainer.length||this._addButtonsContainer();var i={action:t,label:this.d.loc[t]},a=n.template(s,i);e("[data-action="+t+"]",this.$buttonsContainer).length||this.$buttonsContainer.append(a)},_addButtonsContainer:function(){this.d.$datepicker.append(i),this.$buttonsContainer=e(".datepicker--buttons",this.d.$datepicker)},setNavStatus:function(){if((this.opts.minDate||this.opts.maxDate)&&this.opts.disableNavWhenOutOfRange){var t=this.d.parsedDate,e=t.month,i=t.year,s=t.date;switch(this.d.view){case"days":this.d._isInRange(new Date(i,e-1,1),"month")||this._disableNav("prev"),this.d._isInRange(new Date(i,e+1,1),"month")||this._disableNav("next");break;case"months":this.d._isInRange(new Date(i-1,e,s),"year")||this._disableNav("prev"),this.d._isInRange(new Date(i+1,e,s),"year")||this._disableNav("next");break;case"years":var a=n.getDecade(this.d.date);this.d._isInRange(new Date(a[0]-1,0,1),"year")||this._disableNav("prev"),this.d._isInRange(new Date(a[1]+1,0,1),"year")||this._disableNav("next")}}},_disableNav:function(t){e('[data-action="'+t+'"]',this.d.$nav).addClass("-disabled-")},_activateNav:function(t){e('[data-action="'+t+'"]',this.d.$nav).removeClass("-disabled-")},_onClickNavButton:function(t){var i=e(t.target).closest("[data-action]"),s=i.data("action");this.d[s]()},_onClickNavTitle:function(t){return e(t.target).hasClass("-disabled-")?void 0:"days"==this.d.view?this.d.view="months":void(this.d.view="years")}}}(),function(){var t=' #{hourVisible} : #{minValue}
',i=e.fn.datepicker,s=i.Constructor;i.Timepicker=function(t,e){this.d=t,this.opts=e,this.init()},i.Timepicker.prototype={init:function(){var t="input";this._setTime(this.d.date),this._buildHTML(),navigator.userAgent.match(/trident/gi)&&(t="change"),this.d.$el.on("selectDate",this._onSelectDate.bind(this)),this.$ranges.on(t,this._onChangeRange.bind(this)),this.$ranges.on("mouseup",this._onMouseUpRange.bind(this)),this.$ranges.on("mousemove focus ",this._onMouseEnterRange.bind(this)),this.$ranges.on("mouseout blur",this._onMouseOutRange.bind(this))},_setTime:function(t){var e=s.getParsedDate(t);this._handleDate(t),this.hours=e.hourst.getHours()&&(this.minMinutes=this.opts.minMinutes)},_setMaxTimeFromDate:function(t){
+this.maxHours=t.getHours(),this.maxMinutes=t.getMinutes(),this.d.lastSelectedDate&&this.d.lastSelectedDate.getHours()t?0:i.minHours,this.minMinutes=i.minMinutes<0||i.minMinutes>e?0:i.minMinutes,this.maxHours=i.maxHours<0||i.maxHours>t?t:i.maxHours,this.maxMinutes=i.maxMinutes<0||i.maxMinutes>e?e:i.maxMinutes},_validateHoursMinutes:function(t){this.hoursthis.maxHours&&(this.hours=this.maxHours),this.minutesthis.maxMinutes&&(this.minutes=this.maxMinutes)},_buildHTML:function(){var i=s.getLeadingZeroNum,a={hourMin:this.minHours,hourMax:i(this.maxHours),hourStep:this.opts.hoursStep,hourValue:this.hours,hourVisible:i(this.displayHours),minMin:this.minMinutes,minMax:i(this.maxMinutes),minStep:this.opts.minutesStep,minValue:i(this.minutes)},n=s.template(t,a);this.$timepicker=e(n).appendTo(this.d.$datepicker),this.$ranges=e('[type="range"]',this.$timepicker),this.$hours=e('[name="hours"]',this.$timepicker),this.$minutes=e('[name="minutes"]',this.$timepicker),this.$hoursText=e(".datepicker--time-current-hours",this.$timepicker),this.$minutesText=e(".datepicker--time-current-minutes",this.$timepicker),this.d.ampm&&(this.$ampm=e('').appendTo(e(".datepicker--time-current",this.$timepicker)).html(this.dayPeriod),this.$timepicker.addClass("-am-pm-"))},_updateCurrentTime:function(){var t=s.getLeadingZeroNum(this.displayHours),e=s.getLeadingZeroNum(this.minutes);this.$hoursText.html(t),this.$minutesText.html(e),this.d.ampm&&this.$ampm.html(this.dayPeriod)},_updateRanges:function(){this.$hours.attr({min:this.minHours,max:this.maxHours}).val(this.hours),this.$minutes.attr({min:this.minMinutes,max:this.maxMinutes}).val(this.minutes)},_handleDate:function(t){this._setDefaultMinMaxTime(),t&&(s.isSame(t,this.d.opts.minDate)?this._setMinTimeFromDate(this.d.opts.minDate):s.isSame(t,this.d.opts.maxDate)&&this._setMaxTimeFromDate(this.d.opts.maxDate)),this._validateHoursMinutes(t)},update:function(){this._updateRanges(),this._updateCurrentTime()},_getValidHoursFromDate:function(t,e){var i=t,a=t;t instanceof Date&&(i=s.getParsedDate(t),a=i.hours);var n=e||this.d.ampm,h="am";if(n)switch(!0){case 0==a:a=12;break;case 12==a:h="pm";break;case a>11:a-=12,h="pm"}return{hours:a,dayPeriod:h}},set hours(t){this._hours=t;var e=this._getValidHoursFromDate(t);this.displayHours=e.hours,this.dayPeriod=e.dayPeriod},get hours(){return this._hours},_onChangeRange:function(t){var i=e(t.target),s=i.attr("name");this.d.timepickerIsActive=!0,this[s]=i.val(),this._updateCurrentTime(),this.d._trigger("timeChange",[this.hours,this.minutes]),this._handleDate(this.d.lastSelectedDate),this.update()},_onSelectDate:function(t,e){this._handleDate(e),this.update()},_onMouseEnterRange:function(t){var i=e(t.target).attr("name");e(".datepicker--time-current-"+i,this.$timepicker).addClass("-focus-")},_onMouseOutRange:function(t){var i=e(t.target).attr("name");this.d.inFocus||e(".datepicker--time-current-"+i,this.$timepicker).removeClass("-focus-")},_onMouseUpRange:function(t){this.d.timepickerIsActive=!1}}}()}(window,jQuery);
\ No newline at end of file
diff --git a/assets/air-datepicker/js/i18n/datepicker.cs.js b/assets/air-datepicker/js/i18n/datepicker.cs.js
new file mode 100644
index 0000000..a89db7c
--- /dev/null
+++ b/assets/air-datepicker/js/i18n/datepicker.cs.js
@@ -0,0 +1,12 @@
+;(function ($) { $.fn.datepicker.language['cs'] = {
+ days: ['Neděle', 'Pondělí', 'Úterý', 'Středa', 'Čtvrtek', 'Pátek', 'Sobota'],
+ daysShort: ['Ne', 'Po', 'Út', 'St', 'Čt', 'Pá', 'So'],
+ daysMin: ['Ne', 'Po', 'Út', 'St', 'Čt', 'Pá', 'So'],
+ months: ['Leden', 'Únor', 'Březen', 'Duben', 'Květen', 'Červen', 'Červenec', 'Srpen', 'Září', 'Říjen', 'Listopad', 'Prosinec'],
+ monthsShort: ['Led', 'Úno', 'Bře', 'Dub', 'Kvě', 'Čvn', 'Čvc', 'Srp', 'Zář', 'Říj', 'Lis', 'Pro'],
+ today: 'Dnes',
+ clear: 'Vymazat',
+ dateFormat: 'dd.mm.yyyy',
+ timeFormat: 'hh:ii',
+ firstDay: 1
+}; })(jQuery);
\ No newline at end of file
diff --git a/assets/air-datepicker/js/i18n/datepicker.da.js b/assets/air-datepicker/js/i18n/datepicker.da.js
new file mode 100644
index 0000000..f34456e
--- /dev/null
+++ b/assets/air-datepicker/js/i18n/datepicker.da.js
@@ -0,0 +1,12 @@
+;(function ($) { $.fn.datepicker.language['da'] = {
+ days: ['Søndag', 'Mandag', 'Tirsdag', 'Onsdag', 'Torsdag', 'Fredag', 'Lørdag'],
+ daysShort: ['Søn', 'Man', 'Tir', 'Ons', 'Tor', 'Fre', 'Lør'],
+ daysMin: ['Sø', 'Ma', 'Ti', 'On', 'To', 'Fr', 'Lø'],
+ months: ['Januar','Februar','Marts','April','Maj','Juni', 'Juli','August','September','Oktober','November','December'],
+ monthsShort: ['Jan', 'Feb', 'Mar', 'Apr', 'Maj', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dec'],
+ today: 'I dag',
+ clear: 'Nulstil',
+ dateFormat: 'dd/mm/yyyy',
+ timeFormat: 'hh:ii',
+ firstDay: 1
+}; })(jQuery);
\ No newline at end of file
diff --git a/assets/air-datepicker/js/i18n/datepicker.de.js b/assets/air-datepicker/js/i18n/datepicker.de.js
new file mode 100644
index 0000000..fd9f8ff
--- /dev/null
+++ b/assets/air-datepicker/js/i18n/datepicker.de.js
@@ -0,0 +1,13 @@
+;(function ($) { $.fn.datepicker.language['de'] = {
+ days: ['Sonntag', 'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag'],
+ daysShort: ['Son', 'Mon', 'Die', 'Mit', 'Don', 'Fre', 'Sam'],
+ daysMin: ['So', 'Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa'],
+ months: ['Januar','Februar','März','April','Mai','Juni', 'Juli','August','September','Oktober','November','Dezember'],
+ monthsShort: ['Jan', 'Feb', 'Mär', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez'],
+ today: 'Heute',
+ clear: 'Aufräumen',
+ dateFormat: 'dd.mm.yyyy',
+ timeFormat: 'hh:ii',
+ firstDay: 1
+};
+ })(jQuery);
\ No newline at end of file
diff --git a/assets/air-datepicker/js/i18n/datepicker.en.js b/assets/air-datepicker/js/i18n/datepicker.en.js
new file mode 100644
index 0000000..32072f6
--- /dev/null
+++ b/assets/air-datepicker/js/i18n/datepicker.en.js
@@ -0,0 +1,12 @@
+;(function ($) { $.fn.datepicker.language['en'] = {
+ days: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
+ daysShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
+ daysMin: ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'],
+ months: ['January','February','March','April','May','June', 'July','August','September','October','November','December'],
+ monthsShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
+ today: 'Today',
+ clear: 'Clear',
+ dateFormat: 'mm/dd/yyyy',
+ timeFormat: 'hh:ii aa',
+ firstDay: 0
+}; })(jQuery);
\ No newline at end of file
diff --git a/assets/air-datepicker/js/i18n/datepicker.es.js b/assets/air-datepicker/js/i18n/datepicker.es.js
new file mode 100644
index 0000000..a8b6af5
--- /dev/null
+++ b/assets/air-datepicker/js/i18n/datepicker.es.js
@@ -0,0 +1,12 @@
+;(function ($) { $.fn.datepicker.language['es'] = {
+ days: ['Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves', 'Viernes', 'Sábado'],
+ daysShort: ['Dom', 'Lun', 'Mar', 'Mie', 'Jue', 'Vie', 'Sab'],
+ daysMin: ['Do', 'Lu', 'Ma', 'Mi', 'Ju', 'Vi', 'Sa'],
+ months: ['Enero','Febrero','Marzo','Abril','Mayo','Junio', 'Julio','Augosto','Septiembre','Octubre','Noviembre','Diciembre'],
+ monthsShort: ['Ene', 'Feb', 'Mar', 'Abr', 'May', 'Jun', 'Jul', 'Ago', 'Sep', 'Oct', 'Nov', 'Dic'],
+ today: 'Hoy',
+ clear: 'Limpiar',
+ dateFormat: 'dd/mm/yyyy',
+ timeFormat: 'hh:ii aa',
+ firstDay: 1
+}; })(jQuery);
\ No newline at end of file
diff --git a/assets/air-datepicker/js/i18n/datepicker.fi.js b/assets/air-datepicker/js/i18n/datepicker.fi.js
new file mode 100644
index 0000000..9619705
--- /dev/null
+++ b/assets/air-datepicker/js/i18n/datepicker.fi.js
@@ -0,0 +1,13 @@
+;(function ($) { $.fn.datepicker.language['fi'] = {
+ days: ['Sunnuntai', 'Maanantai', 'Tiistai', 'Keskiviikko', 'Torstai', 'Perjantai', 'Lauantai'],
+ daysShort: ['Su', 'Ma', 'Ti', 'Ke', 'To', 'Pe', 'La'],
+ daysMin: ['Su', 'Ma', 'Ti', 'Ke', 'To', 'Pe', 'La'],
+ months: ['Tammikuu','Helmikuu','Maaliskuu','Huhtikuu','Toukokuu','Kesäkuu', 'Heinäkuu','Elokuu','Syyskuu','Lokakuu','Marraskuu','Joulukuu'],
+ monthsShort: ['Tammi', 'Helmi', 'Maalis', 'Huhti', 'Touko', 'Kesä', 'Heinä', 'Elo', 'Syys', 'Loka', 'Marras', 'Joulu'],
+ today: 'Tänään',
+ clear: 'Tyhjennä',
+ dateFormat: 'dd.mm.yyyy',
+ timeFormat: 'hh:ii',
+ firstDay: 1
+};
+ })(jQuery);
\ No newline at end of file
diff --git a/assets/air-datepicker/js/i18n/datepicker.fr.js b/assets/air-datepicker/js/i18n/datepicker.fr.js
new file mode 100644
index 0000000..0d083b2
--- /dev/null
+++ b/assets/air-datepicker/js/i18n/datepicker.fr.js
@@ -0,0 +1,12 @@
+;(function ($) { $.fn.datepicker.language['fr'] = {
+ days: ['Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi', 'Vendredi', 'Samedi'],
+ daysShort: ['Dim', 'Lun', 'Mar', 'Mer', 'Jeu', 'Ven', 'Sam'],
+ daysMin: ['Di', 'Lu', 'Ma', 'Me', 'Je', 'Ve', 'Sa'],
+ months: ['Janvier','Février','Mars','Avril','Mai','Juin', 'Juillet','Août','Septembre','Octobre','Novembre','Decembre'],
+ monthsShort: ['Jan', 'Fév', 'Mars', 'Avr', 'Mai', 'Juin', 'Juil', 'Août', 'Sep', 'Oct', 'Nov', 'Dec'],
+ today: "Aujourd'hui",
+ clear: 'Effacer',
+ dateFormat: 'dd/mm/yyyy',
+ timeFormat: 'hh:ii',
+ firstDay: 1
+}; })(jQuery);
\ No newline at end of file
diff --git a/assets/air-datepicker/js/i18n/datepicker.hu.js b/assets/air-datepicker/js/i18n/datepicker.hu.js
new file mode 100644
index 0000000..7d144b3
--- /dev/null
+++ b/assets/air-datepicker/js/i18n/datepicker.hu.js
@@ -0,0 +1,12 @@
+;(function ($) { ;(function ($) { $.fn.datepicker.language['hu'] = {
+ days: ['Vasárnap', 'Hétfő', 'Kedd', 'Szerda', 'Csütörtök', 'Péntek', 'Szombat'],
+ daysShort: ['Va', 'Hé', 'Ke', 'Sze', 'Cs', 'Pé', 'Szo'],
+ daysMin: ['V', 'H', 'K', 'Sz', 'Cs', 'P', 'Sz'],
+ months: ['Január', 'Február', 'Március', 'Április', 'Május', 'Június', 'Július', 'Augusztus', 'Szeptember', 'Október', 'November', 'December'],
+ monthsShort: ['Jan', 'Feb', 'Már', 'Ápr', 'Máj', 'Jún', 'Júl', 'Aug', 'Szep', 'Okt', 'Nov', 'Dec'],
+ today: 'Ma',
+ clear: 'Törlés',
+ dateFormat: 'yyyy-mm-dd',
+ timeFormat: 'hh:ii aa',
+ firstDay: 1
+}; })(jQuery); })(jQuery);
\ No newline at end of file
diff --git a/assets/air-datepicker/js/i18n/datepicker.nl.js b/assets/air-datepicker/js/i18n/datepicker.nl.js
new file mode 100644
index 0000000..8d29a5a
--- /dev/null
+++ b/assets/air-datepicker/js/i18n/datepicker.nl.js
@@ -0,0 +1,12 @@
+;(function ($) { $.fn.datepicker.language['nl'] = {
+ days: ['zondag', 'maandag', 'dinsdag', 'woensdag', 'donderdag', 'vrijdag', 'zaterdag'],
+ daysShort: ['zo', 'ma', 'di', 'wo', 'do', 'vr', 'za'],
+ daysMin: ['zo', 'ma', 'di', 'wo', 'do', 'vr', 'za'],
+ months: ['Januari', 'Februari', 'Maart', 'April', 'Mei', 'Juni', 'Juli', 'Augustus', 'September', 'Oktober', 'November', 'December'],
+ monthsShort: ['Jan', 'Feb', 'Mrt', 'Apr', 'Mei', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dec'],
+ today: 'Vandaag',
+ clear: 'Legen',
+ dateFormat: 'dd-MM-yy',
+ timeFormat: 'hh:ii',
+ firstDay: 0
+}; })(jQuery);
\ No newline at end of file
diff --git a/assets/air-datepicker/js/i18n/datepicker.pl.js b/assets/air-datepicker/js/i18n/datepicker.pl.js
new file mode 100644
index 0000000..3c0f565
--- /dev/null
+++ b/assets/air-datepicker/js/i18n/datepicker.pl.js
@@ -0,0 +1,13 @@
+;(function ($) { $.fn.datepicker.language['pl'] = {
+ days: ['Niedziela', 'Poniedziałek', 'Wtorek', 'Środa', 'Czwartek', 'Piątek', 'Sobota'],
+ daysShort: ['Nie', 'Pon', 'Wto', 'Śro', 'Czw', 'Pią', 'Sob'],
+ daysMin: ['Nd', 'Pn', 'Wt', 'Śr', 'Czw', 'Pt', 'So'],
+ months: ['Styczeń','Luty','Marzec','Kwiecień','Maj','Czerwiec', 'Lipiec','Sierpień','Wrzesień','Październik','Listopad','Grudzień'],
+ monthsShort: ['Sty', 'Lut', 'Mar', 'Kwi', 'Maj', 'Cze', 'Lip', 'Sie', 'Wrz', 'Paź', 'Lis', 'Gru'],
+ today: 'Dzisiaj',
+ clear: 'Wyczyść',
+ dateFormat: 'yyyy-mm-dd',
+ timeFormat: 'hh:ii:aa',
+ firstDay: 1
+};
+ })(jQuery);
\ No newline at end of file
diff --git a/assets/air-datepicker/js/i18n/datepicker.pt-BR.js b/assets/air-datepicker/js/i18n/datepicker.pt-BR.js
new file mode 100644
index 0000000..13a79f5
--- /dev/null
+++ b/assets/air-datepicker/js/i18n/datepicker.pt-BR.js
@@ -0,0 +1,12 @@
+;(function ($) { $.fn.datepicker.language['pt-BR'] = {
+ days: ['Domingo', 'Segunda', 'Terça', 'Quarta', 'Quinta', 'Sexta', 'Sábado'],
+ daysShort: ['Dom', 'Seg', 'Ter', 'Qua', 'Qui', 'Sex', 'Sab'],
+ daysMin: ['Do', 'Se', 'Te', 'Qu', 'Qu', 'Se', 'Sa'],
+ months: ['Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho', 'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro'],
+ monthsShort: ['Jan', 'Fev', 'Mar', 'Abr', 'Mai', 'Jun', 'Jul', 'Ago', 'Set', 'Out', 'Nov', 'Dez'],
+ today: 'Hoje',
+ clear: 'Limpar',
+ dateFormat: 'dd/mm/yyyy',
+ timeFormat: 'hh:ii',
+ firstDay: 0
+}; })(jQuery);
\ No newline at end of file
diff --git a/assets/air-datepicker/js/i18n/datepicker.pt.js b/assets/air-datepicker/js/i18n/datepicker.pt.js
new file mode 100644
index 0000000..92a3a08
--- /dev/null
+++ b/assets/air-datepicker/js/i18n/datepicker.pt.js
@@ -0,0 +1,12 @@
+;(function ($) { $.fn.datepicker.language['pt'] = {
+ days: ['Domingo', 'Segunda', 'Terça', 'Quarta', 'Quinta', 'Sexta', 'Sábado'],
+ daysShort: ['Dom', 'Seg', 'Ter', 'Qua', 'Qui', 'Sex', 'Sab'],
+ daysMin: ['Do', 'Se', 'Te', 'Qa', 'Qi', 'Sx', 'Sa'],
+ months: ['Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho', 'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro'],
+ monthsShort: ['Jan', 'Fev', 'Mar', 'Abr', 'Mai', 'Jun', 'Jul', 'Ago', 'Set', 'Out', 'Nov', 'Dez'],
+ today: 'Hoje',
+ clear: 'Limpar',
+ dateFormat: 'dd/mm/yyyy',
+ timeFormat: 'hh:ii',
+ firstDay: 1
+}; })(jQuery);
\ No newline at end of file
diff --git a/assets/air-datepicker/js/i18n/datepicker.ro.js b/assets/air-datepicker/js/i18n/datepicker.ro.js
new file mode 100644
index 0000000..0034204
--- /dev/null
+++ b/assets/air-datepicker/js/i18n/datepicker.ro.js
@@ -0,0 +1,13 @@
+;(function ($) { $.fn.datepicker.language['ro'] = {
+ days: ['Duminică', 'Luni', 'Marţi', 'Miercuri', 'Joi', 'Vineri', 'Sâmbătă'],
+ daysShort: ['Dum', 'Lun', 'Mar', 'Mie', 'Joi', 'Vin', 'Sâm'],
+ daysMin: ['D', 'L', 'Ma', 'Mi', 'J', 'V', 'S'],
+ months: ['Ianuarie','Februarie','Martie','Aprilie','Mai','Iunie','Iulie','August','Septembrie','Octombrie','Noiembrie','Decembrie'],
+ monthsShort: ['Ian', 'Feb', 'Mar', 'Apr', 'Mai', 'Iun', 'Iul', 'Aug', 'Sept', 'Oct', 'Nov', 'Dec'],
+ today: 'Azi',
+ clear: 'Şterge',
+ dateFormat: 'dd.mm.yyyy',
+ timeFormat: 'hh:ii',
+ firstDay: 1
+};
+ })(jQuery);
\ No newline at end of file
diff --git a/assets/air-datepicker/js/i18n/datepicker.sk.js b/assets/air-datepicker/js/i18n/datepicker.sk.js
new file mode 100644
index 0000000..3312386
--- /dev/null
+++ b/assets/air-datepicker/js/i18n/datepicker.sk.js
@@ -0,0 +1,12 @@
+;(function ($) { $.fn.datepicker.language['sk'] = {
+ days: ['Nedeľa', 'Pondelok', 'Utorok', 'Streda', 'Štvrtok', 'Piatok', 'Sobota'],
+ daysShort: ['Ned', 'Pon', 'Uto', 'Str', 'Štv', 'Pia', 'Sob'],
+ daysMin: ['Ne', 'Po', 'Ut', 'St', 'Št', 'Pi', 'So'],
+ months: ['Január','Február','Marec','Apríl','Máj','Jún', 'Júl','August','September','Október','November','December'],
+ monthsShort: ['Jan', 'Feb', 'Mar', 'Apr', 'Máj', 'Jún', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dec'],
+ today: 'Dnes',
+ clear: 'Vymazať',
+ dateFormat: 'dd.mm.yyyy',
+ timeFormat: 'hh:ii',
+ firstDay: 1
+}; })(jQuery);
\ No newline at end of file
diff --git a/assets/air-datepicker/js/i18n/datepicker.zh.js b/assets/air-datepicker/js/i18n/datepicker.zh.js
new file mode 100644
index 0000000..08633cc
--- /dev/null
+++ b/assets/air-datepicker/js/i18n/datepicker.zh.js
@@ -0,0 +1,12 @@
+;(function ($) { $.fn.datepicker.language['zh'] = {
+ days: ['周日', '周一', '周二', '周三', '周四', '周五', '周六'],
+ daysShort: ['日', '一', '二', '三', '四', '五', '六'],
+ daysMin: ['日', '一', '二', '三', '四', '五', '六'],
+ months: ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
+ monthsShort: ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
+ today: '今天',
+ clear: '清除',
+ dateFormat: 'yyyy-mm-dd',
+ timeFormat: 'hh:ii',
+ firstDay: 1
+}; })(jQuery);
\ No newline at end of file
diff --git a/assets/align/align.js b/assets/align/align.js
new file mode 100644
index 0000000..c68265c
--- /dev/null
+++ b/assets/align/align.js
@@ -0,0 +1,220 @@
+kit.PluginManager.register('align',function() {
+
+ var AlignClass = function(){
+
+ var Align = function()
+ {
+ this.reset();
+ this.node = null;
+ this.parentNode = null;
+ this.offsetHorizontal = 0;
+ this.offsetVertical = 0;
+ this.offset = 0;
+ };
+
+ /**
+ * @param node HTMLElement
+ * @return {Align}
+ */
+ Align.prototype.setNode = function(node){
+ this.node = node;
+ return this;
+ };
+ /**
+ * @param node HTMLElement
+ * @return {Align}
+ */
+ Align.prototype.setParentNode = function(node){
+ this.parentNode = node;
+ return this;
+ };
+ /**
+ * @return {Align}
+ */
+ Align.prototype.reset = function(hor = true, vert = true){
+ if(hor) {
+ this.right = {applicability: 0, valid: false};
+ this.left = {applicability: 0, valid: false};
+ }
+ if(vert) {
+ this.top = {applicability: 0, valid: false};
+ this.bottom = {applicability: 0, valid: false};
+ }
+ return this;
+ };
+
+ Align.prototype.getContentSizes = function() {
+ return {
+ InnerWidth: window.innerWidth,
+ InnerHeight: window.innerHeight,
+ };
+ };
+
+ /**
+ * @param top bool
+ * @param inner bool
+ * @return {Align}
+ */
+ Align.prototype.setVertical = function(top = false, inner = false){
+ var contentSizes = this.getContentSizes();
+ this.reset(false, true);
+
+ if(top){
+ !this.calcTop(contentSizes, inner) && this.calcBottom(contentSizes, inner);
+ } else {
+ !this.calcBottom(contentSizes, inner) && this.calcTop(contentSizes, inner);
+ }
+
+ if(!this.top.valid && !this.bottom.valid) {
+ if(this.top.applicability > this.bottom.applicability || contentSizes.InnerHeight < this.node.offsetHeight) {
+ this.calcTop(contentSizes, inner, true);
+ } else {
+ this.calcBottom(contentSizes, inner, true);
+ }
+ }
+
+ return this;
+ };
+ Align.prototype.calcTop = function (contentSizes, inner, extra = false) {
+ var top, offset;
+
+ this.node.setAttribute('data-kit-align-vertical','top');
+ offset = this.offsetVertical || this.offset;
+
+ if(inner) {
+ top = 0 - this.node.offsetHeight + this.parentNode.offsetHeight - this.parentNode.clientTop - offset;
+ } else {
+ top = 0 - this.parentNode.clientTop - this.node.offsetHeight + this.node.clientTop - offset;
+ }
+
+ this.node.style.top = '' + top + 'px';
+ this.node.style.bottom = 'unset';
+
+ if(extra) {
+ this.checkTop(contentSizes);
+ this.node.style.top = (top - this.top.applicability) + 'px';
+ return false;
+ }
+ return this.checkTop(contentSizes);
+ };
+ Align.prototype.calcBottom = function (contentSizes, inner, extra = false) {
+
+ var top, offset;
+ this.node.setAttribute('data-kit-align-vertical','bottom');
+ offset = this.offsetVertical || this.offset;
+
+ if(inner) {
+ top = 0 - this.parentNode.clientTop + offset;
+ } else {
+ top = this.parentNode.offsetHeight - this.parentNode.clientTop + offset;
+ }
+
+ this.node.style.top = '' + top + 'px';
+ this.node.style.bottom = 'unset';
+
+ if(extra) {
+ this.checkBottom(contentSizes);
+ this.node.style.top = (top + this.bottom.applicability) + 'px';
+ return false;
+ }
+ return this.checkBottom(contentSizes);
+ };
+ Align.prototype.checkTop = function (contentSizes) {
+ var b = this.node.getBoundingClientRect();
+ this.top.applicability = b.top - 0;
+ this.top.valid = b.top >= 0;
+ return this.top.valid;
+ };
+ Align.prototype.checkBottom = function (contentSizes) {
+ var b = this.node.getBoundingClientRect();
+ this.bottom.applicability = contentSizes.InnerHeight - (b.top + b.height);
+ this.bottom.valid = contentSizes.InnerHeight >= (b.top + b.height);
+ return this.bottom.valid;
+ };
+
+ /**
+ * @param right bool
+ * @param inner bool
+ * @return {Align}
+ */
+ Align.prototype.setHorizontal = function(right = true, inner = false){
+ var contentSizes = this.getContentSizes();
+ this.reset(true, false);
+
+ if(right){
+ !this.calcRight(contentSizes, inner) && this.calcLeft(contentSizes, inner);
+ } else {
+ !this.calcLeft(contentSizes, inner) && this.calcRight(contentSizes, inner);
+ }
+
+ if(!this.left.valid && !this.right.valid) {
+ if(this.left.applicability > this.right.applicability || contentSizes.InnerWidth < this.node.offsetWidth) {
+ this.calcLeft(contentSizes, inner, true);
+ } else {
+ this.calcRight(contentSizes, inner, true)
+ }
+ }
+
+ return this;
+ };
+ Align.prototype.calcLeft = function (contentSizes, inner, extra = false) {
+ var left, offset;
+
+ this.node.setAttribute('data-kit-align-horizontal','left');
+ offset = this.offsetHorizontal || this.offset;
+
+ if(inner) {
+ left = 0 - this.node.offsetWidth + this.parentNode.offsetWidth - this.parentNode.clientLeft - offset;
+ } else {
+ left = 0 - this.parentNode.clientLeft - this.node.offsetWidth + this.node.clientLeft - offset;
+ }
+
+ this.node.style.left = '' + left + 'px';
+ this.node.style.right = 'unset';
+
+ if(extra) {
+ this.checkLeft(contentSizes);
+ this.node.style.left = (left - this.left.applicability) + 'px';
+ return false;
+ }
+ return this.checkLeft(contentSizes);
+ };
+ Align.prototype.calcRight = function (contentSizes, inner, extra = false) {
+ var left, offset;
+ this.node.setAttribute('data-kit-align-horizontal','right');
+ offset = this.offsetHorizontal || this.offset;
+
+ if(inner) {
+ left = 0 - this.parentNode.clientLeft + offset;
+ } else {
+ left = this.parentNode.offsetWidth - this.parentNode.clientLeft + offset;
+ }
+
+ this.node.style.left = '' + left + 'px';
+ this.node.style.right = 'unset';
+
+ if(extra) {
+ this.checkRight(contentSizes);
+ this.node.style.left = (left + this.right.applicability) + 'px';
+ return false;
+ }
+ return this.checkRight(contentSizes);
+ };
+ Align.prototype.checkLeft = function (contentSizes) {
+ var b = this.node.getBoundingClientRect();
+ this.left.applicability = b.left - 0;
+ this.left.valid = b.left >= 0;
+ return this.left.valid;
+ };
+ Align.prototype.checkRight = function (contentSizes) {
+ var b = this.node.getBoundingClientRect();
+ this.right.applicability = contentSizes.InnerWidth - (b.left + b.width);
+ this.right.valid = contentSizes.InnerWidth >= (b.left + b.width);
+ return this.right.valid;
+ };
+ return Align;
+ }();
+
+ this.Class = AlignClass;
+ return this;
+});
diff --git a/assets/bsCore/bsCore.css b/assets/bsCore/bsCore.css
new file mode 100644
index 0000000..9fa6eea
--- /dev/null
+++ b/assets/bsCore/bsCore.css
@@ -0,0 +1,13 @@
+/* modal */
+.modal {
+ display: none;
+}
+.fade {
+ transition: opacity 0.15s linear;
+}
+.fade:not(.show) {
+ opacity: 0;
+}
+.collapse:not(.show) {
+ display: none;
+}
\ No newline at end of file
diff --git a/assets/bsCore/bsCore.js b/assets/bsCore/bsCore.js
new file mode 100644
index 0000000..dbb72a5
--- /dev/null
+++ b/assets/bsCore/bsCore.js
@@ -0,0 +1,1338 @@
+kit.PluginManager.register('bsCore', function(module, exports, require, global){
+
+ module.exports = {
+ dom: {},
+ util: {},
+ };
+ var dom = module.exports.dom;
+ var util = module.exports.util;
+
+ /**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v5.0.2): dom/data.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+ dom.Data = function(){
+ const elementMap = new Map()
+ return {
+ set(element, key, instance) {
+ if (!elementMap.has(element)) {
+ elementMap.set(element, new Map())
+ }
+
+ const instanceMap = elementMap.get(element)
+
+ // make it clear we only want one instance per element
+ // can be removed later when multiple key/instances are fine to be used
+ if (!instanceMap.has(key) && instanceMap.size !== 0) {
+ // eslint-disable-next-line no-console
+ console.error(`Bootstrap doesn't allow more than one instance per element. Bound instance: ${Array.from(instanceMap.keys())[0]}.`)
+ return
+ }
+
+ instanceMap.set(key, instance)
+ },
+
+ get(element, key) {
+ if (elementMap.has(element)) {
+ return elementMap.get(element).get(key) || null
+ }
+
+ return null
+ },
+
+ remove(element, key) {
+ if (!elementMap.has(element)) {
+ return
+ }
+
+ const instanceMap = elementMap.get(element)
+
+ instanceMap.delete(key)
+
+ // free up element references if there are no instances left for an element
+ if (instanceMap.size === 0) {
+ elementMap.delete(element)
+ }
+ }
+ }
+ }();
+
+ /**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v5.0.2): dom/selector-engine.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+ dom.SelectorEngine = function(){
+
+ const NODE_TEXT = 3
+
+ const SelectorEngine = {
+ find(selector, element = document.documentElement) {
+ return [].concat(...Element.prototype.querySelectorAll.call(element, selector))
+ },
+
+ findOne(selector, element = document.documentElement) {
+ return Element.prototype.querySelector.call(element, selector)
+ },
+
+ children(element, selector) {
+ return [].concat(...element.children)
+ .filter(child => child.matches(selector))
+ },
+
+ parents(element, selector) {
+ const parents = []
+
+ let ancestor = element.parentNode
+
+ while (ancestor && ancestor.nodeType === Node.ELEMENT_NODE && ancestor.nodeType !== NODE_TEXT) {
+ if (ancestor.matches(selector)) {
+ parents.push(ancestor)
+ }
+
+ ancestor = ancestor.parentNode
+ }
+
+ return parents
+ },
+
+ prev(element, selector) {
+ let previous = element.previousElementSibling
+
+ while (previous) {
+ if (previous.matches(selector)) {
+ return [previous]
+ }
+
+ previous = previous.previousElementSibling
+ }
+
+ return []
+ },
+
+ next(element, selector) {
+ let next = element.nextElementSibling
+
+ while (next) {
+ if (next.matches(selector)) {
+ return [next]
+ }
+
+ next = next.nextElementSibling
+ }
+
+ return []
+ }
+ }
+ return SelectorEngine;
+ }();
+
+
+ /**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v5.0.2): dom/manipulator.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+
+ dom.Manipulator = function(){
+ function normalizeData(val) {
+ if (val === 'true') {
+ return true
+ }
+
+ if (val === 'false') {
+ return false
+ }
+
+ if (val === Number(val).toString()) {
+ return Number(val)
+ }
+
+ if (val === '' || val === 'null') {
+ return null
+ }
+
+ return val
+ }
+
+ function normalizeDataKey(key) {
+ return key.replace(/[A-Z]/g, chr => `-${chr.toLowerCase()}`)
+ }
+
+ const Manipulator = {
+ setDataAttribute(element, key, value) {
+ element.setAttribute(`data-bs-${normalizeDataKey(key)}`, value)
+ },
+
+ removeDataAttribute(element, key) {
+ element.removeAttribute(`data-bs-${normalizeDataKey(key)}`)
+ },
+
+ getDataAttributes(element) {
+ if (!element) {
+ return {}
+ }
+
+ const attributes = {}
+
+ Object.keys(element.dataset)
+ .filter(key => key.startsWith('bs'))
+ .forEach(key => {
+ let pureKey = key.replace(/^bs/, '')
+ pureKey = pureKey.charAt(0).toLowerCase() + pureKey.slice(1, pureKey.length)
+ attributes[pureKey] = normalizeData(element.dataset[key])
+ })
+
+ return attributes
+ },
+
+ getDataAttribute(element, key) {
+ return normalizeData(element.getAttribute(`data-bs-${normalizeDataKey(key)}`))
+ },
+
+ offset(element) {
+ const rect = element.getBoundingClientRect()
+
+ return {
+ top: rect.top + document.body.scrollTop,
+ left: rect.left + document.body.scrollLeft
+ }
+ },
+
+ position(element) {
+ return {
+ top: element.offsetTop,
+ left: element.offsetLeft
+ }
+ }
+ }
+ return Manipulator;
+ }();
+
+
+ /**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v5.0.2): util/index.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+ util.index = function(SelectorEngine){
+
+ const MAX_UID = 1000000
+ const MILLISECONDS_MULTIPLIER = 1000
+ const TRANSITION_END = 'transitionend'
+
+ // Shoutout AngusCroll (https://goo.gl/pxwQGp)
+ const toType = obj => {
+ if (obj === null || obj === undefined) {
+ return `${obj}`
+ }
+
+ return {}.toString.call(obj).match(/\s([a-z]+)/i)[1].toLowerCase()
+ }
+
+ /**
+ * --------------------------------------------------------------------------
+ * Public Util Api
+ * --------------------------------------------------------------------------
+ */
+
+ const getUID = prefix => {
+ do {
+ prefix += Math.floor(Math.random() * MAX_UID)
+ } while (document.getElementById(prefix))
+
+ return prefix
+ }
+
+ const getSelector = element => {
+ let selector = element.getAttribute('data-bs-target')
+
+ if (!selector || selector === '#') {
+ let hrefAttr = element.getAttribute('href')
+
+ // The only valid content that could double as a selector are IDs or classes,
+ // so everything starting with `#` or `.`. If a "real" URL is used as the selector,
+ // `document.querySelector` will rightfully complain it is invalid.
+ // See https://github.com/twbs/bootstrap/issues/32273
+ if (!hrefAttr || (!hrefAttr.includes('#') && !hrefAttr.startsWith('.'))) {
+ return null
+ }
+
+ // Just in case some CMS puts out a full URL with the anchor appended
+ if (hrefAttr.includes('#') && !hrefAttr.startsWith('#')) {
+ hrefAttr = `#${hrefAttr.split('#')[1]}`
+ }
+
+ selector = hrefAttr && hrefAttr !== '#' ? hrefAttr.trim() : null
+ }
+
+ return selector
+ }
+
+ const getSelectorFromElement = element => {
+ const selector = getSelector(element)
+
+ if (selector) {
+ return document.querySelector(selector) ? selector : null
+ }
+
+ return null
+ }
+
+ const getElementFromSelector = element => {
+ const selector = getSelector(element)
+
+ return selector ? document.querySelector(selector) : null
+ }
+
+ const getTransitionDurationFromElement = element => {
+ if (!element) {
+ return 0
+ }
+
+ // Get transition-duration of the element
+ let { transitionDuration, transitionDelay } = window.getComputedStyle(element)
+
+ const floatTransitionDuration = Number.parseFloat(transitionDuration)
+ const floatTransitionDelay = Number.parseFloat(transitionDelay)
+
+ // Return 0 if element or transition duration is not found
+ if (!floatTransitionDuration && !floatTransitionDelay) {
+ return 0
+ }
+
+ // If multiple durations are defined, take the first
+ transitionDuration = transitionDuration.split(',')[0]
+ transitionDelay = transitionDelay.split(',')[0]
+
+ return (Number.parseFloat(transitionDuration) + Number.parseFloat(transitionDelay)) * MILLISECONDS_MULTIPLIER
+ }
+
+ const triggerTransitionEnd = element => {
+ element.dispatchEvent(new Event(TRANSITION_END))
+ }
+
+ const isElement = obj => {
+ if (!obj || typeof obj !== 'object') {
+ return false
+ }
+
+ if (typeof obj.jquery !== 'undefined') {
+ obj = obj[0]
+ }
+
+ return typeof obj.nodeType !== 'undefined'
+ }
+
+ const getElement = obj => {
+ if (isElement(obj)) { // it's a jQuery object or a node element
+ return obj.jquery ? obj[0] : obj
+ }
+
+ if (typeof obj === 'string' && obj.length > 0) {
+ return SelectorEngine.findOne(obj)
+ }
+
+ return null
+ }
+
+ const typeCheckConfig = (componentName, config, configTypes) => {
+ Object.keys(configTypes).forEach(property => {
+ const expectedTypes = configTypes[property]
+ const value = config[property]
+ const valueType = value && isElement(value) ? 'element' : toType(value)
+
+ if (!new RegExp(expectedTypes).test(valueType)) {
+ throw new TypeError(
+ `${componentName.toUpperCase()}: Option "${property}" provided type "${valueType}" but expected type "${expectedTypes}".`
+ )
+ }
+ })
+ }
+
+ const isVisible = element => {
+ if (!isElement(element) || element.getClientRects().length === 0) {
+ return false
+ }
+
+ return getComputedStyle(element).getPropertyValue('visibility') === 'visible'
+ }
+
+ const isDisabled = element => {
+ if (!element || element.nodeType !== Node.ELEMENT_NODE) {
+ return true
+ }
+
+ if (element.classList.contains('disabled')) {
+ return true
+ }
+
+ if (typeof element.disabled !== 'undefined') {
+ return element.disabled
+ }
+
+ return element.hasAttribute('disabled') && element.getAttribute('disabled') !== 'false'
+ }
+
+ const findShadowRoot = element => {
+ if (!document.documentElement.attachShadow) {
+ return null
+ }
+
+ // Can find the shadow root otherwise it'll return the document
+ if (typeof element.getRootNode === 'function') {
+ const root = element.getRootNode()
+ return root instanceof ShadowRoot ? root : null
+ }
+
+ if (element instanceof ShadowRoot) {
+ return element
+ }
+
+ // when we don't find a shadow root
+ if (!element.parentNode) {
+ return null
+ }
+
+ return findShadowRoot(element.parentNode)
+ }
+
+ const noop = () => {}
+
+ const reflow = element => element.offsetHeight
+
+ const getjQuery = () => {
+ const {jquery} = global
+
+ if (jquery && !document.body.hasAttribute('data-bs-no-jquery')) {
+ return jquery
+ }
+
+ return null
+ }
+
+ const DOMContentLoadedCallbacks = []
+
+ const onDOMContentLoaded = callback => {
+ if (document.readyState === 'loading') {
+ // add listener on the first call when the document is in loading state
+ if (!DOMContentLoadedCallbacks.length) {
+ document.addEventListener('DOMContentLoaded', () => {
+ DOMContentLoadedCallbacks.forEach(callback => callback())
+ })
+ }
+
+ DOMContentLoadedCallbacks.push(callback)
+ } else {
+ callback()
+ }
+ }
+
+ const isRTL = () => document.documentElement.dir === 'rtl'
+
+ const defineJQueryPlugin = plugin => {
+ onDOMContentLoaded(() => {
+ const $ = getjQuery()
+ /* istanbul ignore if */
+ if ($) {
+ const name = plugin.NAME
+ const JQUERY_NO_CONFLICT = $.fn[name]
+ $.fn[name] = plugin.jQueryInterface
+ $.fn[name].Constructor = plugin
+ $.fn[name].noConflict = () => {
+ $.fn[name] = JQUERY_NO_CONFLICT
+ return plugin.jQueryInterface
+ }
+ }
+ })
+ }
+
+ const execute = callback => {
+ if (typeof callback === 'function') {
+ callback()
+ }
+ }
+
+ const executeAfterTransition = (callback, transitionElement, waitForTransition = true) => {
+ if (!waitForTransition) {
+ execute(callback)
+ return
+ }
+
+ const durationPadding = 5
+ const emulatedDuration = getTransitionDurationFromElement(transitionElement) + durationPadding
+
+ let called = false
+
+ const handler = ({ target }) => {
+ if (target !== transitionElement) {
+ return
+ }
+
+ called = true
+ transitionElement.removeEventListener(TRANSITION_END, handler)
+ execute(callback)
+ }
+
+ transitionElement.addEventListener(TRANSITION_END, handler)
+ setTimeout(() => {
+ if (!called) {
+ triggerTransitionEnd(transitionElement)
+ }
+ }, emulatedDuration)
+ }
+
+ /**
+ * Return the previous/next element of a list.
+ *
+ * @param {array} list The list of elements
+ * @param activeElement The active element
+ * @param shouldGetNext Choose to get next or previous element
+ * @param isCycleAllowed
+ * @return {Element|elem} The proper element
+ */
+ const getNextActiveElement = (list, activeElement, shouldGetNext, isCycleAllowed) => {
+ let index = list.indexOf(activeElement)
+
+ // if the element does not exist in the list return an element depending on the direction and if cycle is allowed
+ if (index === -1) {
+ return list[!shouldGetNext && isCycleAllowed ? list.length - 1 : 0]
+ }
+
+ const listLength = list.length
+
+ index += shouldGetNext ? 1 : -1
+
+ if (isCycleAllowed) {
+ index = (index + listLength) % listLength
+ }
+
+ return list[Math.max(0, Math.min(index, listLength - 1))]
+ }
+
+ return {
+ getElement,
+ getUID,
+ getSelectorFromElement,
+ getElementFromSelector,
+ getTransitionDurationFromElement,
+ triggerTransitionEnd,
+ isElement,
+ typeCheckConfig,
+ isVisible,
+ isDisabled,
+ findShadowRoot,
+ noop,
+ getNextActiveElement,
+ reflow,
+ getjQuery,
+ onDOMContentLoaded,
+ isRTL,
+ defineJQueryPlugin,
+ execute,
+ executeAfterTransition
+ }
+ }(dom.SelectorEngine);
+
+ /**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v5.0.2): dom/event-handler.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+ dom.EventHandler = function(getjQuery){
+
+ /**
+ * ------------------------------------------------------------------------
+ * Constants
+ * ------------------------------------------------------------------------
+ */
+
+ const namespaceRegex = /[^.]*(?=\..*)\.|.*/
+ const stripNameRegex = /\..*/
+ const stripUidRegex = /::\d+$/
+ const eventRegistry = {} // Events storage
+ let uidEvent = 1
+ const customEvents = {
+ mouseenter: 'mouseover',
+ mouseleave: 'mouseout'
+ }
+ const customEventsRegex = /^(mouseenter|mouseleave)/i
+ const nativeEvents = new Set([
+ 'click',
+ 'dblclick',
+ 'mouseup',
+ 'mousedown',
+ 'contextmenu',
+ 'mousewheel',
+ 'DOMMouseScroll',
+ 'mouseover',
+ 'mouseout',
+ 'mousemove',
+ 'selectstart',
+ 'selectend',
+ 'keydown',
+ 'keypress',
+ 'keyup',
+ 'orientationchange',
+ 'touchstart',
+ 'touchmove',
+ 'touchend',
+ 'touchcancel',
+ 'pointerdown',
+ 'pointermove',
+ 'pointerup',
+ 'pointerleave',
+ 'pointercancel',
+ 'gesturestart',
+ 'gesturechange',
+ 'gestureend',
+ 'focus',
+ 'blur',
+ 'change',
+ 'reset',
+ 'select',
+ 'submit',
+ 'focusin',
+ 'focusout',
+ 'load',
+ 'unload',
+ 'beforeunload',
+ 'resize',
+ 'move',
+ 'DOMContentLoaded',
+ 'readystatechange',
+ 'error',
+ 'abort',
+ 'scroll'
+ ])
+
+ /**
+ * ------------------------------------------------------------------------
+ * Private methods
+ * ------------------------------------------------------------------------
+ */
+
+ function getUidEvent(element, uid) {
+ return (uid && `${uid}::${uidEvent++}`) || element.uidEvent || uidEvent++
+ }
+
+ function getEvent(element) {
+ const uid = getUidEvent(element)
+
+ element.uidEvent = uid
+ eventRegistry[uid] = eventRegistry[uid] || {}
+
+ return eventRegistry[uid]
+ }
+
+ function bootstrapHandler(element, fn) {
+ return function handler(event) {
+ event.delegateTarget = element
+
+ if (handler.oneOff) {
+ EventHandler.off(element, event.type, fn)
+ }
+
+ return fn.apply(element, [event])
+ }
+ }
+
+ function bootstrapDelegationHandler(element, selector, fn) {
+ return function handler(event) {
+ const domElements = element.querySelectorAll(selector)
+
+ for (let { target } = event; target && target !== this; target = target.parentNode) {
+ for (let i = domElements.length; i--;) {
+ if (domElements[i] === target) {
+ event.delegateTarget = target
+
+ if (handler.oneOff) {
+ // eslint-disable-next-line unicorn/consistent-destructuring
+ EventHandler.off(element, event.type, selector, fn)
+ }
+
+ return fn.apply(target, [event])
+ }
+ }
+ }
+
+ // To please ESLint
+ return null
+ }
+ }
+
+ function findHandler(events, handler, delegationSelector = null) {
+ const uidEventList = Object.keys(events)
+
+ for (let i = 0, len = uidEventList.length; i < len; i++) {
+ const event = events[uidEventList[i]]
+
+ if (event.originalHandler === handler && event.delegationSelector === delegationSelector) {
+ return event
+ }
+ }
+
+ return null
+ }
+
+ function normalizeParams(originalTypeEvent, handler, delegationFn) {
+ const delegation = typeof handler === 'string'
+ const originalHandler = delegation ? delegationFn : handler
+
+ let typeEvent = getTypeEvent(originalTypeEvent)
+ const isNative = nativeEvents.has(typeEvent)
+
+ if (!isNative) {
+ typeEvent = originalTypeEvent
+ }
+
+ return [delegation, originalHandler, typeEvent]
+ }
+
+ function addHandler(element, originalTypeEvent, handler, delegationFn, oneOff) {
+ if (typeof originalTypeEvent !== 'string' || !element) {
+ return
+ }
+
+ if (!handler) {
+ handler = delegationFn
+ delegationFn = null
+ }
+
+ // in case of mouseenter or mouseleave wrap the handler within a function that checks for its DOM position
+ // this prevents the handler from being dispatched the same way as mouseover or mouseout does
+ if (customEventsRegex.test(originalTypeEvent)) {
+ const wrapFn = fn => {
+ return function (event) {
+ if (!event.relatedTarget || (event.relatedTarget !== event.delegateTarget && !event.delegateTarget.contains(event.relatedTarget))) {
+ return fn.call(this, event)
+ }
+ }
+ }
+
+ if (delegationFn) {
+ delegationFn = wrapFn(delegationFn)
+ } else {
+ handler = wrapFn(handler)
+ }
+ }
+
+ const [delegation, originalHandler, typeEvent] = normalizeParams(originalTypeEvent, handler, delegationFn)
+ const events = getEvent(element)
+ const handlers = events[typeEvent] || (events[typeEvent] = {})
+ const previousFn = findHandler(handlers, originalHandler, delegation ? handler : null)
+
+ if (previousFn) {
+ previousFn.oneOff = previousFn.oneOff && oneOff
+
+ return
+ }
+
+ const uid = getUidEvent(originalHandler, originalTypeEvent.replace(namespaceRegex, ''))
+ const fn = delegation ?
+ bootstrapDelegationHandler(element, handler, delegationFn) :
+ bootstrapHandler(element, handler)
+
+ fn.delegationSelector = delegation ? handler : null
+ fn.originalHandler = originalHandler
+ fn.oneOff = oneOff
+ fn.uidEvent = uid
+ handlers[uid] = fn
+
+ element.addEventListener(typeEvent, fn, delegation)
+ }
+
+ function removeHandler(element, events, typeEvent, handler, delegationSelector) {
+ const fn = findHandler(events[typeEvent], handler, delegationSelector)
+
+ if (!fn) {
+ return
+ }
+
+ element.removeEventListener(typeEvent, fn, Boolean(delegationSelector))
+ delete events[typeEvent][fn.uidEvent]
+ }
+
+ function removeNamespacedHandlers(element, events, typeEvent, namespace) {
+ const storeElementEvent = events[typeEvent] || {}
+
+ Object.keys(storeElementEvent).forEach(handlerKey => {
+ if (handlerKey.includes(namespace)) {
+ const event = storeElementEvent[handlerKey]
+
+ removeHandler(element, events, typeEvent, event.originalHandler, event.delegationSelector)
+ }
+ })
+ }
+
+ function getTypeEvent(event) {
+ // allow to get the native events from namespaced events ('click.bs.button' --> 'click')
+ event = event.replace(stripNameRegex, '')
+ return customEvents[event] || event
+ }
+
+ const EventHandler = {
+ on(element, event, handler, delegationFn) {
+ addHandler(element, event, handler, delegationFn, false)
+ },
+
+ one(element, event, handler, delegationFn) {
+ addHandler(element, event, handler, delegationFn, true)
+ },
+
+ off(element, originalTypeEvent, handler, delegationFn) {
+ if (typeof originalTypeEvent !== 'string' || !element) {
+ return
+ }
+
+ const [delegation, originalHandler, typeEvent] = normalizeParams(originalTypeEvent, handler, delegationFn)
+ const inNamespace = typeEvent !== originalTypeEvent
+ const events = getEvent(element)
+ const isNamespace = originalTypeEvent.startsWith('.')
+
+ if (typeof originalHandler !== 'undefined') {
+ // Simplest case: handler is passed, remove that listener ONLY.
+ if (!events || !events[typeEvent]) {
+ return
+ }
+
+ removeHandler(element, events, typeEvent, originalHandler, delegation ? handler : null)
+ return
+ }
+
+ if (isNamespace) {
+ Object.keys(events).forEach(elementEvent => {
+ removeNamespacedHandlers(element, events, elementEvent, originalTypeEvent.slice(1))
+ })
+ }
+
+ const storeElementEvent = events[typeEvent] || {}
+ Object.keys(storeElementEvent).forEach(keyHandlers => {
+ const handlerKey = keyHandlers.replace(stripUidRegex, '')
+
+ if (!inNamespace || originalTypeEvent.includes(handlerKey)) {
+ const event = storeElementEvent[keyHandlers]
+
+ removeHandler(element, events, typeEvent, event.originalHandler, event.delegationSelector)
+ }
+ })
+ },
+
+ trigger(element, event, args) {
+ if (typeof event !== 'string' || !element) {
+ return null
+ }
+
+ const $ = getjQuery()
+ const typeEvent = getTypeEvent(event)
+ const inNamespace = event !== typeEvent
+ const isNative = nativeEvents.has(typeEvent)
+
+ let jQueryEvent
+ let bubbles = true
+ let nativeDispatch = true
+ let defaultPrevented = false
+ let evt = null
+
+ if (inNamespace && $) {
+ jQueryEvent = $.Event(event, args)
+
+ $(element).trigger(jQueryEvent)
+ bubbles = !jQueryEvent.isPropagationStopped()
+ nativeDispatch = !jQueryEvent.isImmediatePropagationStopped()
+ defaultPrevented = jQueryEvent.isDefaultPrevented()
+ }
+
+ if (isNative) {
+ evt = document.createEvent('HTMLEvents')
+ evt.initEvent(typeEvent, bubbles, true)
+ } else {
+ evt = new CustomEvent(event, {
+ bubbles,
+ cancelable: true
+ })
+ }
+
+ // merge custom information in our event
+ if (typeof args !== 'undefined') {
+ Object.keys(args).forEach(key => {
+ Object.defineProperty(evt, key, {
+ get() {
+ return args[key]
+ }
+ })
+ })
+ }
+
+ if (defaultPrevented) {
+ evt.preventDefault()
+ }
+
+ if (nativeDispatch) {
+ element.dispatchEvent(evt)
+ }
+
+ if (evt.defaultPrevented && typeof jQueryEvent !== 'undefined') {
+ jQueryEvent.preventDefault()
+ }
+
+ return evt
+ }
+ }
+ return EventHandler;
+ }(util.index.getjQuery);
+
+
+
+ /**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v5.0.2): util/backdrop.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+ util.Backdrop = function(EventHandler, execute, executeAfterTransition, getElement, reflow, typeCheckConfig){
+ const Default = {
+ isVisible: true, // if false, we use the backdrop helper without adding any element to the dom
+ isAnimated: false,
+ rootElement: 'body', // give the choice to place backdrop under different elements
+ clickCallback: null
+ }
+
+ const DefaultType = {
+ isVisible: 'boolean',
+ isAnimated: 'boolean',
+ rootElement: '(element|string)',
+ clickCallback: '(function|null)'
+ }
+ const NAME = 'backdrop'
+ const CLASS_NAME_BACKDROP = 'modal-backdrop'
+ const CLASS_NAME_FADE = 'fade'
+ const CLASS_NAME_SHOW = 'show'
+
+ const EVENT_MOUSEDOWN = `mousedown.bs.${NAME}`
+
+ class Backdrop {
+ constructor(config) {
+ this._config = this._getConfig(config)
+ this._isAppended = false
+ this._element = null
+ }
+
+ show(callback) {
+ if (!this._config.isVisible) {
+ execute(callback)
+ return
+ }
+
+ this._append()
+
+ if (this._config.isAnimated) {
+ reflow(this._getElement())
+ }
+
+ this._getElement().classList.add(CLASS_NAME_SHOW)
+
+ this._emulateAnimation(() => {
+ execute(callback)
+ })
+ }
+
+ hide(callback) {
+ if (!this._config.isVisible) {
+ execute(callback)
+ return
+ }
+
+ this._getElement().classList.remove(CLASS_NAME_SHOW)
+
+ this._emulateAnimation(() => {
+ this.dispose()
+ execute(callback)
+ })
+ }
+
+ // Private
+
+ _getElement() {
+ if (!this._element) {
+ const backdrop = document.createElement('div')
+ backdrop.className = CLASS_NAME_BACKDROP
+ if (this._config.isAnimated) {
+ backdrop.classList.add(CLASS_NAME_FADE)
+ }
+
+ this._element = backdrop
+ }
+
+ return this._element
+ }
+
+ _getConfig(config) {
+ config = {
+ ...Default,
+ ...(typeof config === 'object' ? config : {})
+ }
+
+ // use getElement() with the default "body" to get a fresh Element on each instantiation
+ config.rootElement = getElement(config.rootElement)
+ typeCheckConfig(NAME, config, DefaultType)
+ return config
+ }
+
+ _append() {
+ if (this._isAppended) {
+ return
+ }
+
+ this._config.rootElement.appendChild(this._getElement())
+
+ EventHandler.on(this._getElement(), EVENT_MOUSEDOWN, () => {
+ execute(this._config.clickCallback)
+ })
+
+ this._isAppended = true
+ }
+
+ dispose() {
+ if (!this._isAppended) {
+ return
+ }
+
+ EventHandler.off(this._element, EVENT_MOUSEDOWN)
+
+ this._element.remove()
+ this._isAppended = false
+ }
+
+ _emulateAnimation(callback) {
+ executeAfterTransition(callback, this._getElement(), this._config.isAnimated)
+ }
+ }
+
+ return Backdrop
+ }(
+ dom.EventHandler,
+ util.index.execute,
+ util.index.executeAfterTransition,
+ util.index.getElement,
+ util.index.reflow,
+ util.index.typeCheckConfig
+ );
+ /**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v5.0.2): util/sanitizer.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+ util.sanitizer = function(){
+
+ const uriAttrs = new Set([
+ 'background',
+ 'cite',
+ 'href',
+ 'itemtype',
+ 'longdesc',
+ 'poster',
+ 'src',
+ 'xlink:href'
+ ])
+
+ const ARIA_ATTRIBUTE_PATTERN = /^aria-[\w-]*$/i
+
+ /**
+ * A pattern that recognizes a commonly useful subset of URLs that are safe.
+ *
+ * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts
+ */
+ const SAFE_URL_PATTERN = /^(?:(?:https?|mailto|ftp|tel|file):|[^#&/:?]*(?:[#/?]|$))/i
+
+ /**
+ * A pattern that matches safe data URLs. Only matches image, video and audio types.
+ *
+ * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts
+ */
+ const DATA_URL_PATTERN = /^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[\d+/a-z]+=*$/i
+
+ const allowedAttribute = (attr, allowedAttributeList) => {
+ const attrName = attr.nodeName.toLowerCase()
+
+ if (allowedAttributeList.includes(attrName)) {
+ if (uriAttrs.has(attrName)) {
+ return Boolean(SAFE_URL_PATTERN.test(attr.nodeValue) || DATA_URL_PATTERN.test(attr.nodeValue))
+ }
+
+ return true
+ }
+
+ const regExp = allowedAttributeList.filter(attrRegex => attrRegex instanceof RegExp)
+
+ // Check if a regular expression validates the attribute.
+ for (let i = 0, len = regExp.length; i < len; i++) {
+ if (regExp[i].test(attrName)) {
+ return true
+ }
+ }
+
+ return false
+ }
+
+ const DefaultAllowlist = {
+ // Global attributes allowed on any supplied element below.
+ '*': ['class', 'dir', 'id', 'lang', 'role', ARIA_ATTRIBUTE_PATTERN],
+ a: ['target', 'href', 'title', 'rel'],
+ area: [],
+ b: [],
+ br: [],
+ col: [],
+ code: [],
+ div: [],
+ em: [],
+ hr: [],
+ h1: [],
+ h2: [],
+ h3: [],
+ h4: [],
+ h5: [],
+ h6: [],
+ i: [],
+ img: ['src', 'srcset', 'alt', 'title', 'width', 'height'],
+ li: [],
+ ol: [],
+ p: [],
+ pre: [],
+ s: [],
+ small: [],
+ span: [],
+ sub: [],
+ sup: [],
+ strong: [],
+ u: [],
+ ul: []
+ }
+
+ function sanitizeHtml(unsafeHtml, allowList, sanitizeFn) {
+ if (!unsafeHtml.length) {
+ return unsafeHtml
+ }
+
+ if (sanitizeFn && typeof sanitizeFn === 'function') {
+ return sanitizeFn(unsafeHtml)
+ }
+
+ const domParser = new window.DOMParser()
+ const createdDocument = domParser.parseFromString(unsafeHtml, 'text/html')
+ const allowlistKeys = Object.keys(allowList)
+ const elements = [].concat(...createdDocument.body.querySelectorAll('*'))
+
+ for (let i = 0, len = elements.length; i < len; i++) {
+ const el = elements[i]
+ const elName = el.nodeName.toLowerCase()
+
+ if (!allowlistKeys.includes(elName)) {
+ el.remove()
+
+ continue
+ }
+
+ const attributeList = [].concat(...el.attributes)
+ const allowedAttributes = [].concat(allowList['*'] || [], allowList[elName] || [])
+
+ attributeList.forEach(attr => {
+ if (!allowedAttribute(attr, allowedAttributes)) {
+ el.removeAttribute(attr.nodeName)
+ }
+ })
+ }
+
+ return createdDocument.body.innerHTML
+ }
+
+ return {
+ DefaultAllowlist,
+ sanitizeHtml
+ };
+ }();
+
+
+ /**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v5.0.2): util/scrollBar.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+ util.ScrollBarHelper = function(SelectorEngine, Manipulator, isElement){
+ const SELECTOR_FIXED_CONTENT = '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top'
+ const SELECTOR_STICKY_CONTENT = '.sticky-top'
+
+ class ScrollBarHelper {
+ constructor() {
+ this._element = document.body
+ }
+
+ getWidth() {
+ // https://developer.mozilla.org/en-US/docs/Web/API/Window/innerWidth#usage_notes
+ const documentWidth = document.documentElement.clientWidth
+ return Math.abs(window.innerWidth - documentWidth)
+ }
+
+ hide() {
+ const width = this.getWidth()
+ this._disableOverFlow()
+ // give padding to element to balance the hidden scrollbar width
+ this._setElementAttributes(this._element, 'paddingRight', calculatedValue => calculatedValue + width)
+ // trick: We adjust positive paddingRight and negative marginRight to sticky-top elements to keep showing fullwidth
+ this._setElementAttributes(SELECTOR_FIXED_CONTENT, 'paddingRight', calculatedValue => calculatedValue + width)
+ this._setElementAttributes(SELECTOR_STICKY_CONTENT, 'marginRight', calculatedValue => calculatedValue - width)
+ }
+
+ _disableOverFlow() {
+ this._saveInitialAttribute(this._element, 'overflow')
+ this._element.style.overflow = 'hidden'
+ }
+
+ _setElementAttributes(selector, styleProp, callback) {
+ const scrollbarWidth = this.getWidth()
+ const manipulationCallBack = element => {
+ if (element !== this._element && window.innerWidth > element.clientWidth + scrollbarWidth) {
+ return
+ }
+
+ this._saveInitialAttribute(element, styleProp)
+ const calculatedValue = window.getComputedStyle(element)[styleProp]
+ element.style[styleProp] = `${callback(Number.parseFloat(calculatedValue))}px`
+ }
+
+ this._applyManipulationCallback(selector, manipulationCallBack)
+ }
+
+ reset() {
+ this._resetElementAttributes(this._element, 'overflow')
+ this._resetElementAttributes(this._element, 'paddingRight')
+ this._resetElementAttributes(SELECTOR_FIXED_CONTENT, 'paddingRight')
+ this._resetElementAttributes(SELECTOR_STICKY_CONTENT, 'marginRight')
+ }
+
+ _saveInitialAttribute(element, styleProp) {
+ const actualValue = element.style[styleProp]
+ if (actualValue) {
+ Manipulator.setDataAttribute(element, styleProp, actualValue)
+ }
+ }
+
+ _resetElementAttributes(selector, styleProp) {
+ const manipulationCallBack = element => {
+ const value = Manipulator.getDataAttribute(element, styleProp)
+ if (typeof value === 'undefined') {
+ element.style.removeProperty(styleProp)
+ } else {
+ Manipulator.removeDataAttribute(element, styleProp)
+ element.style[styleProp] = value
+ }
+ }
+
+ this._applyManipulationCallback(selector, manipulationCallBack)
+ }
+
+ _applyManipulationCallback(selector, callBack) {
+ if (isElement(selector)) {
+ callBack(selector)
+ } else {
+ SelectorEngine.find(selector, this._element).forEach(callBack)
+ }
+ }
+
+ isOverflowing() {
+ return this.getWidth() > 0
+ }
+ }
+ return ScrollBarHelper;
+ }(
+ dom.SelectorEngine,
+ dom.Manipulator,
+ util.index.isElement
+ );
+
+ /**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v5.0.2): base-component.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+ module.exports.BaseComponent = function (Data, executeAfterTransition, getElement, EventHandler) {
+
+ const VERSION = '5.0.2'
+
+ class BaseComponent {
+ constructor(element) {
+ element = getElement(element)
+
+ if (!element) {
+ return
+ }
+
+ this._element = element
+ Data.set(this._element, this.constructor.DATA_KEY, this)
+ }
+
+ dispose() {
+ Data.remove(this._element, this.constructor.DATA_KEY)
+ EventHandler.off(this._element, this.constructor.EVENT_KEY)
+
+ Object.getOwnPropertyNames(this).forEach(propertyName => {
+ this[propertyName] = null
+ })
+ }
+
+ _queueCallback(callback, element, isAnimated = true) {
+ executeAfterTransition(callback, element, isAnimated)
+ }
+
+ /** Static */
+
+ static getInstance(element) {
+ return Data.get(element, this.DATA_KEY)
+ }
+
+ static getOrCreateInstance(element, config = {}) {
+ return this.getInstance(element) || new this(element, typeof config === 'object' ? config : null)
+ }
+
+ static get VERSION() {
+ return VERSION
+ }
+
+ static get NAME() {
+ throw new Error('You have to implement the static method "NAME", for each component!')
+ }
+
+ static get DATA_KEY() {
+ return `bs.${this.NAME}`
+ }
+
+ static get EVENT_KEY() {
+ return `.${this.DATA_KEY}`
+ }
+ }
+
+ return BaseComponent;
+ }(
+ dom.Data,
+ util.index.executeAfterTransition,
+ util.index.getElement,
+ dom.EventHandler
+ );
+
+
+ return module.exports;
+});
\ No newline at end of file
diff --git a/assets/collapse/collapse.css b/assets/collapse/collapse.css
new file mode 100644
index 0000000..304fa1b
--- /dev/null
+++ b/assets/collapse/collapse.css
@@ -0,0 +1,122 @@
+.collapse:not(.show) {
+ display: none;
+}
+
+.collapsing {
+ height: 0;
+ overflow: hidden;
+ transition: height 0.35s ease;
+}
+@media (prefers-reduced-motion: reduce) {
+ .collapsing {
+ /*transition: none;*/
+ }
+}
+.accordion-button {
+ position: relative;
+ display: flex;
+ align-items: center;
+ width: 100%;
+ padding: 1rem 1.25rem;
+ font-size: 1rem;
+ color: #212529;
+ text-align: left;
+ background-color: #fff;
+ border: 0;
+ border-radius: 0;
+ overflow-anchor: none;
+ transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out, border-radius 0.15s ease;
+}
+@media (prefers-reduced-motion: reduce) {
+ .accordion-button {
+ /*transition: none;*/
+ }
+}
+.accordion-button:not(.collapsed) {
+ color: #0c63e4;
+ background-color: #e7f1ff;
+ box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.125);
+}
+.accordion-button:not(.collapsed)::after {
+ background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%230c63e4'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
+ transform: rotate(-180deg);
+}
+.accordion-button::after {
+ flex-shrink: 0;
+ width: 1.25rem;
+ height: 1.25rem;
+ margin-left: auto;
+ content: "";
+ background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23212529'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
+ background-repeat: no-repeat;
+ background-size: 1.25rem;
+ transition: transform 0.2s ease-in-out;
+}
+@media (prefers-reduced-motion: reduce) {
+ .accordion-button::after {
+ /*transition: none;*/
+ }
+}
+.accordion-button:hover {
+ z-index: 2;
+}
+.accordion-button:focus {
+ z-index: 3;
+ border-color: #86b7fe;
+ outline: 0;
+ box-shadow: none;
+}
+
+.accordion-header {
+ margin-bottom: 0;
+}
+
+.accordion-item {
+ background-color: #fff;
+ border: 1px solid rgba(0, 0, 0, 0.125);
+}
+.accordion-item:first-of-type {
+ border-top-left-radius: 0.25rem;
+ border-top-right-radius: 0.25rem;
+}
+.accordion-item:first-of-type .accordion-button {
+ border-top-left-radius: calc(0.25rem - 1px);
+ border-top-right-radius: calc(0.25rem - 1px);
+}
+.accordion-item:not(:first-of-type) {
+ border-top: 0;
+}
+.accordion-item:last-of-type {
+ border-bottom-right-radius: 0.25rem;
+ border-bottom-left-radius: 0.25rem;
+}
+.accordion-item:last-of-type .accordion-button.collapsed {
+ border-bottom-right-radius: calc(0.25rem - 1px);
+ border-bottom-left-radius: calc(0.25rem - 1px);
+}
+.accordion-item:last-of-type .accordion-collapse {
+ border-bottom-right-radius: 0.25rem;
+ border-bottom-left-radius: 0.25rem;
+}
+
+.accordion-body {
+ padding: 1rem 1.25rem;
+}
+
+.accordion-flush .accordion-collapse {
+ border-width: 0;
+}
+.accordion-flush .accordion-item {
+ border-right: 0;
+ border-left: 0;
+ border-radius: 0;
+}
+.accordion-flush .accordion-item:first-child {
+ border-top: 0;
+}
+.accordion-flush .accordion-item:last-child {
+ border-bottom: 0;
+}
+.accordion-flush .accordion-item .accordion-button {
+ border-radius: 0;
+}
\ No newline at end of file
diff --git a/assets/collapse/collapse.js b/assets/collapse/collapse.js
new file mode 100644
index 0000000..5d1ed26
--- /dev/null
+++ b/assets/collapse/collapse.js
@@ -0,0 +1,391 @@
+kit.PluginManager.register('collapse', function(module, exports, require) {
+ var bsCore = require('bsCore');
+
+ /**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v5.0.2): collapse.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+ var {
+ defineJQueryPlugin,
+ getElement,
+ getSelectorFromElement,
+ getElementFromSelector,
+ reflow,
+ typeCheckConfig
+ } = bsCore.util.index;
+ var {Data, EventHandler, Manipulator, SelectorEngine} = bsCore.dom;
+ var BaseComponent = bsCore.BaseComponent;
+
+
+ /**
+ * ------------------------------------------------------------------------
+ * Constants
+ * ------------------------------------------------------------------------
+ */
+
+ const NAME = 'collapse'
+ const DATA_KEY = 'bs.collapse'
+ const EVENT_KEY = `.${DATA_KEY}`
+ const DATA_API_KEY = '.data-api'
+
+ const Default = {
+ toggle: true,
+ parent: ''
+ }
+
+ const DefaultType = {
+ toggle: 'boolean',
+ parent: '(string|element)'
+ }
+
+ const EVENT_SHOW = `show${EVENT_KEY}`
+ const EVENT_SHOWN = `shown${EVENT_KEY}`
+ const EVENT_HIDE = `hide${EVENT_KEY}`
+ const EVENT_HIDDEN = `hidden${EVENT_KEY}`
+ const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`
+
+ const CLASS_NAME_SHOW = 'show'
+ const CLASS_NAME_COLLAPSE = 'collapse'
+ const CLASS_NAME_COLLAPSING = 'collapsing'
+ const CLASS_NAME_COLLAPSED = 'collapsed'
+
+ const WIDTH = 'width'
+ const HEIGHT = 'height'
+
+ const SELECTOR_ACTIVES = '.show, .collapsing'
+ const SELECTOR_DATA_TOGGLE = '[data-bs-toggle="collapse"]'
+
+ /**
+ * ------------------------------------------------------------------------
+ * Class Definition
+ * ------------------------------------------------------------------------
+ */
+
+ class Collapse extends BaseComponent {
+ constructor(element, config) {
+ super(element)
+
+ this._isTransitioning = false
+ this._config = this._getConfig(config)
+ this._triggerArray = SelectorEngine.find(
+ `${SELECTOR_DATA_TOGGLE}[href="#${this._element.id}"],` +
+ `${SELECTOR_DATA_TOGGLE}[data-bs-target="#${this._element.id}"]`
+ )
+
+ const toggleList = SelectorEngine.find(SELECTOR_DATA_TOGGLE)
+
+ for (let i = 0, len = toggleList.length; i < len; i++) {
+ const elem = toggleList[i]
+ const selector = getSelectorFromElement(elem)
+ const filterElement = SelectorEngine.find(selector)
+ .filter(foundElem => foundElem === this._element)
+
+ if (selector !== null && filterElement.length) {
+ this._selector = selector
+ this._triggerArray.push(elem)
+ }
+ }
+
+ this._parent = this._config.parent ? this._getParent() : null
+
+ if (!this._config.parent) {
+ this._addAriaAndCollapsedClass(this._element, this._triggerArray)
+ }
+
+ if (this._config.toggle) {
+ this.toggle()
+ }
+ }
+
+ // Getters
+
+ static get Default() {
+ return Default
+ }
+
+ static get NAME() {
+ return NAME
+ }
+
+ // Public
+
+ toggle() {
+ if (this._element.classList.contains(CLASS_NAME_SHOW)) {
+ this.hide()
+ } else {
+ this.show()
+ }
+ }
+
+ show() {
+ if (this._isTransitioning || this._element.classList.contains(CLASS_NAME_SHOW)) {
+ return
+ }
+
+ let actives
+ let activesData
+
+ if (this._parent) {
+ actives = SelectorEngine.find(SELECTOR_ACTIVES, this._parent)
+ .filter(elem => {
+ if (typeof this._config.parent === 'string') {
+ return elem.getAttribute('data-bs-parent') === this._config.parent
+ }
+
+ return elem.classList.contains(CLASS_NAME_COLLAPSE)
+ })
+
+ if (actives.length === 0) {
+ actives = null
+ }
+ }
+
+ const container = SelectorEngine.findOne(this._selector)
+ if (actives) {
+ const tempActiveData = actives.find(elem => container !== elem)
+ activesData = tempActiveData ? Collapse.getInstance(tempActiveData) : null
+
+ if (activesData && activesData._isTransitioning) {
+ return
+ }
+ }
+
+ const startEvent = EventHandler.trigger(this._element, EVENT_SHOW)
+ if (startEvent.defaultPrevented) {
+ return
+ }
+
+ if (actives) {
+ actives.forEach(elemActive => {
+ if (container !== elemActive) {
+ Collapse.collapseInterface(elemActive, 'hide')
+ }
+
+ if (!activesData) {
+ Data.set(elemActive, DATA_KEY, null)
+ }
+ })
+ }
+
+ const dimension = this._getDimension()
+
+ this._element.classList.remove(CLASS_NAME_COLLAPSE)
+ this._element.classList.add(CLASS_NAME_COLLAPSING)
+
+ this._element.style[dimension] = 0
+
+ if (this._triggerArray.length) {
+ this._triggerArray.forEach(element => {
+ element.classList.remove(CLASS_NAME_COLLAPSED)
+ element.setAttribute('aria-expanded', true)
+ })
+ }
+
+ this.setTransitioning(true)
+
+ const complete = () => {
+ this._element.classList.remove(CLASS_NAME_COLLAPSING)
+ this._element.classList.add(CLASS_NAME_COLLAPSE, CLASS_NAME_SHOW)
+
+ this._element.style[dimension] = ''
+
+ this.setTransitioning(false)
+
+ EventHandler.trigger(this._element, EVENT_SHOWN)
+ }
+
+ const capitalizedDimension = dimension[0].toUpperCase() + dimension.slice(1)
+ const scrollSize = `scroll${capitalizedDimension}`
+
+ this._queueCallback(complete, this._element, true)
+ this._element.style[dimension] = `${this._element[scrollSize]}px`
+ }
+
+ hide() {
+ if (this._isTransitioning || !this._element.classList.contains(CLASS_NAME_SHOW)) {
+ return
+ }
+
+ const startEvent = EventHandler.trigger(this._element, EVENT_HIDE)
+ if (startEvent.defaultPrevented) {
+ return
+ }
+
+ const dimension = this._getDimension()
+
+ this._element.style[dimension] = `${this._element.getBoundingClientRect()[dimension]}px`
+
+ reflow(this._element)
+
+ this._element.classList.add(CLASS_NAME_COLLAPSING)
+ this._element.classList.remove(CLASS_NAME_COLLAPSE, CLASS_NAME_SHOW)
+
+ const triggerArrayLength = this._triggerArray.length
+ if (triggerArrayLength > 0) {
+ for (let i = 0; i < triggerArrayLength; i++) {
+ const trigger = this._triggerArray[i]
+ const elem = getElementFromSelector(trigger)
+
+ if (elem && !elem.classList.contains(CLASS_NAME_SHOW)) {
+ trigger.classList.add(CLASS_NAME_COLLAPSED)
+ trigger.setAttribute('aria-expanded', false)
+ }
+ }
+ }
+
+ this.setTransitioning(true)
+
+ const complete = () => {
+ this.setTransitioning(false)
+ this._element.classList.remove(CLASS_NAME_COLLAPSING)
+ this._element.classList.add(CLASS_NAME_COLLAPSE)
+ EventHandler.trigger(this._element, EVENT_HIDDEN)
+ }
+
+ this._element.style[dimension] = ''
+
+ this._queueCallback(complete, this._element, true)
+ }
+
+ setTransitioning(isTransitioning) {
+ this._isTransitioning = isTransitioning
+ }
+
+ // Private
+
+ _getConfig(config) {
+ config = {
+ ...Default,
+ ...config
+ }
+ config.toggle = Boolean(config.toggle) // Coerce string values
+ typeCheckConfig(NAME, config, DefaultType)
+ return config
+ }
+
+ _getDimension() {
+ return this._element.classList.contains(WIDTH) ? WIDTH : HEIGHT
+ }
+
+ _getParent() {
+ let { parent } = this._config
+
+ parent = getElement(parent)
+
+ const selector = `${SELECTOR_DATA_TOGGLE}[data-bs-parent="${parent}"]`
+
+ SelectorEngine.find(selector, parent)
+ .forEach(element => {
+ const selected = getElementFromSelector(element)
+
+ this._addAriaAndCollapsedClass(
+ selected,
+ [element]
+ )
+ })
+
+ return parent
+ }
+
+ _addAriaAndCollapsedClass(element, triggerArray) {
+ if (!element || !triggerArray.length) {
+ return
+ }
+
+ const isOpen = element.classList.contains(CLASS_NAME_SHOW)
+
+ triggerArray.forEach(elem => {
+ if (isOpen) {
+ elem.classList.remove(CLASS_NAME_COLLAPSED)
+ } else {
+ elem.classList.add(CLASS_NAME_COLLAPSED)
+ }
+
+ elem.setAttribute('aria-expanded', isOpen)
+ })
+ }
+
+ // Static
+
+ static collapseInterface(element, config) {
+ let data = Collapse.getInstance(element)
+ const _config = {
+ ...Default,
+ ...Manipulator.getDataAttributes(element),
+ ...(typeof config === 'object' && config ? config : {})
+ }
+
+ if (!data && _config.toggle && typeof config === 'string' && /show|hide/.test(config)) {
+ _config.toggle = false
+ }
+
+ if (!data) {
+ data = new Collapse(element, _config)
+ }
+
+ if (typeof config === 'string') {
+ if (typeof data[config] === 'undefined') {
+ throw new TypeError(`No method named "${config}"`)
+ }
+
+ data[config]()
+ }
+ }
+
+ static jQueryInterface(config) {
+ return this.each(function () {
+ Collapse.collapseInterface(this, config)
+ })
+ }
+ }
+
+ /**
+ * ------------------------------------------------------------------------
+ * Data Api implementation
+ * ------------------------------------------------------------------------
+ */
+ EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) {
+ // preventDefault only for elements (which change the URL) not inside the collapsible element
+ if (event.target.tagName === 'A' || (event.delegateTarget && event.delegateTarget.tagName === 'A')) {
+ event.preventDefault()
+ }
+
+ const triggerData = Manipulator.getDataAttributes(this)
+ const selector = getSelectorFromElement(this)
+ const selectorElements = SelectorEngine.find(selector)
+
+ selectorElements.forEach(element => {
+ const data = Collapse.getInstance(element)
+ let config
+ if (data) {
+ // update parent attribute
+ if (data._parent === null && typeof triggerData.parent === 'string') {
+ data._config.parent = triggerData.parent
+ data._parent = data._getParent()
+ }
+
+ config = 'toggle'
+ } else {
+ config = triggerData
+ }
+
+ Collapse.collapseInterface(element, config)
+ })
+ })
+
+ /**
+ * ------------------------------------------------------------------------
+ * jQuery
+ * ------------------------------------------------------------------------
+ * add .Collapse to jQuery only if jQuery is present
+ */
+
+ defineJQueryPlugin(Collapse)
+
+ module.exports = Collapse;
+
+ return module.exports;
+});
\ No newline at end of file
diff --git a/assets/core/core.js b/assets/core/core.js
new file mode 100644
index 0000000..c928104
--- /dev/null
+++ b/assets/core/core.js
@@ -0,0 +1,554 @@
+window.kit = window.kit || {};
+(function(global){
+ var stackPromise = {};
+ var stateList = {
+ undefined: 0,
+ registered: 1,
+ loaded: 3,
+ installed: 4,
+ };
+ var moduleTypeList = {
+ loader: 'loader',
+ import: 'import',
+ };
+ var PluginManager = function(global, modules = {}){
+ this.plugins = {};
+ this.global = global;
+ this.registerPlugins(modules);
+ };
+
+ var __proto = PluginManager.prototype;
+
+ __proto.__manual = function(){
+ return {
+ config: {
+ type: {
+ import: 'Значение по умолчанию. Нативный загрузчик модулей. Файл модуля содержит ключевые фразы "export" и "export default"',
+ loader: 'Файл модуля содержит функцию kit.PluginManager.register(pluginId, function(module, exports, require){})',
+ },
+ alias: 'тип Array|string. Список ключей, которые могут быть использованы вместо pluginId, как и в require() так и в global',
+ import: 'тип string. Ссылка на файл с модулем',
+ loader: 'Используется для загрузки модулей типа loader',
+ deps: 'тип Array|string. Зависимости, Id плагинов.',
+ css: 'тип Array|string. Массив путей к стилям. Стили грузятся синхронно при загрузке плагина. Без событий',
+ js: 'тип Array|string. Массив путей к скриптам. Загрузка идет по цепочке. Для синхронной загрузки скрипты ложатся в массив. пр: [1.js, [1.1.js, 1.2.js]]',
+ loadJsAfterModule: 'определяет порядок загрузки скриптов и модуля',
+ onInstall: 'функция выполняемая после установки плагина (однократно)',
+ onLoad: 'функция выполняемая после загрузки плагина (однократно)',
+ path: 'префикс пути для модуля, скриптов и стилей',
+ modulePath: 'префикс пути для модуля. если не указан, то берется config.path',
+ },
+ }
+ }();
+
+ __proto.__checkState = function(pluginId, state){
+ return this.plugins.hasOwnProperty(pluginId) && this.plugins[pluginId].state >= state;
+ };
+
+ /**
+ * @param plugins
+ * @return {PluginManager}
+ */
+ __proto.registerPlugins = function (plugins) {
+ if(Array.isArray(plugins)) {
+ plugins = Object.assign({}, plugins);
+ }
+ for (var pluginId in plugins) {
+ if(plugins.hasOwnProperty(pluginId)) {
+ this.register(pluginId, plugins[pluginId]);
+ }
+ }
+ return this;
+ };
+
+ __proto.register = function (pluginId, config = {}) {
+ //console.warn('PluginManager.register: plugin ' + pluginId + ' ('+(this.plugins[pluginId]?this.plugins[pluginId].state:'0')+')');
+ var defaultPlugin = {
+ module: {
+ exports: {},
+ },
+ config: {
+ },
+ promise: new Promise(function(resolve, reject){resolve()}),
+ id: pluginId,
+ state: stateList.undefined,
+ stateInit: {
+ loading: false,
+ installing: false,
+ },
+ };
+ var plugin = this.__getPlugin(pluginId);
+ if(plugin) {
+ pluginId = plugin.id;
+ } else {
+ plugin = this.plugins[pluginId] = defaultPlugin;
+ }
+
+ if(
+ this.__checkState(pluginId, stateList.installed) ||
+ (
+ (plugin.stateInit.loading || this.__checkState(pluginId, stateList.loaded)) && typeof config === 'object'
+ )
+ ) {
+ console.warn('PluginManager.register: plugin ' + pluginId + ' уже невозможно конфигурировать ('+plugin.state+')');
+ return false;
+ }
+
+ var loader;
+ if(typeof config === 'function') {
+ loader = config;
+ config = plugin.config;
+ config.loader = loader;
+ config.type = 'loader';
+ }
+
+ if(typeof config === 'object') {
+ if(typeof config.onLoad !== 'function') {
+ config.onLoad = function(){};
+ }
+ if(typeof config.onInstall !== 'function') {
+ config.onInstall = function(){};
+ }
+ if(typeof config.onRegister !== 'function') {
+ config.onRegister = function(){};
+ }
+ if(typeof config.path !== 'string') {
+ config.path = '';
+ }
+ if(!config.hasOwnProperty('modulePath')) {
+ config.modulePath = config.path;
+ } else if(typeof config.modulePath !== 'string') {
+ config.modulePath = config.path;
+ }
+ if(typeof config.js === 'string') {
+ config.js = [config.js];
+ } else if(!Array.isArray(config.js)) {
+ config.js = [];
+ }
+ if(typeof config.css === 'string') {
+ config.css = [config.css];
+ } else if(!Array.isArray(config.css)) {
+ config.css = [];
+ }
+
+ if(typeof config.alias === 'string') {
+ config.alias = [config.alias];
+ } else if(!Array.isArray(config.alias)) {
+ config.alias = [];
+ }
+
+ config.loadJsAfterModule = !!config.loadJsAfterModule;
+ config.type = config.type || 'import'; //loader
+
+ if(typeof config.deps === 'string') {
+ config.deps = [config.deps];
+ } else if(!Array.isArray(config.deps)) {
+ config.deps = [];
+ }
+
+ } else {
+ console.warn('PluginManager.register: plugin ' + pluginId + ' is not a valid format');
+ return false;
+ }
+
+ Object.assign(plugin.config, config);
+
+ if(!this.__checkState(pluginId, stateList.registered)) {
+ plugin.state = stateList.registered;
+ plugin.config.onRegister(plugin);
+ }
+
+ return true;
+ };
+
+ /**
+ * @param pluginId
+ * @param callback
+ * @return {PluginManager}
+ */
+ __proto.load = function (pluginId, callback) {
+ //console.log('PluginManager.load: plugin ' + pluginId + ' ('+(this.plugins[pluginId]?this.plugins[pluginId].state:'0')+')');
+ if(typeof callback !== 'function') {
+ callback = function(){};
+ }
+
+ var plugin = this.__getPlugin(pluginId);
+ if(plugin) {
+ pluginId = plugin.id;
+ }
+
+ if(!this.__checkState(pluginId, stateList.registered)) {
+ console.warn('kit.load: plugin ' + pluginId + ' is not register');
+ return this;
+ }
+ if(this.__checkState(pluginId, stateList.loaded)) {
+ //console.warn('PluginManager.load: plugin ' + pluginId + ' уже загружен');
+ callback();
+ return this;
+ }
+
+
+ if(plugin.stateInit.loading) {
+ //console.log('PluginManager.install: plugin ' + pluginId + ' уже грузится');
+ this.__exec(pluginId, callback);
+ return this;
+ }
+ plugin.stateInit.loading = true;
+
+ var configModule = plugin.config;
+
+ var stackPush = function (callbackPromise, argArr = []){
+ if(typeof plugin.promise === 'undefined') {
+ plugin.promise = callbackPromise.apply(this, argArr);
+ } else {
+ plugin.promise = plugin.promise.then(function(m){
+ return callbackPromise.apply(this, argArr);
+ });
+ }
+ }.bind(this);
+
+ var getModulePromise = (function () {
+
+ function loadScript(src, resolveCallback, rejectCallback) {
+ if(typeof resolveCallback !== 'function'){
+ resolveCallback = function(){};
+ }
+ if(typeof rejectCallback !== 'function'){
+ rejectCallback = function(res){
+ console.warn(res.message);
+ };
+ }
+ return new Promise(function(resolve, reject) {
+ var script = document.querySelector('script[src^="'+src+'"]');
+ if (!script) {
+ script = document.createElement('script');
+ script.src = '' + src + '?__pm' + (new Date()).getTime();
+ script.onload = () => resolve(script);
+ script.onerror = () => reject(new Error(`Ошибка загрузки скрипта ${src}`));
+ document.head.append(script);
+ } else {
+ console.warn(`Скрип ${src} уже загружен`);
+ resolve(script);
+ }
+ }).then(resolveCallback, rejectCallback);
+ }
+ function syncLoadScriptList(list) {
+
+ return new Promise(function(resolve, reject) {
+ var i = 0;
+ var status = true;
+ var count = list.length;
+ var checkResolve = function(src, cond){
+ if(!cond) {
+ console.error(`Ошибка загрузки скрипта ${src}`)
+ }
+ status = status && cond;
+ i++;
+ if(i === count) {
+ resolve();
+ }
+ };
+ var syncPromise = new Promise(function(_resolve, _reject){_resolve();});
+ list.forEach(function(item, i, arr){
+ syncPromise.then(function(){
+ var src = configModule.path + item;
+ var script = document.querySelector('script[src^="'+src+'"]');
+ if (!script) {
+ script = document.createElement('script');
+ script.src = '' + src + '?__pm' + (new Date()).getTime();
+ script.onload = () => checkResolve(src, true);
+ script.onerror = () => checkResolve(src, false);
+ document.head.append(script);
+ } else {
+ checkResolve(src, true);
+ }
+ });
+ });
+ })
+ }
+ function loadStyle(src) {
+ return new Promise(function(resolve, reject) {
+ var link = document.querySelector('link[href^="'+src+'"]');
+ if (!link) {
+ link = document.createElement('link');
+ link.rel = 'stylesheet';
+ link.type = 'text/css';
+ link.href = src + '?__pm' + (new Date()).getTime();
+ link.media = 'all';
+ document.head.append(link);
+ resolve(link);
+ } else {
+ console.warn(`Скрип ${src} уже загружен`);
+ resolve(link);
+ }
+ });
+ }
+
+ var getImportPromise = function (){
+ if(configModule.module && configModule.type === 'import') {
+ return import(configModule.modulePath + configModule.module).then(function(m) {
+ m.__esModule = true;
+ plugin.module.exports = m;
+ }.bind(this), function(r){
+ console.error(r);
+ });
+ } else if(configModule.module && configModule.type === 'loader') {
+ return loadScript(configModule.modulePath + configModule.module).then(function() {
+
+ }.bind(this));
+ }
+ return new Promise(function(resolve, reject){resolve();});
+ }.bind(this);
+ var getResPromise = function(){
+ var p = new Promise(function(resolve, reject){resolve();});
+ configModule.js.forEach(function(item, i, array){
+ if(Array.isArray(item)) {
+ p = p.then(function () {
+ return syncLoadScriptList(item);
+ });
+ } else {
+ p = p.then(function () {
+ return loadScript(configModule.path + item);
+ });
+ }
+ //loadScript(configModule.path + item);
+ });
+ return p;
+ }.bind(this);
+ var setSkipLoadPromise = function (depsPromise) {
+
+ var noJsPromise, noImportPromise;
+ if(configModule.js.length === 0) {
+ noJsPromise = true;
+ }
+ if((!configModule.module && configModule.type === 'import') || (configModule.type === 'loader' && typeof configModule.loader === 'function')) {
+ noImportPromise = true;
+ }
+ plugin.skipLoadPromise = noImportPromise && noJsPromise && !depsPromise;
+ return plugin.skipLoadPromise;
+ }.bind(this);
+
+ configModule.css.forEach(function(item, i, array){
+ loadStyle(configModule.path + item);
+ });
+
+ var depsPromise = this.__getDepsPromise(configModule.deps);
+ setSkipLoadPromise(depsPromise);
+
+ if(depsPromise) {
+ stackPush(function () {
+ return depsPromise;
+ });
+ }
+
+ if(configModule.loadJsAfterModule) {
+ stackPush(getImportPromise);
+ stackPush(getResPromise);
+ } else {
+ stackPush(getResPromise);
+ stackPush(getImportPromise);
+ }
+
+ this.__exec(pluginId, function(){
+ plugin.state = stateList.loaded;
+ plugin.skipLoadPromise = true;
+ configModule.onLoad.call(plugin.module.exports);
+ callback();
+ }.bind(this));
+
+ return plugin.promise;
+
+ }).bind(this);
+
+ getModulePromise();
+
+ return this;
+ };
+
+ /**
+ * @param pluginId
+ * @param callback
+ * @return {PluginManager}
+ */
+ __proto.install = function(pluginId, callback){
+ //console.warn('PluginManager.install: plugin ' + pluginId + ' ('+(this.plugins[pluginId]?this.plugins[pluginId].state:'0')+')');
+ if(typeof callback !== 'function') {
+ callback = function(){};
+ }
+
+ var plugin = this.__getPlugin(pluginId);
+ if(plugin) {
+ pluginId = plugin.id;
+ }
+ var module = plugin.module;
+
+ if(!this.__checkState(pluginId, stateList.registered)) {
+ console.warn('PluginManager.install: plugin ' + pluginId + ' is not register');
+ return this;
+ }
+ if(this.__checkState(pluginId, stateList.installed)) {
+ callback();
+ return this;
+ }
+
+ if(plugin.stateInit.installing) {
+ //console.log('PluginManager.install: plugin ' + pluginId + ' уже устанавливается');
+ this.__exec(pluginId, callback);
+ return this;
+ }
+ plugin.stateInit.installing = true;
+
+ this.load(pluginId);
+
+ var installer = function(){
+ var setGlobalExtension = function (key, aliasList, data) {
+ if(data === undefined) {
+ return;
+ }
+ if(!this.global.hasOwnProperty(key)) {
+ this.global[key] = data;
+ } else {
+ console.warn('PluginManager.install: plugin ' + pluginId + ' already exist in kit ('+plugin.state+')');
+ }
+ if(Array.isArray(aliasList) && aliasList.length) {
+ aliasList.forEach(function (alias) {
+ setGlobalExtension(alias, [], data)
+ }.bind(this))
+ }
+ }.bind(this);
+ if(plugin.config.type === moduleTypeList.loader && typeof plugin.config.loader === 'function') {
+ var returnData = plugin.config.loader.bind(module.exports).call(module.exports, module, module.exports, this.require.bind(this), global);
+ setGlobalExtension(pluginId, plugin.config.alias, returnData);
+
+ } else if(plugin.config.type === moduleTypeList.import && typeof plugin.config.module === 'string') {
+ setGlobalExtension(pluginId, plugin.config.alias, (typeof module.exports === 'object' && module.exports.default !== undefined)?module.exports.default:module.exports);
+ }
+ console.log('PluginManager.install: plugin ' + pluginId + ' установлен');
+ plugin.state = stateList.installed;
+ }.bind(this);
+
+ this.__exec(pluginId, function(){
+ installer();
+ plugin.config.onInstall.call(module.exports, plugin);
+ callback();
+ }.bind(this));
+
+ return this;
+ };
+
+ __proto.require = function (pluginId, callback) {
+ //console.warn('PluginManager.require: plugin ' + pluginId + ' ('+(this.plugins[pluginId]?this.plugins[pluginId].state:'0')+')');
+
+ var plugin = this.__getPlugin(pluginId);
+ if(plugin) {
+ pluginId = plugin.id;
+ }
+ var module = plugin.module;
+
+ if(!this.__checkState(pluginId, stateList.registered)) {
+ console.warn('PluginManager.require: plugin ' + pluginId + ' is not register');
+ return false;
+ }
+ if(typeof callback !== 'function') {
+ callback = function(){};
+ }
+
+ this.install(pluginId, callback);
+
+ return module.exports;
+ };
+
+ __proto.exec = function (deps, callback, argArr = []) {
+ if(!Array.isArray(deps)) {
+ deps = [deps];
+ }
+ if(typeof callback !== 'function') {
+ return undefined;
+ }
+ var depsPromise = this.__getDepsPromise(deps);
+
+ var getArgArr = function () {
+ if(argArr.length === 0) {
+ deps.forEach(function (pluginId) {
+ argArr.push(this.require(pluginId));
+ }.bind(this));
+ return argArr;
+ }
+ return argArr;
+ }.bind(this);
+
+ if(depsPromise) {
+ depsPromise.then(function(){
+ callback.apply(this, getArgArr());
+ });
+ } else {
+ callback.apply(this, getArgArr())
+ }
+ };
+
+ __proto.__exec = function (pluginId, callback, argArr = []) {
+
+ var module = this.plugins[pluginId];
+
+ var exec = function(_callback, argArr){
+ if(module.skipLoadPromise) {
+ _callback.apply(this, argArr);
+ } else {
+ module.promise = module.promise.then(function(){
+ _callback.apply(this, argArr);
+ }.bind(this));
+ }
+ }.bind(this);
+
+ exec(callback, argArr);
+ };
+
+ __proto.__getDepsPromise = function (pluginList) {
+ var skipPromise = true;
+ var promise = new Promise((resolve, reject)=>{
+ var i = 0;
+ var checkModule = function(){
+ if(++i === pluginList.length + 1) {
+ resolve();
+ }
+ };
+ checkModule();
+ pluginList.forEach(function(pluginId, i, array){
+ if(!this.__checkState(pluginId, stateList.registered)) {
+ checkModule();
+ return false;
+ }
+ this.install(pluginId, checkModule);
+ skipPromise = skipPromise && this.plugins[pluginId].skipLoadPromise;
+ }.bind(this));
+ });
+
+ return !skipPromise?promise:undefined;
+ };
+
+
+ __proto.__getPlugin = function (pluginId) {
+ if(this.plugins.hasOwnProperty(pluginId)) {
+ return this.plugins[pluginId];
+ }
+ for (var _pluginId in this.plugins) {
+ if(this.plugins.hasOwnProperty(_pluginId) && this.plugins[_pluginId].config.alias.indexOf(pluginId) !== -1) {
+ return this.plugins[_pluginId];
+ }
+ }
+ return undefined;
+ };
+
+ var manager = new PluginManager(global);
+ manager.register('PluginManager', {
+ alias: 'pm',
+ type: moduleTypeList.loader,
+ loader: function(module, exports, require) {
+ return module.exports = manager;
+ }
+ });
+ manager.install('PluginManager');
+ global.PluginManager = manager;
+ global.exec = manager.exec.bind(manager);
+ global.require = manager.require.bind(manager);
+})(kit || window);
\ No newline at end of file
diff --git a/assets/core/core.register.js b/assets/core/core.register.js
new file mode 100644
index 0000000..83539dd
--- /dev/null
+++ b/assets/core/core.register.js
@@ -0,0 +1,133 @@
+kit.PluginManager.registerPlugins({
+ menu: {
+ path: '/local/templates.dev/kit/assets/menu',
+ module: '/menu.js',
+ css: [
+ '/menu.css'
+ ],
+ type: 'loader',
+ deps: ['lib', 'align', 'utils']
+ },
+ lib: {
+ path: '/local/templates.dev/kit/assets/lib',
+ module: '/lib.js',
+ type: 'loader',
+ },
+ align: {
+ path: '/local/templates.dev/kit/assets/align',
+ module: '/align.js',
+ type: 'loader',
+ },
+ utils: {
+ path: '/local/templates.dev/kit/assets/utils',
+ module: '/utils.js',
+ type: 'loader',
+ },
+ jquery: {
+ path: '/local/templates.dev/kit/assets/jquery',
+ module: '/jquery.min.js',
+ type: 'loader',
+ alias: '$',
+ },
+ tooltip: {
+ path: '/local/templates.dev/kit/assets/tooltip',
+ module: '/tooltip.js',
+ type: 'loader',
+ css: '/tooltip.css',
+ onInstall: function(){
+ kit.$('[data-toggle="tooltip"]').tooltip();
+ },
+ deps: ['popper', 'bsCore'],
+ },
+ popper: {
+ path: '/local/templates.dev/kit/assets/popper',
+ alias: 'popper.js',
+ module: '/popper.js',
+ type: 'loader',
+ },
+ bsCore: {
+ path: '/local/templates.dev/kit/assets/bsCore',
+ module: '/bsCore.js',
+ type: 'loader',
+ css: [
+ '/bsCore.css'
+ ]
+ },
+ mask: {
+ path: '/local/templates.dev/kit/assets/mask',
+ module: '/mask.js',
+ type: 'loader',
+ deps: ['jquery'],
+ },
+ toolkit: {
+ path: '/local/templates.dev/kit/assets/toolkit',
+ module: '/toolkit.js',
+ type: 'loader',
+ css: ['/toolkit.css'],
+ deps: ['jquery', 'mask'],
+ },
+ modal: {
+ path: '/local/templates.dev/kit/assets/modal',
+ module: '/modal.js',
+ type: 'loader',
+ css: [
+ '/modal.css',
+ ],
+ deps: ['bsCore'],
+ onRegister: function (plugin) {
+ plugin.onLoadConditionHandler = function (event) {
+ console.log('1',event);
+ if(event.target && event.target.dataset && event.target.dataset.bsTarget && event.target.dataset.bsToggle === 'modal') {
+ console.log('2');
+ kit.exec(plugin.id, function(){
+ var newEvent = new Event("click");
+ event.target.dispatchEvent(newEvent);
+ });
+ }
+ };
+ window.addEventListener('click', plugin.onLoadConditionHandler, false);
+ },
+ onInstall: function (plugin) {
+ if(plugin.onLoadConditionHandler) {
+ window.removeEventListener('click', plugin.onLoadConditionHandler, false);
+ }
+ },
+ },
+ collapse: {
+ path: '/local/templates.dev/kit/assets/collapse',
+ module: '/collapse.js',
+ type: 'loader',
+ css: [
+ '/collapse.css',
+ ],
+ deps: ['bsCore'],
+ onRegister: function (plugin) {
+ kit.PluginManager.install('collapse')
+ },
+ onInstall: function (plugin) {
+ },
+ },
+
+});
+
+kit.exec([], function () {
+ console.log('start init');
+
+ function _init(){
+ console.log('_init');
+ kit.PluginManager.install('jquery');
+ kit.PluginManager.install('toolkit');
+ kit.PluginManager.install('tooltip');
+ kit.PluginManager.install('bsCore');
+ }
+
+ if (/complete|interactive|loaded/.test(document.readyState)) {
+ // In case the document has finished parsing, document's readyState will
+ // be one of "complete", "interactive" or (non-standard) "loaded".
+ _init();
+ } else {
+ // The document is not ready yet, so wait for the DOMContentLoaded event
+ document.addEventListener("DOMContentLoaded", _init);
+
+ }
+});
\ No newline at end of file
diff --git a/assets/flex-kit/flex-kit.css b/assets/flex-kit/flex-kit.css
new file mode 100644
index 0000000..5470ebe
--- /dev/null
+++ b/assets/flex-kit/flex-kit.css
@@ -0,0 +1,936 @@
+/* flex-kit.css */
+* {
+ box-sizing: border-box;
+ outline: none;
+ margin: 0;
+ padding: 0;
+}
+:root {
+ --flex-padding: 15px 15px;
+ --gap: 10px;
+ --gap-section: 30px;
+ --gap-wrapper: 30px;
+ --col-count: 4;
+ --line-clamp: 3;
+ --line-clamp-height: 1.3em;
+ --width-wrapper: 800px;
+ --flex-aspect-ratio: 1;
+ --flex-line-count: 1;
+ --flex-col-count: 2;
+ --aspect-ratio: 1;
+ --font-ratio-height: 0.9;
+ --font-ratio-bottom: 0.1;
+}
+.kit-wrapper {
+ box-sizing: border-box;
+ position: relative;
+ margin-left: auto;
+ margin-right: auto;
+ width: var(--width-wrapper);
+ max-width: 100%;
+ padding: 0 var(--gap-wrapper);
+}
+
+.kit-sections {
+ box-sizing: border-box;
+ position: relative;
+ padding-top: var(--gap-section);
+}
+.kit-section {
+ box-sizing: border-box;
+ position: relative;
+ margin-bottom: var(--gap-section);
+}
+.col-count:not(.slick-slider) {
+ position: relative;
+ margin-left: calc(var(--gap) / -2) !important;
+ margin-right: calc(var(--gap) / -2) !important;
+}
+.col-count:not(.slick-slider) > * {
+ width: calc(100% / var(--col-count)) !important;
+ max-width: calc(100% / var(--col-count)) !important;
+ flex-basis: calc(100% / var(--col-count)) !important;
+ padding-left: calc(var(--gap) / 2);
+ padding-right: calc(var(--gap) / 2);
+ padding-bottom: var(--gap);
+}
+
+.kit-line-clamp {
+ line-height: var(--line-clamp-height);
+ max-height: calc(var(--line-clamp-height) * var(--line-clamp));
+ display: inline-block;
+ word-wrap: break-word;
+ overflow: hidden;
+ text-overflow: -o-ellipsis-lastline;
+ text-overflow: ellipsis;
+ -webkit-box-orient: vertical;
+ -webkit-line-clamp: var(--line-clamp);
+ display: -webkit-box;
+ word-break: break-word;
+ white-space: normal;
+}
+
+.flex-list {
+ position: relative;
+ display: -ms-flexbox;
+ display: -webkit-flex;
+ display: flex;
+ -webkit-flex-direction: row;
+ -ms-flex-direction: row;
+ flex-direction: row;
+ -webkit-flex-wrap: wrap;
+ -ms-flex-wrap: wrap;
+ flex-wrap: wrap;
+ -webkit-justify-content: flex-start;
+ -ms-flex-pack: start;
+ justify-content: flex-start;
+ -webkit-align-content: flex-start;
+ -ms-flex-line-pack: start;
+ align-content: flex-start;
+ -webkit-align-items: stretch;
+ -ms-flex-align: stretch;
+ align-items: stretch;
+}
+.flex-list:not(.owl-loaded) {
+ margin-left: calc(var(--gap) / -2) !important;
+ margin-right: calc(var(--gap) / -2) !important;
+}
+
+.flex-list:before,
+.flex-list:after {
+ content: '';
+}
+.flex-list:not(.owl-loaded) > * {
+ position: relative;
+ padding-left: calc(var(--gap) / 2);
+ padding-right: calc(var(--gap) / 2);
+}
+.flex-list > .flex-list-item {
+ --col-width: calc((100%) / var(--col-count));
+ width: var(--col-width) !important;
+ max-width: var(--col-width) !important;
+ flex-basis: var(--col-width) !important;
+ margin-bottom: var(--gap);
+}
+.flex-list-item:before,
+.flex-list-item:after {
+ content: '';
+}
+
+.flex-list-item-delimiter {
+ height: 0;
+ width: 0;
+ flex: 1 0 0;
+}
+
+.flex-center {
+ display: -ms-flexbox;
+ display: -webkit-flex;
+ display: flex;
+ -webkit-flex-direction: column;
+ -ms-flex-direction: column;
+ flex-direction: column;
+ -webkit-flex-wrap: nowrap;
+ -ms-flex-wrap: nowrap;
+ flex-wrap: nowrap;
+ -webkit-justify-content: center;
+ -ms-flex-pack: center;
+ justify-content: center;
+ -webkit-align-content: stretch;
+ -ms-flex-line-pack: stretch;
+ align-content: stretch;
+ -webkit-align-items: center;
+ -ms-flex-align: center;
+ align-items: center;
+}
+
+
+
+script, style {
+ display: none !important;
+}
+
+.flex-line > *,
+.flex-col > *,
+.flex-line-wrap > *,
+.flex-col-wrap > *,
+.flex-line.flex-aspect-ratio:not(.owl-loaded) > *:not(.flex-cell-aspect-auto) > :first-child,
+.flex-col.flex-aspect-ratio:not(.owl-loaded) > *:not(.flex-cell-aspect-auto) > :first-child,
+.flex-line-wrap.flex-aspect-ratio:not(.owl-loaded) > *:not(.flex-cell-aspect-auto) > :first-child,
+.flex-col-wrap.flex-aspect-ratio:not(.owl-loaded) > *:not(.flex-cell-aspect-auto) > :first-child
+{
+ padding: var(--flex-padding);
+}
+
+.flex-list.flex-aspect-ratio:not(.owl-loaded) > * > :first-child,
+.flex-list-item.aspect-ratio > :first-child
+{
+ padding: 0 calc(var(--gap) / 2);
+}
+
+/* деф настрйоки для ячейки */
+.flex-line > *,
+.flex-line-wrap > *,
+.flex-col > *,
+.flex-col-wrap > *,
+.flex-aspect-ratio:not(.owl-loaded) > *:not(.flex-cell-aspect-auto) > :first-child,
+.flex-aspect-ratio.owl-loaded > .owl-stage-outer > .owl-stage > .owl-item > *:not(.flex-cell-aspect-auto) > :first-child
+{
+ display: -ms-flexbox;
+ display: -webkit-flex;
+ display: flex;
+ -webkit-flex-direction: column;
+ -ms-flex-direction: column;
+ flex-direction: column;
+ -webkit-flex-wrap: nowrap;
+ -ms-flex-wrap: nowrap;
+ flex-wrap: nowrap;
+ -webkit-justify-content: center;
+ -ms-flex-pack: center;
+ justify-content: center;
+ -webkit-align-content: stretch;
+ -ms-flex-line-pack: stretch;
+ align-content: stretch;
+
+ -webkit-box-flex: 0;
+ -ms-flex-positive: 0;
+ flex-grow: 0;
+
+ -ms-flex-negative: 0;
+ flex-shrink: 0;
+
+ -ms-flex-preferred-size: auto;
+ -webkit-flex-basis: auto;
+ flex-basis: auto;
+}
+
+.flex-line > .flex-line,
+.flex-line > .flex-col,
+.flex-line > .flex-col-wrap,
+.flex-line > .flex-line-wrap,
+
+.flex-col > .flex-line,
+.flex-col > .flex-col,
+.flex-col > .flex-col-wrap,
+.flex-col > .flex-line-wrap,
+
+.flex-line-wrap > .flex-line,
+.flex-line-wrap > .flex-col,
+.flex-line-wrap > .flex-col-wrap,
+.flex-line-wrap > .flex-line-wrap,
+
+.flex-col-wrap > .flex-line,
+.flex-col-wrap > .flex-col,
+.flex-col-wrap > .flex-col-wrap,
+.flex-col-wrap > .flex-line-wrap
+{
+ -ms-flex-preferred-size: 0;
+ -webkit-flex-basis: 0;
+ flex-basis: 0;
+}
+
+/*.flex-line > .flex-line,*/
+/*.flex-line > .flex-col,*/
+/*.flex-line > .flex-col-wrap,*/
+.flex-line > .flex-line-wrap:not(.flex-cell-full-content),
+
+.flex-col > .flex-line:not(.flex-cell-full-content),
+.flex-col > .flex-col:not(.flex-cell-full-content),
+ /*.flex-col > .flex-col-wrap,*/
+.flex-col > .flex-line-wrap:not(.flex-cell-full-content),
+
+.flex-line-wrap > .flex-line:not(.flex-cell-full-content),
+ /*.flex-line-wrap > .flex-col,*/
+ /*.flex-line-wrap > .flex-col-wrap,*/
+.flex-line-wrap > .flex-line-wrap:not(.flex-cell-full-content),
+
+.flex-col-wrap > .flex-line:not(.flex-cell-full-content),
+ /*.flex-col-wrap > .flex-col,*/
+ /*.flex-col-wrap > .flex-col-wrap,*/
+.flex-col-wrap > .flex-line-wrap:not(.flex-cell-full-content)
+{
+ -ms-flex-preferred-size: auto;
+ -webkit-flex-basis: auto;
+ flex-basis: auto;
+}
+
+
+
+.flex-col > *,
+.flex-col-wrap > *,
+.flex-line > *,
+.flex-line-wrap > *,
+.flex-aspect-ratio:not(.owl-loaded) > *:not(.flex-cell-aspect-auto) > :first-child,
+.flex-aspect-ratio.owl-loaded > .owl-stage-outer > .owl-stage > .owl-item > *:not(.flex-cell-aspect-auto) > :first-child
+{
+ -webkit-box-align: center;
+ -webkit-align-items: center;
+ -ms-flex-align: center;
+ align-items: center;
+
+ max-width: 100%;
+}
+
+
+
+.flex-aspect-ratio:not(.owl-loaded) > *:not(.flex-cell-aspect-auto) > *:not(:first-child)
+{
+ display: none;
+}
+
+.flex-line:not(.flex-cell) > *:empty, .flex-col:not(.flex-cell) > *:empty, .flex-cell:empty {
+ /*display: none !important;*/
+}
+
+
+.flex-col,
+.flex-col-wrap,
+.flex-line,
+.flex-line-wrap
+{
+ /*width: 100%;*/
+ padding: 0 !important;
+
+ display: -ms-flexbox;
+ display: -webkit-flex;
+ display: flex;
+
+ -webkit-justify-content: flex-start;
+ -ms-flex-pack: start;
+ justify-content: flex-start;
+
+ -webkit-align-content: stretch;
+ -ms-flex-line-pack: stretch;
+ align-content: stretch;
+
+ -webkit-align-items: stretch;
+ -ms-flex-align: stretch;
+ align-items: stretch;
+}
+
+.flex-col, .flex-col-wrap {
+ -webkit-align-content: flex-start;
+ -ms-flex-line-pack: start;
+ align-content: flex-start;
+}
+.flex-col, .flex-line, .flex-line-wrap, .flex-col-wrap {
+ -webkit-box-flex: 0;
+ -ms-flex-positive: 0;
+ flex-grow: 0;
+
+ -ms-flex-negative: 0;
+ flex-shrink: 0;
+
+ -ms-flex-preferred-size: auto;
+ -webkit-flex-basis: auto;
+ flex-basis: auto;
+}
+
+.flex-col, .flex-col-wrap {
+ -webkit-flex-direction: column;
+ -ms-flex-direction: column;
+ flex-direction: column;
+}
+.flex-line, .flex-line-wrap {
+ -webkit-flex-direction: row;
+ -ms-flex-direction: row;
+ flex-direction: row;
+}
+/* flex-wrap: nowrap */
+.flex-col,
+.flex-line {
+ -webkit-flex-wrap: nowrap;
+ -ms-flex-wrap: nowrap;
+ flex-wrap: nowrap;
+}
+.flex-line-wrap, .flex-col-wrap
+{
+ -webkit-flex-wrap: wrap;
+ -ms-flex-wrap: wrap;
+ flex-wrap: wrap;
+}
+.flex-cell
+{
+ display: -ms-flexbox;
+ display: -webkit-flex;
+ display: flex;
+ /*-webkit-flex-direction: column;*/
+ /*-ms-flex-direction: column;*/
+ /*flex-direction: column;*/
+ /*-webkit-flex-wrap: nowrap;*/
+ /*-ms-flex-wrap: nowrap;*/
+ /*flex-wrap: nowrap;*/
+ -webkit-justify-content: center;
+ -ms-flex-pack: center;
+ justify-content: center;
+ -webkit-align-content: stretch;
+ -ms-flex-line-pack: stretch;
+ align-content: stretch;
+
+ -webkit-align-items: center;
+ -ms-flex-align: center;
+ align-items: center;
+
+ -webkit-box-flex: 0;
+ -ms-flex-positive: 0;
+ flex-grow: 0;
+
+ -ms-flex-negative: 0;
+ flex-shrink: 0;
+
+ -ms-flex-preferred-size: auto;
+ -webkit-flex-basis: auto;
+ flex-basis: auto;
+}
+.flex-col.flex-cell,
+.flex-col-wrap.flex-cell,
+.flex-line.flex-cell,
+.flex-line-wrap.flex-cell
+{
+ padding: var(--flex-padding) !important;
+}
+
+
+
+
+
+
+
+.flex-direction-column {
+ -webkit-flex-direction: column;
+ -ms-flex-direction: column;
+ flex-direction: column;
+}
+.flex-direction-row {
+ -webkit-box-orient: horizontal;
+ -webkit-box-direction: normal;
+ -webkit-flex-direction: row;
+ -ms-flex-direction: row;
+ flex-direction: row;
+}
+
+
+
+/* применяем к таблице: ПРОДОЛЬНОЕ выравнивание элементов в строке или колонке */
+.flex-align-start {
+ -webkit-justify-content: flex-start !important;
+ -ms-flex-pack: start !important;
+ justify-content: flex-start !important;
+}
+.flex-align-end {
+ -webkit-justify-content: flex-end !important;
+ -ms-flex-pack: end !important;
+ justify-content: flex-end !important;
+}
+.flex-align-center {
+ -webkit-justify-content: center !important;
+ -ms-flex-pack: center !important;
+ justify-content: center !important;
+}
+.flex-align-around {
+ -webkit-justify-content: space-around;
+ -ms-flex-pack: distribute;
+ justify-content: space-around;
+}
+
+/* попереное */
+.flex-align--stretch {
+ -webkit-align-items: stretch;
+ -ms-flex-align: stretch;
+ align-items: stretch;
+}
+.flex-align--center {
+ -webkit-align-items: center;
+ -ms-flex-align: center;
+ align-items: center;
+}
+
+
+/* применяем к ячейкам: поперечное выравнивание */
+.flex-cell-align--start {
+ -webkit-align-self: flex-start;
+ -ms-flex-item-align: start;
+ align-self: flex-start;
+}
+.flex-cell-align--end {
+ -webkit-align-self: flex-end;
+ -ms-flex-item-align: end;
+ align-self: flex-end;
+}
+.flex-cell-align--center {
+ -webkit-align-self: center;
+ -ms-flex-item-align: center;
+ align-self: center;
+}
+.flex-cell-align--stretch {
+ -webkit-align-self: stretch;
+ -ms-flex-item-align: stretch;
+ align-self: stretch;
+}
+
+
+.flex-wrap
+{
+ -webkit-flex-wrap: wrap;
+ -ms-flex-wrap: wrap;
+ flex-wrap: wrap;
+}
+
+/* применяем к ячейке определяя макс возможное заполнение*/
+.flex-cell-full-content {
+ -ms-flex-positive: 1;
+ -webkit-box-flex: 1;
+ flex-grow: 1;
+}
+
+.flex-cell-fill {
+ -ms-flex-negative: 1;
+ flex-shrink: 1;
+
+ -ms-flex-positive: 1;
+ -webkit-box-flex: 1;
+ flex-grow: 1;
+ flex-basis: auto;
+}
+
+.flex-box-fill > * {
+ -ms-flex-negative: 1;
+ flex-shrink: 1;
+
+ -ms-flex-positive: 1;
+ -webkit-box-flex: 1;
+ flex-grow: 1;
+ flex-basis: auto;
+}
+
+
+.flex-col-count {
+
+}
+
+@supports (--flex-col-count:property) {
+ .flex-col-count > * {
+ width: calc(100% / (var(--flex-col-count)));
+ max-width: calc(100% / (var(--flex-col-count)));
+ box-sizing: border-box;
+ }
+
+ .flex-line-wrap.flex-col-count > *,
+ .flex-line.flex-col-count > *
+ {
+ -ms-flex-preferred-size: calc(100% / var(--flex-col-count));
+ -webkit-flex-basis: calc(100% / var(--flex-col-count));
+ flex-basis: calc(100% / var(--flex-col-count));
+ box-sizing: border-box;
+ }
+}
+
+
+.flex-col-count.flex-col-without-frame {
+
+}
+
+.flex-line-count {
+
+}
+@supports (--flex-line-count:property) {
+ .flex-col-wrap.flex-line-count > *,
+ .flex-col.flex-line-count > *
+ {
+ -ms-flex-preferred-size: calc(100% / (var(--flex-line-count)));
+ -webkit-flex-basis: calc(100% / (var(--flex-line-count)));
+ flex-basis: calc(100% / (var(--flex-line-count)));
+ box-sizing: border-box;
+ }
+}
+
+
+.flex-cell-aspect-auto {
+ flex-grow: 1000;
+ flex-shrink: 1;
+}
+
+@supports (--flex-aspect-ratio:property) {
+
+ .flex-aspect-ratio:not(.owl-loaded) > *:not(.flex-cell-aspect-auto) > img
+ {
+ height: auto;
+ object-fit: contain;
+ }
+
+ .flex-aspect-ratio:not(.owl-loaded) > *:not(.flex-cell-aspect-auto),
+ .flex-aspect-ratio.owl-loaded > .owl-stage-outer > .owl-stage > .owl-item > *:not(.flex-cell-aspect-auto)
+ {
+ position: relative;
+ padding: 0;
+ }
+
+ .flex-aspect-ratio:not(.owl-loaded):not(.flex-list) > *:not(.flex-cell-aspect-auto)::before,
+ .flex-aspect-ratio.owl-loaded:not(.flex-list) > .owl-stage-outer > .owl-stage > .owl-item > *:not(.flex-cell-aspect-auto)::before
+ {
+ content: "";
+ display: block;
+ width: 100%;
+ padding-bottom: calc(100% / (var(--flex-aspect-ratio)));
+ }
+
+ .flex-aspect-ratio.flex-list:not(.owl-loaded) > *:not(.flex-cell-aspect-auto)::before
+ {
+ content: "";
+ display: block;
+ width: 100%;
+ padding-bottom: calc((100% - var(--gap)) / (var(--flex-aspect-ratio)));
+ }
+
+ .flex-aspect-ratio.flex-list.owl-loaded > .owl-stage-outer > .owl-stage > .owl-item > *:not(.flex-cell-aspect-auto)::before
+ {
+ content: "";
+ display: block;
+ width: 100%;
+ padding-bottom: calc(100% / (var(--flex-aspect-ratio)));
+ }
+
+ .flex-aspect-ratio:not(.owl-loaded) > *:not(.flex-cell-aspect-auto) > :first-child,
+ .flex-aspect-ratio.owl-loaded > .owl-stage-outer > .owl-stage > .owl-item > *:not(.flex-cell-aspect-auto) > :first-child
+ {
+ position: absolute;
+ top: 0;
+ left: 0;
+ height: 100%;
+ width: 100%;
+ object-fit: contain;
+ }
+ .flex-aspect-ratio:not(.owl-loaded) > *:not(.flex-cell-aspect-auto) > :first-child > picture,
+ .flex-aspect-ratio.owl-loaded > .owl-stage-outer > .owl-stage > .owl-item > *:not(.flex-cell-aspect-auto) > :first-child > picture {
+ width: 100%;
+ height: 100%;
+ }
+ .flex-aspect-ratio:not(.owl-loaded) > *:not(.flex-cell-aspect-auto) > :first-child > picture > img,
+ .flex-aspect-ratio.owl-loaded > .owl-stage-outer > .owl-stage > .owl-item > *:not(.flex-cell-aspect-auto) > :first-child > picture > img {
+ object-fit: contain;
+ width: 100%;
+ height: 100%;
+ }
+
+}
+
+
+/* --aspect-ratio */
+
+@supports (--aspect-ratio:0) {
+
+ .aspect-ratio {
+ position: relative;
+ width: 100%;
+ }
+
+ .aspect-ratio > img {
+ height: auto;
+ object-fit: contain;
+ }
+ .aspect-ratio::before {
+ content: "";
+ display: block;
+ width: 100%;
+ padding-bottom: calc(100% / (var(--aspect-ratio)));
+ }
+ .aspect-ratio > :first-child {
+ width: 100%;
+ position: absolute;
+ top: 0;
+ left: 0;
+ height: 100%;
+ object-fit: contain;
+ }
+}
+
+
+
+/* flex-marginator */
+
+
+:root {
+ --flex-marginator: 15px;
+ --flex-marginator-index: 0;
+}
+
+.flex-marginator {
+ display: flex;
+ flex-direction: row;
+ flex-wrap: wrap;
+ justify-content: center;
+ gap: var(--flex-marginator);
+}
+
+.flex-marginator > *:empty {
+ display:none;
+}
+
+
+/* flex-delimiter text */
+
+:root {
+ --flex-delimiter: ', ';
+ --flex-delimiter-index: 0;
+}
+
+.flex-delimiter > *:not(:first-child):not(:empty)::before {
+ content: var(--flex-delimiter);
+ --flex-delimiter-index:1;
+}
+
+.flex-delimiter > *:empty + *:not(:empty)::before
+{
+ content: '';
+ --flex-delimiter-index:0;
+}
+
+.flex-delimiter > *:not(:empty) ~ *:empty + *:not(:empty)::before
+{
+ content: var(--flex-delimiter);
+ --flex-delimiter-index:1;
+}
+
+.flex-delimiter > *:empty {
+ display:none;
+}
+
+/* flex-card */
+
+.flex-card {
+ --aspect-ratio: calc(200 / 300);
+ --gap-inner: 10px;
+}
+.flex-card:hover .flex-card__content {
+ box-shadow: 0 0 27px 0 rgba(0, 0, 0, 0.1);
+}
+.flex-card__content {
+ position: relative;
+ width: 100%;
+ height: 100%;
+ display: flex;
+ flex-direction: column;
+ justify-content: stretch;
+ border-width: 1px;
+ border-style: solid;
+ border-color: #e9e9e9;
+ /*border-radius: 3px;*/
+ overflow: hidden;
+ transition: 0.3s;
+ background-color: var(--kit-color-content);
+ /*padding-bottom: calc(var(--gap-inner) / 2);*/
+ /*padding-top: calc(var(--gap-inner) / 2);*/
+}
+.flex-card__content:after,
+.flex-card__body:before,
+.flex-card__body:after {
+ content: '';
+ display: block;
+ flex-basis: calc(var(--gap-inner) / 2);
+ flex-grow: 0;
+ flex-shrink: 0;
+}
+.flex-card__content > *:empty {
+ display: none;
+}
+.flex-card__header {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+}
+.flex-card__body {
+ display: flex;
+ flex-direction: column;
+ justify-content: stretch;
+ align-items: stretch;
+ height: 100%;
+ flex: 1 0 100%;
+}
+.flex-card__body > *, .flex-card__hover > * {
+ margin: calc(var(--gap-inner) / 2) var(--gap-inner);
+}
+.flex-card__body > *:empty, .flex-card__hover > *:empty {
+ display: none;
+}
+.flex-card__footer {
+ position: relative;
+}
+.flex-card__hover {
+ position: relative;
+ opacity: 0;
+ visibility: hidden;
+}
+.flex-card:hover .flex-card__content {
+ height: auto;
+ z-index: 100;
+}
+.flex-card:hover .flex-card__content > .flex-card__hover {
+ opacity: 1;
+ visibility: visible;
+ margin-top: calc(-1 * var(--gap-inner) / 2);
+}
+
+.flex-card__picture {
+ flex-basis: 50%;
+ flex-grow: 0;
+ flex-shrink: 1;
+ height: 0%;
+ --aspect-ratio: 1;
+}
+.flex-card__picture.aspect-ratio {
+ --aspect-ratio: 1;
+ flex-basis: auto;
+ flex-grow: 0;
+ flex-shrink: 1;
+ height: auto;
+}
+
+.flex-card__picture .kit-picture {
+ height: 100%;
+ width: 100%;
+ background-position: center;
+ background-repeat: no-repeat;
+ background-size: contain;
+ background-origin: content-box;
+}
+.flex-card__name, .flex-card__title {
+ --line-clamp: 2;
+ --line-clamp-height: 1.1em;
+ /*flex-shrink: 0;*/
+}
+.flex-card__props {
+ position: relative;
+}
+.flex-card__text {
+ position: relative;
+}
+.flex-card__manager {
+ position: relative;
+}
+.flex-card__flex-delimiter {
+ flex: 1 10 0;
+ display: block !important;
+ margin: 0 !important;
+ padding: 0 !important;
+ background: transparent;
+}
+.flex-card__ticket {
+ position: absolute;
+ top: var(--gap-inner);
+ left: var(--gap-inner);
+}
+/* flex-card-list--list */
+
+.flex-card-list--list {
+ --col-count: 1;
+}
+
+.flex-card-list--list .flex-card.aspect-ratio:before {
+ padding-bottom: unset;
+}
+.flex-card-list--list .flex-card.aspect-ratio:before {
+ padding-bottom: unset;
+}
+.flex-card-list--list .flex-card.aspect-ratio > .flex-card__section {
+ position: relative;
+}
+.flex-card-list--list .flex-card__body-shell.aspect-ratio:before {
+ padding-bottom: unset;
+}
+.flex-card-list--list .flex-card__body {
+ position: relative;
+ flex-direction: row;
+}
+.flex-card-list--list .flex-card__body > .flex-card__picture {
+ flex-basis: 12%;
+ flex-shrink: 0;
+ height: auto;
+ position: relative;
+}
+.flex-card-list--list .flex-card__body > .flex-card__picture {
+ flex-basis: 50px;
+ flex-shrink: 0;
+ height: auto;
+ position: relative;
+}
+.flex-card-list--list .flex-card__body > .flex-card__picture:before {
+ content: "";
+ display: block;
+ width: 100%;
+ padding-bottom: calc(100% / (var(--aspect-ratio)));
+}
+.flex-card-list--list .flex-card__body > .flex-card__picture > .kit-picture {
+ width: 100%;
+ position: absolute;
+ top: 0;
+ left: 0;
+ height: 100%;
+ object-fit: contain;
+}
+
+/* ticket */
+
+.flex-list--ticket {
+ --col-count: 1;
+ --gap: 3px;
+ --line-clamp: 1;
+ --line-clamp-height: 1em;
+ font-size: 0.7em;
+ flex-direction: column;
+ align-items: flex-start;
+}
+.flex-list--ticket > .flex-list-item {
+ --col-width: auto;
+}
+.ticket-item {
+ padding: calc(2 * 0.1em) calc(6 * 0.1em);
+ background-color: hsl(0, 0%, 95%);
+}
+
+
+/* picture - icon */
+
+.kit-picture-line, .kit-icon-line {
+ display: inline-block;
+ margin-bottom: calc(-1em * var(--font-ratio-bottom, 0.2));
+}
+.kit-picture-line svg,
+.kit-picture-line picture,
+.kit-picture-line img,
+.kit-icon-line svg,
+.kit-icon-line picture,
+.kit-icon-line img {
+ height: calc(1em * var(--font-ratio-height, 1));
+ width: auto;
+ vertical-align: baseline;
+ display: block;
+ fill: currentColor;
+ transition: inherit;
+ object-fit: contain;
+ object-position: center;
+}
+
+
+.kit-icon picture,
+.kit-icon img,
+.kit-icon svg,
+.kit-picture picture,
+.kit-picture img,
+.kit-picture svg {
+ width: 100%;
+ height: 100%;
+ max-width: 100%;
+ max-height: 100%;
+ display: block;
+ fill: currentColor;
+ transition: inherit;
+ object-fit: contain;
+ object-position: center;
+}
+
+
+
+
+
+/* flex-kit.css end */
\ No newline at end of file
diff --git a/assets/jquery/jquery.js b/assets/jquery/jquery.js
new file mode 100644
index 0000000..4ccda6e
--- /dev/null
+++ b/assets/jquery/jquery.js
@@ -0,0 +1,10888 @@
+kit.PluginManager.register('jquery', function(module, exports, require){
+
+ /*!
+ * jQuery JavaScript Library v3.6.0
+ * https://jquery.com/
+ *
+ * Includes Sizzle.js
+ * https://sizzlejs.com/
+ *
+ * Copyright OpenJS Foundation and other contributors
+ * Released under the MIT license
+ * https://jquery.org/license
+ *
+ * Date: 2021-03-02T17:08Z
+ */
+ ( function( global, factory ) {
+
+ "use strict";
+
+ if ( typeof module === "object" && typeof module.exports === "object" ) {
+
+ // For CommonJS and CommonJS-like environments where a proper `window`
+ // is present, execute the factory and get jQuery.
+ // For environments that do not have a `window` with a `document`
+ // (such as Node.js), expose a factory as module.exports.
+ // This accentuates the need for the creation of a real `window`.
+ // e.g. var jQuery = require("jquery")(window);
+ // See ticket #14549 for more info.
+ module.exports = global.document ?
+ factory( global, true ) :
+ function( w ) {
+ if ( !w.document ) {
+ throw new Error( "jQuery requires a window with a document" );
+ }
+ return factory( w );
+ };
+ } else {
+ factory( global );
+ }
+
+// Pass this if window is not defined yet
+ } )( typeof window !== "undefined" ? window : this, function( window, noGlobal )
+ {
+
+// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1
+// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode
+// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common
+// enough that all such attempts are guarded in a try block.
+ "use strict";
+
+ var arr = [];
+
+ var getProto = Object.getPrototypeOf;
+
+ var slice = arr.slice;
+
+ var flat = arr.flat ? function( array ) {
+ return arr.flat.call( array );
+ } : function( array ) {
+ return arr.concat.apply( [], array );
+ };
+
+
+ var push = arr.push;
+
+ var indexOf = arr.indexOf;
+
+ var class2type = {};
+
+ var toString = class2type.toString;
+
+ var hasOwn = class2type.hasOwnProperty;
+
+ var fnToString = hasOwn.toString;
+
+ var ObjectFunctionString = fnToString.call( Object );
+
+ var support = {};
+
+ var isFunction = function isFunction( obj ) {
+
+ // Support: Chrome <=57, Firefox <=52
+ // In some browsers, typeof returns "function" for HTML