├── assets ├── css │ ├── air-datepicker.css │ ├── air-datepicker.min.css │ └── main.min.css ├── fonts │ ├── inter-v12-latin-500.woff2 │ ├── inter-v12-latin-600.woff2 │ ├── inter-v12-latin-800.woff2 │ └── inter-v12-latin-regular.woff2 ├── images │ ├── apple-touch-icon.png │ ├── banner-1544x500.png │ ├── banner-772x250.png │ ├── favicon.ico │ ├── icon-128.png │ ├── icon-128x128.png │ ├── icon-192.png │ ├── icon-196.png │ ├── icon-256x256.png │ ├── icon-32.png │ ├── icon-96.png │ ├── icon-og.png │ ├── icon-rounded.png │ ├── icon-square.png │ ├── illustration-1.png │ ├── illustration-1.svg │ ├── illustration-els.png │ ├── illustration-els.svg │ ├── illustration-og.png │ ├── screenshot-1.png │ └── screenshot-2.png └── js │ ├── all-calculators.js │ ├── app.js │ ├── calculator.js │ ├── chart.js │ ├── datepicker.js │ ├── dialog-table.js │ ├── dropdown-icon.js │ ├── fractions.js │ ├── functions.js │ ├── helpers.js │ ├── hourpicker.js │ ├── lib │ ├── air-datepicker.js │ ├── chartjs │ │ ├── chart.js │ │ ├── chart.js.map │ │ ├── chart.min.js │ │ ├── chart.umd.js │ │ ├── chart.umd.js.map │ │ ├── chunks │ │ │ ├── helpers.core.d.ts │ │ │ ├── helpers.segment.js │ │ │ └── helpers.segment.js.map │ │ ├── helpers.d.ts │ │ ├── helpers.js │ │ ├── helpers.js.map │ │ └── types.d.ts │ ├── input-mask.min.js │ ├── katex │ │ ├── auto-render.min.js │ │ ├── fonts │ │ │ ├── KaTeX_AMS-Regular.ttf │ │ │ ├── KaTeX_AMS-Regular.woff │ │ │ ├── KaTeX_AMS-Regular.woff2 │ │ │ ├── KaTeX_Caligraphic-Bold.ttf │ │ │ ├── KaTeX_Caligraphic-Bold.woff │ │ │ ├── KaTeX_Caligraphic-Bold.woff2 │ │ │ ├── KaTeX_Caligraphic-Regular.ttf │ │ │ ├── KaTeX_Caligraphic-Regular.woff │ │ │ ├── KaTeX_Caligraphic-Regular.woff2 │ │ │ ├── KaTeX_Fraktur-Bold.ttf │ │ │ ├── KaTeX_Fraktur-Bold.woff │ │ │ ├── KaTeX_Fraktur-Bold.woff2 │ │ │ ├── KaTeX_Fraktur-Regular.ttf │ │ │ ├── KaTeX_Fraktur-Regular.woff │ │ │ ├── KaTeX_Fraktur-Regular.woff2 │ │ │ ├── KaTeX_Main-Bold.ttf │ │ │ ├── KaTeX_Main-Bold.woff │ │ │ ├── KaTeX_Main-Bold.woff2 │ │ │ ├── KaTeX_Main-BoldItalic.ttf │ │ │ ├── KaTeX_Main-BoldItalic.woff │ │ │ ├── KaTeX_Main-BoldItalic.woff2 │ │ │ ├── KaTeX_Main-Italic.ttf │ │ │ ├── KaTeX_Main-Italic.woff │ │ │ ├── KaTeX_Main-Italic.woff2 │ │ │ ├── KaTeX_Main-Regular.ttf │ │ │ ├── KaTeX_Main-Regular.woff │ │ │ ├── KaTeX_Main-Regular.woff2 │ │ │ ├── KaTeX_Math-BoldItalic.ttf │ │ │ ├── KaTeX_Math-BoldItalic.woff │ │ │ ├── KaTeX_Math-BoldItalic.woff2 │ │ │ ├── KaTeX_Math-Italic.ttf │ │ │ ├── KaTeX_Math-Italic.woff │ │ │ ├── KaTeX_Math-Italic.woff2 │ │ │ ├── KaTeX_SansSerif-Bold.ttf │ │ │ ├── KaTeX_SansSerif-Bold.woff │ │ │ ├── KaTeX_SansSerif-Bold.woff2 │ │ │ ├── KaTeX_SansSerif-Italic.ttf │ │ │ ├── KaTeX_SansSerif-Italic.woff │ │ │ ├── KaTeX_SansSerif-Italic.woff2 │ │ │ ├── KaTeX_SansSerif-Regular.ttf │ │ │ ├── KaTeX_SansSerif-Regular.woff │ │ │ ├── KaTeX_SansSerif-Regular.woff2 │ │ │ ├── KaTeX_Script-Regular.ttf │ │ │ ├── KaTeX_Script-Regular.woff │ │ │ ├── KaTeX_Script-Regular.woff2 │ │ │ ├── KaTeX_Size1-Regular.ttf │ │ │ ├── KaTeX_Size1-Regular.woff │ │ │ ├── KaTeX_Size1-Regular.woff2 │ │ │ ├── KaTeX_Size2-Regular.ttf │ │ │ ├── KaTeX_Size2-Regular.woff │ │ │ ├── KaTeX_Size2-Regular.woff2 │ │ │ ├── KaTeX_Size3-Regular.ttf │ │ │ ├── KaTeX_Size3-Regular.woff │ │ │ ├── KaTeX_Size3-Regular.woff2 │ │ │ ├── KaTeX_Size4-Regular.ttf │ │ │ ├── KaTeX_Size4-Regular.woff │ │ │ ├── KaTeX_Size4-Regular.woff2 │ │ │ ├── KaTeX_Typewriter-Regular.ttf │ │ │ ├── KaTeX_Typewriter-Regular.woff │ │ │ └── KaTeX_Typewriter-Regular.woff2 │ │ ├── katex.min.css │ │ └── katex.min.js │ ├── lazysizes.min.js │ └── math.min.js │ ├── mask.js │ ├── module.js │ ├── options.js │ ├── themes.js │ └── timepicker.js ├── ci_days_calculator.php ├── index.html ├── plugin.php ├── readme.md └── readme.txt /assets/css/air-datepicker.css: -------------------------------------------------------------------------------- 1 | .air-datepicker-cell { 2 | /* border-radius: var(--adp-cell-border-radius); */ 3 | box-sizing: border-box; 4 | cursor: pointer; 5 | display: flex; 6 | position: relative; 7 | align-items: center; 8 | justify-content: center; 9 | z-index: 1 10 | } 11 | 12 | /* .air-datepicker-cell.-focus- { 13 | background: var(--adp-cell-background-color-hover) 14 | } */ 15 | 16 | /* .air-datepicker-cell.-current- { 17 | color: var(--adp-color-current-date) 18 | } */ 19 | 20 | .air-datepicker-cell.-current-.-focus- { 21 | color: var(--adp-color) 22 | } 23 | 24 | .air-datepicker-cell.-current-.-in-range- { 25 | color: var(--adp-color-current-date) 26 | } 27 | 28 | .air-datepicker-cell.-disabled- { 29 | cursor: default; 30 | color: var(--adp-color-disabled) 31 | } 32 | 33 | .air-datepicker-cell.-disabled-.-focus- { 34 | color: var(--adp-color-disabled) 35 | } 36 | 37 | .air-datepicker-cell.-disabled-.-in-range- { 38 | color: var(--adp-color-disabled-in-range) 39 | } 40 | 41 | .air-datepicker-cell.-disabled-.-current-.-focus- { 42 | color: var(--adp-color-disabled) 43 | } 44 | 45 | .air-datepicker-cell.-in-range- { 46 | background: var(--adp-cell-background-color-in-range); 47 | border-radius: 0 48 | } 49 | 50 | .air-datepicker-cell.-in-range-:hover { 51 | background: var(--adp-cell-background-color-in-range-hover) 52 | } 53 | 54 | .air-datepicker-cell.-range-from- { 55 | border: 1px solid var(--adp-cell-border-color-in-range); 56 | background-color: var(--adp-cell-background-color-in-range); 57 | border-radius: var(--adp-cell-border-radius) 0 0 var(--adp-cell-border-radius) 58 | } 59 | 60 | .air-datepicker-cell.-range-to- { 61 | border: 1px solid var(--adp-cell-border-color-in-range); 62 | background-color: var(--adp-cell-background-color-in-range); 63 | border-radius: 0 var(--adp-cell-border-radius) var(--adp-cell-border-radius) 0 64 | } 65 | 66 | .air-datepicker-cell.-range-to-.-range-from- { 67 | border-radius: var(--adp-cell-border-radius) 68 | } 69 | 70 | /* .air-datepicker-cell.-selected- { 71 | color: #fff; 72 | border: none; 73 | background: var(--adp-cell-background-color-selected) 74 | } */ 75 | 76 | /* .air-datepicker-cell.-selected-.-current- { 77 | color: #fff; 78 | background: var(--adp-cell-background-color-selected) 79 | } */ 80 | 81 | /* .air-datepicker-cell.-selected-.-focus- { 82 | background: var(--adp-cell-background-color-selected-hover) 83 | } */ 84 | 85 | .air-datepicker-body { 86 | transition: all var(--adp-transition-duration) var(--adp-transition-ease) 87 | } 88 | 89 | .air-datepicker-body.-hidden- { 90 | display: none 91 | } 92 | 93 | .air-datepicker-body--day-names { 94 | display: grid; 95 | grid-template-columns: repeat(7, var(--adp-day-cell-width)); 96 | /* margin: 8px 0 3px */ 97 | } 98 | 99 | .air-datepicker-body--day-name { 100 | /* color: var(--adp-day-name-color); */ 101 | display: flex; 102 | align-items: center; 103 | justify-content: center; 104 | flex: 1; 105 | text-align: center; 106 | text-transform: uppercase; 107 | /* font-size: .8em */ 108 | } 109 | 110 | .air-datepicker-body--day-name.-clickable- { 111 | cursor: pointer 112 | } 113 | 114 | .air-datepicker-body--day-name.-clickable-:hover { 115 | color: var(--adp-day-name-color-hover) 116 | } 117 | 118 | .air-datepicker-body--cells { 119 | display: grid 120 | } 121 | 122 | .air-datepicker-nav { 123 | display: flex; 124 | justify-content: space-between; 125 | /* border-bottom: 1px solid var(--adp-border-color-inner); */ 126 | /* min-height: var(--adp-nav-height); */ 127 | /* padding: var(--adp-padding); */ 128 | box-sizing: content-box 129 | } 130 | 131 | .-only-timepicker- .air-datepicker-nav { 132 | display: none 133 | } 134 | 135 | .air-datepicker-nav--title, 136 | .air-datepicker-nav--action { 137 | display: flex; 138 | cursor: pointer; 139 | align-items: center; 140 | justify-content: center 141 | } 142 | 143 | .air-datepicker-nav--action { 144 | border-radius: var(--adp-border-radius); 145 | -webkit-user-select: none; 146 | -moz-user-select: none; 147 | user-select: none; 148 | width: 24px; 149 | height: 24px; 150 | } 151 | 152 | /* .air-datepicker-nav--action:hover { 153 | background: var(--adp-background-color-hover) 154 | } */ 155 | 156 | /* .air-datepicker-nav--action:active { 157 | background: var(--adp-background-color-active) 158 | } */ 159 | 160 | .air-datepicker-nav--action.-disabled- { 161 | visibility: hidden 162 | } 163 | 164 | .air-datepicker-nav--action svg { 165 | width: 24px; 166 | height: 24px 167 | } 168 | 169 | .air-datepicker-nav--action path { 170 | fill: none; 171 | stroke: var(--adp-nav-arrow-color); 172 | stroke-width: 2px 173 | } 174 | 175 | .air-datepicker-nav--title { 176 | border-radius: var(--adp-border-radius); 177 | padding: 0 8px 178 | } 179 | 180 | .air-datepicker-nav--title i { 181 | font-style: normal; 182 | color: var(--adp-nav-color-secondary); 183 | margin-left: .3em 184 | } 185 | 186 | /* .air-datepicker-nav--title:hover { 187 | background: var(--adp-background-color-hover) 188 | } */ 189 | 190 | /* .air-datepicker-nav--title:active { 191 | background: var(--adp-background-color-active) 192 | } */ 193 | 194 | .air-datepicker-nav--title.-disabled- { 195 | cursor: default; 196 | background: none 197 | } 198 | 199 | .air-datepicker-buttons { 200 | display: grid; 201 | grid-auto-columns: 1fr; 202 | grid-auto-flow: column 203 | } 204 | 205 | .air-datepicker-button { 206 | display: inline-flex; 207 | color: var(--adp-btn-color); 208 | border-radius: var(--adp-btn-border-radius); 209 | cursor: pointer; 210 | height: var(--adp-btn-height); 211 | border: none; 212 | background: rgba(255, 255, 255, 0) 213 | } 214 | 215 | .air-datepicker-button:hover { 216 | color: var(--adp-btn-color-hover); 217 | background: var(--adp-btn-background-color-hover) 218 | } 219 | 220 | .air-datepicker-button:focus { 221 | color: var(--adp-btn-color-hover); 222 | background: var(--adp-btn-background-color-hover); 223 | outline: none 224 | } 225 | 226 | .air-datepicker-button:active { 227 | background: var(--adp-btn-background-color-active) 228 | } 229 | 230 | .air-datepicker-button span { 231 | outline: none; 232 | display: flex; 233 | align-items: center; 234 | justify-content: center; 235 | width: 100%; 236 | height: 100% 237 | } 238 | 239 | .air-datepicker-time { 240 | display: grid; 241 | grid-template-columns: -webkit-max-content 1fr; 242 | grid-template-columns: max-content 1fr; 243 | grid-column-gap: 12px; 244 | align-items: center; 245 | position: relative; 246 | padding: 0 var(--adp-time-padding-inner) 247 | } 248 | 249 | .-only-timepicker- .air-datepicker-time { 250 | border-top: none 251 | } 252 | 253 | .air-datepicker-time--current { 254 | display: flex; 255 | align-items: center; 256 | flex: 1; 257 | font-size: 14px; 258 | text-align: center 259 | } 260 | 261 | .air-datepicker-time--current-colon { 262 | margin: 0 2px 3px; 263 | line-height: 1 264 | } 265 | 266 | .air-datepicker-time--current-hours, 267 | .air-datepicker-time--current-minutes { 268 | line-height: 1; 269 | font-size: 19px; 270 | font-family: "Century Gothic", CenturyGothic, AppleGothic, sans-serif; 271 | position: relative; 272 | z-index: 1 273 | } 274 | 275 | .air-datepicker-time--current-hours:after, 276 | .air-datepicker-time--current-minutes:after { 277 | content: ''; 278 | background: var(--adp-background-color-hover); 279 | border-radius: var(--adp-border-radius); 280 | position: absolute; 281 | left: -2px; 282 | top: -3px; 283 | right: -2px; 284 | bottom: -2px; 285 | z-index: -1; 286 | opacity: 0 287 | } 288 | 289 | .air-datepicker-time--current-hours.-focus-:after, 290 | .air-datepicker-time--current-minutes.-focus-:after { 291 | opacity: 1 292 | } 293 | 294 | .air-datepicker-time--current-ampm { 295 | text-transform: uppercase; 296 | align-self: flex-end; 297 | color: var(--adp-time-day-period-color); 298 | margin-left: 6px; 299 | font-size: 11px; 300 | margin-bottom: 1px 301 | } 302 | 303 | .air-datepicker-time--row { 304 | display: flex; 305 | align-items: center; 306 | font-size: 11px; 307 | height: 17px; 308 | background: linear-gradient(to right, var(--adp-time-track-color), var(--adp-time-track-color)) left 50%/100% var(--adp-time-track-height) no-repeat 309 | } 310 | 311 | .air-datepicker-time--row:first-child { 312 | margin-bottom: 4px 313 | } 314 | 315 | .air-datepicker-time--row input[type='range'] { 316 | background: none; 317 | cursor: pointer; 318 | flex: 1; 319 | height: 100%; 320 | width: 100%; 321 | padding: 0; 322 | margin: 0; 323 | -webkit-appearance: none 324 | } 325 | 326 | .air-datepicker-time--row input[type='range']::-webkit-slider-thumb { 327 | -webkit-appearance: none 328 | } 329 | 330 | .air-datepicker-time--row input[type='range']::-ms-tooltip { 331 | display: none 332 | } 333 | 334 | .air-datepicker-time--row input[type='range']:hover::-webkit-slider-thumb { 335 | border-color: var(--adp-time-track-color-hover) 336 | } 337 | 338 | .air-datepicker-time--row input[type='range']:hover::-moz-range-thumb { 339 | border-color: var(--adp-time-track-color-hover) 340 | } 341 | 342 | .air-datepicker-time--row input[type='range']:hover::-ms-thumb { 343 | border-color: var(--adp-time-track-color-hover) 344 | } 345 | 346 | .air-datepicker-time--row input[type='range']:focus { 347 | outline: none 348 | } 349 | 350 | .air-datepicker-time--row input[type='range']:focus::-webkit-slider-thumb { 351 | background: var(--adp-cell-background-color-selected); 352 | border-color: var(--adp-cell-background-color-selected) 353 | } 354 | 355 | .air-datepicker-time--row input[type='range']:focus::-moz-range-thumb { 356 | background: var(--adp-cell-background-color-selected); 357 | border-color: var(--adp-cell-background-color-selected) 358 | } 359 | 360 | .air-datepicker-time--row input[type='range']:focus::-ms-thumb { 361 | background: var(--adp-cell-background-color-selected); 362 | border-color: var(--adp-cell-background-color-selected) 363 | } 364 | 365 | .air-datepicker-time--row input[type='range']::-webkit-slider-thumb { 366 | box-sizing: border-box; 367 | height: 12px; 368 | width: 12px; 369 | border-radius: 3px; 370 | border: 1px solid var(--adp-time-track-color); 371 | background: #fff; 372 | cursor: pointer; 373 | -webkit-transition: background var(--adp-transition-duration); 374 | transition: background var(--adp-transition-duration) 375 | } 376 | 377 | .air-datepicker-time--row input[type='range']::-moz-range-thumb { 378 | box-sizing: border-box; 379 | height: 12px; 380 | width: 12px; 381 | border-radius: 3px; 382 | border: 1px solid var(--adp-time-track-color); 383 | background: #fff; 384 | cursor: pointer; 385 | -moz-transition: background var(--adp-transition-duration); 386 | transition: background var(--adp-transition-duration) 387 | } 388 | 389 | .air-datepicker-time--row input[type='range']::-ms-thumb { 390 | box-sizing: border-box; 391 | height: 12px; 392 | width: 12px; 393 | border-radius: 3px; 394 | border: 1px solid var(--adp-time-track-color); 395 | background: #fff; 396 | cursor: pointer; 397 | -ms-transition: background var(--adp-transition-duration); 398 | transition: background var(--adp-transition-duration) 399 | } 400 | 401 | .air-datepicker-time--row input[type='range']::-webkit-slider-thumb { 402 | margin-top: calc(var(--adp-time-thumb-size) / 2 * -1) 403 | } 404 | 405 | .air-datepicker-time--row input[type='range']::-webkit-slider-runnable-track { 406 | border: none; 407 | height: var(--adp-time-track-height); 408 | cursor: pointer; 409 | color: transparent; 410 | background: transparent 411 | } 412 | 413 | .air-datepicker-time--row input[type='range']::-moz-range-track { 414 | border: none; 415 | height: var(--adp-time-track-height); 416 | cursor: pointer; 417 | color: transparent; 418 | background: transparent 419 | } 420 | 421 | .air-datepicker-time--row input[type='range']::-ms-track { 422 | border: none; 423 | height: var(--adp-time-track-height); 424 | cursor: pointer; 425 | color: transparent; 426 | background: transparent 427 | } 428 | 429 | .air-datepicker-time--row input[type='range']::-ms-fill-lower { 430 | background: transparent 431 | } 432 | 433 | .air-datepicker-time--row input[type='range']::-ms-fill-upper { 434 | background: transparent 435 | } 436 | 437 | .air-datepicker { 438 | --adp-font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; 439 | --adp-font-size: 14px; 440 | --adp-width: 246px; 441 | --adp-z-index: 100; 442 | --adp-padding: 4px; 443 | --adp-grid-areas: 444 | 'nav' 445 | 'body' 446 | 'timepicker' 447 | 'buttons'; 448 | --adp-transition-duration: .3s; 449 | --adp-transition-ease: ease-out; 450 | --adp-transition-offset: 8px; 451 | --adp-background-color: #fff; 452 | --adp-background-color-hover: #f0f0f0; 453 | --adp-background-color-active: #eaeaea; 454 | --adp-background-color-in-range: rgba(92, 196, 239, .1); 455 | --adp-background-color-in-range-focused: rgba(92, 196, 239, .2); 456 | --adp-background-color-selected-other-month-focused: #8ad5f4; 457 | --adp-background-color-selected-other-month: #a2ddf6; 458 | --adp-color: #4a4a4a; 459 | --adp-color-secondary: #9c9c9c; 460 | --adp-accent-color: #4eb5e6; 461 | --adp-color-current-date: var(--adp-accent-color); 462 | --adp-color-other-month: #dedede; 463 | --adp-color-disabled: #aeaeae; 464 | --adp-color-disabled-in-range: #939393; 465 | --adp-color-other-month-hover: #c5c5c5; 466 | --adp-border-color: #dbdbdb; 467 | --adp-border-color-inner: #efefef; 468 | --adp-border-radius: 4px; 469 | --adp-border-color-inline: #d7d7d7; 470 | --adp-nav-height: 32px; 471 | --adp-nav-arrow-color: var(--adp-color-secondary); 472 | --adp-nav-action-size: 32px; 473 | --adp-nav-color-secondary: var(--adp-color-secondary); 474 | --adp-day-name-color: #ff9a19; 475 | --adp-day-name-color-hover: #8ad5f4; 476 | --adp-day-cell-width: 1fr; 477 | --adp-day-cell-height: 32px; 478 | --adp-month-cell-height: 42px; 479 | --adp-year-cell-height: 56px; 480 | --adp-pointer-size: 10px; 481 | --adp-poiner-border-radius: 2px; 482 | --adp-pointer-offset: 14px; 483 | --adp-cell-border-radius: 4px; 484 | --adp-cell-background-color-hover: var(--adp-background-color-hover); 485 | --adp-cell-background-color-selected: #5cc4ef; 486 | --adp-cell-background-color-selected-hover: #45bced; 487 | --adp-cell-background-color-in-range: rgba(92, 196, 239, 0.1); 488 | --adp-cell-background-color-in-range-hover: rgba(92, 196, 239, 0.2); 489 | --adp-cell-border-color-in-range: var(--adp-cell-background-color-selected); 490 | --adp-btn-height: 32px; 491 | --adp-btn-color: var(--adp-accent-color); 492 | --adp-btn-color-hover: var(--adp-color); 493 | --adp-btn-border-radius: var(--adp-border-radius); 494 | --adp-btn-background-color-hover: var(--adp-background-color-hover); 495 | --adp-btn-background-color-active: var(--adp-background-color-active); 496 | --adp-time-track-height: 1px; 497 | --adp-time-track-color: #dedede; 498 | --adp-time-track-color-hover: #b1b1b1; 499 | --adp-time-thumb-size: 12px; 500 | --adp-time-padding-inner: 10px; 501 | --adp-time-day-period-color: var(--adp-color-secondary); 502 | --adp-mobile-font-size: 16px; 503 | --adp-mobile-nav-height: 40px; 504 | --adp-mobile-width: 320px; 505 | --adp-mobile-day-cell-height: 38px; 506 | --adp-mobile-month-cell-height: 48px; 507 | --adp-mobile-year-cell-height: 64px 508 | } 509 | 510 | .air-datepicker-overlay { 511 | --adp-overlay-background-color: rgba(0, 0, 0, .3); 512 | --adp-overlay-transition-duration: .3s; 513 | --adp-overlay-transition-ease: ease-out; 514 | --adp-overlay-z-index: 99 515 | } 516 | 517 | .air-datepicker { 518 | background: var(--adp-background-color); 519 | /* border: 1px solid var(--adp-border-color); */ 520 | /* box-shadow: 10px 10px 30px rgba(#FE5141, 0.2); */ 521 | /* border-radius: var(--adp-border-radius); */ 522 | box-sizing: content-box; 523 | display: grid; 524 | grid-template-columns: 1fr; 525 | grid-template-rows: repeat(4, -webkit-max-content); 526 | grid-template-rows: repeat(4, max-content); 527 | grid-template-areas: var(--adp-grid-areas); 528 | font-family: var(--adp-font-family), sans-serif; 529 | font-size: var(--adp-font-size); 530 | color: var(--adp-color); 531 | /* width: var(--adp-width); */ 532 | position: absolute; 533 | transition: opacity var(--adp-transition-duration) var(--adp-transition-ease), transform var(--adp-transition-duration) var(--adp-transition-ease); 534 | z-index: var(--adp-z-index) 535 | } 536 | 537 | .air-datepicker:not(.-custom-position-) { 538 | opacity: 0 539 | } 540 | 541 | .air-datepicker.-from-top- { 542 | transform: translateY(calc(var(--adp-transition-offset) * -1)) 543 | } 544 | 545 | .air-datepicker.-from-right- { 546 | transform: translateX(var(--adp-transition-offset)) 547 | } 548 | 549 | .air-datepicker.-from-bottom- { 550 | transform: translateY(var(--adp-transition-offset)) 551 | } 552 | 553 | .air-datepicker.-from-left- { 554 | transform: translateX(calc(var(--adp-transition-offset) * -1)) 555 | } 556 | 557 | .air-datepicker.-active-:not(.-custom-position-) { 558 | transform: translate(0, 0); 559 | opacity: 1 560 | } 561 | 562 | .air-datepicker.-active-.-custom-position- { 563 | transition: none 564 | } 565 | 566 | .air-datepicker.-inline- { 567 | border-color: var(--adp-border-color-inline); 568 | box-shadow: none; 569 | position: static; 570 | left: auto; 571 | right: auto; 572 | opacity: 1; 573 | transform: none 574 | } 575 | 576 | .air-datepicker.-inline- .air-datepicker--pointer { 577 | display: none 578 | } 579 | 580 | .air-datepicker.-is-mobile- { 581 | --adp-font-size: var(--adp-mobile-font-size); 582 | --adp-day-cell-height: var(--adp-mobile-day-cell-height); 583 | --adp-month-cell-height: var(--adp-mobile-month-cell-height); 584 | --adp-year-cell-height: var(--adp-mobile-year-cell-height); 585 | --adp-nav-height: var(--adp-mobile-nav-height); 586 | --adp-nav-action-size: var(--adp-mobile-nav-height); 587 | position: fixed; 588 | width: var(--adp-mobile-width); 589 | border: none 590 | } 591 | 592 | .air-datepicker.-is-mobile- * { 593 | -webkit-tap-highlight-color: transparent 594 | } 595 | 596 | .air-datepicker.-is-mobile- .air-datepicker--pointer { 597 | display: none 598 | } 599 | 600 | .air-datepicker.-is-mobile-:not(.-custom-position-) { 601 | transform: translate(-50%, calc(-50% + var(--adp-transition-offset))) 602 | } 603 | 604 | .air-datepicker.-is-mobile-.-active-:not(.-custom-position-) { 605 | transform: translate(-50%, -50%) 606 | } 607 | 608 | .air-datepicker.-custom-position- { 609 | transition: none 610 | } 611 | 612 | .air-datepicker-global-container { 613 | position: absolute; 614 | left: 0; 615 | top: 0 616 | } 617 | 618 | .air-datepicker--pointer { 619 | --pointer-half-size: calc(var(--adp-pointer-size) / 2); 620 | position: absolute; 621 | width: var(--adp-pointer-size); 622 | height: var(--adp-pointer-size); 623 | z-index: -1; 624 | display: none; 625 | } 626 | 627 | .air-datepicker--pointer:after { 628 | content: ''; 629 | position: absolute; 630 | background: #fff; 631 | border-top: 1px solid var(--adp-border-color-inline); 632 | border-right: 1px solid var(--adp-border-color-inline); 633 | border-top-right-radius: var(--adp-poiner-border-radius); 634 | width: var(--adp-pointer-size); 635 | height: var(--adp-pointer-size); 636 | box-sizing: border-box 637 | } 638 | 639 | .-top-left- .air-datepicker--pointer, 640 | .-top-center- .air-datepicker--pointer, 641 | .-top-right- .air-datepicker--pointer, 642 | [data-popper-placement^='top'] .air-datepicker--pointer { 643 | top: calc(100% - var(--pointer-half-size) + 1px) 644 | } 645 | 646 | .-top-left- .air-datepicker--pointer:after, 647 | .-top-center- .air-datepicker--pointer:after, 648 | .-top-right- .air-datepicker--pointer:after, 649 | [data-popper-placement^='top'] .air-datepicker--pointer:after { 650 | transform: rotate(135deg) 651 | } 652 | 653 | .-right-top- .air-datepicker--pointer, 654 | .-right-center- .air-datepicker--pointer, 655 | .-right-bottom- .air-datepicker--pointer, 656 | [data-popper-placement^='right'] .air-datepicker--pointer { 657 | right: calc(100% - var(--pointer-half-size) + 1px) 658 | } 659 | 660 | .-right-top- .air-datepicker--pointer:after, 661 | .-right-center- .air-datepicker--pointer:after, 662 | .-right-bottom- .air-datepicker--pointer:after, 663 | [data-popper-placement^='right'] .air-datepicker--pointer:after { 664 | transform: rotate(225deg) 665 | } 666 | 667 | .-bottom-left- .air-datepicker--pointer, 668 | .-bottom-center- .air-datepicker--pointer, 669 | .-bottom-right- .air-datepicker--pointer, 670 | [data-popper-placement^='bottom'] .air-datepicker--pointer { 671 | bottom: calc(100% - var(--pointer-half-size) + 1px) 672 | } 673 | 674 | .-bottom-left- .air-datepicker--pointer:after, 675 | .-bottom-center- .air-datepicker--pointer:after, 676 | .-bottom-right- .air-datepicker--pointer:after, 677 | [data-popper-placement^='bottom'] .air-datepicker--pointer:after { 678 | transform: rotate(315deg) 679 | } 680 | 681 | .-left-top- .air-datepicker--pointer, 682 | .-left-center- .air-datepicker--pointer, 683 | .-left-bottom- .air-datepicker--pointer, 684 | [data-popper-placement^='left'] .air-datepicker--pointer { 685 | left: calc(100% - var(--pointer-half-size) + 1px) 686 | } 687 | 688 | .-left-top- .air-datepicker--pointer:after, 689 | .-left-center- .air-datepicker--pointer:after, 690 | .-left-bottom- .air-datepicker--pointer:after, 691 | [data-popper-placement^='left'] .air-datepicker--pointer:after { 692 | transform: rotate(45deg) 693 | } 694 | 695 | .-top-left- .air-datepicker--pointer, 696 | .-bottom-left- .air-datepicker--pointer { 697 | left: var(--adp-pointer-offset) 698 | } 699 | 700 | .-top-right- .air-datepicker--pointer, 701 | .-bottom-right- .air-datepicker--pointer { 702 | right: var(--adp-pointer-offset) 703 | } 704 | 705 | .-top-center- .air-datepicker--pointer, 706 | .-bottom-center- .air-datepicker--pointer { 707 | left: calc(50% - var(--adp-pointer-size) / 2) 708 | } 709 | 710 | .-left-top- .air-datepicker--pointer, 711 | .-right-top- .air-datepicker--pointer { 712 | top: var(--adp-pointer-offset) 713 | } 714 | 715 | .-left-bottom- .air-datepicker--pointer, 716 | .-right-bottom- .air-datepicker--pointer { 717 | bottom: var(--adp-pointer-offset) 718 | } 719 | 720 | .-left-center- .air-datepicker--pointer, 721 | .-right-center- .air-datepicker--pointer { 722 | top: calc(50% - var(--adp-pointer-size) / 2) 723 | } 724 | 725 | .air-datepicker--navigation { 726 | grid-area: nav 727 | } 728 | 729 | .air-datepicker--content { 730 | box-sizing: content-box; 731 | padding: var(--adp-padding); 732 | grid-area: body 733 | } 734 | 735 | .-only-timepicker- .air-datepicker--content { 736 | display: none 737 | } 738 | 739 | .air-datepicker--time { 740 | grid-area: timepicker 741 | } 742 | 743 | .air-datepicker--buttons { 744 | grid-area: buttons 745 | } 746 | 747 | .air-datepicker--buttons, 748 | .air-datepicker--time { 749 | padding: var(--adp-padding); 750 | border-top: 1px solid var(--adp-border-color-inner) 751 | } 752 | 753 | .air-datepicker-overlay { 754 | position: fixed; 755 | background: var(--adp-overlay-background-color); 756 | left: 0; 757 | top: 0; 758 | width: 0; 759 | height: 0; 760 | opacity: 0; 761 | transition: opacity var(--adp-overlay-transition-duration) var(--adp-overlay-transition-ease), left 0s, height 0s, width 0s; 762 | transition-delay: 0s, var(--adp-overlay-transition-duration), var(--adp-overlay-transition-duration), var(--adp-overlay-transition-duration); 763 | z-index: var(--adp-overlay-z-index) 764 | } 765 | 766 | .air-datepicker-overlay.-active- { 767 | opacity: 1; 768 | width: 100%; 769 | height: 100%; 770 | transition: opacity var(--adp-overlay-transition-duration) var(--adp-overlay-transition-ease), height 0s, width 0s 771 | } -------------------------------------------------------------------------------- /assets/css/air-datepicker.min.css: -------------------------------------------------------------------------------- 1 | .air-datepicker-cell{box-sizing:border-box;cursor:pointer;display:flex;position:relative;align-items:center;justify-content:center;z-index:1}.air-datepicker-cell.-current-.-focus-{color:var(--adp-color)}.air-datepicker-cell.-current-.-in-range-{color:var(--adp-color-current-date)}.air-datepicker-cell.-disabled-{cursor:default;color:var(--adp-color-disabled)}.air-datepicker-cell.-disabled-.-focus-{color:var(--adp-color-disabled)}.air-datepicker-cell.-disabled-.-in-range-{color:var(--adp-color-disabled-in-range)}.air-datepicker-cell.-disabled-.-current-.-focus-{color:var(--adp-color-disabled)}.air-datepicker-cell.-in-range-{background:var(--adp-cell-background-color-in-range);border-radius:0}.air-datepicker-cell.-in-range-:hover{background:var(--adp-cell-background-color-in-range-hover)}.air-datepicker-cell.-range-from-{border:1px solid var(--adp-cell-border-color-in-range);background-color:var(--adp-cell-background-color-in-range);border-radius:var(--adp-cell-border-radius) 0 0 var(--adp-cell-border-radius)}.air-datepicker-cell.-range-to-{border:1px solid var(--adp-cell-border-color-in-range);background-color:var(--adp-cell-background-color-in-range);border-radius:0 var(--adp-cell-border-radius) var(--adp-cell-border-radius) 0}.air-datepicker-cell.-range-to-.-range-from-{border-radius:var(--adp-cell-border-radius)}.air-datepicker-body{transition:all var(--adp-transition-duration) var(--adp-transition-ease)}.air-datepicker-body.-hidden-{display:none}.air-datepicker-body--day-names{display:grid;grid-template-columns:repeat(7,var(--adp-day-cell-width))}.air-datepicker-body--day-name{display:flex;align-items:center;justify-content:center;flex:1;text-align:center;text-transform:uppercase}.air-datepicker-body--day-name.-clickable-{cursor:pointer}.air-datepicker-body--day-name.-clickable-:hover{color:var(--adp-day-name-color-hover)}.air-datepicker-body--cells{display:grid}.air-datepicker-nav{display:flex;justify-content:space-between;box-sizing:content-box}.-only-timepicker- .air-datepicker-nav{display:none}.air-datepicker-nav--action,.air-datepicker-nav--title{display:flex;cursor:pointer;align-items:center;justify-content:center}.air-datepicker-nav--action{border-radius:var(--adp-border-radius);-webkit-user-select:none;-moz-user-select:none;user-select:none;width:24px;height:24px}.air-datepicker-nav--action.-disabled-{visibility:hidden}.air-datepicker-nav--action svg{width:24px;height:24px}.air-datepicker-nav--action path{fill:none;stroke:var(--adp-nav-arrow-color);stroke-width:2px}.air-datepicker-nav--title{border-radius:var(--adp-border-radius);padding:0 8px}.air-datepicker-nav--title i{font-style:normal;color:var(--adp-nav-color-secondary);margin-left:.3em}.air-datepicker-nav--title.-disabled-{cursor:default;background:0 0}.air-datepicker-buttons{display:grid;grid-auto-columns:1fr;grid-auto-flow:column}.air-datepicker-button{display:inline-flex;color:var(--adp-btn-color);border-radius:var(--adp-btn-border-radius);cursor:pointer;height:var(--adp-btn-height);border:none;background:rgba(255,255,255,0)}.air-datepicker-button:hover{color:var(--adp-btn-color-hover);background:var(--adp-btn-background-color-hover)}.air-datepicker-button:focus{color:var(--adp-btn-color-hover);background:var(--adp-btn-background-color-hover);outline:0}.air-datepicker-button:active{background:var(--adp-btn-background-color-active)}.air-datepicker-button span{outline:0;display:flex;align-items:center;justify-content:center;width:100%;height:100%}.air-datepicker-time{display:grid;grid-template-columns:-webkit-max-content 1fr;grid-template-columns:max-content 1fr;grid-column-gap:12px;align-items:center;position:relative;padding:0 var(--adp-time-padding-inner)}.-only-timepicker- .air-datepicker-time{border-top:none}.air-datepicker-time--current{display:flex;align-items:center;flex:1;font-size:14px;text-align:center}.air-datepicker-time--current-colon{margin:0 2px 3px;line-height:1}.air-datepicker-time--current-hours,.air-datepicker-time--current-minutes{line-height:1;font-size:19px;font-family:"Century Gothic",CenturyGothic,AppleGothic,sans-serif;position:relative;z-index:1}.air-datepicker-time--current-hours:after,.air-datepicker-time--current-minutes:after{content:'';background:var(--adp-background-color-hover);border-radius:var(--adp-border-radius);position:absolute;left:-2px;top:-3px;right:-2px;bottom:-2px;z-index:-1;opacity:0}.air-datepicker-time--current-hours.-focus-:after,.air-datepicker-time--current-minutes.-focus-:after{opacity:1}.air-datepicker-time--current-ampm{text-transform:uppercase;align-self:flex-end;color:var(--adp-time-day-period-color);margin-left:6px;font-size:11px;margin-bottom:1px}.air-datepicker-time--row{display:flex;align-items:center;font-size:11px;height:17px;background:linear-gradient(to right,var(--adp-time-track-color),var(--adp-time-track-color)) left 50%/100% var(--adp-time-track-height) no-repeat}.air-datepicker-time--row:first-child{margin-bottom:4px}.air-datepicker-time--row input[type=range]{background:0 0;cursor:pointer;flex:1;height:100%;width:100%;padding:0;margin:0;-webkit-appearance:none}.air-datepicker-time--row input[type=range]::-webkit-slider-thumb{-webkit-appearance:none}.air-datepicker-time--row input[type=range]::-ms-tooltip{display:none}.air-datepicker-time--row input[type=range]:hover::-webkit-slider-thumb{border-color:var(--adp-time-track-color-hover)}.air-datepicker-time--row input[type=range]:hover::-moz-range-thumb{border-color:var(--adp-time-track-color-hover)}.air-datepicker-time--row input[type=range]:hover::-ms-thumb{border-color:var(--adp-time-track-color-hover)}.air-datepicker-time--row input[type=range]:focus{outline:0}.air-datepicker-time--row input[type=range]:focus::-webkit-slider-thumb{background:var(--adp-cell-background-color-selected);border-color:var(--adp-cell-background-color-selected)}.air-datepicker-time--row input[type=range]:focus::-moz-range-thumb{background:var(--adp-cell-background-color-selected);border-color:var(--adp-cell-background-color-selected)}.air-datepicker-time--row input[type=range]:focus::-ms-thumb{background:var(--adp-cell-background-color-selected);border-color:var(--adp-cell-background-color-selected)}.air-datepicker-time--row input[type=range]::-webkit-slider-thumb{box-sizing:border-box;height:12px;width:12px;border-radius:3px;border:1px solid var(--adp-time-track-color);background:#fff;cursor:pointer;-webkit-transition:background var(--adp-transition-duration);transition:background var(--adp-transition-duration)}.air-datepicker-time--row input[type=range]::-moz-range-thumb{box-sizing:border-box;height:12px;width:12px;border-radius:3px;border:1px solid var(--adp-time-track-color);background:#fff;cursor:pointer;-moz-transition:background var(--adp-transition-duration);transition:background var(--adp-transition-duration)}.air-datepicker-time--row input[type=range]::-ms-thumb{box-sizing:border-box;height:12px;width:12px;border-radius:3px;border:1px solid var(--adp-time-track-color);background:#fff;cursor:pointer;-ms-transition:background var(--adp-transition-duration);transition:background var(--adp-transition-duration)}.air-datepicker-time--row input[type=range]::-webkit-slider-thumb{margin-top:calc(var(--adp-time-thumb-size)/ 2 * -1)}.air-datepicker-time--row input[type=range]::-webkit-slider-runnable-track{border:none;height:var(--adp-time-track-height);cursor:pointer;color:transparent;background:0 0}.air-datepicker-time--row input[type=range]::-moz-range-track{border:none;height:var(--adp-time-track-height);cursor:pointer;color:transparent;background:0 0}.air-datepicker-time--row input[type=range]::-ms-track{border:none;height:var(--adp-time-track-height);cursor:pointer;color:transparent;background:0 0}.air-datepicker-time--row input[type=range]::-ms-fill-lower{background:0 0}.air-datepicker-time--row input[type=range]::-ms-fill-upper{background:0 0}.air-datepicker{--adp-font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";--adp-font-size:14px;--adp-width:246px;--adp-z-index:100;--adp-padding:4px;--adp-grid-areas:'nav' 'body' 'timepicker' 'buttons';--adp-transition-duration:.3s;--adp-transition-ease:ease-out;--adp-transition-offset:8px;--adp-background-color:#fff;--adp-background-color-hover:#f0f0f0;--adp-background-color-active:#eaeaea;--adp-background-color-in-range:rgba(92, 196, 239, .1);--adp-background-color-in-range-focused:rgba(92, 196, 239, .2);--adp-background-color-selected-other-month-focused:#8ad5f4;--adp-background-color-selected-other-month:#a2ddf6;--adp-color:#4a4a4a;--adp-color-secondary:#9c9c9c;--adp-accent-color:#4eb5e6;--adp-color-current-date:var(--adp-accent-color);--adp-color-other-month:#dedede;--adp-color-disabled:#aeaeae;--adp-color-disabled-in-range:#939393;--adp-color-other-month-hover:#c5c5c5;--adp-border-color:#dbdbdb;--adp-border-color-inner:#efefef;--adp-border-radius:4px;--adp-border-color-inline:#d7d7d7;--adp-nav-height:32px;--adp-nav-arrow-color:var(--adp-color-secondary);--adp-nav-action-size:32px;--adp-nav-color-secondary:var(--adp-color-secondary);--adp-day-name-color:#ff9a19;--adp-day-name-color-hover:#8ad5f4;--adp-day-cell-width:1fr;--adp-day-cell-height:32px;--adp-month-cell-height:42px;--adp-year-cell-height:56px;--adp-pointer-size:10px;--adp-poiner-border-radius:2px;--adp-pointer-offset:14px;--adp-cell-border-radius:4px;--adp-cell-background-color-hover:var(--adp-background-color-hover);--adp-cell-background-color-selected:#5cc4ef;--adp-cell-background-color-selected-hover:#45bced;--adp-cell-background-color-in-range:rgba(92, 196, 239, 0.1);--adp-cell-background-color-in-range-hover:rgba(92, 196, 239, 0.2);--adp-cell-border-color-in-range:var(--adp-cell-background-color-selected);--adp-btn-height:32px;--adp-btn-color:var(--adp-accent-color);--adp-btn-color-hover:var(--adp-color);--adp-btn-border-radius:var(--adp-border-radius);--adp-btn-background-color-hover:var(--adp-background-color-hover);--adp-btn-background-color-active:var(--adp-background-color-active);--adp-time-track-height:1px;--adp-time-track-color:#dedede;--adp-time-track-color-hover:#b1b1b1;--adp-time-thumb-size:12px;--adp-time-padding-inner:10px;--adp-time-day-period-color:var(--adp-color-secondary);--adp-mobile-font-size:16px;--adp-mobile-nav-height:40px;--adp-mobile-width:320px;--adp-mobile-day-cell-height:38px;--adp-mobile-month-cell-height:48px;--adp-mobile-year-cell-height:64px}.air-datepicker-overlay{--adp-overlay-background-color:rgba(0, 0, 0, .3);--adp-overlay-transition-duration:.3s;--adp-overlay-transition-ease:ease-out;--adp-overlay-z-index:99}.air-datepicker{background:var(--adp-background-color);box-sizing:content-box;display:grid;grid-template-columns:1fr;grid-template-rows:repeat(4,-webkit-max-content);grid-template-rows:repeat(4,max-content);grid-template-areas:var(--adp-grid-areas);font-family:var(--adp-font-family),sans-serif;font-size:var(--adp-font-size);color:var(--adp-color);position:absolute;transition:opacity var(--adp-transition-duration) var(--adp-transition-ease),transform var(--adp-transition-duration) var(--adp-transition-ease);z-index:var(--adp-z-index)}.air-datepicker:not(.-custom-position-){opacity:0}.air-datepicker.-from-top-{transform:translateY(calc(var(--adp-transition-offset) * -1))}.air-datepicker.-from-right-{transform:translateX(var(--adp-transition-offset))}.air-datepicker.-from-bottom-{transform:translateY(var(--adp-transition-offset))}.air-datepicker.-from-left-{transform:translateX(calc(var(--adp-transition-offset) * -1))}.air-datepicker.-active-:not(.-custom-position-){transform:translate(0,0);opacity:1}.air-datepicker.-active-.-custom-position-{transition:none}.air-datepicker.-inline-{border-color:var(--adp-border-color-inline);box-shadow:none;position:static;left:auto;right:auto;opacity:1;transform:none}.air-datepicker.-inline- .air-datepicker--pointer{display:none}.air-datepicker.-is-mobile-{--adp-font-size:var(--adp-mobile-font-size);--adp-day-cell-height:var(--adp-mobile-day-cell-height);--adp-month-cell-height:var(--adp-mobile-month-cell-height);--adp-year-cell-height:var(--adp-mobile-year-cell-height);--adp-nav-height:var(--adp-mobile-nav-height);--adp-nav-action-size:var(--adp-mobile-nav-height);position:fixed;width:var(--adp-mobile-width);border:none}.air-datepicker.-is-mobile- *{-webkit-tap-highlight-color:transparent}.air-datepicker.-is-mobile- .air-datepicker--pointer{display:none}.air-datepicker.-is-mobile-:not(.-custom-position-){transform:translate(-50%,calc(-50% + var(--adp-transition-offset)))}.air-datepicker.-is-mobile-.-active-:not(.-custom-position-){transform:translate(-50%,-50%)}.air-datepicker.-custom-position-{transition:none}.air-datepicker-global-container{position:absolute;left:0;top:0}.air-datepicker--pointer{--pointer-half-size:calc(var(--adp-pointer-size) / 2);position:absolute;width:var(--adp-pointer-size);height:var(--adp-pointer-size);z-index:-1;display:none}.air-datepicker--pointer:after{content:'';position:absolute;background:#fff;border-top:1px solid var(--adp-border-color-inline);border-right:1px solid var(--adp-border-color-inline);border-top-right-radius:var(--adp-poiner-border-radius);width:var(--adp-pointer-size);height:var(--adp-pointer-size);box-sizing:border-box}.-top-center- .air-datepicker--pointer,.-top-left- .air-datepicker--pointer,.-top-right- .air-datepicker--pointer,[data-popper-placement^=top] .air-datepicker--pointer{top:calc(100% - var(--pointer-half-size) + 1px)}.-top-center- .air-datepicker--pointer:after,.-top-left- .air-datepicker--pointer:after,.-top-right- .air-datepicker--pointer:after,[data-popper-placement^=top] .air-datepicker--pointer:after{transform:rotate(135deg)}.-right-bottom- .air-datepicker--pointer,.-right-center- .air-datepicker--pointer,.-right-top- .air-datepicker--pointer,[data-popper-placement^=right] .air-datepicker--pointer{right:calc(100% - var(--pointer-half-size) + 1px)}.-right-bottom- .air-datepicker--pointer:after,.-right-center- .air-datepicker--pointer:after,.-right-top- .air-datepicker--pointer:after,[data-popper-placement^=right] .air-datepicker--pointer:after{transform:rotate(225deg)}.-bottom-center- .air-datepicker--pointer,.-bottom-left- .air-datepicker--pointer,.-bottom-right- .air-datepicker--pointer,[data-popper-placement^=bottom] .air-datepicker--pointer{bottom:calc(100% - var(--pointer-half-size) + 1px)}.-bottom-center- .air-datepicker--pointer:after,.-bottom-left- .air-datepicker--pointer:after,.-bottom-right- .air-datepicker--pointer:after,[data-popper-placement^=bottom] .air-datepicker--pointer:after{transform:rotate(315deg)}.-left-bottom- .air-datepicker--pointer,.-left-center- .air-datepicker--pointer,.-left-top- .air-datepicker--pointer,[data-popper-placement^=left] .air-datepicker--pointer{left:calc(100% - var(--pointer-half-size) + 1px)}.-left-bottom- .air-datepicker--pointer:after,.-left-center- .air-datepicker--pointer:after,.-left-top- .air-datepicker--pointer:after,[data-popper-placement^=left] .air-datepicker--pointer:after{transform:rotate(45deg)}.-bottom-left- .air-datepicker--pointer,.-top-left- .air-datepicker--pointer{left:var(--adp-pointer-offset)}.-bottom-right- .air-datepicker--pointer,.-top-right- .air-datepicker--pointer{right:var(--adp-pointer-offset)}.-bottom-center- .air-datepicker--pointer,.-top-center- .air-datepicker--pointer{left:calc(50% - var(--adp-pointer-size)/ 2)}.-left-top- .air-datepicker--pointer,.-right-top- .air-datepicker--pointer{top:var(--adp-pointer-offset)}.-left-bottom- .air-datepicker--pointer,.-right-bottom- .air-datepicker--pointer{bottom:var(--adp-pointer-offset)}.-left-center- .air-datepicker--pointer,.-right-center- .air-datepicker--pointer{top:calc(50% - var(--adp-pointer-size)/ 2)}.air-datepicker--navigation{grid-area:nav}.air-datepicker--content{box-sizing:content-box;padding:var(--adp-padding);grid-area:body}.-only-timepicker- .air-datepicker--content{display:none}.air-datepicker--time{grid-area:timepicker}.air-datepicker--buttons{grid-area:buttons}.air-datepicker--buttons,.air-datepicker--time{padding:var(--adp-padding);border-top:1px solid var(--adp-border-color-inner)}.air-datepicker-overlay{position:fixed;background:var(--adp-overlay-background-color);left:0;top:0;width:0;height:0;opacity:0;transition:opacity var(--adp-overlay-transition-duration) var(--adp-overlay-transition-ease),left 0s,height 0s,width 0s;transition-delay:0s,var(--adp-overlay-transition-duration),var(--adp-overlay-transition-duration),var(--adp-overlay-transition-duration);z-index:var(--adp-overlay-z-index)}.air-datepicker-overlay.-active-{opacity:1;width:100%;height:100%;transition:opacity var(--adp-overlay-transition-duration) var(--adp-overlay-transition-ease),height 0s,width 0s} -------------------------------------------------------------------------------- /assets/fonts/inter-v12-latin-500.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pub-calculator-io/days-calculator/c03763c129f8aa6616e0e80720207e423e999700/assets/fonts/inter-v12-latin-500.woff2 -------------------------------------------------------------------------------- /assets/fonts/inter-v12-latin-600.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pub-calculator-io/days-calculator/c03763c129f8aa6616e0e80720207e423e999700/assets/fonts/inter-v12-latin-600.woff2 -------------------------------------------------------------------------------- /assets/fonts/inter-v12-latin-800.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pub-calculator-io/days-calculator/c03763c129f8aa6616e0e80720207e423e999700/assets/fonts/inter-v12-latin-800.woff2 -------------------------------------------------------------------------------- /assets/fonts/inter-v12-latin-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pub-calculator-io/days-calculator/c03763c129f8aa6616e0e80720207e423e999700/assets/fonts/inter-v12-latin-regular.woff2 -------------------------------------------------------------------------------- /assets/images/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pub-calculator-io/days-calculator/c03763c129f8aa6616e0e80720207e423e999700/assets/images/apple-touch-icon.png -------------------------------------------------------------------------------- /assets/images/banner-1544x500.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pub-calculator-io/days-calculator/c03763c129f8aa6616e0e80720207e423e999700/assets/images/banner-1544x500.png -------------------------------------------------------------------------------- /assets/images/banner-772x250.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pub-calculator-io/days-calculator/c03763c129f8aa6616e0e80720207e423e999700/assets/images/banner-772x250.png -------------------------------------------------------------------------------- /assets/images/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pub-calculator-io/days-calculator/c03763c129f8aa6616e0e80720207e423e999700/assets/images/favicon.ico -------------------------------------------------------------------------------- /assets/images/icon-128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pub-calculator-io/days-calculator/c03763c129f8aa6616e0e80720207e423e999700/assets/images/icon-128.png -------------------------------------------------------------------------------- /assets/images/icon-128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pub-calculator-io/days-calculator/c03763c129f8aa6616e0e80720207e423e999700/assets/images/icon-128x128.png -------------------------------------------------------------------------------- /assets/images/icon-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pub-calculator-io/days-calculator/c03763c129f8aa6616e0e80720207e423e999700/assets/images/icon-192.png -------------------------------------------------------------------------------- /assets/images/icon-196.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pub-calculator-io/days-calculator/c03763c129f8aa6616e0e80720207e423e999700/assets/images/icon-196.png -------------------------------------------------------------------------------- /assets/images/icon-256x256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pub-calculator-io/days-calculator/c03763c129f8aa6616e0e80720207e423e999700/assets/images/icon-256x256.png -------------------------------------------------------------------------------- /assets/images/icon-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pub-calculator-io/days-calculator/c03763c129f8aa6616e0e80720207e423e999700/assets/images/icon-32.png -------------------------------------------------------------------------------- /assets/images/icon-96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pub-calculator-io/days-calculator/c03763c129f8aa6616e0e80720207e423e999700/assets/images/icon-96.png -------------------------------------------------------------------------------- /assets/images/icon-og.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pub-calculator-io/days-calculator/c03763c129f8aa6616e0e80720207e423e999700/assets/images/icon-og.png -------------------------------------------------------------------------------- /assets/images/icon-rounded.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pub-calculator-io/days-calculator/c03763c129f8aa6616e0e80720207e423e999700/assets/images/icon-rounded.png -------------------------------------------------------------------------------- /assets/images/icon-square.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pub-calculator-io/days-calculator/c03763c129f8aa6616e0e80720207e423e999700/assets/images/icon-square.png -------------------------------------------------------------------------------- /assets/images/illustration-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pub-calculator-io/days-calculator/c03763c129f8aa6616e0e80720207e423e999700/assets/images/illustration-1.png -------------------------------------------------------------------------------- /assets/images/illustration-els.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pub-calculator-io/days-calculator/c03763c129f8aa6616e0e80720207e423e999700/assets/images/illustration-els.png -------------------------------------------------------------------------------- /assets/images/illustration-og.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pub-calculator-io/days-calculator/c03763c129f8aa6616e0e80720207e423e999700/assets/images/illustration-og.png -------------------------------------------------------------------------------- /assets/images/screenshot-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pub-calculator-io/days-calculator/c03763c129f8aa6616e0e80720207e423e999700/assets/images/screenshot-1.png -------------------------------------------------------------------------------- /assets/images/screenshot-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pub-calculator-io/days-calculator/c03763c129f8aa6616e0e80720207e423e999700/assets/images/screenshot-2.png -------------------------------------------------------------------------------- /assets/js/app.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | window._ = document.getElementById.bind(document); 4 | window.$ = document.querySelector.bind(document); 5 | window.$$ = document.querySelectorAll.bind(document); 6 | 7 | console.log('Script is OK! ༼ つ ◕_◕ ༽つ') 8 | // IS MAIN PAGE 9 | // if(window.location.pathname === '/') document.body.classList.add('isMainPage') 10 | 11 | // DIALOG TABLE 12 | if(document.querySelector('.result-table__dialog')) { 13 | import('./dialog-table.js').then(e => { 14 | console.log("Dialog table loaded (づ ◕‿◕ )づ") 15 | }).catch(e => { 16 | console.log("Sorry, dialog tables not loaded (ಥ﹏ಥ)", e) 17 | }) 18 | } 19 | // MASK 20 | if(document.querySelector('[data-inputmask]')) { 21 | import('./mask.js').then(e => { 22 | console.log("Mask loaded (づ ◕‿◕ )づ") 23 | }).catch(e => { 24 | console.log("Sorry, masks not loaded (ಥ﹏ಥ)", e) 25 | }) 26 | } 27 | // DATEPICKER 28 | if(document.querySelector('.datepicker')) { 29 | import('./datepicker.js').then(e => { 30 | console.log("Datepicker loaded (づ ◕‿◕ )づ") 31 | }).catch(e => { 32 | console.log("Sorry, datepicker not loaded (ಥ﹏ಥ)", e) 33 | }) 34 | } 35 | // TIMEPICKER 36 | if(document.querySelector('.timepicker-input')) { 37 | import('./timepicker.js').then(e => { 38 | console.log("Timepicker loaded (づ ◕‿◕ )づ") 39 | }).catch(e => { 40 | console.log("Sorry, timepicker not loaded (ಥ﹏ಥ)", e) 41 | }) 42 | } 43 | // HOURPICKER 44 | if(document.querySelector('.hourpicker-input')) { 45 | import('./hourpicker.js').then(e => { 46 | console.log("Hourpicker loaded (づ ◕‿◕ )づ") 47 | }).catch(e => { 48 | console.log("Sorry, Hourpicker not loaded (ಥ﹏ಥ)", e) 49 | }) 50 | } 51 | // OPTIONS 52 | if(document.querySelector('.calculator-content--options')) { 53 | import('./options.js').then(e => { 54 | console.log("Options loaded (づ ◕‿◕ )づ") 55 | }).catch(e => { 56 | console.log("Sorry, options not loaded (ಥ﹏ಥ)", e) 57 | }) 58 | } 59 | // ICON DROPDOWN 60 | if(document.querySelector('.dropdown-icon')) { 61 | import('./dropdown-icon.js').then(e => { 62 | console.log("Dropdown-icon loaded (づ ◕‿◕ )づ") 63 | }).catch(e => { 64 | console.log("Sorry, dropdown-icon not loaded (ಥ﹏ಥ)", e) 65 | }) 66 | } 67 | 68 | // MODAL 69 | const MODAL_OPENERS = document.querySelectorAll('.js-modal-open') 70 | const MODAL_CLOSERS = document.querySelectorAll('.js-modal-close') 71 | const MODAL_WINDOW = document.querySelector('.modal-window') 72 | 73 | let currentShare = 0 74 | let isOpenPopupHeader = false; 75 | let focusedElement = 0; 76 | 77 | const closeAll = () => { 78 | MODAL_SEARCH.value = '' 79 | MODAL_SEARCH_LIST.classList.remove('modal-search__list--error') 80 | MODAL_SEARCH_LIST.classList.remove('modal-search__list--active') 81 | MODAL_OPENERS.forEach(MODAL_OPENER => { 82 | const MODAL_ID = MODAL_OPENER.getAttribute('data-modal') 83 | const MODAL = document.querySelector(`.modal-${MODAL_ID}`) 84 | MODAL.classList.remove(`modal-${MODAL_ID}--active`) 85 | }) 86 | } 87 | 88 | window.addEventListener('click', (e) => { 89 | let controllerTheme = document.querySelector('#popup-theme') 90 | let controllerLang = document.querySelector('#popup-lang') 91 | if(isOpenPopupHeader && !(e.composedPath().includes(controllerLang) || e.composedPath().includes(controllerTheme))) { 92 | isOpenPopupHeader = false 93 | document.querySelector('.modal-lang--active')?.classList.remove(`modal-lang--active`) 94 | document.querySelector('.modal-theme--active')?.classList.remove(`modal-theme--active`) 95 | } 96 | }) 97 | 98 | window.addEventListener('keydown', (e) => { 99 | if(e.key === 'Escape') { 100 | MODAL_WINDOW.classList.remove('modal-window--active') 101 | closeAll() 102 | } 103 | 104 | if((e.metaKey && e.key === 'k') || (e.ctrlKey && e.key === 'k')) { 105 | closeAll(); 106 | $('.modal-search__input').focus(); 107 | MODAL_WINDOW.classList.add(`modal-window--active`) 108 | $('.modal-search').classList.toggle(`modal-search--active`); 109 | } 110 | 111 | if(!MODAL_WINDOW) return; 112 | 113 | if(e.key === 'ArrowUp') { 114 | let listItem = [...MODAL_SEARCH_LIST_CONTENT.children] 115 | if(focusedElement - 1 < 0) { 116 | focusedElement = listItem.length - 1 117 | } else { 118 | focusedElement-- 119 | } 120 | listItem[focusedElement]?.focus() 121 | // listItem[focusedElement].scrollIntoView(true) 122 | } 123 | 124 | if(e.key === 'ArrowDown') { 125 | let listItem = [...MODAL_SEARCH_LIST_CONTENT.children] 126 | listItem[focusedElement]?.focus() 127 | if(focusedElement + 1 > listItem.length - 1) { 128 | focusedElement = 0 129 | } else { 130 | focusedElement++ 131 | } 132 | } 133 | }) 134 | 135 | if(MODAL_WINDOW) { 136 | MODAL_WINDOW.addEventListener('click', (e) => { 137 | if(e.target.classList.contains('modal-window')) { 138 | MODAL_WINDOW.classList.remove(`modal-window--active`) 139 | MODAL_WINDOW.classList.remove(`modal-window--active-mini`) 140 | closeAll() 141 | } 142 | }) 143 | } 144 | if(MODAL_OPENERS.length > 0) { 145 | MODAL_OPENERS.forEach(MODAL_OPENER => { 146 | MODAL_OPENER.addEventListener('click', () => { 147 | const MODAL_ID = MODAL_OPENER.getAttribute('data-modal') 148 | const MODAL = document.querySelector(`.modal-${MODAL_ID}`) 149 | 150 | closeAll(); 151 | 152 | if(MODAL_ID !== 'lang' && MODAL_ID !== 'theme') MODAL_WINDOW.classList.toggle(`modal-window--active`) 153 | else isOpenPopupHeader = true 154 | 155 | if(MODAL_ID === 'search') document.querySelector('.modal-search__input').focus() 156 | if(MODAL_ID === 'share') { 157 | console.log($('.modal-share__textarea').value) 158 | $$('.modal-share__textarea')[currentShare].focus() 159 | $$('.modal-share__textarea')[currentShare].setSelectionRange(0, $$('.modal-share__textarea')[currentShare].value.length) 160 | } 161 | 162 | MODAL.classList.toggle(`modal-${MODAL_ID}--active`) 163 | }) 164 | }) 165 | } 166 | if(MODAL_CLOSERS.length > 0) { 167 | MODAL_CLOSERS.forEach(MODAL_CLOSER => { 168 | MODAL_CLOSER.addEventListener('click', () => { 169 | const MODAL_ID = MODAL_CLOSER.getAttribute('data-modal') 170 | const MODAL = document.querySelector(`.modal-${MODAL_ID}`) 171 | 172 | closeAll(); 173 | 174 | if(MODAL_ID !== 'lang' && MODAL_ID !== 'theme') MODAL_WINDOW.classList.toggle(`modal-window--active`) 175 | else isOpenPopupHeader = true 176 | 177 | MODAL.classList.remove(`modal-${MODAL_ID}--active`) 178 | }) 179 | }) 180 | } 181 | 182 | // THEME 183 | const light = document.querySelectorAll('.light-theme'); 184 | const dark = document.querySelectorAll('.dark-theme'); 185 | const system = document.querySelectorAll('.system-theme'); 186 | 187 | light.forEach((i) => 188 | i.addEventListener('click', () => { 189 | document.documentElement.classList = ''; 190 | localStorage.setItem('theme', 'light'); 191 | setActiveThemeButton('light') 192 | if(switchTheme !== null) { 193 | if(typeof switchTheme === 'object') { 194 | switchTheme.forEach(element => element('light')) 195 | } else { 196 | switchTheme('light') 197 | } 198 | } 199 | }), 200 | ); 201 | dark.forEach((i) => 202 | i.addEventListener('click', () => { 203 | document.documentElement.classList = 'dark'; 204 | localStorage.setItem('theme', 'dark'); 205 | setActiveThemeButton('dark') 206 | if(switchTheme !== null) { 207 | if(typeof switchTheme === 'object') { 208 | switchTheme.forEach(element => element('dark')) 209 | } else { 210 | switchTheme('dark') 211 | } 212 | } 213 | }), 214 | ); 215 | system.forEach((i) => 216 | i.addEventListener('click', () => { 217 | document.documentElement.classList = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : ''; 218 | localStorage.setItem('theme', 'system'); 219 | setActiveThemeButton('system') 220 | if(switchTheme !== null) { 221 | if(typeof switchTheme === 'object') { 222 | switchTheme.forEach(element => element(window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light')) 223 | } else { 224 | switchTheme(window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light') 225 | } 226 | } 227 | }), 228 | ); 229 | 230 | // SEARCH 231 | const MODAL_SEARCH = document.querySelector('.modal-search__input') 232 | const MODAL_SEARCH_LIST = document.querySelector('.modal-search__list') 233 | const MODAL_SEARCH_LIST_CONTENT = document.querySelector('.modal-search__list-content') 234 | 235 | if(MODAL_SEARCH) MODAL_SEARCH.addEventListener('input', (e) => { 236 | focusedElement = 0 237 | if(e.target.value.length > 0) { 238 | const FILTERED_JSON = JSON_CALCULATORS.filter(CALCULATOR => { 239 | return (CALCULATOR.description.toLowerCase().match(e.target.value.toLowerCase()) !== null) || 240 | CALCULATOR.title.toLowerCase().match(e.target.value.toLowerCase()) !== null; 241 | }) 242 | if(FILTERED_JSON.length > 0) { 243 | MODAL_SEARCH_LIST.classList.remove('modal-search__list--error') 244 | MODAL_SEARCH_LIST.classList.add('modal-search__list--active') 245 | MODAL_SEARCH_LIST_CONTENT.innerHTML = '' 246 | FILTERED_JSON.forEach(CALCULATOR => { 247 | let calculatorWrapper = document.createElement('a') 248 | calculatorWrapper.classList.add('modal-search-item') 249 | calculatorWrapper.href = CALCULATOR.uri 250 | 251 | let calculatorImg = document.createElement('img') 252 | calculatorImg.classList.add('modal-search-item__img') 253 | calculatorImg.src = CALCULATOR.image 254 | 255 | let calculatorTitle = document.createElement('span') 256 | calculatorTitle.classList.add('modal-search-item__text') 257 | calculatorTitle.innerText = CALCULATOR.title 258 | 259 | calculatorWrapper.append(calculatorImg, calculatorTitle) 260 | MODAL_SEARCH_LIST_CONTENT.append(calculatorWrapper) 261 | }) 262 | } else { 263 | MODAL_SEARCH_LIST_CONTENT.innerHTML = '' 264 | MODAL_SEARCH_LIST.classList.remove('modal-search__list--active') 265 | MODAL_SEARCH_LIST.classList.add('modal-search__list--error') 266 | } 267 | } else { 268 | MODAL_SEARCH_LIST_CONTENT.innerHTML = '' 269 | MODAL_SEARCH_LIST.classList.remove('modal-search__list--active') 270 | MODAL_SEARCH_LIST.classList.remove('modal-search__list--error') 271 | } 272 | }) 273 | 274 | // LANG 275 | const LANG_SELECTS = document.querySelectorAll('.header-lang__select') 276 | 277 | if (LANG_SELECTS){ 278 | let langIsEng = true 279 | 280 | for (const LANG_SELECT of LANG_SELECTS) { 281 | if(LANG_SELECT.innerText !== 'ENG' && window.location.href.match(LANG_SELECT.href) !== null) { 282 | LANG_SELECT.classList.add('header-lang__select--active') 283 | langIsEng = false 284 | } 285 | } 286 | 287 | if(langIsEng) LANG_SELECTS[0]?.classList?.add('header-lang__select--active') 288 | } 289 | 290 | // SHARE 291 | $$('.modal-share__button').forEach((button,index) => { 292 | button.addEventListener('click', () => { 293 | $$('.modal-share__button').forEach(i => i.classList.remove('modal-share__button--active')) 294 | $$('.modal-share__content').forEach(i => i.classList.remove('modal-share__content--active')) 295 | button.classList.add('modal-share__button--active') 296 | $$('.modal-share__content')[index].classList.add('modal-share__content--active') 297 | $$('.modal-share__textarea')[index].setSelectionRange(0, $$('.modal-share__textarea')[index].value.length) 298 | currentShare = index 299 | }) 300 | }) 301 | 302 | window.copyWidget = function (button) { 303 | button.classList.add('button--copy-active') 304 | navigator.clipboard.writeText($$('.modal-share__textarea')[currentShare].value) 305 | setTimeout(() => { 306 | button.classList.remove('button--copy-active') 307 | }, 1000) 308 | } 309 | 310 | window.now = function (suffix = 0){ 311 | let date = new Date(); 312 | date.setDate(date.getDate() + suffix); 313 | return ("0" + date.getHours()).slice(-2) + ':' + ("0" + date.getMinutes()).slice(-2) + ':' + ("0" + date.getSeconds()).slice(-2) 314 | } 315 | 316 | if(window.innerWidth < 1024){ 317 | $$('.calculator-content .button--primary').forEach((button) => { 318 | button.addEventListener('click', () => { 319 | let scrollValue = _('result-container').offsetTop; 320 | window.scrollTo({ top: scrollValue, behavior: 'smooth'}); 321 | }) 322 | }); 323 | } 324 | -------------------------------------------------------------------------------- /assets/js/calculator.js: -------------------------------------------------------------------------------- 1 | function calculate() { 2 | 3 | let dateFrom = input.get('start_date').date().raw(); 4 | let dateTo = input.get('end_date').date().gt('start_date').raw(); 5 | 6 | if (!input.valid()) return; 7 | 8 | const seconds = (dateTo.getTime() - dateFrom.getTime()) / 1000; 9 | 10 | let results = []; 11 | 12 | const minutes = seconds / 60; 13 | const hours = minutes / 60; 14 | const days = Math.trunc(hours / 24); 15 | 16 | results.unshift(plural(days, 'days:day:days:days:days:days')); 17 | 18 | const holidays = getUserHolidays(); 19 | 20 | const {weekdays, weekends, holidayCount} = countBusinessAndweekends(dateFrom, dateTo, holidays); 21 | results.push(plural(weekdays, 'work days:work day:work days:work days:work days:work days')); 22 | results.push(plural(weekends, 'weekend days:weekend day:weekend days:weekend days:weekend days:weekend days')); 23 | if(holidayCount) results.push(plural(holidayCount, 'holiday days:holiday day:holiday days:holiday days:holiday days:holiday days')); 24 | 25 | $('.result-age__text').innerHTML = '
' + results.join('
') + '
'; 26 | 27 | generateCalendar(dateFrom); 28 | generateCalendar(dateTo, 'result-age--to'); 29 | } 30 | 31 | function generateCalendar(date, calendar = 'result-age--from') { 32 | const daysInMonth = new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate(); 33 | let firstDay = new Date(date.getFullYear(), date.getMonth(), 1).getDay(); 34 | const daysInMonthPrev = new Date(date.getFullYear(), date.getMonth(), 0).getDate(); 35 | 36 | const isStartCalendar = calendar === 'result-age--from' || calendar === 'result-age--from-two'; 37 | const isEndCalendar = calendar === 'result-age--to' || calendar === 'result-age--to-two'; 38 | 39 | if (!firstDay) firstDay = 7; 40 | 41 | let activeClass = 'current'; 42 | 43 | const $days = $$(`.${calendar} .result-age--days p`); 44 | 45 | let i = 0; 46 | while (i <= $days.length) { 47 | if ($days[i]) { 48 | $days[i].innerHTML = ''; 49 | $days[i].classList.remove('current', 'current-between', 'active', 'after-date', 'before-date'); 50 | } 51 | let day = i - firstDay + 1; 52 | const $current_month_day = $days[i - 1]; 53 | 54 | /*Current month*/ 55 | if (i >= firstDay && i < daysInMonth + firstDay) { 56 | $current_month_day.innerHTML = day; 57 | $current_month_day.classList.add('active'); 58 | if (day === date.getDate()) $current_month_day.classList.add(activeClass); 59 | 60 | if (day < date.getDate() && isEndCalendar || 61 | day > date.getDate() && isStartCalendar) { 62 | $current_month_day.classList.add('current-between'); 63 | } 64 | } else if (i < firstDay - 1) { 65 | /*Prev month*/ 66 | if ($days[i]) $days[i].innerHTML = daysInMonthPrev - firstDay + i + 2; 67 | if (calendar === 'result-age--to') { 68 | $days[i].classList.add('current-between'); 69 | } 70 | } else if (i >= firstDay) { 71 | /*Next month*/ 72 | $current_month_day.innerHTML = i - daysInMonth - firstDay + 1; 73 | if (calendar === 'result-age--from') { 74 | $current_month_day.classList.add('current-between'); 75 | } 76 | } 77 | i++; 78 | } 79 | 80 | $(`.${calendar} .date-title--date`).innerHTML = convertDateToDMY(date); 81 | } 82 | 83 | function convertDateToDMY(date) { 84 | const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 85 | 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; 86 | 87 | const day = date.getDate(); 88 | const monthIndex = date.getMonth(); 89 | const year = date.getFullYear(); 90 | 91 | return `${day} ${months[monthIndex]} ${year}`; 92 | } 93 | 94 | function setCommas(number) { 95 | return number.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ','); 96 | } 97 | 98 | function getUserHolidays() { 99 | const count_holidays = input.get('count_holidays').checked().raw(); 100 | if (!count_holidays) return []; 101 | const holidayKeys = 'abcdefghijklmnopqrstuvwxyz'; 102 | const holidays = []; 103 | 104 | /*We need to validate only if month and day are filled*/ 105 | holidayKeys.split('').map(key => { 106 | if (_('count_month_' + key) !== null) { 107 | let month = input.get('count_month_' + key).raw(); 108 | let day = input.get('count_day_' + key).raw(); 109 | if (parseInt(month) && parseInt(day)) holidays.push(month + '.' + day) 110 | } 111 | }); 112 | 113 | const default_holidays = { 114 | 'new_years_day': '1.1', 115 | 'juneteenth_day': '6.19', 116 | 'independence_day': '7.4', 117 | 'veterans_day': '11.11', 118 | 'christmas_day': '12.25', 119 | } 120 | 121 | for (const [key, value] of Object.entries(default_holidays)) { 122 | if (input.get(key).checked().raw()) { 123 | holidays.push(value); 124 | } 125 | } 126 | 127 | return holidays; 128 | } 129 | 130 | function countBusinessAndweekends(startDate, endDate, holidays) { 131 | // Convert the start and end dates to Date objects 132 | startDate = new Date(startDate); 133 | endDate = new Date(endDate); 134 | 135 | // Initialize counters for business days and weekend days 136 | let weekdays = 0; 137 | let weekends = 0; 138 | let holidayCount = 0; 139 | 140 | // Iterate through each day from the start date to the end date 141 | while (startDate < endDate) { 142 | // Check if the current day is a weekend day (0 for Sunday, 6 for Saturday) 143 | const dayOfWeek = startDate.getDay(); 144 | const dateString = (startDate.getMonth() + 1) + '.' + startDate.getDate(); 145 | if (dayOfWeek === 0 || dayOfWeek === 6) { 146 | weekends++; 147 | } else { 148 | weekdays++; 149 | } 150 | 151 | // Check if the current day is a holiday 152 | if (holidays.includes(dateString)) { 153 | weekdays--; // Subtract a business day if it's a holiday 154 | holidayCount++; 155 | } 156 | 157 | // Move to the next day 158 | startDate.setDate(startDate.getDate() + 1); 159 | } 160 | 161 | // If the end date is a weekend day, decrement the respective count 162 | if (endDate.getDay() === 0 || endDate.getDay() === 6) { 163 | weekends--; 164 | } else { 165 | weekdays--; 166 | } 167 | 168 | // Return the counts 169 | return {weekdays, weekends, holidayCount}; 170 | } 171 | 172 | function convert() { 173 | let startDate = input.get('start_date_two').date().raw(); 174 | let years = input.get('years').optional().positive().val(); 175 | let months = input.get('months').optional().positive().val(); 176 | let weeks = input.get('weeks').optional().positive().val(); 177 | let days = input.get('days').optional().positive().val(); 178 | let action = input.get('add_subtract').raw(); 179 | 180 | if (!input.valid()) return; 181 | 182 | const isAdd = action === 'add'; 183 | 184 | let endDate = new Date(startDate); 185 | 186 | if(isAdd) { 187 | if (years) endDate.setFullYear(endDate.getFullYear() + years); 188 | if (months) endDate.setMonth(endDate.getMonth() + months); 189 | if (weeks) endDate.setDate(endDate.getDate() + weeks * 7); 190 | if (days) endDate.setDate(endDate.getDate() + days); 191 | } else { 192 | if (years) endDate.setFullYear(endDate.getFullYear() - years); 193 | if (months) endDate.setMonth(endDate.getMonth() - months); 194 | if (weeks) endDate.setDate(endDate.getDate() - weeks * 7); 195 | if (days) endDate.setDate(endDate.getDate() - days); 196 | } 197 | 198 | generateCalendar(startDate, 'result-age--from-two'); 199 | generateCalendar(endDate, 'result-age--to-two'); 200 | } -------------------------------------------------------------------------------- /assets/js/chart.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | let theme = 'light'; 4 | if (localStorage.getItem('theme') === 'dark' || (localStorage.getItem('theme') === 'system' && window.matchMedia('(prefers-color-scheme: dark)').matches)) theme = 'dark'; 5 | 6 | Chart.defaults.borderColor = '#000'; 7 | 8 | const colors = { 9 | light: { 10 | purple: '#A78BFA', 11 | yellow: '#FBBF24', 12 | sky: '#7DD3FC', 13 | blue: '#1D4ED8', 14 | textColor: '#6B7280', 15 | yellowGradientStart: 'rgba(250, 219, 139, 0.33)', 16 | purpleGradientStart: 'rgba(104, 56, 248, 0.16)', 17 | skyGradientStart: 'rgba(56, 187, 248, 0.16)', 18 | tealGradientStart: 'rgba(56, 248, 222, 0.16)', 19 | yellowGradientStop: 'rgba(250, 219, 139, 0)', 20 | purpleGradientStop: 'rgba(104, 56, 248, 0)', 21 | gridColor: '#DBEAFE', 22 | tooltipBackground: '#fff', 23 | fractionColor: '#EDE9FE', 24 | }, 25 | dark: { 26 | purple: '#7C3AED', 27 | yellow: '#D97706', 28 | sky: '#0284C7', 29 | blue: '#101E47', 30 | textColor: '#fff', 31 | yellowGradientStart: 'rgba(146, 123, 67, 0.23)', 32 | purpleGradientStart: 'rgba(78, 55, 144, 0.11)', 33 | skyGradientStart: 'rgba(56, 187, 248, 0.16)', 34 | tealGradientStart: 'rgba(56, 248, 222, 0.16)', 35 | yellowGradientStop: 'rgba(250, 219, 139, 0)', 36 | purpleGradientStop: 'rgba(104, 56, 248, 0)', 37 | gridColor: '#162B64', 38 | tooltipBackground: '#1C3782', 39 | fractionColor: '#41467D', 40 | }, 41 | }; 42 | 43 | class Custom extends LineController { 44 | draw() { 45 | super.draw(arguments); 46 | 47 | const ctx = this.chart.ctx; 48 | let _stroke = ctx.stroke; 49 | 50 | ctx.stroke = function () { 51 | ctx.save(); 52 | ctx.shadowColor = 'black'; 53 | ctx.shadowBlur = 20; 54 | ctx.shadowOffsetX = 0; 55 | ctx.shadowOffsetY = 20; 56 | _stroke.apply(this, arguments); 57 | ctx.restore(); 58 | }; 59 | } 60 | } 61 | 62 | Custom.id = 'shadowLine'; 63 | Custom.defaults = LineController.defaults; 64 | 65 | Chart.register(Custom); 66 | 67 | let switchTheme = [] 68 | 69 | if (document.getElementById('chartC150')) { 70 | let ctx = document.getElementById('chartC150').getContext('2d'); 71 | 72 | let purpleGradient = ctx.createLinearGradient(0, 0, 2048, 0); 73 | purpleGradient.addColorStop(0, 'rgba(152, 96, 250, 0)'); 74 | purpleGradient.addColorStop(1, 'rgba(152, 96, 250, .8)'); 75 | 76 | const dataCharts = { 77 | labels: [0, 1, 2, 3, 4, 5, 6], 78 | datasets: [ 79 | { 80 | label: 'D1', 81 | data: [{ x: 4, y: 40 }], 82 | backgroundColor: '#7C3AED', 83 | borderWidth: 0, 84 | radius: 6, 85 | hoverRadius: 6, 86 | type: 'scatter', 87 | stacked: true, 88 | order: 0, 89 | }, 90 | { 91 | label: 'D2', 92 | data: [0, 10, 20, 40, 60, 80, 100], 93 | borderColor: colors[theme].purple, 94 | type: 'line', 95 | fill: '-1', 96 | order: 1, 97 | pointHoverRadius: 0, 98 | }, 99 | { 100 | label: 'D3', 101 | data: [0, 5, 5, 15, 25, 35, 45], 102 | borderColor: colors[theme].purple, 103 | backgroundColor: purpleGradient, 104 | type: 'line', 105 | fill: '-1', 106 | order: 1, 107 | pointHoverRadius: 0, 108 | }, 109 | ], 110 | }; 111 | 112 | let chart = new Chart(document.getElementById('chartC150'), { 113 | data: dataCharts, 114 | options: { 115 | stepSize: 1, 116 | response: true, 117 | elements: { 118 | point: { 119 | radius: 0, 120 | }, 121 | }, 122 | plugins: { 123 | legend: { 124 | display: false, 125 | }, 126 | tooltip: false, 127 | }, 128 | interaction: { 129 | mode: 'index', 130 | intersect: false, 131 | }, 132 | scales: { 133 | y: { 134 | max: 100, 135 | grid: { 136 | tickLength: 0, 137 | color: colors[theme].gridColor, 138 | }, 139 | ticks: { 140 | display: false, 141 | stepSize: 25, 142 | }, 143 | border: { 144 | color: colors[theme].gridColor, 145 | }, 146 | }, 147 | x: { 148 | stacked: false, 149 | border: { 150 | color: colors[theme].gridColor, 151 | }, 152 | ticks: { 153 | display: false, 154 | color: colors[theme].gridColor, 155 | stepSize: 1, 156 | }, 157 | grid: { 158 | tickLength: 0, 159 | color: colors[theme].gridColor, 160 | }, 161 | }, 162 | }, 163 | }, 164 | }); 165 | 166 | let switchThemeChartC150 = function(theme) { 167 | let y = chart.config.options.scales.y 168 | let x = chart.config.options.scales.x 169 | let data = chart.config.data 170 | y.grid.color = colors[theme].gridColor; 171 | y.border.color = colors[theme].gridColor; 172 | x.border.color = colors[theme].gridColor; 173 | x.grid.color = colors[theme].gridColor; 174 | x.ticks.color = colors[theme].gridColor; 175 | data.datasets[1].borderColor = colors[theme].purple; 176 | data.datasets[2].borderColor = colors[theme].purple; 177 | chart.update() 178 | } 179 | 180 | switchTheme.push(switchThemeChartC150) 181 | 182 | } -------------------------------------------------------------------------------- /assets/js/datepicker.js: -------------------------------------------------------------------------------- 1 | document.querySelectorAll('.datepicker_us').forEach((datepicker) => { 2 | new AirDatepicker(datepicker, { 3 | dateFormat: 'MM/dd/yyyy', 4 | autoClose: true, 5 | onSelect: function(event){ 6 | return updateDate(event.datepicker.$el); 7 | }, 8 | // visible: true, 9 | prevHtml: 10 | '', 11 | nextHtml: 12 | '', 13 | locale: { 14 | months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'], 15 | monthsShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], 16 | days: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], 17 | daysShort: ['S', 'M', 'T', 'W', 'T', 'F', 'S'], 18 | daysMin: ['S', 'M', 'T', 'W', 'T', 'F', 'S'], 19 | }, 20 | }); 21 | }); 22 | 23 | document.querySelectorAll('.datepicker').forEach((datepicker) => { 24 | new AirDatepicker(datepicker, { 25 | dateFormat: 'yyyy-MM-dd', 26 | autoClose: true, 27 | onSelect: function(event){ 28 | return updateDate(event.datepicker.$el); 29 | }, 30 | // visible: true, 31 | prevHtml: 32 | '', 33 | nextHtml: 34 | '', 35 | locale: { 36 | months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'], 37 | monthsShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], 38 | days: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], 39 | daysShort: ['S', 'M', 'T', 'W', 'T', 'F', 'S'], 40 | daysMin: ['S', 'M', 'T', 'W', 'T', 'F', 'S'], 41 | }, 42 | }); 43 | }); -------------------------------------------------------------------------------- /assets/js/dialog-table.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | $$('.result-table__dialog').forEach(element => { 4 | const ELEMENT_OPEN = element.querySelector('.result-table__open'); 5 | ELEMENT_OPEN.addEventListener('click', () => { 6 | element.classList.toggle('result-table__dialog--active'); 7 | }) 8 | }) -------------------------------------------------------------------------------- /assets/js/dropdown-icon.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const setSelect = (list, index) => { 4 | list.forEach(item => { 5 | item.classList.remove('dropdown-select--selected') 6 | }) 7 | list[index].classList.add('dropdown-select--selected') 8 | } 9 | 10 | const setValue = (input, value, index) => { 11 | if(index !== undefined) { 12 | setTab(index) 13 | } 14 | input.innerHTML = value 15 | } 16 | 17 | const setTab = (index) => { 18 | document.querySelectorAll(`[data-tab]`)?.forEach(element => { 19 | if(element.getAttribute('data-tab') == index) { 20 | element.classList.add('tab--active'); 21 | } else { 22 | element.classList.remove('tab--active'); 23 | element.classList.remove('tab--active') 24 | } 25 | }) 26 | } 27 | 28 | const DROPDOWN_WRAPPER = document.querySelectorAll('.dropdown-wrapper') 29 | 30 | 31 | DROPDOWN_WRAPPER.forEach(wrapper => { 32 | // CLOSE DROPDOWN WHEN CLICK OUTSIDE 33 | window.addEventListener('click', (e) => { 34 | if(!(e.composedPath().includes(wrapper))) { 35 | wrapper.classList.remove('dropdown-wrapper--active') 36 | } 37 | }) 38 | 39 | const DROPDOWN_FIELD = wrapper.querySelector('.input-field') 40 | const DROPDOWN_VALUE = wrapper.querySelector('.input-field__text') 41 | const DROPDOWN_SELECTS = wrapper.querySelectorAll('.dropdown-select') 42 | // DEFAULT TAB 43 | setTab(0) 44 | 45 | // OPEN DROPDOWN WHEN CLICK ON INPUT 46 | DROPDOWN_FIELD.addEventListener('click', () => { 47 | // CLOSE OTHERS DROPDOWN 48 | if(!wrapper.classList.contains('dropdown-wrapper--active')) { 49 | DROPDOWN_WRAPPER.forEach(wrapper => {wrapper.classList.remove('dropdown-wrapper--active')}) 50 | } 51 | // OPEN THIS DROPDOWN 52 | wrapper.classList.toggle('dropdown-wrapper--active') 53 | }) 54 | 55 | // SET EVENT LISTENERS FOR SELECT 56 | DROPDOWN_SELECTS.forEach((select, index) => { 57 | const SELECT_VALUE = select.innerHTML 58 | select.addEventListener('click', () => { 59 | wrapper.classList.remove('dropdown-wrapper--active') 60 | 61 | // SET SELECT FOR DROPDOWN 62 | setSelect(DROPDOWN_SELECTS, index) 63 | 64 | // SET VALUE FOR DROPDOWN 65 | if(select.classList.contains('dropdown-select--tab')) { 66 | // IF DROPDOWN IS DROPDOWN TAB : example due-date-calculator dropdown "Calculate based on" 67 | setValue(DROPDOWN_VALUE,SELECT_VALUE, index) 68 | } else { 69 | setValue(DROPDOWN_VALUE,SELECT_VALUE) 70 | } 71 | }) 72 | }) 73 | }) -------------------------------------------------------------------------------- /assets/js/fractions.js: -------------------------------------------------------------------------------- 1 | const Fractions = { 2 | // helpers 3 | isCorrectMixed(whole, num, denom){ 4 | return !(!whole && !num && !denom || !num && denom || num && !denom); 5 | }, 6 | buildFrac(whole, num, denom){ 7 | whole = Number(whole); 8 | num = Number(num); 9 | denom = Number(denom); 10 | return num && denom ? 11 | math.fraction( 12 | (math.sign(whole) || 1) * (math.sign(num) || 1) * (math.sign(denom) || 1) * 13 | (math.abs(whole) * math.abs(denom) + math.abs(num)), math.abs(denom) 14 | ) : 15 | math.fraction(whole, 1) 16 | ; 17 | }, 18 | getFracPart(frac){ 19 | return frac.d != 1 ? { 20 | num: frac.n % frac.d, denom: frac.d, 21 | } : ''; 22 | }, 23 | getWholePart(frac){ 24 | const sign = frac.s == -1 ? '-' : ''; 25 | const wholePart = (frac.n - frac.n % frac.d) / frac.d; 26 | if(wholePart == 0 && this.getFracPart(frac)) return sign; 27 | return sign + wholePart; 28 | }, 29 | getChartData(frac){ 30 | const fracPart = this.getFracPart(frac); 31 | const wholePart = this.getWholePart(frac); 32 | return fracPart ? [fracPart.num, fracPart.denom-fracPart.num] : (wholePart == 0 ? [0,1]:[1,0]); 33 | }, 34 | outputFrac(frac, prefix){ 35 | const isWhole = frac.d == 1; 36 | const sign = frac.s == -1 ? '-' : ''; 37 | _(prefix+'Whole').classList[!isWhole && !sign ? 'add':'remove']('hidden'); 38 | _(prefix+'Whole').innerText = sign + (isWhole ? frac.n : ''); 39 | _(prefix+'Frac').classList[isWhole?'add':'remove']('hidden'); 40 | _(prefix+'Num').innerText = frac.n; 41 | _(prefix+'Denom').innerText = frac.d; 42 | }, 43 | outputMixed(frac, prefix){ 44 | const fracPart = this.getFracPart(frac); 45 | const wholePart = this.getWholePart(frac); 46 | _(prefix+'Whole').classList[!wholePart?'add':'remove']('hidden'); 47 | _(prefix+'Whole').innerText = wholePart; 48 | _(prefix+'Frac').classList[!fracPart?'add':'remove']('hidden'); 49 | _(prefix+'Num').innerText = fracPart.num; 50 | _(prefix+'Denom').innerText = fracPart.denom; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /assets/js/functions.js: -------------------------------------------------------------------------------- 1 | window.log = console.log; 2 | 3 | window.setValue = function (inputId, value, index){ 4 | _(inputId).value = value; 5 | _(inputId).index = index; 6 | } 7 | 8 | window.switcher = function(button, id, action) { 9 | $('#' + id).value = button.value; 10 | $('#' + id).onchange && $('#' + id).onchange(button.value); 11 | $('#' + id + '-a')?.classList.remove("button-switcher--active"); 12 | $('#' + id + '-b')?.classList.remove("button-switcher--active"); 13 | $('#' + id + '-c')?.classList.remove("button-switcher--active"); 14 | $('#' + id + '-d')?.classList.remove("button-switcher--active"); 15 | $('#' + id + '-e')?.classList.remove("button-switcher--active"); 16 | button.classList.add("button-switcher--active"); 17 | toggleRelatedInputs(button, id, action); 18 | } 19 | 20 | window.toggleRelatedInputs = function(element, id, action){ 21 | element = element instanceof Event ? element.target : element 22 | id = id ?? element.id; 23 | let value = element.value; 24 | if(element.type == 'select-one') value = element.selectedIndex; 25 | $$('.' + id).forEach(element => { 26 | if(action === "disabled") { 27 | element.classList.remove("disabled"); 28 | } else if (action === "finding") { 29 | element.classList.remove("disabled"); 30 | if(element.querySelector('.input-field__input').value === "???") { 31 | element.querySelector('.input-field__input').value = "" 32 | } 33 | } else { 34 | element.classList.add("related-item-hidden"); 35 | } 36 | }); 37 | $$('.related-to-' + id + '-' + value)?.forEach(element => { 38 | if(action === "disabled") { 39 | element.classList.add("disabled"); 40 | } else if (action === "finding") { 41 | element.querySelector('.input-field__input').value = "???" 42 | element.classList.add("disabled"); 43 | } else { 44 | element.classList.remove("related-item-hidden"); 45 | } 46 | }); 47 | } 48 | 49 | window.switch_data_tab = function(owner, index, value){ 50 | $$('[data-tab]')?.forEach(element => { 51 | if(element.getAttribute('data-tab') == index) { 52 | element.classList.add('tab--active'); 53 | owner.classList.add('tab--active'); 54 | } else { 55 | element.classList.remove('tab--active'); 56 | } 57 | }); 58 | } 59 | 60 | window.isMetricSystem = function() { 61 | return $('.system-switcher').classList.contains('system-switcher--active'); 62 | } 63 | 64 | window.setSystem = function(system) { 65 | const add = (system == "metric" ? ".imperial-system-item" : ".metric-system-item"); 66 | $$(".system-item-hidden").forEach(element => { 67 | element.classList.remove("system-item-hidden"); 68 | }); 69 | $$(add).forEach(element => { 70 | element.classList.add("system-item-hidden"); 71 | }); 72 | localStorage.setItem("system", system); 73 | } 74 | 75 | window.toggleSystem = function(button) { 76 | button.classList.toggle('system-switcher--active'); 77 | if(button.classList.contains('system-switcher--active')) { 78 | return setSystem('metric'); 79 | } 80 | return setSystem('imperial'); 81 | } 82 | 83 | window.isHidden = function(element) { 84 | const styles = window.getComputedStyle(element); 85 | return styles.display === 'none' || styles.visibility === 'hidden'; 86 | } 87 | 88 | window.output = { 89 | value: null, 90 | val: function(value){ 91 | this.value = value; 92 | return this; 93 | }, 94 | replace: function(search, replacement) { 95 | this.value = this.value.replace(search, replacement); 96 | return this; 97 | }, 98 | set: function(elementId){ 99 | _(elementId).innerHTML = this.value; 100 | return this; 101 | } 102 | }; 103 | 104 | // check erroneous result of expression (or if it's not string - check itself) 105 | // usefull in cases when erroneous values of input fields are unknown 106 | window.calc = (expression,scope,resultType) => { 107 | let result = expression; 108 | scope = scope || {}; 109 | if(typeof expression == 'string'){ 110 | result = math.evaluate(expression,scope); // can throw error as well 111 | } 112 | let valid = true; 113 | switch(resultType){ 114 | case 'positive': valid = result > 0; 115 | } 116 | if(isNaN(result)||result.im||!valid) { 117 | const args = Object.keys(scope).map(arg=>arg+'='+scope[arg]); 118 | throw new Error( 119 | `result of expression ${expression} is ${result}.` 120 | + (resultType ? `
Should be ${resultType}.`:'') 121 | + (args.length != 0 ? `
Args: ${args.join(', ')}.`:'') 122 | ); 123 | } 124 | return result; 125 | }; 126 | 127 | // allows to show accurate results with fixed precision/length (instead of using BigNumber) 128 | window.format = number => math.format(number,{precision:7}) 129 | 130 | window.input = { 131 | box: $('#error-box'), 132 | list: $('#error-list'), 133 | value: null, 134 | elementId: null, 135 | shown: false, 136 | processed: false, 137 | silent: false, 138 | reset: function(){ 139 | this.shown = false; 140 | this.box.classList.remove('calculator-result--error-active'); 141 | $$('.input-field--error')?.forEach(el => el.classList.remove('input-field--error')) 142 | $$('.calculator-result:not(.calculator-result--error)').forEach(el => el.classList.remove('calculator-result--hidden')) 143 | }, 144 | error: function (inputId, message = `Incorrect value for "${inputId}"`, last = false) { 145 | if(this.silent) return; 146 | if(this.processed) this.reset(); 147 | if(!Array.isArray(inputId)) inputId = [inputId]; 148 | for(const inputIdItem of inputId) _(inputIdItem).parentNode.classList.add('input-field--error'); 149 | if(!this.shown){ 150 | this.processed = false; 151 | this.shown = true; 152 | this.list.innerHTML = ''; 153 | this.box.classList.add('calculator-result--error-active'); 154 | $$('.calculator-result:not(.calculator-result--error)').forEach(el => el.classList.add('calculator-result--hidden')) 155 | } 156 | const element = document.createElement('p'); 157 | element.classList.add('calculator-error__item'); 158 | element.innerHTML = message; 159 | this.list.append(element); 160 | if(last) this.processed = true; 161 | }, 162 | // sometimes it's complicated to check input values 163 | // so we're checking `calc` result for an erroneous result, show exception and return 164 | // e.g.: try{calc(...);}catch(e){input.exception(field{s},e);return;} 165 | exception(inputId, message){ 166 | if(typeof message != 'string'){ 167 | let error = ''; 168 | if(message instanceof Error){ 169 | error = message.toString(); 170 | } 171 | // default message 172 | if(Array.isArray(inputId) && inputId.length == 0){ 173 | message = `${error}`; 174 | } else { 175 | message = `Value${Array.isArray(inputId)?'s':` "${this.get(inputId).value}"`} of "${inputId}" ${Array.isArray(inputId)?'are':'is'} invalid.
${error}`; 176 | } 177 | } 178 | return this.error(inputId, message, true); 179 | }, 180 | valid: function(){ 181 | if(!this.shown || this.processed) this.reset(); 182 | this.processed = true; 183 | this.silent = false; 184 | return !this.shown; 185 | }, 186 | get: function(elementId){ 187 | this.elementId = elementId; 188 | let element = _(elementId); 189 | this.silent = false; 190 | if(element == null){ 191 | this.value = null; 192 | } else { 193 | this.value = element.value; 194 | for (; element && element !== document; element = element.parentNode ) { 195 | if(element.classList.contains('related-item-hidden')) this.silent = true; 196 | } 197 | } 198 | return this; 199 | }, 200 | index: function(){ 201 | this.value = _(this.elementId).selectedIndex; 202 | return this; 203 | }, 204 | checked: function(elementId){ 205 | this.value = _(this.elementId).checked; 206 | return this; 207 | }, 208 | split: function(separator){ 209 | this.value = this.value.split(separator); 210 | return this; 211 | }, 212 | replace: function(pattern, replacement){ 213 | this.value = this.value.replace(pattern, replacement); 214 | return this; 215 | }, 216 | default: function(value){ 217 | if(!this.value) this.value = value; 218 | return this; 219 | }, 220 | optional: function(value){ 221 | if(!this.value) this.silent = true; 222 | return this; 223 | }, 224 | gt: function(compare = 0, errorText = `The ${this.elementId} must be greater than ${compare}.`){ 225 | if (this.value instanceof Date) { 226 | compare = compare instanceof Date ? compare : new Date(_(compare).value); 227 | if (this.value.getTime() <= compare.getTime()) this.error(this.elementId, errorText); 228 | } else { 229 | compare = isNaN(compare) ? Number(_(compare).value) : compare; 230 | if(this.value === '' || isNaN(Number(this.value))) 231 | this.error(this.elementId, `The ${this.elementId} must be a number.`); 232 | else 233 | if (Number(this.value) <= compare) this.error(this.elementId, errorText); 234 | } 235 | return this; 236 | }, 237 | gte: function(compare = 0, errorText = `The ${this.elementId} must be greater than or equal to ${compare}.`){ 238 | if (this.value instanceof Date) { 239 | compare = compare instanceof Date ? compare : new Date(_(compare).value); 240 | if (this.value.getTime() < compare.getTime()) this.error(this.elementId, errorText); 241 | } else { 242 | compare = isNaN(compare) ? Number(_(compare).value) : compare; 243 | if(this.value === '' || isNaN(Number(this.value))) 244 | this.error(this.elementId, `The ${this.elementId} must be a number.`); 245 | else 246 | if (Number(this.value) < compare) this.error(this.elementId, errorText); 247 | } 248 | return this; 249 | }, 250 | lt: function(compare = 0, errorText = `The ${this.elementId} must be less than ${compare}.`){ 251 | if (this.value instanceof Date) { 252 | compare = compare instanceof Date ? compare : new Date(_(compare).value); 253 | if (this.value.getTime() >= compare.getTime()) this.error(this.elementId, errorText); 254 | } else { 255 | compare = isNaN(compare) ? Number(_(compare).value) : compare; 256 | if(this.value === '' || isNaN(Number(this.value))) 257 | this.error(this.elementId, `The ${this.elementId} must be a number.`); 258 | else 259 | if (Number(this.value) >= compare) this.error(this.elementId, errorText); 260 | } 261 | return this; 262 | }, 263 | lte: function(compare = 0, errorText = `The ${this.elementId} must be less than or equal to ${compare}.`){ 264 | if (this.value instanceof Date) { 265 | compare = compare instanceof Date ? compare : new Date(_(compare).value); 266 | if (this.value.getTime() > compare.getTime()) this.error(this.elementId, errorText); 267 | } else { 268 | compare = isNaN(compare) ? Number(_(compare).value) : compare; 269 | if(this.value === '' || isNaN(Number(this.value))) 270 | this.error(this.elementId, `The ${this.elementId} must be a number.`); 271 | else 272 | if (Number(this.value) > compare) this.error(this.elementId, errorText); 273 | } 274 | return this; 275 | }, 276 | integer: function(errorText = `The ${this.elementId} must be integer number (-3, -2, -1, 0, 1, 2, 3, ...).`){ 277 | if (!this.value.match(/^-?(0|[1-9]\d*)$/)) this.error(this.elementId, errorText); 278 | return this; 279 | }, 280 | _naturalRegexp: /^([1-9]\d*)$/, 281 | natural: function(errorText = `The ${this.elementId} must be a natural number (1, 2, 3, ...).`){ 282 | if (!this.value.match(this._naturalRegexp)) this.error(this.elementId, errorText); 283 | return this; 284 | }, 285 | natural_numbers: function(errorText = `The ${this.elementId} must be a set of natural numbers (1, 2, 3, ...).`){ 286 | this.split(/[ ,]+/); 287 | if (!this.value.every(value=>value.match(this._naturalRegexp))) this.error(this.elementId, errorText); 288 | return this; 289 | }, 290 | _mixedRegexp: /^(0|-?[1-9]\d*|-?[1-9]\d*\/[1-9]\d*|-?[1-9]\d*\s[1-9]\d*\/[1-9]\d*)$/, 291 | mixed: function(errorText = `The ${this.elementId} must be an integer/fraction/mixed number (1, 2/3, 4 5/6, ...).`){ 292 | if (!this.value.match(this._mixedRegexp)) this.error(this.elementId, errorText); 293 | return this; 294 | }, 295 | mixed_numbers: function(errorText = `The ${this.elementId} must be a set of integer/fraction/mixed numbers (1, 2/3, 4 5/6, ...).`){ 296 | this.split(/,\s*/); 297 | if (!this.value.every(value=>value.match(this._mixedRegexp))) this.error(this.elementId, errorText); 298 | return this; 299 | }, 300 | number: function(errorText = `The "${this.elementId}" must be a number.`){ 301 | if(this.value === '' || isNaN(Number(this.value))) this.error(this.elementId, errorText); 302 | return this; 303 | }, 304 | probability: function(errorText = `The "${this.elementId}" must be a number between 0 and 1.`){ 305 | if(this.value === '' || isNaN(Number(this.value)) || Number(this.value) < 0 || Number(this.value) > 1) 306 | this.error(this.elementId, errorText); 307 | return this; 308 | }, 309 | percentage: function(errorText = `The "${this.elementId}" must be a number between 0 and 100.`){ 310 | if(this.value === '' || isNaN(Number(this.value)) || Number(this.value) < 0 || Number(this.value) > 100) 311 | this.error(this.elementId, errorText); 312 | return this; 313 | }, 314 | numbers: function(errorText = `The ${this.elementId} must be a set of numbers.`){ 315 | if (this.value.filter(value => isNaN(Number(value))).length) this.error(this.elementId, errorText); 316 | return this; 317 | }, 318 | whole: function(errorText = `The ${this.elementId} must be a whole number.`){ 319 | if (!this.value.match(/^(0|[1-9]\d*)$/)) this.error(this.elementId, errorText); 320 | return this; 321 | }, 322 | positive: function(errorText = `The ${this.elementId} must be greater than 0.`){ 323 | this.gt(0, errorText); 324 | return this; 325 | }, 326 | nonZero: function(errorText = `The ${this.elementId} must be non-zero.`){ 327 | if(this.value === '' || isNaN(Number(this.value))) 328 | this.error(this.elementId, `The ${this.elementId} must be a number.`); 329 | else 330 | if(Number(this.value) == 0) this.error(this.elementId, errorText); 331 | return this; 332 | }, 333 | nonNegative: function(errorText = `The ${this.elementId} must be greater than or equal to 0.`){ 334 | this.gte(0, errorText); 335 | return this; 336 | }, 337 | negative: function(errorText = `The ${this.elementId} must be less than 0.`){ 338 | this.lt(0, errorText); 339 | return this; 340 | }, 341 | scientific: function(errorText = `The ${this.elementId} must be in scientific notation.`){ 342 | if (!this.value.match(/^(-|\+)?((0|[1-9]\d*)(\.\d*)?|(\.\d+))((e|\s?(\*|x)\s?10\^)(-|\+)?(0|[1-9]\d*))?$/i)) this.error(this.elementId, errorText); 343 | return this; 344 | }, 345 | periodic: function(errorText = `The ${this.elementId} must be regular or periodic number.`){ 346 | if (this.value === '' || isNaN(Number(this.value)) && !this.value.match(/\.\d*\(\d+\)$/)) this.error(this.elementId, errorText); 347 | return this; 348 | }, 349 | time: function(format = 'hh:mm:ss', errorText = `The ${this.elementId} must be in format ${format}.`){ 350 | let regex = new RegExp("^" + format.replace(/[\:\-\/\\]/g, '\\$&').replace(/h|m|s/g, '\\d') + "$"); 351 | if (!this.value.match(regex) || isNaN(this.value = new Date(`1900-01-01 ${this.value}`))) this.error(this.elementId, errorText); 352 | return this; 353 | }, 354 | date: function(format = 'yyyy-mm-dd', errorText = `The ${this.elementId} is required field.`){ 355 | let regex = new RegExp("^" + format.replace(/[\:\-\/\\]/g, '\\$&').replace(/y|m|d|h|s/g, '\\d') + "$"); 356 | if (!this.value.match(regex) || isNaN(this.value = new Date(this.value))) this.error(this.elementId, errorText); 357 | this.value = convertTZ(this.value, "UTC"); 358 | return this; 359 | }, 360 | bool: function(){ 361 | return !!this.value; 362 | }, 363 | val: function(){ 364 | if(this.value === '' || this.value === null) return null; 365 | return Number(this.value); 366 | }, 367 | vals: function(){ 368 | return this.value.map(value => Number(value)); 369 | }, 370 | raw: function(){ 371 | return this.value; 372 | }, 373 | group(name,ids){ 374 | const result = ids.split('|') 375 | .reduce((result,ids)=>{ 376 | const obj = ids.split('.').every(id=>_(name+id.match(/^[_a-zA-Z]+/)[0]).value) ? 377 | ids.split('.').reduce((obj,id)=>{ 378 | let type = 'number'; 379 | let getter = 'val'; 380 | switch((id.match(/[^_a-zA-Z]+$/)||[])[0]){ 381 | case '+': type = 'positive'; break; 382 | case '!0': type = 'nonZero'; break; 383 | case '#': getter = 'raw'; break; 384 | default: /* custom modificator */; break; 385 | } 386 | id = id.match(/^[_a-zA-Z]+/)[0]; 387 | return {...obj, ...{ 388 | [id]: input.get(name+id)[type]()[getter]() 389 | }}; 390 | }, {}) : null; 391 | if(!result && !obj) return null; 392 | return {...result,...obj}; 393 | }, null); 394 | return result; 395 | }, 396 | } 397 | 398 | window.sysnumconv = function(element){ 399 | const id = element.dataset.target; 400 | const metric = _(id); 401 | const imperial = _(id + "_imperial"); 402 | if(window.isMetricSystem()){ 403 | let value = metric.value; 404 | imperial.value = eval(imperial.dataset.formula).toFixed(2); 405 | } else { 406 | let value = imperial.value; 407 | metric.value = eval(metric.dataset.formula).toFixed(2); 408 | } 409 | }; 410 | 411 | window.updateHeight = function(element){ 412 | var id = element.dataset.target; 413 | var cm = _(id); 414 | var feet = _(id + "_ft"); 415 | var inches = _(id + "_in"); 416 | if(window.isMetricSystem()){ 417 | feet.value = Math.floor(cm.value * 0.393701 / 12); 418 | inches.value = (cm.value * 0.393701 % 12).toFixed(2); 419 | } else { 420 | cm.value = ((feet.value * 30.48) + (inches.value * 2.54)).toFixed(2); 421 | } 422 | }; 423 | 424 | window.setDate = function (id, suffix) { 425 | var date = new Date(); 426 | var date_m = _(id); 427 | var date_us = _(id + "_us"); 428 | date.setDate(date.getDate() + suffix); 429 | date_us.value = ("0" + (date.getMonth() + 1)).slice(-2) + '/' + ("0" + date.getDate()).slice(-2) + '/' + date.getFullYear(); 430 | date_m.value = date.getFullYear() + '-' + ("0" + (date.getMonth() + 1)).slice(-2) + '-' + ("0" + date.getDate()).slice(-2); 431 | } 432 | 433 | window.updateDate = function(element){ 434 | var id = element.dataset.target; 435 | var date_m = _(id); 436 | var date_us = _(id + "_us"); 437 | if(window.isMetricSystem()){ 438 | let date = new Date(Date.parse(date_m.value)); 439 | date_us.value = ("0" + (date.getMonth() + 1)).slice(-2) + '/' + ("0" + date.getDate()).slice(-2) + '/' + date.getFullYear(); 440 | } else { 441 | let date = new Date(Date.parse(date_us.value)); 442 | date_m.value = date.getFullYear() + '-' + ("0" + (date.getMonth() + 1)).slice(-2) + '-' + ("0" + date.getDate()).slice(-2); 443 | } 444 | }; 445 | 446 | window.switchTab = function (event, index) { 447 | if(index !== undefined && index !== null) { 448 | if(event.target.classList.contains('tab-item')) { 449 | $$(`.${event.target.classList[0]}`).forEach((tab, i) => { 450 | if(index === i) { 451 | tab.classList.add('tab-item--active') 452 | } else { 453 | tab.classList.remove('tab-item--active') 454 | } 455 | }) 456 | } 457 | } 458 | $$(`[data-tab]`).forEach(element => { 459 | if(element.dataset.tab == event.selectedIndex || element.dataset.tab == index) { 460 | element.classList.add('tab--active') 461 | } else { 462 | element.classList.remove('tab--active') 463 | } 464 | }) 465 | } 466 | 467 | window.setMaxLength = function(element, maxLength) { 468 | if(getComputedStyle(element).getPropertyValue('--fontStep') !== '') { 469 | element.style = `--maxWidth: ${Number(getComputedStyle(element).getPropertyValue('--fontStep').replace(/px/gi, '')) * (element.value.length === 0 ? 1 : element.value.length > maxLength ? maxLength : element.value.length) }px` 470 | } 471 | if(element.value.length > maxLength) { 472 | element.value = element.value.substring(0, maxLength); 473 | } 474 | } 475 | 476 | window.relatedToggle = function(element, related, action) { 477 | if(action === "disabled") { 478 | if(element.target.checked) { 479 | $$(`.related-to-${related}`)?.forEach(el => el.classList.remove('disabled')) 480 | } else { 481 | $$(`.related-to-${related}`)?.forEach(el => el.classList.add('disabled')) 482 | } 483 | } else { 484 | if(element.target.checked) { 485 | $$(`.related-to-${related}-a`)?.forEach(el => el.classList.add('related-item-hidden')) 486 | $$(`.related-to-${related}-b`)?.forEach(el => el.classList.remove('related-item-hidden')) 487 | } else { 488 | $$(`.related-to-${related}-a`)?.forEach(el => el.classList.remove('related-item-hidden')) 489 | $$(`.related-to-${related}-b`)?.forEach(el => el.classList.add('related-item-hidden')) 490 | } 491 | } 492 | } 493 | 494 | window.roundTo = function (num, decimals = 5) { 495 | if (typeof num !== 'number' || !isFinite(num)) return num; 496 | if (num.toString().includes('e')) { 497 | const splitted = num.toString().split('e'); 498 | return roundTo(+splitted[0], decimals) + `e${splitted[1]}`; 499 | }; 500 | return +(Math.round(num + `e+${decimals}`) + `e-${decimals}`); 501 | } 502 | 503 | window.delay = ms => new Promise(resolve => setTimeout(resolve, ms)); 504 | window.generateRandomDigit = () => Math.floor(Math.random() * 10); 505 | window.convertTZ = (date, tzString) => new Date((typeof date === "string" ? new Date(date) : date).toLocaleString("en-US", {timeZone: tzString})); 506 | window.animateElement = async (element, isText) => { 507 | const originalText = element.innerHTML; 508 | let digitIndices = []; 509 | let originalDigits = []; 510 | 511 | [...originalText].forEach((char, index) => { 512 | if (!isNaN(parseInt(char, 10)) && char !== ' ') { 513 | digitIndices.push(index); 514 | originalDigits.push(char); 515 | } 516 | }); 517 | 518 | for (let i = 0; i < 10; i++) { 519 | let textArray = [...originalText]; 520 | digitIndices.forEach(index => { 521 | textArray[index] = generateRandomDigit(); 522 | }); 523 | element.innerHTML = textArray.join(''); 524 | await delay(30); 525 | } 526 | 527 | digitIndices.forEach((index, digitIndex) => { 528 | let textArray = [...originalText]; 529 | textArray[index] = originalDigits[digitIndex]; 530 | element.innerHTML = textArray.join(''); 531 | }); 532 | }; 533 | window.animateElements = function(){ 534 | $$('.animate').forEach(async (element) => animateElement(element)); 535 | $$('.animate-text').forEach(async (element) => animateElement(element, true)); 536 | } 537 | window.plural = function (number, versions, options = { showNumber: true, localize: true, locale: null }) { 538 | const words = { 539 | zero: "", 540 | one: "", 541 | two: "", 542 | few: "", 543 | many: "", 544 | other: "" 545 | }; 546 | const parts = versions.split(':'); 547 | if (parts.length === 1) { 548 | Object.keys(words).forEach(key => words[key] = versions); 549 | } else { 550 | let i = 0; 551 | for (let key in words) { 552 | words[key] = parts[i] || parts[0]; 553 | i++; 554 | } 555 | } 556 | const rule = new Intl.PluralRules(options.locale ?? window.locale).select(Math.floor(number)); 557 | return `${options.showNumber ? `${options.localize ? number.toLocaleString(options.locale ?? window.locale) : number} ` : ''}${words[rule]}`; 558 | }; 559 | 560 | window.numberToWords = function(num) { 561 | if (num === 0) return 'zero'; 562 | const belowTwenty = [ 563 | '', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 564 | 'ten', 'eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen', 565 | 'sixteen', 'seventeen', 'eighteen', 'nineteen']; 566 | 567 | const tens = ['', '', 'twenty', 'thirty', 'forty', 'fifty', 'sixty', 'seventy', 'eighty', 'ninety']; 568 | 569 | const hundreds = [ 570 | '', 'one hundred', 'two hundred', 'three hundred', 'four hundred', 'five hundred', 571 | 'six hundred', 'seven hundred', 'eight hundred', 'nine hundred']; 572 | 573 | const integerScales = [ 574 | 'thousands:thousand:thousands:thousands:thousands:thousands', 'millions:million:millions:millions:millions:millions', 'billions:billion:billions:billions:billions:billions', 'trillions:trillion:trillions:trillions:trillions:trillions', 'quadrillions:quadrillion:quadrillions:quadrillions:quadrillions:quadrillions', 575 | 'quintillions:quintillion:quintillions:quintillions:quintillions:quintillions', 'sextillions:sextillion:sextillions:sextillions:sextillions:sextillions', 'septillions:septillion:septillions:septillions:septillions:septillions', 'octillions:octillion:octillions:octillions:octillions:octillions', 'nonillions:nonillion:nonillions:nonillions:nonillions:nonillions', 576 | 'decillions:decillion:decillions:decillions:decillions:decillions', 'undecillions:undecillion:undecillions:undecillions:undecillions:undecillions', 'duodecillions:duodecillion:duodecillions:duodecillions:duodecillions:duodecillions', 'tredecillions:tredecillion:tredecillions:tredecillions:tredecillions:tredecillions', 'quattuordecillions:quattuordecillion:quattuordecillions:quattuordecillions:quattuordecillions:quattuordecillions', 577 | 'quindecillions:quindecillion:quindecillions:quindecillions:quindecillions:quindecillions', 'sexdecillions:sexdecillion:sexdecillions:sexdecillions:sexdecillions:sexdecillions', 'septendecillions:septendecillion:septendecillions:septendecillions:septendecillions:septendecillions', 'octodecillions:octodecillion:octodecillions:octodecillions:octodecillions:octodecillions', 578 | 'novemdecillions:novemdecillion:novemdecillions:novemdecillions:novemdecillions:novemdecillions', 'vigintillions:vigintillion:vigintillions:vigintillions:vigintillions:vigintillions']; 579 | 580 | const decimalScales = [ 581 | 'tenths:tenth:tenths:tenths:tenths:tenths', 'hundredths:hundredth:hundredths:hundredths:hundredths:hundredths', 'thousandths:thousandth:thousandths:thousandths:thousandths:thousandths', 'ten-thousandths:ten-thousandth:ten-thousandths:ten-thousandths:ten-thousandths:ten-thousandths', 'hundred-thousandths:hundred-thousandth:hundred-thousandths:hundred-thousandths:hundred-thousandths:hundred-thousandths', 'millionths:millionth:millionths:millionths:millionths:millionths', 582 | 'ten-millionths:ten-millionth:ten-millionths:ten-millionths:ten-millionths:ten-millionths', 'hundred-millionths:hundred-millionth:hundred-millionths:hundred-millionths:hundred-millionths:hundred-millionths', 'billionths:billionth:billionths:billionths:billionths:billionths', 'ten-billionths:ten-billionth:ten-billionths:ten-billionths:ten-billionths:ten-billionths', 'hundred-billionths:hundred-billionth:hundred-billionths:hundred-billionths:hundred-billionths:hundred-billionths', 583 | 'trillionths:trillionth:trillionths:trillionths:trillionths:trillionths', 'ten-trillionths:ten-trillionth:ten-trillionths:ten-trillionths:ten-trillionths:ten-trillionths', 'hundred-trillionths:hundred-trillionth:hundred-trillionths:hundred-trillionths:hundred-trillionths:hundred-trillionths', 'quadrillionths:quadrillionth:quadrillionths:quadrillionths:quadrillionths:quadrillionths', 'ten-quadrillionths:ten-quadrillionth:ten-quadrillionths:ten-quadrillionths:ten-quadrillionths:ten-quadrillionths', 584 | 'hundred-quadrillionths:hundred-quadrillionth:hundred-quadrillionths:hundred-quadrillionths:hundred-quadrillionths:hundred-quadrillionths', 'quintillionths:quintillionth:quintillionths:quintillionths:quintillionths:quintillionths', 'ten-quintillionths:ten-quintillionth:ten-quintillionths:ten-quintillionths:ten-quintillionths:ten-quintillionths', 'hundred-quintillionths:hundred-quintillionth:hundred-quintillionths:hundred-quintillionths:hundred-quintillionths:hundred-quintillionths', 585 | 'sextillionths:sextillionth:sextillionths:sextillionths:sextillionths:sextillionths', 'septillionths:septillionth:septillionths:septillionths:septillionths:septillionths', 'octillionths:octillionth:octillionths:octillionths:octillionths:octillionths', 'nonillionths:nonillionth:nonillionths:nonillionths:nonillionths:nonillionths', 'decillionths:decillionth:decillionths:decillionths:decillionths:decillionths', 586 | 'undecillionths:undecillionth:undecillionths:undecillionths:undecillionths:undecillionths', 'duodecillionths:duodecillionth:duodecillionths:duodecillionths:duodecillionths:duodecillionths', 'tredecillionths:tredecillionth:tredecillionths:tredecillionths:tredecillionths:tredecillionths', 'quattuordecillionths:quattuordecillionth:quattuordecillionths:quattuordecillionths:quattuordecillionths:quattuordecillionths', 'quindecillionths:quindecillionth:quindecillionths:quindecillionths:quindecillionths:quindecillionths', 587 | 'sexdecillionths:sexdecillionth:sexdecillionths:sexdecillionths:sexdecillionths:sexdecillionths', 'septendecillionths:septendecillionth:septendecillionths:septendecillionths:septendecillionths:septendecillionths', 'octodecillionths:octodecillionth:octodecillionths:octodecillionths:octodecillionths:octodecillionths', 'novemdecillionths:novemdecillionth:novemdecillionths:novemdecillionths:novemdecillionths:novemdecillionths', 'vigintillionths:vigintillionth:vigintillionths:vigintillionths:vigintillionths:vigintillionths']; 588 | 589 | let chunks = []; 590 | let currentNum = BigInt(Math.floor(num)); 591 | 592 | while (currentNum > 0n) { 593 | chunks.unshift(currentNum % 1000n); 594 | currentNum = currentNum / 1000n; 595 | } 596 | 597 | if (chunks.length === 0) chunks.push(0n); // Handle numbers less than 1 598 | 599 | let integerWords = chunks.map((chunk, index) => { 600 | chunk = Number(chunk); 601 | if (chunk === 0) return ''; 602 | const hundred = Math.floor(chunk / 100); 603 | const tenUnit = chunk % 100; 604 | const ten = Math.floor(tenUnit / 10); 605 | const unit = tenUnit % 10; 606 | 607 | let chunkText = ''; 608 | 609 | if (hundred > 0) chunkText += hundreds[hundred] + ' '; 610 | if (tenUnit >= 20) { 611 | chunkText += tens[ten] + ' '; 612 | if (unit > 0) chunkText += belowTwenty[unit]; 613 | } else if (tenUnit > 0) { 614 | chunkText += belowTwenty[tenUnit]; 615 | } 616 | 617 | if (chunk > 0 && index < chunks.length - 1) { 618 | let scale = integerScales[chunks.length - index - 2]; 619 | return chunkText.trim() + ' ' + plural(chunk, scale, {showNumber: false}); 620 | } 621 | return chunkText.trim(); 622 | }).join(' ').trim(); 623 | 624 | let decimalPart = (num - Math.floor(num)).toFixed(num.toString().split('.')?.[1]?.length).toString().slice(2); 625 | let decimalLength = decimalPart > 0 ? decimalPart.toString().replace('-', '').length : 0; 626 | 627 | return (integerWords.length > 0 ? integerWords : 'zero') + (decimalLength > 0 ? ' point ' + numberToWords(decimalPart) + ' ' + plural(decimalPart, decimalScales[decimalLength-1], {showNumber: false}) : ''); 628 | } 629 | 630 | window.toSentenceCase = function(str){ 631 | const firstLetter = str.substr(0, 1); 632 | return firstLetter.toUpperCase() + str.substr(1).toLowerCase(); 633 | } 634 | 635 | window.toTitleCase = function(str) { 636 | return str.toLowerCase().split(' ').map(function(word) { 637 | return (word.charAt(0).toUpperCase() + word.slice(1)); 638 | }).join(' '); 639 | } 640 | 641 | window.setCookie = function(key, value){ 642 | const date = new Date(); 643 | date.setTime(date.getTime() + (10 * 365 * 24 * 60 * 60 * 1000)); 644 | document.cookie = `${key}=${value};expires=${date.toUTCString()};path=/`; 645 | } 646 | 647 | window.getCookie = function(key) { 648 | let nameEQ = key + "="; 649 | let ca = document.cookie.split(';'); 650 | for (let i = 0; i < ca.length; i++) { 651 | let c = ca[i]; 652 | while (c.charAt(0) === ' ') c = c.substring(1); 653 | if (c.indexOf(nameEQ) === 0) { 654 | return decodeURIComponent(c.substring(nameEQ.length, c.length)); 655 | } 656 | } 657 | return null; 658 | } -------------------------------------------------------------------------------- /assets/js/helpers.js: -------------------------------------------------------------------------------- 1 | class addFields { 2 | constructor(type = 'count') { 3 | this.type = type; 4 | this.letters = 'abcdefghijklmnopqrstuvwxyz'; 5 | this.key = 0; 6 | this.holidays = []; 7 | this.appendTo = $(`#option_${this.type}_holidays > .calculator-content-body`); 8 | this.days = Array.from({length: 31}, (_, i) => i + 1); 9 | this.months = Array.from({length: 12}, (_, i) => i + 1); 10 | this.monthLabels = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 11 | 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; 12 | 13 | this.addField(); 14 | } 15 | 16 | addField() { 17 | const letter = this.letters[this.key]; 18 | this.holidays.push(letter); 19 | const disabled = _(`${this.type}_holidays`).checked ? '' : 'disabled'; 20 | const holiday = ` 21 | `; 52 | 53 | this.appendTo.insertAdjacentHTML('beforeend', holiday); 54 | 55 | /*KeyListeners*/ 56 | this.removeField(); 57 | this.addNewField(); 58 | } 59 | 60 | removeField() { 61 | let _this = this; 62 | $$('.input-field--clear').forEach(btn => { 63 | btn.addEventListener("click", function (event) { 64 | const letter = event.target.getAttribute('data-letter'); 65 | const row = _(`${_this.type}_field_${letter}`); 66 | if(row !== null) row.remove(); 67 | _this.resetFields(); 68 | }); 69 | }); 70 | } 71 | 72 | addNewField() { 73 | const _this = this; 74 | 75 | const selects = $$('.input-field__select'); 76 | let added = false; 77 | selects.forEach(select => { 78 | select.addEventListener("change", function (event, target) { 79 | const letter = event.target.getAttribute('data-letter'); 80 | /*Get month and date values*/ 81 | const month = _(`${_this.type}_month_${letter}`).value; 82 | const day = _(`${_this.type}_day_${letter}`).value; 83 | if (parseInt(month) && parseInt(day) && !added) { 84 | _this.key++; 85 | _this.addField(); 86 | added = true; 87 | } 88 | }); 89 | }) 90 | } 91 | 92 | resetFields() { 93 | const rows = $$(`.${this.type}_holiday_row`); 94 | if(rows.length) return false; 95 | 96 | this.key = 0; 97 | this.addField(); 98 | } 99 | } 100 | 101 | new addFields(); -------------------------------------------------------------------------------- /assets/js/hourpicker.js: -------------------------------------------------------------------------------- 1 | const INPUTS = $$('.hourpicker-input'); 2 | let timepickerFormat = true 3 | let currentInput = { 4 | input: null, 5 | hour: null, 6 | minute: null, 7 | } 8 | 9 | function createTimepicker() { 10 | const TIMEPICKER = document.createElement('div'); 11 | const {top, left} = currentInput.input.getBoundingClientRect() 12 | const {offsetHeight} = currentInput.input 13 | const VALUE = currentInput.input.value.split(':') 14 | 15 | TIMEPICKER.classList.add('timepicker'); 16 | TIMEPICKER.classList.add('timepicker--hourpicker'); 17 | TIMEPICKER.innerHTML = ` 18 |
19 |
20 |
21 |

Hour

22 | 23 |
24 |

:

25 |
26 |

Minute

27 | 28 |
29 |
30 |
31 | 34 | 37 |
38 |
39 | 40 | 49 | ` 50 | document.body.appendChild(TIMEPICKER); 51 | TIMEPICKER.style.top = top + window.scrollY + 9 + offsetHeight + 'px'; 52 | TIMEPICKER.style.left = left - 13 + 'px'; 53 | TIMEPICKER.classList.add('timepicker--active'); 54 | 55 | const TIMEPICKER_DONE = document.getElementById('timepicker_done') 56 | const TIMEPICKER_CANCEL = document.getElementById('timepicker_cancel') 57 | const TIMEPICKER_HOUR = document.getElementById('timepicker_hour') 58 | const TIMEPICKER_MINUTE = document.getElementById('timepicker_minute') 59 | const TIMEPICKER_FORMAT_SWITCHER = document.getElementById('timepicker_format_switcher') 60 | const TIMEPICKER_FORMAT = document.getElementById('timepicker_format') 61 | const SWITCH_TO_AM = document.getElementById('switch_to_am') 62 | const SWITCH_TO_PM = document.getElementById('switch_to_pm') 63 | 64 | SWITCH_TO_AM.addEventListener('click', () => { 65 | SWITCH_TO_PM.classList.remove('button-switcher--active') 66 | SWITCH_TO_AM.classList.add('button-switcher--active') 67 | }) 68 | 69 | SWITCH_TO_PM.addEventListener('click', () => { 70 | SWITCH_TO_AM.classList.remove('button-switcher--active') 71 | SWITCH_TO_PM.classList.add('button-switcher--active') 72 | }) 73 | 74 | TIMEPICKER_HOUR.addEventListener('input', (event) => { 75 | limitLengthHandler(event.target, 2) 76 | currentInput.hour = event.target.value 77 | if(event.target.value.length === 2) TIMEPICKER_MINUTE.focus() 78 | }) 79 | TIMEPICKER_MINUTE.addEventListener('input', (event) => { 80 | limitLengthHandler(event.target, 2) 81 | currentInput.minute = event.target.value 82 | }) 83 | 84 | TIMEPICKER_FORMAT_SWITCHER.addEventListener('input', (event) => { 85 | if(event.target.checked) { 86 | TIMEPICKER_FORMAT.style.display = 'none' 87 | timepickerFormat = false 88 | } 89 | else { 90 | TIMEPICKER_FORMAT.style.display = 'flex' 91 | timepickerFormat = true 92 | } 93 | }) 94 | 95 | TIMEPICKER_DONE.addEventListener('click', onDoneTimepicker) 96 | window.addEventListener('keydown', onDoneTimepickerEnter) 97 | 98 | TIMEPICKER_CANCEL.addEventListener('click', () => { 99 | onCloseTimepicker(); 100 | }) 101 | } 102 | 103 | function limitLengthHandler(input, limit) { 104 | if(input.value.length > limit) { 105 | input.value = input.value.slice(0, limit); 106 | } 107 | return input.value; 108 | } 109 | 110 | function onDoneTimepickerEnter (event) { 111 | if(event.key === 'Enter') { 112 | onDoneTimepicker(); 113 | } 114 | } 115 | 116 | function onDoneTimepicker () { 117 | let hours = currentInput.hour < 10 ? '0' + currentInput.hour : currentInput.hour 118 | let minutes = currentInput.minute < 10 ? '0' + currentInput.minute : currentInput.minute 119 | 120 | currentInput.input.value = `${hours > 0 ? hours : '00'}:${minutes > 0 ? minutes : '00'}` 121 | onCloseTimepicker(); 122 | window.removeEventListener('keydown', onDoneTimepickerEnter) 123 | window.removeEventListener('click', onCloseTimepickerOutside) 124 | } 125 | 126 | function onCloseTimepicker() { 127 | currentInput.input = null 128 | document.body.removeChild($('.timepicker')); 129 | window.removeEventListener('click', onCloseTimepickerOutside) 130 | } 131 | 132 | function onCloseTimepickerOutside(event) { 133 | if($('.timepicker') && !(event.composedPath().includes($('.timepicker')) || event.composedPath().includes(currentInput.input))) { 134 | onCloseTimepicker(); 135 | } 136 | } 137 | 138 | window.timepicker = (event) => { 139 | if($('.timepicker')) { 140 | onCloseTimepicker(); 141 | } else { 142 | currentInput.input = event.target 143 | createTimepicker() 144 | window.addEventListener('click', onCloseTimepickerOutside) 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /assets/js/lib/chartjs/helpers.d.ts: -------------------------------------------------------------------------------- 1 | import { Color } from '@kurkle/color'; 2 | import { P as Point$1, f as ChartArea, e as ChartEvent, C as Chart, au as ChartMeta, b as PointElement, cn as TRBL, co as TRBLCorners, aZ as FontSpec, b9 as PointStyle, ck as Color$1, cp as RoundedRect } from './chunks/helpers.core.js'; 3 | export { cg as EasingFunction, cE as MergeOptions, cL as _capitalize, cI as _deprecated, cB as _elementsEqual, cP as _isClickEvent, cD as _merger, cH as _mergerIf, cJ as _splitKey, cz as callback, cC as clone, cM as defined, cA as each, cv as finiteOrDefault, ct as isArray, cq as isFinite, cN as isFunction, cs as isNullOrUndef, cu as isObject, cF as merge, cG as mergeIf, n as noop, cK as resolveObjectKey, cO as setsEqual, cy as toDimension, cx as toPercentage, cr as uid, cw as valueOrDefault } from './chunks/helpers.core.js'; 4 | 5 | declare function isPatternOrGradient(value: unknown): value is CanvasPattern | CanvasGradient; 6 | declare function color(value: CanvasGradient): CanvasGradient; 7 | declare function color(value: CanvasPattern): CanvasPattern; 8 | declare function color(value: string | { 9 | r: number; 10 | g: number; 11 | b: number; 12 | a: number; 13 | } | [number, number, number] | [number, number, number, number]): Color; 14 | declare function getHoverColor(value: CanvasGradient): CanvasGradient; 15 | declare function getHoverColor(value: CanvasPattern): CanvasPattern; 16 | declare function getHoverColor(value: string): string; 17 | 18 | /** 19 | * Note: typedefs are auto-exported, so use a made-up `canvas` namespace where 20 | * necessary to avoid duplicates with `export * from './helpers`; see 21 | * https://github.com/microsoft/TypeScript/issues/46011 22 | */ 23 | type Point = Point$1; 24 | 25 | /** 26 | * Binary search 27 | * @param table - the table search. must be sorted! 28 | * @param value - value to find 29 | * @param cmp 30 | * @private 31 | */ 32 | declare function _lookup(table: number[], value: number, cmp?: (value: number) => boolean): { 33 | lo: number; 34 | hi: number; 35 | }; 36 | declare function _lookup(table: T[], value: number, cmp: (value: number) => boolean): { 37 | lo: number; 38 | hi: number; 39 | }; 40 | /** 41 | * Binary search 42 | * @param table - the table search. must be sorted! 43 | * @param key - property name for the value in each entry 44 | * @param value - value to find 45 | * @param last - lookup last index 46 | * @private 47 | */ 48 | declare const _lookupByKey: (table: Record[], key: string, value: number, last?: boolean) => { 49 | lo: number; 50 | hi: number; 51 | }; 52 | /** 53 | * Reverse binary search 54 | * @param table - the table search. must be sorted! 55 | * @param key - property name for the value in each entry 56 | * @param value - value to find 57 | * @private 58 | */ 59 | declare const _rlookupByKey: (table: Record[], key: string, value: number) => { 60 | lo: number; 61 | hi: number; 62 | }; 63 | /** 64 | * Return subset of `values` between `min` and `max` inclusive. 65 | * Values are assumed to be in sorted order. 66 | * @param values - sorted array of values 67 | * @param min - min value 68 | * @param max - max value 69 | */ 70 | declare function _filterBetween(values: number[], min: number, max: number): number[]; 71 | interface ArrayListener { 72 | _onDataPush?(...item: T[]): void; 73 | _onDataPop?(): void; 74 | _onDataShift?(): void; 75 | _onDataSplice?(index: number, deleteCount: number, ...items: T[]): void; 76 | _onDataUnshift?(...item: T[]): void; 77 | } 78 | /** 79 | * Hooks the array methods that add or remove values ('push', pop', 'shift', 'splice', 80 | * 'unshift') and notify the listener AFTER the array has been altered. Listeners are 81 | * called on the '_onData*' callbacks (e.g. _onDataPush, etc.) with same arguments. 82 | */ 83 | declare function listenArrayEvents(array: T[], listener: ArrayListener): void; 84 | /** 85 | * Removes the given array event listener and cleanup extra attached properties (such as 86 | * the _chartjs stub and overridden methods) if array doesn't have any more listeners. 87 | */ 88 | declare function unlistenArrayEvents(array: T[], listener: ArrayListener): void; 89 | /** 90 | * @param items 91 | */ 92 | declare function _arrayUnique(items: T[]): T[]; 93 | 94 | interface SplinePoint { 95 | x: number; 96 | y: number; 97 | skip?: boolean; 98 | cp1x?: number; 99 | cp1y?: number; 100 | cp2x?: number; 101 | cp2y?: number; 102 | } 103 | declare function splineCurve(firstPoint: SplinePoint, middlePoint: SplinePoint, afterPoint: SplinePoint, t: number): { 104 | previous: SplinePoint; 105 | next: SplinePoint; 106 | }; 107 | /** 108 | * This function calculates Bézier control points in a similar way than |splineCurve|, 109 | * but preserves monotonicity of the provided data and ensures no local extremums are added 110 | * between the dataset discrete points due to the interpolation. 111 | * See : https://en.wikipedia.org/wiki/Monotone_cubic_interpolation 112 | */ 113 | declare function splineCurveMonotone(points: SplinePoint[], indexAxis?: 'x' | 'y'): void; 114 | /** 115 | * @private 116 | */ 117 | declare function _updateBezierControlPoints(points: SplinePoint[], options: any, area: ChartArea, loop: boolean, indexAxis: 'x' | 'y'): void; 118 | 119 | /** 120 | * Note: typedefs are auto-exported, so use a made-up `dom` namespace where 121 | * necessary to avoid duplicates with `export * from './helpers`; see 122 | * https://github.com/microsoft/TypeScript/issues/46011 123 | * @typedef { import("../core/core.controller").default } dom.Chart 124 | * @typedef { import('../../types').ChartEvent } ChartEvent 125 | */ 126 | /** 127 | * @private 128 | */ 129 | declare function _isDomSupported(): boolean; 130 | /** 131 | * @private 132 | */ 133 | declare function _getParentNode(domNode: HTMLCanvasElement): HTMLCanvasElement; 134 | declare function getStyle(el: HTMLElement, property: string): string; 135 | /** 136 | * Gets an event's x, y coordinates, relative to the chart area 137 | * @param event 138 | * @param chart 139 | * @returns x and y coordinates of the event 140 | */ 141 | declare function getRelativePosition(event: Event | ChartEvent | TouchEvent | MouseEvent, chart: Chart): { 142 | x: number; 143 | y: number; 144 | }; 145 | declare function getMaximumSize(canvas: HTMLCanvasElement, bbWidth?: number, bbHeight?: number, aspectRatio?: number): { 146 | width: number; 147 | height: number; 148 | }; 149 | /** 150 | * @param chart 151 | * @param forceRatio 152 | * @param forceStyle 153 | * @returns True if the canvas context size or transformation has changed. 154 | */ 155 | declare function retinaScale(chart: Chart, forceRatio: number, forceStyle?: boolean): boolean | void; 156 | /** 157 | * Detects support for options object argument in addEventListener. 158 | * https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#Safely_detecting_option_support 159 | * @private 160 | */ 161 | declare const supportsEventListenerOptions: boolean; 162 | /** 163 | * The "used" size is the final value of a dimension property after all calculations have 164 | * been performed. This method uses the computed style of `element` but returns undefined 165 | * if the computed style is not expressed in pixels. That can happen in some cases where 166 | * `element` has a size relative to its parent and this last one is not yet displayed, 167 | * for example because of `display: none` on a parent node. 168 | * @see https://developer.mozilla.org/en-US/docs/Web/CSS/used_value 169 | * @returns Size in pixels or undefined if unknown. 170 | */ 171 | declare function readUsedSize(element: HTMLElement, property: 'width' | 'height'): number | undefined; 172 | 173 | declare function fontString(pixelSize: number, fontStyle: string, fontFamily: string): string; 174 | /** 175 | * Request animation polyfill 176 | */ 177 | declare const requestAnimFrame: (((callback: FrameRequestCallback) => number) & typeof requestAnimationFrame) | ((callback: any) => any); 178 | /** 179 | * Throttles calling `fn` once per animation frame 180 | * Latest arguments are used on the actual call 181 | */ 182 | declare function throttled>(fn: (...args: TArgs) => void, thisArg: any): (...args: TArgs) => void; 183 | /** 184 | * Debounces calling `fn` for `delay` ms 185 | */ 186 | declare function debounce>(fn: (...args: TArgs) => void, delay: number): (...args: TArgs) => number; 187 | /** 188 | * Converts 'start' to 'left', 'end' to 'right' and others to 'center' 189 | * @private 190 | */ 191 | declare const _toLeftRightCenter: (align: 'start' | 'end' | 'center') => "center" | "right" | "left"; 192 | /** 193 | * Returns `start`, `end` or `(start + end) / 2` depending on `align`. Defaults to `center` 194 | * @private 195 | */ 196 | declare const _alignStartEnd: (align: 'start' | 'end' | 'center', start: number, end: number) => number; 197 | /** 198 | * Returns `left`, `right` or `(left + right) / 2` depending on `align`. Defaults to `left` 199 | * @private 200 | */ 201 | declare const _textX: (align: 'left' | 'right' | 'center', left: number, right: number, rtl: boolean) => number; 202 | /** 203 | * Return start and count of visible points. 204 | * @private 205 | */ 206 | declare function _getStartAndCountOfVisiblePoints(meta: ChartMeta<'line' | 'scatter'>, points: PointElement[], animationsDisabled: boolean): { 207 | start: number; 208 | count: number; 209 | }; 210 | /** 211 | * Checks if the scale ranges have changed. 212 | * @param {object} meta - dataset meta. 213 | * @returns {boolean} 214 | * @private 215 | */ 216 | declare function _scaleRangesChanged(meta: any): boolean; 217 | 218 | /** 219 | * @private 220 | */ 221 | declare function _pointInLine(p1: Point$1, p2: Point$1, t: number, mode?: any): { 222 | x: number; 223 | y: number; 224 | }; 225 | /** 226 | * @private 227 | */ 228 | declare function _steppedInterpolation(p1: Point$1, p2: Point$1, t: number, mode: 'middle' | 'after' | unknown): { 229 | x: number; 230 | y: number; 231 | }; 232 | /** 233 | * @private 234 | */ 235 | declare function _bezierInterpolation(p1: SplinePoint, p2: SplinePoint, t: number, mode?: any): { 236 | x: number; 237 | y: number; 238 | }; 239 | 240 | declare function formatNumber(num: number, locale: string, options?: Intl.NumberFormatOptions): string; 241 | 242 | /** 243 | * @alias Chart.helpers.options 244 | * @namespace 245 | */ 246 | /** 247 | * Converts the given line height `value` in pixels for a specific font `size`. 248 | * @param value - The lineHeight to parse (eg. 1.6, '14px', '75%', '1.6em'). 249 | * @param size - The font size (in pixels) used to resolve relative `value`. 250 | * @returns The effective line height in pixels (size * 1.2 if value is invalid). 251 | * @see https://developer.mozilla.org/en-US/docs/Web/CSS/line-height 252 | * @since 2.7.0 253 | */ 254 | declare function toLineHeight(value: number | string, size: number): number; 255 | /** 256 | * @param value 257 | * @param props 258 | */ 259 | declare function _readValueToProps(value: number | Record, props: K[]): Record; 260 | declare function _readValueToProps(value: number | Record, props: Record): Record; 261 | /** 262 | * Converts the given value into a TRBL object. 263 | * @param value - If a number, set the value to all TRBL component, 264 | * else, if an object, use defined properties and sets undefined ones to 0. 265 | * x / y are shorthands for same value for left/right and top/bottom. 266 | * @returns The padding values (top, right, bottom, left) 267 | * @since 3.0.0 268 | */ 269 | declare function toTRBL(value: number | TRBL | Point): Record<"top" | "right" | "bottom" | "left", number>; 270 | /** 271 | * Converts the given value into a TRBL corners object (similar with css border-radius). 272 | * @param value - If a number, set the value to all TRBL corner components, 273 | * else, if an object, use defined properties and sets undefined ones to 0. 274 | * @returns The TRBL corner values (topLeft, topRight, bottomLeft, bottomRight) 275 | * @since 3.0.0 276 | */ 277 | declare function toTRBLCorners(value: number | TRBLCorners): Record<"topLeft" | "topRight" | "bottomLeft" | "bottomRight", number>; 278 | /** 279 | * Converts the given value into a padding object with pre-computed width/height. 280 | * @param value - If a number, set the value to all TRBL component, 281 | * else, if an object, use defined properties and sets undefined ones to 0. 282 | * x / y are shorthands for same value for left/right and top/bottom. 283 | * @returns The padding values (top, right, bottom, left, width, height) 284 | * @since 2.7.0 285 | */ 286 | declare function toPadding(value?: number | TRBL): ChartArea; 287 | interface CanvasFontSpec extends FontSpec { 288 | string: string; 289 | } 290 | /** 291 | * Parses font options and returns the font object. 292 | * @param options - A object that contains font options to be parsed. 293 | * @param fallback - A object that contains fallback font options. 294 | * @return The font object. 295 | * @private 296 | */ 297 | declare function toFont(options: Partial, fallback?: Partial): { 298 | family: string; 299 | lineHeight: number; 300 | size: number; 301 | style: "normal" | "italic" | "oblique" | "initial" | "inherit"; 302 | weight: string; 303 | string: string; 304 | }; 305 | /** 306 | * Evaluates the given `inputs` sequentially and returns the first defined value. 307 | * @param inputs - An array of values, falling back to the last value. 308 | * @param context - If defined and the current value is a function, the value 309 | * is called with `context` as first argument and the result becomes the new input. 310 | * @param index - If defined and the current value is an array, the value 311 | * at `index` become the new input. 312 | * @param info - object to return information about resolution in 313 | * @param info.cacheable - Will be set to `false` if option is not cacheable. 314 | * @since 2.7.0 315 | */ 316 | declare function resolve(inputs: Array, context?: object, index?: number, info?: { 317 | cacheable: boolean; 318 | }): unknown; 319 | /** 320 | * @param minmax 321 | * @param grace 322 | * @param beginAtZero 323 | * @private 324 | */ 325 | declare function _addGrace(minmax: { 326 | min: number; 327 | max: number; 328 | }, grace: number | string, beginAtZero: boolean): { 329 | min: number; 330 | max: number; 331 | }; 332 | /** 333 | * Create a context inheriting parentContext 334 | * @param parentContext 335 | * @param context 336 | * @returns 337 | */ 338 | declare function createContext

(parentContext: P, context: T): P extends null ? T : P & T; 339 | 340 | /** 341 | * @alias Chart.helpers.math 342 | * @namespace 343 | */ 344 | declare const PI: number; 345 | declare const TAU: number; 346 | declare const PITAU: number; 347 | declare const INFINITY: number; 348 | declare const RAD_PER_DEG: number; 349 | declare const HALF_PI: number; 350 | declare const QUARTER_PI: number; 351 | declare const TWO_THIRDS_PI: number; 352 | declare const log10: (x: number) => number; 353 | declare const sign: (x: number) => number; 354 | declare function almostEquals(x: number, y: number, epsilon: number): boolean; 355 | /** 356 | * Implementation of the nice number algorithm used in determining where axis labels will go 357 | */ 358 | declare function niceNum(range: number): number; 359 | /** 360 | * Returns an array of factors sorted from 1 to sqrt(value) 361 | * @private 362 | */ 363 | declare function _factorize(value: number): number[]; 364 | declare function isNumber(n: unknown): n is number; 365 | declare function almostWhole(x: number, epsilon: number): boolean; 366 | /** 367 | * @private 368 | */ 369 | declare function _setMinAndMaxByKey(array: Record[], target: { 370 | min: number; 371 | max: number; 372 | }, property: string): void; 373 | declare function toRadians(degrees: number): number; 374 | declare function toDegrees(radians: number): number; 375 | /** 376 | * Returns the number of decimal places 377 | * i.e. the number of digits after the decimal point, of the value of this Number. 378 | * @param x - A number. 379 | * @returns The number of decimal places. 380 | * @private 381 | */ 382 | declare function _decimalPlaces(x: number): number; 383 | declare function getAngleFromPoint(centrePoint: Point$1, anglePoint: Point$1): { 384 | angle: number; 385 | distance: number; 386 | }; 387 | declare function distanceBetweenPoints(pt1: Point$1, pt2: Point$1): number; 388 | /** 389 | * Shortest distance between angles, in either direction. 390 | * @private 391 | */ 392 | declare function _angleDiff(a: number, b: number): number; 393 | /** 394 | * Normalize angle to be between 0 and 2*PI 395 | * @private 396 | */ 397 | declare function _normalizeAngle(a: number): number; 398 | /** 399 | * @private 400 | */ 401 | declare function _angleBetween(angle: number, start: number, end: number, sameAngleIsFullCircle?: boolean): boolean; 402 | /** 403 | * Limit `value` between `min` and `max` 404 | * @param value 405 | * @param min 406 | * @param max 407 | * @private 408 | */ 409 | declare function _limitValue(value: number, min: number, max: number): number; 410 | /** 411 | * @param {number} value 412 | * @private 413 | */ 414 | declare function _int16Range(value: number): number; 415 | /** 416 | * @param value 417 | * @param start 418 | * @param end 419 | * @param [epsilon] 420 | * @private 421 | */ 422 | declare function _isBetween(value: number, start: number, end: number, epsilon?: number): boolean; 423 | 424 | interface RTLAdapter { 425 | x(x: number): number; 426 | setWidth(w: number): void; 427 | textAlign(align: 'center' | 'left' | 'right'): 'center' | 'left' | 'right'; 428 | xPlus(x: number, value: number): number; 429 | leftForLtr(x: number, itemWidth: number): number; 430 | } 431 | declare function getRtlAdapter(rtl: boolean, rectX: number, width: number): RTLAdapter; 432 | declare function overrideTextDirection(ctx: CanvasRenderingContext2D, direction: 'ltr' | 'rtl'): void; 433 | declare function restoreTextDirection(ctx: CanvasRenderingContext2D, original?: [string, string]): void; 434 | 435 | declare function clearCanvas(canvas: HTMLCanvasElement, ctx?: CanvasRenderingContext2D): void; 436 | 437 | declare function clipArea(ctx: CanvasRenderingContext2D, area: ChartArea): void; 438 | 439 | declare function unclipArea(ctx: CanvasRenderingContext2D): void; 440 | 441 | interface DrawPointOptions { 442 | pointStyle: PointStyle; 443 | rotation?: number; 444 | radius: number; 445 | borderWidth: number; 446 | } 447 | 448 | declare function drawPoint(ctx: CanvasRenderingContext2D, options: DrawPointOptions, x: number, y: number): void; 449 | 450 | declare function drawPointLegend(ctx: CanvasRenderingContext2D, options: DrawPointOptions, x: number, y: number, w: number): void; 451 | 452 | /** 453 | * Converts the given font object into a CSS font string. 454 | * @param font a font object 455 | * @return The CSS font string. See https://developer.mozilla.org/en-US/docs/Web/CSS/font 456 | */ 457 | declare function toFontString(font: { size: number; family: string; style?: string; weight?: string }): string | null; 458 | 459 | interface RenderTextOpts { 460 | /** 461 | * The fill color of the text. If unset, the existing 462 | * fillStyle property of the canvas is unchanged. 463 | */ 464 | color?: Color$1; 465 | 466 | /** 467 | * The width of the strikethrough / underline 468 | * @default 2 469 | */ 470 | decorationWidth?: number; 471 | 472 | /** 473 | * The max width of the text in pixels 474 | */ 475 | maxWidth?: number; 476 | 477 | /** 478 | * A rotation to be applied to the canvas 479 | * This is applied after the translation is applied 480 | */ 481 | rotation?: number; 482 | 483 | /** 484 | * Apply a strikethrough effect to the text 485 | */ 486 | strikethrough?: boolean; 487 | 488 | /** 489 | * The color of the text stroke. If unset, the existing 490 | * strokeStyle property of the context is unchanged 491 | */ 492 | strokeColor?: Color$1; 493 | 494 | /** 495 | * The text stroke width. If unset, the existing 496 | * lineWidth property of the context is unchanged 497 | */ 498 | strokeWidth?: number; 499 | 500 | /** 501 | * The text alignment to use. If unset, the existing 502 | * textAlign property of the context is unchanged 503 | */ 504 | textAlign: CanvasTextAlign; 505 | 506 | /** 507 | * The text baseline to use. If unset, the existing 508 | * textBaseline property of the context is unchanged 509 | */ 510 | textBaseline: CanvasTextBaseline; 511 | 512 | /** 513 | * If specified, a translation to apply to the context 514 | */ 515 | translation?: [number, number]; 516 | 517 | /** 518 | * Underline the text 519 | */ 520 | underline?: boolean; 521 | } 522 | 523 | declare function renderText( 524 | ctx: CanvasRenderingContext2D, 525 | text: string | string[], 526 | x: number, 527 | y: number, 528 | font: CanvasFontSpec, 529 | opts?: RenderTextOpts 530 | ): void; 531 | 532 | declare function addRoundedRectPath(ctx: CanvasRenderingContext2D, rect: RoundedRect): void; 533 | 534 | export { ArrayListener, CanvasFontSpec, DrawPointOptions, HALF_PI, INFINITY, PI, PITAU, QUARTER_PI, RAD_PER_DEG, RTLAdapter, RenderTextOpts, SplinePoint, TAU, TWO_THIRDS_PI, _addGrace, _alignStartEnd, _angleBetween, _angleDiff, _arrayUnique, _bezierInterpolation, _decimalPlaces, _factorize, _filterBetween, _getParentNode, _getStartAndCountOfVisiblePoints, _int16Range, _isBetween, _isDomSupported, _limitValue, _lookup, _lookupByKey, _normalizeAngle, _pointInLine, _readValueToProps, _rlookupByKey, _scaleRangesChanged, _setMinAndMaxByKey, _steppedInterpolation, _textX, _toLeftRightCenter, _updateBezierControlPoints, addRoundedRectPath, almostEquals, almostWhole, clearCanvas, clipArea, color, createContext, debounce, distanceBetweenPoints, drawPoint, drawPointLegend, fontString, formatNumber, getAngleFromPoint, getHoverColor, getMaximumSize, getRelativePosition, getRtlAdapter, getStyle, isNumber, isPatternOrGradient, listenArrayEvents, log10, niceNum, overrideTextDirection, readUsedSize, renderText, requestAnimFrame, resolve, restoreTextDirection, retinaScale, sign, splineCurve, splineCurveMonotone, supportsEventListenerOptions, throttled, toDegrees, toFont, toFontString, toLineHeight, toPadding, toRadians, toTRBL, toTRBLCorners, unclipArea, unlistenArrayEvents }; 535 | -------------------------------------------------------------------------------- /assets/js/lib/chartjs/helpers.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Chart.js v4.0.1 3 | * https://www.chartjs.org 4 | * (c) 2022 Chart.js Contributors 5 | * Released under the MIT License 6 | */ 7 | export { H as HALF_PI, b2 as INFINITY, P as PI, b1 as PITAU, b4 as QUARTER_PI, b3 as RAD_PER_DEG, T as TAU, b5 as TWO_THIRDS_PI, R as _addGrace, X as _alignPixel, a2 as _alignStartEnd, p as _angleBetween, b6 as _angleDiff, _ as _arrayUnique, a8 as _attachContext, as as _bezierCurveTo, ap as _bezierInterpolation, ax as _boundSegment, an as _boundSegments, a5 as _capitalize, am as _computeSegments, a9 as _createResolver, aK as _decimalPlaces, aV as _deprecated, aa as _descriptors, ah as _elementsEqual, N as _factorize, aO as _filterBetween, I as _getParentNode, q as _getStartAndCountOfVisiblePoints, W as _int16Range, aj as _isBetween, ai as _isClickEvent, M as _isDomSupported, C as _isPointInArea, S as _limitValue, aN as _longestText, aP as _lookup, B as _lookupByKey, V as _measureText, aT as _merger, aU as _mergerIf, ay as _normalizeAngle, y as _parseObjectDataRadialScale, aq as _pointInLine, ak as _readValueToProps, A as _rlookupByKey, w as _scaleRangesChanged, aG as _setMinAndMaxByKey, aW as _splitKey, ao as _steppedInterpolation, ar as _steppedLineTo, aB as _textX, a1 as _toLeftRightCenter, al as _updateBezierControlPoints, au as addRoundedRectPath, aJ as almostEquals, aI as almostWhole, Q as callback, af as clearCanvas, Y as clipArea, aS as clone, c as color, j as createContext, ad as debounce, h as defined, aE as distanceBetweenPoints, at as drawPoint, aD as drawPointLegend, F as each, e as easingEffects, O as finiteOrDefault, a$ as fontString, o as formatNumber, D as getAngleFromPoint, aR as getHoverColor, G as getMaximumSize, z as getRelativePosition, az as getRtlAdapter, a_ as getStyle, b as isArray, g as isFinite, a7 as isFunction, k as isNullOrUndef, x as isNumber, i as isObject, aQ as isPatternOrGradient, l as listenArrayEvents, aM as log10, a4 as merge, ab as mergeIf, aH as niceNum, aF as noop, aA as overrideTextDirection, J as readUsedSize, Z as renderText, r as requestAnimFrame, a as resolve, f as resolveObjectKey, aC as restoreTextDirection, ae as retinaScale, ag as setsEqual, s as sign, aY as splineCurve, aZ as splineCurveMonotone, K as supportsEventListenerOptions, L as throttled, U as toDegrees, n as toDimension, a0 as toFont, aX as toFontString, b0 as toLineHeight, E as toPadding, m as toPercentage, t as toRadians, av as toTRBL, aw as toTRBLCorners, ac as uid, $ as unclipArea, u as unlistenArrayEvents, v as valueOrDefault } from './chunks/helpers.segment.js'; 8 | //# sourceMappingURL=helpers.js.map 9 | -------------------------------------------------------------------------------- /assets/js/lib/chartjs/helpers.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"helpers.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;"} -------------------------------------------------------------------------------- /assets/js/lib/katex/auto-render.min.js: -------------------------------------------------------------------------------- 1 | !function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("katex")):"function"==typeof define&&define.amd?define(["katex"],t):"object"==typeof exports?exports.renderMathInElement=t(require("katex")):e.renderMathInElement=t(e.katex)}("undefined"!=typeof self?self:this,(function(e){return function(){"use strict";var t={771:function(t){t.exports=e}},r={};function n(e){var i=r[e];if(void 0!==i)return i.exports;var a=r[e]={exports:{}};return t[e](a,a.exports,n),a.exports}n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,{a:t}),t},n.d=function(e,t){for(var r in t)n.o(t,r)&&!n.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)};var i={};return function(){n.d(i,{default:function(){return s}});var e=n(771),t=n.n(e),r=function(e,t,r){for(var n=r,i=0,a=e.length;n0&&(i.push({type:"text",data:e.slice(0,n)}),e=e.slice(n));var l=t.findIndex((function(t){return e.startsWith(t.left)}));if(-1===(n=r(t[l].right,e,t[l].left.length)))break;var d=e.slice(0,n+t[l].right.length),s=a.test(d)?d:e.slice(t[l].left.length,n);i.push({type:"math",data:s,rawData:d,display:t[l].display}),e=e.slice(n+t[l].right.length)}return""!==e&&i.push({type:"text",data:e}),i},l=function(e,r){var n=o(e,r.delimiters);if(1===n.length&&"text"===n[0].type)return null;for(var i=document.createDocumentFragment(),a=0;a.newline{display:block}.katex .base{position:relative;white-space:nowrap;width:-webkit-min-content;width:-moz-min-content;width:min-content}.katex .base,.katex .strut{display:inline-block}.katex .textbf{font-weight:700}.katex .textit{font-style:italic}.katex .textrm{font-family:KaTeX_Main}.katex .textsf{font-family:KaTeX_SansSerif}.katex .texttt{font-family:KaTeX_Typewriter}.katex .mathnormal{font-family:KaTeX_Math;font-style:italic}.katex .mathit{font-family:KaTeX_Main;font-style:italic}.katex .mathrm{font-style:normal}.katex .mathbf{font-family:KaTeX_Main;font-weight:700}.katex .boldsymbol{font-family:KaTeX_Math;font-style:italic;font-weight:700}.katex .amsrm,.katex .mathbb,.katex .textbb{font-family:KaTeX_AMS}.katex .mathcal{font-family:KaTeX_Caligraphic}.katex .mathfrak,.katex .textfrak{font-family:KaTeX_Fraktur}.katex .mathtt{font-family:KaTeX_Typewriter}.katex .mathscr,.katex .textscr{font-family:KaTeX_Script}.katex .mathsf,.katex .textsf{font-family:KaTeX_SansSerif}.katex .mathboldsf,.katex .textboldsf{font-family:KaTeX_SansSerif;font-weight:700}.katex .mathitsf,.katex .textitsf{font-family:KaTeX_SansSerif;font-style:italic}.katex .mainrm{font-family:KaTeX_Main;font-style:normal}.katex .vlist-t{border-collapse:collapse;display:inline-table;table-layout:fixed}.katex .vlist-r{display:table-row}.katex .vlist{display:table-cell;position:relative;vertical-align:bottom}.katex .vlist>span{display:block;height:0;position:relative}.katex .vlist>span>span{display:inline-block}.katex .vlist>span>.pstrut{overflow:hidden;width:0}.katex .vlist-t2{margin-right:-2px}.katex .vlist-s{display:table-cell;font-size:1px;min-width:2px;vertical-align:bottom;width:2px}.katex .vbox{align-items:baseline;display:inline-flex;flex-direction:column}.katex .hbox{width:100%}.katex .hbox,.katex .thinbox{display:inline-flex;flex-direction:row}.katex .thinbox{max-width:0;width:0}.katex .msupsub{text-align:left}.katex .mfrac>span>span{text-align:center}.katex .mfrac .frac-line{border-bottom-style:solid;display:inline-block;width:100%}.katex .hdashline,.katex .hline,.katex .mfrac .frac-line,.katex .overline .overline-line,.katex .rule,.katex .underline .underline-line{min-height:1px}.katex .mspace{display:inline-block}.katex .clap,.katex .llap,.katex .rlap{position:relative;width:0}.katex .clap>.inner,.katex .llap>.inner,.katex .rlap>.inner{position:absolute}.katex .clap>.fix,.katex .llap>.fix,.katex .rlap>.fix{display:inline-block}.katex .llap>.inner{right:0}.katex .clap>.inner,.katex .rlap>.inner{left:0}.katex .clap>.inner>span{margin-left:-50%;margin-right:50%}.katex .rule{border:0 solid;display:inline-block;position:relative}.katex .hline,.katex .overline .overline-line,.katex .underline .underline-line{border-bottom-style:solid;display:inline-block;width:100%}.katex .hdashline{border-bottom-style:dashed;display:inline-block;width:100%}.katex .sqrt>.root{margin-left:.27777778em;margin-right:-.55555556em}.katex .fontsize-ensurer.reset-size1.size1,.katex .sizing.reset-size1.size1{font-size:1em}.katex .fontsize-ensurer.reset-size1.size2,.katex .sizing.reset-size1.size2{font-size:1.2em}.katex .fontsize-ensurer.reset-size1.size3,.katex .sizing.reset-size1.size3{font-size:1.4em}.katex .fontsize-ensurer.reset-size1.size4,.katex .sizing.reset-size1.size4{font-size:1.6em}.katex .fontsize-ensurer.reset-size1.size5,.katex .sizing.reset-size1.size5{font-size:1.8em}.katex .fontsize-ensurer.reset-size1.size6,.katex .sizing.reset-size1.size6{font-size:2em}.katex .fontsize-ensurer.reset-size1.size7,.katex .sizing.reset-size1.size7{font-size:2.4em}.katex .fontsize-ensurer.reset-size1.size8,.katex .sizing.reset-size1.size8{font-size:2.88em}.katex .fontsize-ensurer.reset-size1.size9,.katex .sizing.reset-size1.size9{font-size:3.456em}.katex .fontsize-ensurer.reset-size1.size10,.katex .sizing.reset-size1.size10{font-size:4.148em}.katex .fontsize-ensurer.reset-size1.size11,.katex .sizing.reset-size1.size11{font-size:4.976em}.katex .fontsize-ensurer.reset-size2.size1,.katex .sizing.reset-size2.size1{font-size:.83333333em}.katex .fontsize-ensurer.reset-size2.size2,.katex .sizing.reset-size2.size2{font-size:1em}.katex .fontsize-ensurer.reset-size2.size3,.katex .sizing.reset-size2.size3{font-size:1.16666667em}.katex .fontsize-ensurer.reset-size2.size4,.katex .sizing.reset-size2.size4{font-size:1.33333333em}.katex .fontsize-ensurer.reset-size2.size5,.katex .sizing.reset-size2.size5{font-size:1.5em}.katex .fontsize-ensurer.reset-size2.size6,.katex .sizing.reset-size2.size6{font-size:1.66666667em}.katex .fontsize-ensurer.reset-size2.size7,.katex .sizing.reset-size2.size7{font-size:2em}.katex .fontsize-ensurer.reset-size2.size8,.katex .sizing.reset-size2.size8{font-size:2.4em}.katex .fontsize-ensurer.reset-size2.size9,.katex .sizing.reset-size2.size9{font-size:2.88em}.katex .fontsize-ensurer.reset-size2.size10,.katex .sizing.reset-size2.size10{font-size:3.45666667em}.katex .fontsize-ensurer.reset-size2.size11,.katex .sizing.reset-size2.size11{font-size:4.14666667em}.katex .fontsize-ensurer.reset-size3.size1,.katex .sizing.reset-size3.size1{font-size:.71428571em}.katex .fontsize-ensurer.reset-size3.size2,.katex .sizing.reset-size3.size2{font-size:.85714286em}.katex .fontsize-ensurer.reset-size3.size3,.katex .sizing.reset-size3.size3{font-size:1em}.katex .fontsize-ensurer.reset-size3.size4,.katex .sizing.reset-size3.size4{font-size:1.14285714em}.katex .fontsize-ensurer.reset-size3.size5,.katex .sizing.reset-size3.size5{font-size:1.28571429em}.katex .fontsize-ensurer.reset-size3.size6,.katex .sizing.reset-size3.size6{font-size:1.42857143em}.katex .fontsize-ensurer.reset-size3.size7,.katex .sizing.reset-size3.size7{font-size:1.71428571em}.katex .fontsize-ensurer.reset-size3.size8,.katex .sizing.reset-size3.size8{font-size:2.05714286em}.katex .fontsize-ensurer.reset-size3.size9,.katex .sizing.reset-size3.size9{font-size:2.46857143em}.katex .fontsize-ensurer.reset-size3.size10,.katex .sizing.reset-size3.size10{font-size:2.96285714em}.katex .fontsize-ensurer.reset-size3.size11,.katex .sizing.reset-size3.size11{font-size:3.55428571em}.katex .fontsize-ensurer.reset-size4.size1,.katex .sizing.reset-size4.size1{font-size:.625em}.katex .fontsize-ensurer.reset-size4.size2,.katex .sizing.reset-size4.size2{font-size:.75em}.katex .fontsize-ensurer.reset-size4.size3,.katex .sizing.reset-size4.size3{font-size:.875em}.katex .fontsize-ensurer.reset-size4.size4,.katex .sizing.reset-size4.size4{font-size:1em}.katex .fontsize-ensurer.reset-size4.size5,.katex .sizing.reset-size4.size5{font-size:1.125em}.katex .fontsize-ensurer.reset-size4.size6,.katex .sizing.reset-size4.size6{font-size:1.25em}.katex .fontsize-ensurer.reset-size4.size7,.katex .sizing.reset-size4.size7{font-size:1.5em}.katex .fontsize-ensurer.reset-size4.size8,.katex .sizing.reset-size4.size8{font-size:1.8em}.katex .fontsize-ensurer.reset-size4.size9,.katex .sizing.reset-size4.size9{font-size:2.16em}.katex .fontsize-ensurer.reset-size4.size10,.katex .sizing.reset-size4.size10{font-size:2.5925em}.katex .fontsize-ensurer.reset-size4.size11,.katex .sizing.reset-size4.size11{font-size:3.11em}.katex .fontsize-ensurer.reset-size5.size1,.katex .sizing.reset-size5.size1{font-size:.55555556em}.katex .fontsize-ensurer.reset-size5.size2,.katex .sizing.reset-size5.size2{font-size:.66666667em}.katex .fontsize-ensurer.reset-size5.size3,.katex .sizing.reset-size5.size3{font-size:.77777778em}.katex .fontsize-ensurer.reset-size5.size4,.katex .sizing.reset-size5.size4{font-size:.88888889em}.katex .fontsize-ensurer.reset-size5.size5,.katex .sizing.reset-size5.size5{font-size:1em}.katex .fontsize-ensurer.reset-size5.size6,.katex .sizing.reset-size5.size6{font-size:1.11111111em}.katex .fontsize-ensurer.reset-size5.size7,.katex .sizing.reset-size5.size7{font-size:1.33333333em}.katex .fontsize-ensurer.reset-size5.size8,.katex .sizing.reset-size5.size8{font-size:1.6em}.katex .fontsize-ensurer.reset-size5.size9,.katex .sizing.reset-size5.size9{font-size:1.92em}.katex .fontsize-ensurer.reset-size5.size10,.katex .sizing.reset-size5.size10{font-size:2.30444444em}.katex .fontsize-ensurer.reset-size5.size11,.katex .sizing.reset-size5.size11{font-size:2.76444444em}.katex .fontsize-ensurer.reset-size6.size1,.katex .sizing.reset-size6.size1{font-size:.5em}.katex .fontsize-ensurer.reset-size6.size2,.katex .sizing.reset-size6.size2{font-size:.6em}.katex .fontsize-ensurer.reset-size6.size3,.katex .sizing.reset-size6.size3{font-size:.7em}.katex .fontsize-ensurer.reset-size6.size4,.katex .sizing.reset-size6.size4{font-size:.8em}.katex .fontsize-ensurer.reset-size6.size5,.katex .sizing.reset-size6.size5{font-size:.9em}.katex .fontsize-ensurer.reset-size6.size6,.katex .sizing.reset-size6.size6{font-size:1em}.katex .fontsize-ensurer.reset-size6.size7,.katex .sizing.reset-size6.size7{font-size:1.2em}.katex .fontsize-ensurer.reset-size6.size8,.katex .sizing.reset-size6.size8{font-size:1.44em}.katex .fontsize-ensurer.reset-size6.size9,.katex .sizing.reset-size6.size9{font-size:1.728em}.katex .fontsize-ensurer.reset-size6.size10,.katex .sizing.reset-size6.size10{font-size:2.074em}.katex .fontsize-ensurer.reset-size6.size11,.katex .sizing.reset-size6.size11{font-size:2.488em}.katex .fontsize-ensurer.reset-size7.size1,.katex .sizing.reset-size7.size1{font-size:.41666667em}.katex .fontsize-ensurer.reset-size7.size2,.katex .sizing.reset-size7.size2{font-size:.5em}.katex .fontsize-ensurer.reset-size7.size3,.katex .sizing.reset-size7.size3{font-size:.58333333em}.katex .fontsize-ensurer.reset-size7.size4,.katex .sizing.reset-size7.size4{font-size:.66666667em}.katex .fontsize-ensurer.reset-size7.size5,.katex .sizing.reset-size7.size5{font-size:.75em}.katex .fontsize-ensurer.reset-size7.size6,.katex .sizing.reset-size7.size6{font-size:.83333333em}.katex .fontsize-ensurer.reset-size7.size7,.katex .sizing.reset-size7.size7{font-size:1em}.katex .fontsize-ensurer.reset-size7.size8,.katex .sizing.reset-size7.size8{font-size:1.2em}.katex .fontsize-ensurer.reset-size7.size9,.katex .sizing.reset-size7.size9{font-size:1.44em}.katex .fontsize-ensurer.reset-size7.size10,.katex .sizing.reset-size7.size10{font-size:1.72833333em}.katex .fontsize-ensurer.reset-size7.size11,.katex .sizing.reset-size7.size11{font-size:2.07333333em}.katex .fontsize-ensurer.reset-size8.size1,.katex .sizing.reset-size8.size1{font-size:.34722222em}.katex .fontsize-ensurer.reset-size8.size2,.katex .sizing.reset-size8.size2{font-size:.41666667em}.katex .fontsize-ensurer.reset-size8.size3,.katex .sizing.reset-size8.size3{font-size:.48611111em}.katex .fontsize-ensurer.reset-size8.size4,.katex .sizing.reset-size8.size4{font-size:.55555556em}.katex .fontsize-ensurer.reset-size8.size5,.katex .sizing.reset-size8.size5{font-size:.625em}.katex .fontsize-ensurer.reset-size8.size6,.katex .sizing.reset-size8.size6{font-size:.69444444em}.katex .fontsize-ensurer.reset-size8.size7,.katex .sizing.reset-size8.size7{font-size:.83333333em}.katex .fontsize-ensurer.reset-size8.size8,.katex .sizing.reset-size8.size8{font-size:1em}.katex .fontsize-ensurer.reset-size8.size9,.katex .sizing.reset-size8.size9{font-size:1.2em}.katex .fontsize-ensurer.reset-size8.size10,.katex .sizing.reset-size8.size10{font-size:1.44027778em}.katex .fontsize-ensurer.reset-size8.size11,.katex .sizing.reset-size8.size11{font-size:1.72777778em}.katex .fontsize-ensurer.reset-size9.size1,.katex .sizing.reset-size9.size1{font-size:.28935185em}.katex .fontsize-ensurer.reset-size9.size2,.katex .sizing.reset-size9.size2{font-size:.34722222em}.katex .fontsize-ensurer.reset-size9.size3,.katex .sizing.reset-size9.size3{font-size:.40509259em}.katex .fontsize-ensurer.reset-size9.size4,.katex .sizing.reset-size9.size4{font-size:.46296296em}.katex .fontsize-ensurer.reset-size9.size5,.katex .sizing.reset-size9.size5{font-size:.52083333em}.katex .fontsize-ensurer.reset-size9.size6,.katex .sizing.reset-size9.size6{font-size:.5787037em}.katex .fontsize-ensurer.reset-size9.size7,.katex .sizing.reset-size9.size7{font-size:.69444444em}.katex .fontsize-ensurer.reset-size9.size8,.katex .sizing.reset-size9.size8{font-size:.83333333em}.katex .fontsize-ensurer.reset-size9.size9,.katex .sizing.reset-size9.size9{font-size:1em}.katex .fontsize-ensurer.reset-size9.size10,.katex .sizing.reset-size9.size10{font-size:1.20023148em}.katex .fontsize-ensurer.reset-size9.size11,.katex .sizing.reset-size9.size11{font-size:1.43981481em}.katex .fontsize-ensurer.reset-size10.size1,.katex .sizing.reset-size10.size1{font-size:.24108004em}.katex .fontsize-ensurer.reset-size10.size2,.katex .sizing.reset-size10.size2{font-size:.28929605em}.katex .fontsize-ensurer.reset-size10.size3,.katex .sizing.reset-size10.size3{font-size:.33751205em}.katex .fontsize-ensurer.reset-size10.size4,.katex .sizing.reset-size10.size4{font-size:.38572806em}.katex .fontsize-ensurer.reset-size10.size5,.katex .sizing.reset-size10.size5{font-size:.43394407em}.katex .fontsize-ensurer.reset-size10.size6,.katex .sizing.reset-size10.size6{font-size:.48216008em}.katex .fontsize-ensurer.reset-size10.size7,.katex .sizing.reset-size10.size7{font-size:.57859209em}.katex .fontsize-ensurer.reset-size10.size8,.katex .sizing.reset-size10.size8{font-size:.69431051em}.katex .fontsize-ensurer.reset-size10.size9,.katex .sizing.reset-size10.size9{font-size:.83317261em}.katex .fontsize-ensurer.reset-size10.size10,.katex .sizing.reset-size10.size10{font-size:1em}.katex .fontsize-ensurer.reset-size10.size11,.katex .sizing.reset-size10.size11{font-size:1.19961427em}.katex .fontsize-ensurer.reset-size11.size1,.katex .sizing.reset-size11.size1{font-size:.20096463em}.katex .fontsize-ensurer.reset-size11.size2,.katex .sizing.reset-size11.size2{font-size:.24115756em}.katex .fontsize-ensurer.reset-size11.size3,.katex .sizing.reset-size11.size3{font-size:.28135048em}.katex .fontsize-ensurer.reset-size11.size4,.katex .sizing.reset-size11.size4{font-size:.32154341em}.katex .fontsize-ensurer.reset-size11.size5,.katex .sizing.reset-size11.size5{font-size:.36173633em}.katex .fontsize-ensurer.reset-size11.size6,.katex .sizing.reset-size11.size6{font-size:.40192926em}.katex .fontsize-ensurer.reset-size11.size7,.katex .sizing.reset-size11.size7{font-size:.48231511em}.katex .fontsize-ensurer.reset-size11.size8,.katex .sizing.reset-size11.size8{font-size:.57877814em}.katex .fontsize-ensurer.reset-size11.size9,.katex .sizing.reset-size11.size9{font-size:.69453376em}.katex .fontsize-ensurer.reset-size11.size10,.katex .sizing.reset-size11.size10{font-size:.83360129em}.katex .fontsize-ensurer.reset-size11.size11,.katex .sizing.reset-size11.size11{font-size:1em}.katex .delimsizing.size1{font-family:KaTeX_Size1}.katex .delimsizing.size2{font-family:KaTeX_Size2}.katex .delimsizing.size3{font-family:KaTeX_Size3}.katex .delimsizing.size4{font-family:KaTeX_Size4}.katex .delimsizing.mult .delim-size1>span{font-family:KaTeX_Size1}.katex .delimsizing.mult .delim-size4>span{font-family:KaTeX_Size4}.katex .nulldelimiter{display:inline-block;width:.12em}.katex .delimcenter,.katex .op-symbol{position:relative}.katex .op-symbol.small-op{font-family:KaTeX_Size1}.katex .op-symbol.large-op{font-family:KaTeX_Size2}.katex .accent>.vlist-t,.katex .op-limits>.vlist-t{text-align:center}.katex .accent .accent-body{position:relative}.katex .accent .accent-body:not(.accent-full){width:0}.katex .overlay{display:block}.katex .mtable .vertical-separator{display:inline-block;min-width:1px}.katex .mtable .arraycolsep{display:inline-block}.katex .mtable .col-align-c>.vlist-t{text-align:center}.katex .mtable .col-align-l>.vlist-t{text-align:left}.katex .mtable .col-align-r>.vlist-t{text-align:right}.katex .svg-align{text-align:left}.katex svg{fill:currentColor;stroke:currentColor;fill-rule:nonzero;fill-opacity:1;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:block;height:inherit;position:absolute;width:100%}.katex svg path{stroke:none}.katex img{border-style:none;max-height:none;max-width:none;min-height:0;min-width:0}.katex .stretchy{display:block;overflow:hidden;position:relative;width:100%}.katex .stretchy:after,.katex .stretchy:before{content:""}.katex .hide-tail{overflow:hidden;position:relative;width:100%}.katex .halfarrow-left{left:0;overflow:hidden;position:absolute;width:50.2%}.katex .halfarrow-right{overflow:hidden;position:absolute;right:0;width:50.2%}.katex .brace-left{left:0;overflow:hidden;position:absolute;width:25.1%}.katex .brace-center{left:25%;overflow:hidden;position:absolute;width:50%}.katex .brace-right{overflow:hidden;position:absolute;right:0;width:25.1%}.katex .x-arrow-pad{padding:0 .5em}.katex .cd-arrow-pad{padding:0 .55556em 0 .27778em}.katex .mover,.katex .munder,.katex .x-arrow{text-align:center}.katex .boxpad{padding:0 .3em}.katex .fbox,.katex .fcolorbox{border:.04em solid;box-sizing:border-box}.katex .cancel-pad{padding:0 .2em}.katex .cancel-lap{margin-left:-.2em;margin-right:-.2em}.katex .sout{border-bottom-style:solid;border-bottom-width:.08em}.katex .angl{border-right:.049em solid;border-top:.049em solid;box-sizing:border-box;margin-right:.03889em}.katex .anglpad{padding:0 .03889em}.katex .eqn-num:before{content:"(" counter(katexEqnNo) ")";counter-increment:katexEqnNo}.katex .mml-eqn-num:before{content:"(" counter(mmlEqnNo) ")";counter-increment:mmlEqnNo}.katex .mtr-glue{width:50%}.katex .cd-vert-arrow{display:inline-block;position:relative}.katex .cd-label-left{display:inline-block;position:absolute;right:calc(50% + .3em);text-align:left}.katex .cd-label-right{display:inline-block;left:calc(50% + .3em);position:absolute;text-align:right}.katex-display{display:block;margin:1em 0;text-align:center}.katex-display>.katex{display:block;text-align:center;white-space:nowrap}.katex-display>.katex>.katex-html{display:block;position:relative}.katex-display>.katex>.katex-html>.tag{position:absolute;right:0}.katex-display.leqno>.katex>.katex-html>.tag{left:0;right:auto}.katex-display.fleqn>.katex{padding-left:2em;text-align:left}body{counter-reset:katexEqnNo mmlEqnNo} 2 | -------------------------------------------------------------------------------- /assets/js/lib/lazysizes.min.js: -------------------------------------------------------------------------------- 1 | /*! lazysizes - v5.3.2 */ 2 | 3 | !function(e){var t=function(u,D,f){"use strict";var k,H;if(function(){var e;var t={lazyClass:"lazyload",loadedClass:"lazyloaded",loadingClass:"lazyloading",preloadClass:"lazypreload",errorClass:"lazyerror",autosizesClass:"lazyautosizes",fastLoadedClass:"ls-is-cached",iframeLoadMode:0,srcAttr:"data-src",srcsetAttr:"data-srcset",sizesAttr:"data-sizes",minSize:40,customMedia:{},init:true,expFactor:1.5,hFac:.8,loadMode:2,loadHidden:true,ricTimeout:0,throttleDelay:125};H=u.lazySizesConfig||u.lazysizesConfig||{};for(e in t){if(!(e in H)){H[e]=t[e]}}}(),!D||!D.getElementsByClassName){return{init:function(){},cfg:H,noSupport:true}}var O=D.documentElement,i=u.HTMLPictureElement,P="addEventListener",$="getAttribute",q=u[P].bind(u),I=u.setTimeout,U=u.requestAnimationFrame||I,o=u.requestIdleCallback,j=/^picture$/i,r=["load","error","lazyincluded","_lazyloaded"],a={},G=Array.prototype.forEach,J=function(e,t){if(!a[t]){a[t]=new RegExp("(\\s|^)"+t+"(\\s|$)")}return a[t].test(e[$]("class")||"")&&a[t]},K=function(e,t){if(!J(e,t)){e.setAttribute("class",(e[$]("class")||"").trim()+" "+t)}},Q=function(e,t){var a;if(a=J(e,t)){e.setAttribute("class",(e[$]("class")||"").replace(a," "))}},V=function(t,a,e){var i=e?P:"removeEventListener";if(e){V(t,a)}r.forEach(function(e){t[i](e,a)})},X=function(e,t,a,i,r){var n=D.createEvent("Event");if(!a){a={}}a.instance=k;n.initEvent(t,!i,!r);n.detail=a;e.dispatchEvent(n);return n},Y=function(e,t){var a;if(!i&&(a=u.picturefill||H.pf)){if(t&&t.src&&!e[$]("srcset")){e.setAttribute("srcset",t.src)}a({reevaluate:true,elements:[e]})}else if(t&&t.src){e.src=t.src}},Z=function(e,t){return(getComputedStyle(e,null)||{})[t]},s=function(e,t,a){a=a||e.offsetWidth;while(a49?function(){o(t,{timeout:n});if(n!==H.ricTimeout){n=H.ricTimeout}}:te(function(){I(t)},true);return function(e){var t;if(e=e===true){n=33}if(a){return}a=true;t=r-(f.now()-i);if(t<0){t=0}if(e||t<9){s()}else{I(s,t)}}},ie=function(e){var t,a;var i=99;var r=function(){t=null;e()};var n=function(){var e=f.now()-a;if(e0;if(r&&Z(i,"overflow")!="visible"){a=i.getBoundingClientRect();r=C>a.left&&pa.top-1&&g500&&O.clientWidth>500?500:370:H.expand;k._defEx=u;f=u*H.expFactor;c=H.hFac;A=null;if(w2&&h>2&&!D.hidden){w=f;N=0}else if(h>1&&N>1&&M<6){w=u}else{w=_}}if(l!==n){y=innerWidth+n*c;z=innerHeight+n;s=n*-1;l=n}a=d[t].getBoundingClientRect();if((b=a.bottom)>=s&&(g=a.top)<=z&&(C=a.right)>=s*c&&(p=a.left)<=y&&(b||C||p||g)&&(H.loadHidden||x(d[t]))&&(m&&M<3&&!o&&(h<3||N<4)||W(d[t],n))){R(d[t]);r=true;if(M>9){break}}else if(!r&&m&&!i&&M<4&&N<4&&h>2&&(v[0]||H.preloadAfterLoad)&&(v[0]||!o&&(b||C||p||g||d[t][$](H.sizesAttr)!="auto"))){i=v[0]||d[t]}}if(i&&!r){R(i)}}};var a=ae(t);var S=function(e){var t=e.target;if(t._lazyCache){delete t._lazyCache;return}L(e);K(t,H.loadedClass);Q(t,H.loadingClass);V(t,B);X(t,"lazyloaded")};var i=te(S);var B=function(e){i({target:e.target})};var T=function(e,t){var a=e.getAttribute("data-load-mode")||H.iframeLoadMode;if(a==0){e.contentWindow.location.replace(t)}else if(a==1){e.src=t}};var F=function(e){var t;var a=e[$](H.srcsetAttr);if(t=H.customMedia[e[$]("data-media")||e[$]("media")]){e.setAttribute("media",t)}if(a){e.setAttribute("srcset",a)}};var s=te(function(t,e,a,i,r){var n,s,o,l,u,f;if(!(u=X(t,"lazybeforeunveil",e)).defaultPrevented){if(i){if(a){K(t,H.autosizesClass)}else{t.setAttribute("sizes",i)}}s=t[$](H.srcsetAttr);n=t[$](H.srcAttr);if(r){o=t.parentNode;l=o&&j.test(o.nodeName||"")}f=e.firesLoad||"src"in t&&(s||n||l);u={target:t};K(t,H.loadingClass);if(f){clearTimeout(c);c=I(L,2500);V(t,B,true)}if(l){G.call(o.getElementsByTagName("source"),F)}if(s){t.setAttribute("srcset",s)}else if(n&&!l){if(d.test(t.nodeName)){T(t,n)}else{t.src=n}}if(r&&(s||l)){Y(t,{src:n})}}if(t._lazyRace){delete t._lazyRace}Q(t,H.lazyClass);ee(function(){var e=t.complete&&t.naturalWidth>1;if(!f||e){if(e){K(t,H.fastLoadedClass)}S(u);t._lazyCache=true;I(function(){if("_lazyCache"in t){delete t._lazyCache}},9)}if(t.loading=="lazy"){M--}},true)});var R=function(e){if(e._lazyRace){return}var t;var a=n.test(e.nodeName);var i=a&&(e[$](H.sizesAttr)||e[$]("sizes"));var r=i=="auto";if((r||!m)&&a&&(e[$]("src")||e.srcset)&&!e.complete&&!J(e,H.errorClass)&&J(e,H.lazyClass)){return}t=X(e,"lazyunveilread").detail;if(r){re.updateElem(e,true,e.offsetWidth)}e._lazyRace=true;M++;s(e,t,r,i,a)};var r=ie(function(){H.loadMode=3;a()});var o=function(){if(H.loadMode==3){H.loadMode=2}r()};var l=function(){if(m){return}if(f.now()-e<999){I(l,999);return}m=true;H.loadMode=3;a();q("scroll",o,true)};return{_:function(){e=f.now();k.elements=D.getElementsByClassName(H.lazyClass);v=D.getElementsByClassName(H.lazyClass+" "+H.preloadClass);q("scroll",a,true);q("resize",a,true);q("pageshow",function(e){if(e.persisted){var t=D.querySelectorAll("."+H.loadingClass);if(t.length&&t.forEach){U(function(){t.forEach(function(e){if(e.complete){R(e)}})})}}});if(u.MutationObserver){new MutationObserver(a).observe(O,{childList:true,subtree:true,attributes:true})}else{O[P]("DOMNodeInserted",a,true);O[P]("DOMAttrModified",a,true);setInterval(a,999)}q("hashchange",a,true);["focus","mouseover","click","load","transitionend","animationend"].forEach(function(e){D[P](e,a,true)});if(/d$|^c/.test(D.readyState)){l()}else{q("load",l);D[P]("DOMContentLoaded",a);I(l,2e4)}if(k.elements.length){t();ee._lsFlush()}else{a()}},checkElems:a,unveil:R,_aLSL:o}}(),re=function(){var a;var n=te(function(e,t,a,i){var r,n,s;e._lazysizesWidth=i;i+="px";e.setAttribute("sizes",i);if(j.test(t.nodeName||"")){r=t.getElementsByTagName("source");for(n=0,s=r.length;n { 4 | const OPTION_HEAD = option.querySelector('.calculator-content-head') 5 | 6 | OPTION_HEAD.addEventListener('click', (event) => { 7 | 8 | if(!event.composedPath().includes($('.js-add-button'))) { 9 | option.classList.toggle('calculator-content--active') 10 | } 11 | }) 12 | }) -------------------------------------------------------------------------------- /assets/js/themes.js: -------------------------------------------------------------------------------- 1 | const setActiveThemeButton = (theme) => { 2 | document.querySelectorAll('.header-popup__button').forEach(button => { 3 | if(button.classList.contains(`${theme}-theme`)) button.classList.add('header-popup__button--active') 4 | else button.classList.remove('header-popup__button--active') 5 | }) 6 | } 7 | 8 | switch (localStorage.getItem('theme')) { 9 | case 'light': 10 | document.documentElement.classList = ''; 11 | console.log('Theme: Light'); 12 | localStorage.setItem('theme', 'light'); 13 | window.addEventListener('DOMContentLoaded', () => { 14 | setActiveThemeButton('light') 15 | }) 16 | break; 17 | case 'dark': 18 | document.documentElement.classList = 'dark'; 19 | console.log('Theme: Dark'); 20 | localStorage.setItem('theme', 'dark'); 21 | window.addEventListener('DOMContentLoaded', () => { 22 | setActiveThemeButton('dark') 23 | }) 24 | break; 25 | case 'system': 26 | default: 27 | document.documentElement.classList = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : ''; 28 | console.log('Theme: System'); 29 | localStorage.setItem('theme', 'system'); 30 | window.addEventListener('DOMContentLoaded', () => { 31 | setActiveThemeButton('system') 32 | }) 33 | } -------------------------------------------------------------------------------- /assets/js/timepicker.js: -------------------------------------------------------------------------------- 1 | const INPUTS = $$('.timepicker-input'); 2 | let timepickerFormat = true 3 | let currentInput = { 4 | input: null, 5 | hour: null, 6 | minute: null, 7 | second: null, 8 | } 9 | 10 | function createTimepicker() { 11 | const TIMEPICKER = document.createElement('div'); 12 | const {top, left} = currentInput.input.getBoundingClientRect() 13 | const {offsetHeight} = currentInput.input 14 | const VALUE = currentInput.input.value.split(':') 15 | 16 | TIMEPICKER.classList.add('timepicker'); 17 | TIMEPICKER.innerHTML = ` 18 |

19 |
20 |
21 |

Hour

22 | 23 |
24 |

:

25 |
26 |

Minute

27 | 28 |
29 |

:

30 |
31 |

Second

32 | 33 |
34 |
35 |
36 | 39 | 42 |
43 |
44 | 45 | 54 | ` 55 | document.body.appendChild(TIMEPICKER); 56 | TIMEPICKER.style.top = top + window.scrollY + 9 + offsetHeight + 'px'; 57 | TIMEPICKER.style.left = left - 13 + 'px'; 58 | TIMEPICKER.classList.add('timepicker--active'); 59 | 60 | const TIMEPICKER_DONE = document.getElementById('timepicker_done') 61 | const TIMEPICKER_CANCEL = document.getElementById('timepicker_cancel') 62 | const TIMEPICKER_HOUR = document.getElementById('timepicker_hour') 63 | const TIMEPICKER_MINUTE = document.getElementById('timepicker_minute') 64 | const TIMEPICKER_SECOND = document.getElementById('timepicker_second') 65 | const TIMEPICKER_FORMAT_SWITCHER = document.getElementById('timepicker_format_switcher') 66 | const TIMEPICKER_FORMAT = document.getElementById('timepicker_format') 67 | const SWITCH_TO_AM = document.getElementById('switch_to_am') 68 | const SWITCH_TO_PM = document.getElementById('switch_to_pm') 69 | 70 | SWITCH_TO_AM.addEventListener('click', () => { 71 | SWITCH_TO_PM.classList.remove('button-switcher--active') 72 | SWITCH_TO_AM.classList.add('button-switcher--active') 73 | }) 74 | 75 | SWITCH_TO_PM.addEventListener('click', () => { 76 | SWITCH_TO_AM.classList.remove('button-switcher--active') 77 | SWITCH_TO_PM.classList.add('button-switcher--active') 78 | }) 79 | 80 | TIMEPICKER_HOUR.addEventListener('input', (event) => { 81 | limitLengthHandler(event.target, 2) 82 | currentInput.hour = event.target.value 83 | if(event.target.value.length === 2) TIMEPICKER_MINUTE.focus() 84 | }) 85 | TIMEPICKER_MINUTE.addEventListener('input', (event) => { 86 | limitLengthHandler(event.target, 2) 87 | currentInput.minute = event.target.value 88 | if(event.target.value.length === 2) TIMEPICKER_SECOND.focus() 89 | }) 90 | TIMEPICKER_SECOND.addEventListener('input', (event) => { 91 | currentInput.second = event.target.value 92 | limitLengthHandler(event.target, 2) 93 | }) 94 | 95 | TIMEPICKER_FORMAT_SWITCHER.addEventListener('input', (event) => { 96 | if(event.target.checked) { 97 | TIMEPICKER_FORMAT.style.display = 'none' 98 | timepickerFormat = false 99 | } 100 | else { 101 | TIMEPICKER_FORMAT.style.display = 'flex' 102 | timepickerFormat = true 103 | } 104 | }) 105 | 106 | TIMEPICKER_DONE.addEventListener('click', onDoneTimepicker) 107 | window.addEventListener('keydown', onDoneTimepickerEnter) 108 | 109 | TIMEPICKER_CANCEL.addEventListener('click', () => { 110 | onCloseTimepicker(); 111 | }) 112 | } 113 | 114 | function limitLengthHandler(input, limit) { 115 | if(input.value.length > limit) { 116 | input.value = input.value.slice(0, limit); 117 | } 118 | return input.value; 119 | } 120 | 121 | function onDoneTimepickerEnter (event) { 122 | if(event.key === 'Enter') { 123 | onDoneTimepicker(); 124 | } 125 | } 126 | 127 | function onDoneTimepicker () { 128 | let hours = currentInput.hour < 10 ? '0' + currentInput.hour : currentInput.hour 129 | let minutes = currentInput.minute < 10 ? '0' + currentInput.minute : currentInput.minute 130 | let seconds = currentInput.second < 10 ? '0' + currentInput.second : currentInput.second 131 | 132 | currentInput.input.value = `${hours > 0 ? hours : '00'}:${minutes > 0 ? minutes : '00'}:${seconds > 0 ? seconds : '00'}` 133 | onCloseTimepicker(); 134 | window.removeEventListener('keydown', onDoneTimepickerEnter) 135 | window.removeEventListener('click', onCloseTimepickerOutside) 136 | } 137 | 138 | function onCloseTimepicker() { 139 | currentInput.input = null 140 | document.body.removeChild($('.timepicker')); 141 | window.removeEventListener('click', onCloseTimepickerOutside) 142 | } 143 | 144 | function onCloseTimepickerOutside(event) { 145 | if($('.timepicker') && !(event.composedPath().includes($('.timepicker')) || event.composedPath().includes(currentInput.input))) { 146 | onCloseTimepicker(); 147 | } 148 | } 149 | 150 | window.timepicker = (event) => { 151 | if($('.timepicker')) { 152 | onCloseTimepicker(); 153 | } else { 154 | currentInput.input = event.target 155 | createTimepicker() 156 | window.addEventListener('click', onCloseTimepickerOutside) 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /ci_days_calculator.php: -------------------------------------------------------------------------------- 1 | Days Calculator
'; 20 | } 21 | 22 | 23 | add_shortcode( 'ci_days_calculator', 'display_calcio_ci_days_calculator' ); -------------------------------------------------------------------------------- /plugin.php: -------------------------------------------------------------------------------- 1 | Days Calculator
'; 20 | } 21 | 22 | add_shortcode( 'ci_days_calculator', 'display_ci_days_calculator' ); -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Days Calculator Widget for WordPress 2 | 3 | The free days calculator makes it easy to figure out how many days between two dates. This day tracker can include or exclude weekends and holidays. 4 | 5 | ![Days Calculator Input Form](/assets/images/screenshot-1.png "Days Calculator Input Form") 6 | 7 | ## Installation 8 | 9 | 1. [Download](https://github.com/pub-calculator-io/days-calculator/archive/refs/heads/master.zip) the ZIP file of this repository. 10 | 2. Upload the /days-calculator-master/ folder to the /wp-content/plugins/ directory. 11 | 3. Activate the [Days Calculator](https://www.calculator.io/days-calculator/ "Days Calculator Homepage") plugin through the "Plugins" menu in WordPress. 12 | 13 | ## Usage 14 | * Add the shortcode `[ci_days_calculator]` to your page, post or sidebar. 15 | * Or add the following code: `` to your template where you would like the Days Calculator to appear. 16 | 17 | ## Libraries in Use 18 | 1. https://mathjs.org/ 19 | 2. https://katex.org/ 20 | 3. https://github.com/aFarkas/lazysizes 21 | 4. https://github.com/RobinHerbots/Inputmask 22 | 5. https://air-datepicker.com/ 23 | 6. https://www.chartjs.org/ 24 | -------------------------------------------------------------------------------- /readme.txt: -------------------------------------------------------------------------------- 1 | === CI Days calculator === 2 | Contributors: calculatorio 3 | Tags: days between dates calculator, calculate days until event, workday counter tool, vacation countdown calculator, payment tracking calculator, project deadline calculator, educational planning tool, calculate weekdays and weekends, public holiday date calculator, daily countdown tool 4 | Requires at least: 5.0 5 | Tested up to: 6.4.0 6 | Stable tag: 1.0.0 7 | License: GPLv2 or later 8 | License URI: https://www.gnu.org/licenses/gpl-2.0.html 9 | 10 | The free days calculator makes it easy to figure out how many days between two dates. This day tracker can include or exclude weekends and holidays. 11 | 12 | [https://www.calculator.io/days-calculator/](https://www.calculator.io/days-calculator/) 13 | 14 | == Usage == 15 | 16 | Add the Days Calculator shortcode to your page, post or sidebar: 17 | 18 | `[ci_days_calculator]` 19 | 20 | Add the following code to your template where you would like the Days Calculator to appear: 21 | 22 | `` 23 | 24 | == Screenshots == 25 | 26 | 1. The Days Calculator Input Form. 27 | 28 | == Installation == 29 | 30 | 1. Upload the Days Calculator /ci_days_calculator/ folder to the /wp-content/plugins/ directory. 31 | 2. Activate the Days Calculator plugin through the "Plugins" menu in WordPress. 32 | 33 | == Changelog == 34 | 35 | = 1.0.0 = 36 | * Initial release of Days Calculator 37 | --------------------------------------------------------------------------------