├── 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-1280x640.png │ ├── banner-1544x500.png │ ├── banner-772x250.png │ ├── favicon.ico │ ├── icon-128.png │ ├── icon-128x128.png │ ├── icon-16.png │ ├── icon-192.png │ ├── icon-196.png │ ├── icon-256.png │ ├── icon-256x256.png │ ├── icon-32.png │ ├── icon-48.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 │ ├── 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_ovulation_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/ovulation-calculator/7aa3a0c120755ded6d1ad41212b819bafe40ba7b/assets/fonts/inter-v12-latin-500.woff2 -------------------------------------------------------------------------------- /assets/fonts/inter-v12-latin-600.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pub-calculator-io/ovulation-calculator/7aa3a0c120755ded6d1ad41212b819bafe40ba7b/assets/fonts/inter-v12-latin-600.woff2 -------------------------------------------------------------------------------- /assets/fonts/inter-v12-latin-800.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pub-calculator-io/ovulation-calculator/7aa3a0c120755ded6d1ad41212b819bafe40ba7b/assets/fonts/inter-v12-latin-800.woff2 -------------------------------------------------------------------------------- /assets/fonts/inter-v12-latin-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pub-calculator-io/ovulation-calculator/7aa3a0c120755ded6d1ad41212b819bafe40ba7b/assets/fonts/inter-v12-latin-regular.woff2 -------------------------------------------------------------------------------- /assets/images/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pub-calculator-io/ovulation-calculator/7aa3a0c120755ded6d1ad41212b819bafe40ba7b/assets/images/apple-touch-icon.png -------------------------------------------------------------------------------- /assets/images/banner-1280x640.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pub-calculator-io/ovulation-calculator/7aa3a0c120755ded6d1ad41212b819bafe40ba7b/assets/images/banner-1280x640.png -------------------------------------------------------------------------------- /assets/images/banner-1544x500.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pub-calculator-io/ovulation-calculator/7aa3a0c120755ded6d1ad41212b819bafe40ba7b/assets/images/banner-1544x500.png -------------------------------------------------------------------------------- /assets/images/banner-772x250.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pub-calculator-io/ovulation-calculator/7aa3a0c120755ded6d1ad41212b819bafe40ba7b/assets/images/banner-772x250.png -------------------------------------------------------------------------------- /assets/images/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pub-calculator-io/ovulation-calculator/7aa3a0c120755ded6d1ad41212b819bafe40ba7b/assets/images/favicon.ico -------------------------------------------------------------------------------- /assets/images/icon-128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pub-calculator-io/ovulation-calculator/7aa3a0c120755ded6d1ad41212b819bafe40ba7b/assets/images/icon-128.png -------------------------------------------------------------------------------- /assets/images/icon-128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pub-calculator-io/ovulation-calculator/7aa3a0c120755ded6d1ad41212b819bafe40ba7b/assets/images/icon-128x128.png -------------------------------------------------------------------------------- /assets/images/icon-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pub-calculator-io/ovulation-calculator/7aa3a0c120755ded6d1ad41212b819bafe40ba7b/assets/images/icon-16.png -------------------------------------------------------------------------------- /assets/images/icon-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pub-calculator-io/ovulation-calculator/7aa3a0c120755ded6d1ad41212b819bafe40ba7b/assets/images/icon-192.png -------------------------------------------------------------------------------- /assets/images/icon-196.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pub-calculator-io/ovulation-calculator/7aa3a0c120755ded6d1ad41212b819bafe40ba7b/assets/images/icon-196.png -------------------------------------------------------------------------------- /assets/images/icon-256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pub-calculator-io/ovulation-calculator/7aa3a0c120755ded6d1ad41212b819bafe40ba7b/assets/images/icon-256.png -------------------------------------------------------------------------------- /assets/images/icon-256x256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pub-calculator-io/ovulation-calculator/7aa3a0c120755ded6d1ad41212b819bafe40ba7b/assets/images/icon-256x256.png -------------------------------------------------------------------------------- /assets/images/icon-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pub-calculator-io/ovulation-calculator/7aa3a0c120755ded6d1ad41212b819bafe40ba7b/assets/images/icon-32.png -------------------------------------------------------------------------------- /assets/images/icon-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pub-calculator-io/ovulation-calculator/7aa3a0c120755ded6d1ad41212b819bafe40ba7b/assets/images/icon-48.png -------------------------------------------------------------------------------- /assets/images/icon-96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pub-calculator-io/ovulation-calculator/7aa3a0c120755ded6d1ad41212b819bafe40ba7b/assets/images/icon-96.png -------------------------------------------------------------------------------- /assets/images/icon-og.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pub-calculator-io/ovulation-calculator/7aa3a0c120755ded6d1ad41212b819bafe40ba7b/assets/images/icon-og.png -------------------------------------------------------------------------------- /assets/images/icon-rounded.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pub-calculator-io/ovulation-calculator/7aa3a0c120755ded6d1ad41212b819bafe40ba7b/assets/images/icon-rounded.png -------------------------------------------------------------------------------- /assets/images/icon-square.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pub-calculator-io/ovulation-calculator/7aa3a0c120755ded6d1ad41212b819bafe40ba7b/assets/images/icon-square.png -------------------------------------------------------------------------------- /assets/images/illustration-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pub-calculator-io/ovulation-calculator/7aa3a0c120755ded6d1ad41212b819bafe40ba7b/assets/images/illustration-1.png -------------------------------------------------------------------------------- /assets/images/illustration-els.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pub-calculator-io/ovulation-calculator/7aa3a0c120755ded6d1ad41212b819bafe40ba7b/assets/images/illustration-els.png -------------------------------------------------------------------------------- /assets/images/illustration-og.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pub-calculator-io/ovulation-calculator/7aa3a0c120755ded6d1ad41212b819bafe40ba7b/assets/images/illustration-og.png -------------------------------------------------------------------------------- /assets/images/screenshot-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pub-calculator-io/ovulation-calculator/7aa3a0c120755ded6d1ad41212b819bafe40ba7b/assets/images/screenshot-1.png -------------------------------------------------------------------------------- /assets/images/screenshot-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pub-calculator-io/ovulation-calculator/7aa3a0c120755ded6d1ad41212b819bafe40ba7b/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 | const firstDay = input.get('first_day').date().raw(); 3 | let cyclesLength = input.get('avg_cycles_length').index().val(); 4 | if(!input.valid()) return; 5 | cyclesLength = cyclesLength + 22; 6 | const ovulationWindow = calculateOvulationWindow(cyclesLength, firstDay); 7 | const mostProbableOvulationDay = new Date(ovulationWindow.startDate); 8 | mostProbableOvulationDay.setDate(mostProbableOvulationDay.getDate() + 2); 9 | 10 | const intercourseDay = new Date(ovulationWindow.startDate); 11 | intercourseDay.setDate(intercourseDay.getDate() - 3); 12 | 13 | const testDay = new Date(ovulationWindow.endDate); 14 | testDay.setDate(testDay.getDate() + 7); 15 | 16 | const nextPeriod = new Date(firstDay); 17 | nextPeriod.setDate(nextPeriod.getDate() + cyclesLength); 18 | 19 | output.val(formattedDate(ovulationWindow.startDate) + ' - ' + formattedDate(ovulationWindow.endDate)).set('ovulation-window'); 20 | output.val(formattedDate(intercourseDay) + ' - ' + formattedDate(ovulationWindow.endDate)).set('intercourse-window'); 21 | output.val(formattedDate(mostProbableOvulationDay)).set('most-probable'); 22 | output.val(formattedDate(testDay)).set('test-day'); 23 | output.val(formattedDate(nextPeriod)).set('next-period'); 24 | 25 | let estimationTable = ''; 26 | for(let i = 1; i <= 6; i++){ 27 | let date = new Date(firstDay); 28 | date.setDate(date.getDate() + (cyclesLength * (i - 1))); 29 | let ovulationWin = calculateOvulationWindow(cyclesLength, date); 30 | let dueDate = new Date(date); 31 | dueDate.setDate(dueDate.getDate() + cyclesLength - 28 + 280); 32 | estimationTable += ` 33 | ${i} 34 | ${formattedDate(date)} 35 | ${formattedDate(ovulationWin.startDate)} - ${formattedDate(ovulationWin.endDate)} 36 | ${formattedDate(dueDate)} 37 | `; 38 | } 39 | 40 | output.val(estimationTable).set('next-6-cycles'); 41 | generateCalendar(ovulationWindow.startDate, ovulationWindow.startDate, ovulationWindow.endDate); 42 | 43 | } 44 | 45 | function calculateOvulationWindow(cycleLength, firstDay) { 46 | cycleLength = Number(cycleLength); 47 | 48 | var firstDayDate = new Date(firstDay); 49 | 50 | var startDate = new Date(firstDayDate); 51 | startDate.setDate(firstDayDate.getDate() + (cycleLength - 16)); 52 | 53 | var endDate = new Date(firstDayDate); 54 | endDate.setDate(firstDayDate.getDate() + (cycleLength - 12)); 55 | 56 | return { 57 | startDate, 58 | endDate 59 | }; 60 | } 61 | 62 | function formattedDate(date, onlyMonth = false){ 63 | const monthNames = ["Jan", "Feb", "Marc", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; 64 | const day = date.getDate(); 65 | const month = monthNames[date.getMonth()] 66 | const year = date.getFullYear(); 67 | if(onlyMonth) return month + ' ' + year; 68 | return month + ' ' + day + ', ' + year; 69 | } 70 | 71 | function generateCalendar(date, startDate, endDate, holidays = [], calendar = 'result-start-date') { 72 | const daysInMonth = new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate(); 73 | let firstDay = new Date(date.getFullYear(), date.getMonth(), 1).getDay(); 74 | const daysInMonthPrev = new Date(date.getFullYear(), date.getMonth(), 0).getDate(); 75 | 76 | if (!firstDay) firstDay = 7; 77 | 78 | let activeClass = 'current'; 79 | 80 | const $days = $$(`.${calendar} .result-age--days p`); 81 | 82 | let i = 0; 83 | while (i <= $days.length) { 84 | if ($days[i]) { 85 | $days[i].innerHTML = ''; 86 | $days[i].classList.remove('current', 'active', 'current-between', 'holiday', 'next'); 87 | } 88 | let day = i - firstDay + 1; 89 | const $current_month_day = $days[i - 1]; 90 | const currentDate = new Date(date.getFullYear(), date.getMonth(), day); 91 | /*Current month*/ 92 | if (i >= firstDay && i < daysInMonth + firstDay) { 93 | $current_month_day.innerHTML = day; 94 | $current_month_day.classList.add('active'); 95 | if(holidays.find(holiday => ((holiday.day === day) && (holiday.month === (date.getMonth() + 1))))) { 96 | $current_month_day.classList.add('holiday'); 97 | } 98 | 99 | if ((day === date.getDate() && date.getMonth() === currentDate.getMonth() && date.getFullYear() === currentDate.getFullYear()) || (day === startDate.getDate() && startDate.getMonth() === currentDate.getMonth() && startDate.getFullYear() === currentDate.getFullYear()) || (day === endDate.getDate() && endDate.getMonth() === currentDate.getMonth() && endDate.getFullYear() === currentDate.getFullYear())) { 100 | $current_month_day.classList.add(activeClass); 101 | } 102 | /*Prev month*/ 103 | } else if (i < firstDay - 1) { 104 | $days[i].classList.add('next'); 105 | if ($days[i]) $days[i].innerHTML = daysInMonthPrev - firstDay + i + 2; 106 | if(holidays.find(holiday => ((holiday.day === (daysInMonthPrev - firstDay + i + 2)) && (holiday.month === (date.getMonth()))))) { 107 | $days[i].classList.add('holiday'); 108 | } 109 | /*Next month*/ 110 | } else if (i >= firstDay) { 111 | $current_month_day.classList.add('next'); 112 | if(holidays.find(holiday => ((holiday.day === (i - daysInMonth - firstDay + 1)) && (holiday.month === (date.getMonth() + 2))))) { 113 | $current_month_day.classList.add('holiday'); 114 | } 115 | $current_month_day.innerHTML = i - daysInMonth - firstDay + 1; 116 | } 117 | /*Holidays*/ 118 | if (holidays.length) { 119 | 120 | } 121 | if(typeof $current_month_day !== 'undefined' && currentDate.getTime() >= startDate.getTime() && currentDate.getTime() < endDate.getTime() && day !== date.getDate() && day !== endDate.getDate()) { 122 | $current_month_day.classList.add('current-between'); 123 | } 124 | i++; 125 | } 126 | 127 | $(`.${calendar} .date-title--date`).innerHTML = formattedDate(date, true); 128 | } 129 | -------------------------------------------------------------------------------- /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/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_ovulation_calculator.php: -------------------------------------------------------------------------------- 1 | Ovulation Calculator
'; 20 | } 21 | 22 | 23 | add_shortcode( 'ci_ovulation_calculator', 'display_calcio_ci_ovulation_calculator' ); -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Ovulation Calculator 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 20 | 21 | 22 | 23 | 24 | 25 |
26 |
27 |
28 |
29 |
30 |
31 | 46 |
47 |
48 |
126 |
127 | 128 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 |
164 |
165 |
166 |
167 |
168 |
169 | 170 | 174 | 175 |

There was an error with your calculation.

176 |
177 |
178 |
179 |
180 |
181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 |
Ovulation WindowJun 13, 2023 - Jun 17, 2023
Most Probable Ovulation DateJun 15, 2023
Intercourse Window for PregnancyJun 10, 2023 - Jun 17, 2023
Pregnancy TestJun 24, 2023
Next Period StartJun 29, 2023
207 |
208 |
209 |

Jun 2023

210 |
211 |

M

212 |

T

213 |

W

214 |

T

215 |

F

216 |

S

217 |

S

218 |
219 |
220 |

29

221 |

30

222 |

31

223 |

1

224 |

2

225 |

3

226 |

4

227 |

5

228 |

6

229 |

7

230 |

8

231 |

9

232 |

10

233 |

11

234 |

12

235 |

13

236 |

14

237 |

15

238 |

16

239 |

17

240 |

18

241 |

19

242 |

20

243 |

21

244 |

22

245 |

23

246 |

24

247 |

25

248 |

26

249 |

27

250 |

28

251 |

29

252 |

30

253 |

1

254 |

2

255 |

3

256 |

4

257 |

5

258 |

6

259 |

7

260 |

8

261 |

9

262 |
263 |
264 |
265 |
266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 |
ESTIMATIONS FOR THE NEXT 6 CYCLES
Period StartOvulation WindowDue Date
1Jun 1, 2023Jun 13, 2023 - Jun 17, 2023Marc 7, 2024
2Jun 29, 2023Jul 11, 2023 - Jul 15, 2023Apr 4, 2024
3Jul 27, 2023Aug 8, 2023 - Aug 12, 2023May 2, 2024
4Aug 24, 2023Sep 5, 2023 - Sep 9, 2023May 30, 2024
5Sep 21, 2023Oct 3, 2023 - Oct 7, 2023Jun 27, 2024
6Oct 19, 2023Oct 31, 2023 - Nov 4, 2023Jul 25, 2024
319 |
320 |
321 |
322 |
323 |
324 | 325 | 326 | 327 | 328 | 329 | -------------------------------------------------------------------------------- /plugin.php: -------------------------------------------------------------------------------- 1 | Ovulation Calculator
'; 20 | } 21 | 22 | add_shortcode( 'ci_ovulation_calculator', 'display_ci_ovulation_calculator' ); -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Ovulation Calculator Widget for WordPress 2 | 3 | Not sure when you’re ovulating? Use this free ovulation calculator to estimate your most fertile days and know when you are most likely to conceive. 4 | 5 | ![Ovulation Calculator Input Form](/assets/images/screenshot-1.png "Ovulation Calculator Input Form") 6 | 7 | ## Installation 8 | 9 | 1. [Download](https://github.com/pub-calculator-io/ovulation-calculator/archive/refs/heads/master.zip) the ZIP file of this repository. 10 | 2. Upload the /ovulation-calculator-master/ folder to the /wp-content/plugins/ directory. 11 | 3. Activate the [Ovulation Calculator](https://www.calculator.io/ovulation-calculator/ "Ovulation Calculator Homepage") plugin through the "Plugins" menu in WordPress. 12 | 13 | ## Usage 14 | * Add the shortcode `[ci_ovulation_calculator]` to your page, post or sidebar. 15 | * Or add the following code: `` to your template where you would like the Ovulation 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 Ovulation calculator === 2 | Contributors: calculatorio 3 | Tags: ovulation calculator, fertile days, menstrual cycle, fertility calculator, conception calculator, pregnancy planning, ovulation prediction, pregnancy calculator, menstrual period, ovulation date 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 | Not sure when you’re ovulating? Use this free ovulation calculator to estimate your most fertile days and know when you are most likely to conceive. 11 | 12 | [https://www.calculator.io/ovulation-calculator/](https://www.calculator.io/ovulation-calculator/) 13 | 14 | == Usage == 15 | 16 | Add the Ovulation Calculator shortcode to your page, post or sidebar: 17 | 18 | `[ci_ovulation_calculator]` 19 | 20 | Add the following code to your template where you would like the Ovulation Calculator to appear: 21 | 22 | `` 23 | 24 | == Screenshots == 25 | 26 | 1. The Ovulation Calculator Input Form. 27 | 28 | == Installation == 29 | 30 | 1. Upload the Ovulation Calculator /ci_ovulation_calculator/ folder to the /wp-content/plugins/ directory. 31 | 2. Activate the Ovulation Calculator plugin through the "Plugins" menu in WordPress. 32 | 33 | == Changelog == 34 | 35 | = 1.0.0 = 36 | * Initial release of Ovulation Calculator 37 | --------------------------------------------------------------------------------