Задача №3
Користувач задає рік народження. Визначити кількість років користувача.
Рішення:
'use strict'
/**
* @param {number} from
* @param {number} to
*/
function getRandomNumber(from, to) {
return from + Math.floor(Math.random() * (to - from + 1))
}
function getRandomCharacter() {
const characters = '1234567890abcdefghijklmnopqrstuvwxyz'
const randomIndex = getRandomNumber(0, characters.length - 1)
return characters[randomIndex]
}
function getRandomId(size = 10) {
let id = ''
for (let i = 0; i < size; i++) {
id += getRandomCharacter()
}
return id
}
/**
* Create element using an HTML string, that represent it.
*
* @param {string} markup
*/
function createElementFromMarkup(markup) {
const template = document.createElement('template')
template.innerHTML = markup
return template.content.firstElementChild
}
// =============================================================================
class AgeWidget {
#outputEl
#widgetEl
/**
* @param {string} cssSelector
*/
constructor(cssSelector) {
this.#outputEl = document.querySelector(cssSelector)
if (!this.#outputEl)
throw new Error("Can't find the HTML element to output to.")
this.#init()
}
#getMarkup() {
const id = getRandomId()
return `
<form class="u-p-400 u-rounded-lg u-border u-border-zinc-700 u-flow-400">
<h3 class="u-text-400 u-font-bolder">Обчислення віку</h3>
<ul class="u-flow-300">
<li class="u-grid u-gap-100">
<label class="u-font-bolder" for="${id}">Рік народження</label>
<input class="c-input" id="${id}" type="date" min="1900-01-01" name="year">
</li>
<li class="u-grid u-gap-100">
<span class="u-font-bolder">Вік</span>
<output for="${id}" name="age">0</output>
</li>
</ul>
</form>
`
}
#buildUI() {
this.#widgetEl = createElementFromMarkup(this.#getMarkup())
}
/**
* @param {Date} birthDate
*/
#calculateAge(birthDate) {
const today = new Date()
if (Number.isNaN(Number(birthDate))) return 0
let age = today.getFullYear() - birthDate.getFullYear()
// Check if birthday hasn't occurred yet this year
const birthDateThisYear = structuredClone(birthDate)
birthDateThisYear.setFullYear(today.getFullYear())
if (birthDateThisYear > today) age--
return age
}
#attachEventListener() {
const inputEl = this.#widgetEl.elements.year
const outputEl = this.#widgetEl.elements.age
inputEl.addEventListener('input', () => {
const birthDate = new Date(inputEl.value)
outputEl.innerText = this.#calculateAge(birthDate)
})
}
#appendUI() {
this.#outputEl.append(this.#widgetEl)
}
#init() {
this.#buildUI()
this.#attachEventListener()
this.#appendUI()
}
}
// =============================================================================
function createAddWidget() {
const markup = `
<div
class="
u-p-400
u-rounded-lg
u-border
u-border-zinc-700
u-flow-400
js-add-widget
u-grid
u-place-items-center
"
>
<button
class="u-text-800 u-font-bolder u-leading-none"
type="button"
>
+
</button>
</div>
`
const addWidget = createElementFromMarkup(markup)
const addWidgetBtn = addWidget.querySelector('button')
const widgetsContainer = document.querySelector('.js-widgets')
addWidgetBtn.addEventListener('click', () => {
new AgeWidget('.js-widgets')
widgetsContainer.append(addWidget)
})
return addWidget
}
// =============================================================================
try {
const widgetsContainer = document.querySelector('.js-widgets')
const addWidget = createAddWidget()
new AgeWidget('.js-widgets')
widgetsContainer.append(addWidget)
} catch (error) {
console.error(error)
}
