├── assets
├── 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-and.png
│ ├── illustration-and.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_mean_median_mode_calculator.php
├── index.html
├── plugin.php
├── readme.md
└── readme.txt
/assets/fonts/inter-v12-latin-500.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pub-calculator-io/mean-median-mode-calculator/51ba79275fa36342dfef3a9132fdb70bc11c0f9a/assets/fonts/inter-v12-latin-500.woff2
--------------------------------------------------------------------------------
/assets/fonts/inter-v12-latin-600.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pub-calculator-io/mean-median-mode-calculator/51ba79275fa36342dfef3a9132fdb70bc11c0f9a/assets/fonts/inter-v12-latin-600.woff2
--------------------------------------------------------------------------------
/assets/fonts/inter-v12-latin-800.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pub-calculator-io/mean-median-mode-calculator/51ba79275fa36342dfef3a9132fdb70bc11c0f9a/assets/fonts/inter-v12-latin-800.woff2
--------------------------------------------------------------------------------
/assets/fonts/inter-v12-latin-regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pub-calculator-io/mean-median-mode-calculator/51ba79275fa36342dfef3a9132fdb70bc11c0f9a/assets/fonts/inter-v12-latin-regular.woff2
--------------------------------------------------------------------------------
/assets/images/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pub-calculator-io/mean-median-mode-calculator/51ba79275fa36342dfef3a9132fdb70bc11c0f9a/assets/images/apple-touch-icon.png
--------------------------------------------------------------------------------
/assets/images/banner-1280x640.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pub-calculator-io/mean-median-mode-calculator/51ba79275fa36342dfef3a9132fdb70bc11c0f9a/assets/images/banner-1280x640.png
--------------------------------------------------------------------------------
/assets/images/banner-1544x500.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pub-calculator-io/mean-median-mode-calculator/51ba79275fa36342dfef3a9132fdb70bc11c0f9a/assets/images/banner-1544x500.png
--------------------------------------------------------------------------------
/assets/images/banner-772x250.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pub-calculator-io/mean-median-mode-calculator/51ba79275fa36342dfef3a9132fdb70bc11c0f9a/assets/images/banner-772x250.png
--------------------------------------------------------------------------------
/assets/images/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pub-calculator-io/mean-median-mode-calculator/51ba79275fa36342dfef3a9132fdb70bc11c0f9a/assets/images/favicon.ico
--------------------------------------------------------------------------------
/assets/images/icon-128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pub-calculator-io/mean-median-mode-calculator/51ba79275fa36342dfef3a9132fdb70bc11c0f9a/assets/images/icon-128.png
--------------------------------------------------------------------------------
/assets/images/icon-128x128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pub-calculator-io/mean-median-mode-calculator/51ba79275fa36342dfef3a9132fdb70bc11c0f9a/assets/images/icon-128x128.png
--------------------------------------------------------------------------------
/assets/images/icon-16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pub-calculator-io/mean-median-mode-calculator/51ba79275fa36342dfef3a9132fdb70bc11c0f9a/assets/images/icon-16.png
--------------------------------------------------------------------------------
/assets/images/icon-192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pub-calculator-io/mean-median-mode-calculator/51ba79275fa36342dfef3a9132fdb70bc11c0f9a/assets/images/icon-192.png
--------------------------------------------------------------------------------
/assets/images/icon-196.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pub-calculator-io/mean-median-mode-calculator/51ba79275fa36342dfef3a9132fdb70bc11c0f9a/assets/images/icon-196.png
--------------------------------------------------------------------------------
/assets/images/icon-256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pub-calculator-io/mean-median-mode-calculator/51ba79275fa36342dfef3a9132fdb70bc11c0f9a/assets/images/icon-256.png
--------------------------------------------------------------------------------
/assets/images/icon-256x256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pub-calculator-io/mean-median-mode-calculator/51ba79275fa36342dfef3a9132fdb70bc11c0f9a/assets/images/icon-256x256.png
--------------------------------------------------------------------------------
/assets/images/icon-32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pub-calculator-io/mean-median-mode-calculator/51ba79275fa36342dfef3a9132fdb70bc11c0f9a/assets/images/icon-32.png
--------------------------------------------------------------------------------
/assets/images/icon-48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pub-calculator-io/mean-median-mode-calculator/51ba79275fa36342dfef3a9132fdb70bc11c0f9a/assets/images/icon-48.png
--------------------------------------------------------------------------------
/assets/images/icon-96.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pub-calculator-io/mean-median-mode-calculator/51ba79275fa36342dfef3a9132fdb70bc11c0f9a/assets/images/icon-96.png
--------------------------------------------------------------------------------
/assets/images/icon-og.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pub-calculator-io/mean-median-mode-calculator/51ba79275fa36342dfef3a9132fdb70bc11c0f9a/assets/images/icon-og.png
--------------------------------------------------------------------------------
/assets/images/icon-rounded.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pub-calculator-io/mean-median-mode-calculator/51ba79275fa36342dfef3a9132fdb70bc11c0f9a/assets/images/icon-rounded.png
--------------------------------------------------------------------------------
/assets/images/icon-square.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pub-calculator-io/mean-median-mode-calculator/51ba79275fa36342dfef3a9132fdb70bc11c0f9a/assets/images/icon-square.png
--------------------------------------------------------------------------------
/assets/images/illustration-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pub-calculator-io/mean-median-mode-calculator/51ba79275fa36342dfef3a9132fdb70bc11c0f9a/assets/images/illustration-1.png
--------------------------------------------------------------------------------
/assets/images/illustration-and.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pub-calculator-io/mean-median-mode-calculator/51ba79275fa36342dfef3a9132fdb70bc11c0f9a/assets/images/illustration-and.png
--------------------------------------------------------------------------------
/assets/images/illustration-els.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pub-calculator-io/mean-median-mode-calculator/51ba79275fa36342dfef3a9132fdb70bc11c0f9a/assets/images/illustration-els.png
--------------------------------------------------------------------------------
/assets/images/illustration-els.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/assets/images/illustration-og.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pub-calculator-io/mean-median-mode-calculator/51ba79275fa36342dfef3a9132fdb70bc11c0f9a/assets/images/illustration-og.png
--------------------------------------------------------------------------------
/assets/images/screenshot-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pub-calculator-io/mean-median-mode-calculator/51ba79275fa36342dfef3a9132fdb70bc11c0f9a/assets/images/screenshot-1.png
--------------------------------------------------------------------------------
/assets/images/screenshot-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pub-calculator-io/mean-median-mode-calculator/51ba79275fa36342dfef3a9132fdb70bc11c0f9a/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 numbers = input.get('data_set').split(/[ ,]+/).numbers().vals();
3 | if(!input.valid()) return;
4 |
5 | const numbersLength = numbers.length;
6 | const sum = numbers.reduce((a, b) => a + b, 0);
7 | const mean = sum / numbersLength;
8 | let median;
9 |
10 | if(numbersLength % 2 === 0){
11 | median = (numbers[numbersLength / 2] + numbers[(numbersLength / 2) - 1]) / 2;
12 | }
13 | else {
14 | median = numbers[Math.floor(numbersLength / 2)]
15 | }
16 | const modeValue = mode(numbers);
17 | const min = Math.min(...numbers);
18 | const max = Math.max(...numbers);
19 | const range = max - min;
20 | const q1Value = q1(numbers);
21 | const q3Value = q3(numbers);
22 | const iqr = q3Value - q1Value;
23 | const outliersValue = outliers(numbers, q1Value, q3Value);
24 | _('mean-x').innerHTML = mean;
25 | _('outliers').innerHTML = outliersValue;
26 | _('median-x').innerHTML = median;
27 | _('q-1').innerHTML = q1Value;
28 | _('q-2').innerHTML = median;
29 | _('q-3').innerHTML = q3Value;
30 | _('mode').innerHTML = modeValue;
31 | _('range').innerHTML = range;
32 | _('min').innerHTML = min;
33 | _('max').innerHTML = max;
34 | _('iqr').innerHTML = iqr;
35 | _('sum').innerHTML = sum;
36 | _('count').innerHTML = numbersLength;
37 | }
38 |
39 | function mode(array) {
40 | let counts = {}
41 | let result = [];
42 | array.forEach((e) => {
43 | if(counts[e] === undefined) {
44 | counts[e] = 0
45 | }
46 | counts[e] += 1
47 | });
48 |
49 | let values = Object.values(counts);
50 | let keys = Object.keys(counts);
51 |
52 | const max = Math.max(...values);
53 | if(max === 1) {
54 | return 'All values appeared just once.';
55 | }
56 | keys.forEach((key) => {
57 | if(counts[key] === max) {
58 | result.push(key)
59 | }
60 | });
61 | if(result.length === 1) {
62 | return result[0] + ' appeared ' + plural(max, 'times:time:times:times:times:times');
63 | }
64 | else {
65 | return result.join(', ') + ' each appeared ' + plural(max, 'times:time:times:times:times:times');
66 | }
67 | }
68 |
69 | function q3(numbers) {
70 | const position = Math.ceil(numbers.length / 2);
71 | let array = numbers.map(x => x);
72 | array = array.splice(position);
73 | const arrayLength = array.length;
74 | let median;
75 | if(arrayLength % 2 === 0){
76 | median = (array[arrayLength / 2] + array[(arrayLength / 2) - 1]) / 2;
77 | }
78 | else {
79 | median = array[Math.floor(arrayLength / 2)]
80 | }
81 | return median;
82 | }
83 |
84 | function q1(numbers) {
85 | const arrayLength = Math.floor(numbers.length / 2);
86 | let array = numbers.map(x => x);
87 | array = array.splice(0, arrayLength);
88 | if(arrayLength % 2 === 0){
89 | return (array[arrayLength / 2] + array[(arrayLength / 2) - 1]) / 2;
90 | }
91 | else {
92 | return array[Math.floor(arrayLength / 2)]
93 | }
94 | }
95 |
96 | function outliers(numbers, q1, q3) {
97 | const iqr = q3 - q1;
98 | const result = [];
99 | numbers.forEach(x => {
100 | if(x > (q3 + 1.5 * iqr) || x < (q1 - 1.5 * iqr)){
101 | result.push(x)
102 | }
103 | })
104 | if(!result.length) {
105 | return 'none';
106 | }
107 | else {
108 | return result.join(', ');
109 | }
110 | }
111 |
--------------------------------------------------------------------------------
/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 |
Hour
22 | 23 |:
25 |Minute
27 | 28 |(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 Hour : Minute : Second There was an error with your calculation. {
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 | Mean, Median, Mode Calculator';
20 | }
21 |
22 |
23 | add_shortcode( 'ci_mean_median_mode_calculator', 'display_calcio_ci_mean_median_mode_calculator' );
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
86 |
87 |
142 |
88 |
90 |
91 |
92 | Result
89 |
93 |
98 | Mean x̄
94 | 16.75
95 | Outliers
96 | 6, 33, 35
97 |
99 |
104 | Median x̃
100 | 15
101 | Quartile Q1
102 | 12.5
103 |
105 |
110 | Mode
106 | 15 appeared 3 times
107 | Quartile Q2
108 | 15
109 |
111 |
116 | Range
112 | 29
113 | Quartile Q3
114 | 16
115 |
117 |
122 | Minimum
118 | 6
119 | Interquartile Range IQR
120 | 3.5
121 |
123 |
128 | Maximum
124 | 35
125 |
126 |
127 |
129 |
134 | Sum
130 | 201
131 |
132 |
133 |
135 |
140 |
141 | Count n
136 | 12
137 |
138 |
139 | Mean, Median, Mode Calculator';
20 | }
21 |
22 | add_shortcode( 'ci_mean_median_mode_calculator', 'display_ci_mean_median_mode_calculator' );
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | # Mean, Median, Mode Calculator Widget for WordPress
2 |
3 | Calculator for mean, median, and mode in statistics. Use this calculator to get the mean, median, mode, range, and the average for any data set.
4 |
5 | 
6 |
7 | ## Installation
8 |
9 | 1. [Download](https://github.com/pub-calculator-io/mean-median-mode-calculator/archive/refs/heads/master.zip) the ZIP file of this repository.
10 | 2. Upload the /mean-median-mode-calculator-master/ folder to the /wp-content/plugins/ directory.
11 | 3. Activate the [Mean, Median, Mode Calculator](https://www.calculator.io/mean-median-mode-calculator/ "Mean, Median, Mode Calculator Homepage") plugin through the "Plugins" menu in WordPress.
12 |
13 | ## Usage
14 | * Add the shortcode `[ci_mean_median_mode_calculator]` to your page, post or sidebar.
15 | * Or add the following code: `` to your template where you would like the Mean, Median, Mode 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 Mean median mode calculator ===
2 | Contributors: calculatorio
3 | Tags: mean median mode calculator, calculate mean median mode, central tendency calculator, find mean median mode, statistical calculator, arithmetic mean, median calculation, mode of data, mean median mode formula, calculate central tendency
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 | Calculator for mean, median, and mode in statistics. Use this calculator to get the mean, median, mode, range, and the average for any data set.
11 |
12 | [https://www.calculator.io/mean-median-mode-calculator/](https://www.calculator.io/mean-median-mode-calculator/)
13 |
14 | == Usage ==
15 |
16 | Add the Mean, Median, Mode Calculator shortcode to your page, post or sidebar:
17 |
18 | `[ci_mean_median_mode_calculator]`
19 |
20 | Add the following code to your template where you would like the Mean, Median, Mode Calculator to appear:
21 |
22 | ``
23 |
24 | == Screenshots ==
25 |
26 | 1. The Mean, Median, Mode Calculator Input Form.
27 |
28 | == Installation ==
29 |
30 | 1. Upload the Mean, Median, Mode Calculator /ci_mean_median_mode_calculator/ folder to the /wp-content/plugins/ directory.
31 | 2. Activate the Mean, Median, Mode Calculator plugin through the "Plugins" menu in WordPress.
32 |
33 | == Changelog ==
34 |
35 | = 1.0.0 =
36 | * Initial release of Mean, Median, Mode Calculator
37 |
--------------------------------------------------------------------------------