This repository has been archived on 2024-10-16. You can view files and clone it, but cannot push or open issues or pull requests.
ebala/mirzaev/ebala/system/public/js/markets.js

3545 lines
143 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use strict";
if (typeof window.markets !== "function") {
// Not initialized
// Initialize of the class in global namespace
window.markets = class markets {
/**
* Заблокировать функцию закрытия всплывающего окна?
*/
static freeze = false;
/**
* Тело всплывающего окна (массив)
*/
static body = {};
/**
* Инициализирован класс?
*/
static initialized = false;
/**
* Управление кнопками (escape, enter...)
*
* Содержит функцию инициализирующую обработчики событий keydown для document
* функция деинициализируется с document при закрытии окна
*/
static buttons;
/**
* Ожидание зависимости: ядро
*
* @param {function} execute Функция, которая будет встроена в демпфер
* @param {mixed} args Аргументы встраиваемой функции
*
* @return {void}
*/
static core(execute, ...args) {
if (typeof execute === "function") {
// Получена функция
// Инициализация интервала для ожидания загрузки зависимостей
const interval = setInterval(() => {
if (typeof core === "function") {
// Инициализировано ядро
// Деинициализация интервала для ожидания загрузки записимостей
clearInterval(interval);
// Запуск выполнения
return execute(...args);
}
}, 100);
// Инициализация деинициализации интервала для ожидания загрузки зависимостей спустя большой срок времени
setTimeout(() => clearInterval(interval), 3000);
}
}
/**
* Ожидание зависимости: демпфер
*
* @param {function} execute Функция, которая будет встроена в демпфер
* @param {number} timer Количество миллисекунд для демпфера
* @param {mixed} args Аргументы встраиваемой функции
*
* @return {void}
*/
static damper(execute, timer = 3000, ...args) {
if (typeof execute === "function") {
// Получена функция
// Инициализация интервала для ожидания загрузки зависимостей
const interval = setInterval(() => {
if (typeof damper === "function") {
// Инициализирован демпфер
// Деинициализация интервала для ожидания загрузки записимостей
clearInterval(interval);
// Запуск выполнения
return damper(() => execute(...args), timer);
}
}, 100);
// Инициализация деинициализации интервала для ожидания загрузки зависимостей спустя большой срок времени
setTimeout(() => clearInterval(interval), 3000);
}
}
/**
* Авторизация
*
* @param {function} execute Функция, которая будет встроена в демпфер
* @param {mixed} args Аргументы встраиваемой функции
*
* @return {void}
*/
static authorization(execute, ...args) {
if (typeof execute === "function") {
// Получена функция
if (core.page === this.page) {
// Пройдена проверка на страницу
// Запуск выполнения
return execute(...args);
}
}
}
/**
* Создать аккаунт и магазин (вызов демпфера)
*
* @param {HTMLElement} button Кнопка <button>
* @param {HTMLElement} market_name_first Имя представителя магазина <input>
* @param {HTMLElement} market_name_second Фамилия представителя магазина <input>
* @param {HTMLElement} market_name_last Отчество представителя магазина <input>
* @param {HTMLElement} market_number SIM-номер представителя магазина <input>
* @param {HTMLElement} market_mail Почта представителя магазина <input>
* @param {HTMLElement} market_id Идентификатор магазина <input>
* @param {HTMLElement} market_type Тип магазина <select>
* @param {HTMLElement} market_city Город магазина <select>
* @param {HTMLElement} market_district Регион магазина <input>
* @param {HTMLElement} market_address Адрес магазина <input>
* @param {HTMLElement} account_name_first Имя аккаунта представителя магазина <input>
* @param {HTMLElement} account_name_second Фамилия аккаунта представителя магазина <input>
* @param {HTMLElement} account_name_last Отчество/Матчество аккаунта представителя магазина <input>
* @param {HTMLElement} account_number SIM-номер аккаунта представителя магазина <input>
* @param {HTMLElement} account_mail Почта аккаунта представителя магазина <input>
* @param {HTMLElement} account_password Пароль аккаунта представителя <input>
* @param {HTMLElement} account_commentary Комментарий аккаунта представителя <textarea>
*
* @return {void}
*/
static _create(
button,
market_name_first,
market_name_second,
market_name_last,
market_number,
market_mail,
market_id,
market_type,
market_city,
market_district,
market_address,
account_name_first,
account_name_second,
account_name_last,
account_number,
account_mail,
account_password,
account_commentary
) {
// Блокировка полей ввода
market_name_first.setAttribute("readonly", true);
market_name_second.setAttribute("readonly", true);
market_name_last.setAttribute("readonly", true);
market_number.setAttribute("readonly", true);
market_mail.setAttribute("readonly", true);
market_id.setAttribute("readonly", true);
market_type.setAttribute("readonly", true);
market_city.setAttribute("readonly", true);
market_district.setAttribute("readonly", true);
market_address.setAttribute("readonly", true);
account_name_first.setAttribute("readonly", true);
account_name_second.setAttribute("readonly", true);
account_name_last.setAttribute("readonly", true);
account_number.setAttribute("readonly", true);
account_mail.setAttribute("readonly", true);
account_password.setAttribute("readonly", true);
account_commentary.setAttribute("readonly", true);
// Блокировка кнопки
button.setAttribute("disabled", true);
// Запуск выполнения
this.__create(
button,
market_name_first,
market_name_second,
market_name_last,
market_number,
market_mail,
market_id,
market_type,
market_city,
market_district,
market_address,
account_name_first,
account_name_second,
account_name_last,
account_number,
account_mail,
account_password,
account_commentary
);
}
/**
* Создать аккаунт и магазин (демпфер)
*
* @param {HTMLElement} button Кнопка <button>
* @param {HTMLElement} market_name_first Имя представителя магазина <input>
* @param {HTMLElement} market_name_second Фамилия представителя магазина <input>
* @param {HTMLElement} market_name_last Отчество представителя магазина <input>
* @param {HTMLElement} market_number SIM-номер представителя магазина <input>
* @param {HTMLElement} market_mail Почта представителя магазина <input>
* @param {HTMLElement} market_id Идентификатор магазина <input>
* @param {HTMLElement} market_type Тип магазина <select>
* @param {HTMLElement} market_city Город магазина <select>
* @param {HTMLElement} market_district Регион магазина <input>
* @param {HTMLElement} market_address Адрес магазина <input>
* @param {HTMLElement} account_name_first Имя аккаунта представителя магазина <input>
* @param {HTMLElement} account_name_second Фамилия аккаунта представителя магазина <input>
* @param {HTMLElement} account_name_last Отчество/Матчество аккаунта представителя магазина <input>
* @param {HTMLElement} account_number SIM-номер аккаунта представителя магазина <input>
* @param {HTMLElement} account_mail Почта аккаунта представителя магазина <input>
* @param {HTMLElement} account_password Пароль аккаунта представителя <input>
* @param {HTMLElement} account_commentary Комментарий аккаунта представителя <textarea>
*
* @return {void}
*/
static __create = damper(
async (
button,
market_name_first,
market_name_second,
market_name_last,
market_number,
market_mail,
market_id,
market_type,
market_city,
market_district,
market_address,
account_name_first,
account_name_second,
account_name_last,
account_number,
account_mail,
account_password,
account_commentary
) => {
// Инициализация функции разблокировки
function unblock() {
// Разблокировка полей ввода
market_name_first.removeAttribute("readonly");
market_name_second.removeAttribute("readonly");
market_name_last.removeAttribute("readonly");
market_number.removeAttribute("readonly");
market_mail.removeAttribute("readonly");
market_id.removeAttribute("readonly");
market_type.removeAttribute("readonly");
market_city.removeAttribute("readonly");
market_district.removeAttribute("readonly");
market_address.removeAttribute("readonly");
account_name_first.removeAttribute("readonly");
account_name_second.removeAttribute("readonly");
account_name_last.removeAttribute("readonly");
account_number.removeAttribute("readonly");
account_mail.removeAttribute("readonly");
account_password.removeAttribute("readonly");
account_commentary.removeAttribute("readonly");
// Разблокировка кнопки
button.removeAttribute("disabled");
}
// Запуск отсрочки разблокировки на случай, если сервер не отвечает
const timeout = setTimeout(() => {
this.errors(["Сервер не отвечает"]);
unblock();
}, 5000);
// Запрос к серверу
return await fetch("/markets/create", {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
body: `market_name_first=${market_name_first.value}&market_name_second=${market_name_second.value}&market_name_last=${market_name_last.value}&market_number=${market_number.mask.unmaskedValue}&market_mail=${market_mail.value}&market_id=${market_id.value}&market_type=${market_type.value}&market_city=${market_city.value}&market_district=${market_district.value}&market_address=${market_address.value}&account_name_first=${account_name_first.value}&account_name_second=${account_name_second.value}&account_name_last=${account_name_last.value}&account_number=${account_number.mask.unmaskedValue}&account_mail=${account_mail.value}&account_password=${account_password.value}&account_commentary=${account_commentary.value}`,
})
.then((response) => response.json())
.then((data) => {
// Удаление отсрочки разблокировки
clearTimeout(timeout);
if (this.errors(data.errors)) {
// Сгенерированы ошибки
// Разблокировка полей ввода и кнопок
unblock();
} else {
// Не сгенерированы ошибки (подразумевается их отсутствие)
if (data.clipboard.length > 0) {
// Получены данные для записи в буфер обмена
// Запись в буфер обмена (подразумеваются данные созданного аккаунта представителя)
navigator.clipboard.writeText(data.clipboard);
}
if (this.body.wrap instanceof HTMLElement) {
// Найдено активное окно
// Деинициализация быстрых действий по кнопкам
document.removeEventListener("keydown", this.buttons);
// Сброс блокировки
this.freeze = false;
// Деинициализация активного окна
this.body.wrap.remove();
}
// Реинициализация строк
this.reinit();
}
});
},
300
);
/**
* Сгенерировать окно создания аккаунта и магазина
*
* @param {HTMLElement} row Строка
*
* @return {void}
*/
static create = damper(() => {
// Инициализация оболочки всплывающего окна
this.body.wrap = document.createElement("div");
this.body.wrap.setAttribute("id", "popup");
// Инициализация всплывающего окна
const popup = document.createElement("section");
popup.classList.add("list", "extensive", "medium");
// Инициализация заголовка всплывающего окна
const title = document.createElement("h3");
title.classList.add("unselectable");
title.innerText = "Создание магазина";
// Инициализация оболочки с основной информацией
const main = document.createElement("section");
main.classList.add("main");
// Инициализация колонки
const market = document.createElement("div");
market.classList.add("column");
market.setAttribute("data-column", "market");
market.style.setProperty("width", "450px");
// Инициализация строки
const market_name_first = document.createElement("div");
market_name_first.classList.add("row", "merged");
// Инициализация оболочки для строки
const market_name_first_label = document.createElement("label");
market_name_first_label.setAttribute("id", "market_first");
// Инициализация заголовка для поля ввода
const market_name_first_title = document.createElement("b");
market_name_first_title.classList.add(
"separated",
"right",
"unselectable"
);
market_name_first_title.innerText = "Имя:";
// Инициализация поля ввода
const market_name_first_input = document.createElement("input");
market_name_first_input.classList.add("large");
market_name_first_input.setAttribute("type", "text");
market_name_first_input.setAttribute("name", "first");
market_name_first_input.setAttribute("autocomplete", "given-name");
market_name_first_input.setAttribute("minlength", "0");
market_name_first_input.setAttribute("maxlength", "100");
market_name_first_input.setAttribute(
"oninput",
`this.parentElement.parentElement.parentElement.parentElement.children[1].querySelector('[name="first"]').value = this.value`
);
market_name_first_input.setAttribute(
"title",
"Имя представителя магазина"
);
market_name_first_input.setAttribute("placeholder", "Иван");
// Инициализация строки
const market_name_second = document.createElement("div");
market_name_second.classList.add("row", "merged");
// Инициализация оболочки для строки
const market_name_second_label = document.createElement("label");
market_name_second_label.setAttribute("id", "market_second");
// Инициализация заголовка для поля ввода
const market_name_second_title = document.createElement("b");
market_name_second_title.classList.add(
"separated",
"right",
"unselectable"
);
market_name_second_title.innerText = "Фамилия:";
// Инициализация поля ввода
const market_name_second_input = document.createElement("input");
market_name_second_input.classList.add("large");
market_name_second_input.setAttribute("autocomplete", "family-name");
market_name_second_input.setAttribute("name", "second");
market_name_second_input.setAttribute("type", "text");
market_name_second_input.setAttribute("minlength", "0");
market_name_second_input.setAttribute("maxlength", "100");
market_name_second_input.setAttribute(
"oninput",
`this.parentElement.parentElement.parentElement.parentElement.children[1].querySelector('[name="second"]').value = this.value`
);
market_name_second_input.setAttribute(
"title",
"Фамилия представителя магазина"
);
market_name_second_input.setAttribute("placeholder", "Иванов");
// Инициализация строки
const market_name_last = document.createElement("div");
market_name_last.classList.add("row", "merged");
// Инициализация оболочки для строки
const market_name_last_label = document.createElement("label");
market_name_last_label.setAttribute("id", "market_last");
// Инициализация заголовка для поля ввода
const market_name_last_title = document.createElement("b");
market_name_last_title.classList.add(
"separated",
"right",
"unselectable"
);
market_name_last_title.innerText = "Отчество:";
// Инициализация поля ввода
const market_name_last_input = document.createElement("input");
market_name_last_input.classList.add("large");
market_name_last_input.setAttribute("name", "last");
market_name_last_input.setAttribute("autocomplete", "additional-name");
market_name_last_input.setAttribute("type", "text");
market_name_last_input.setAttribute("minlength", "0");
market_name_last_input.setAttribute("maxlength", "100");
market_name_last_input.setAttribute(
"oninput",
`this.parentElement.parentElement.parentElement.parentElement.children[1].querySelector('[name="last"]').value = this.value`
);
market_name_last_input.setAttribute(
"title",
"Отчество/Матчество представителя магазина"
);
market_name_last_input.setAttribute("placeholder", "Иванович");
// Инициализация строки
const market_number = document.createElement("div");
market_number.classList.add("row", "merged", "divided");
// Инициализация оболочки для строки
const market_number_label = document.createElement("label");
market_number_label.setAttribute("id", "market_number");
// Инициализация заголовка для поля ввода
const market_number_title = document.createElement("b");
market_number_title.classList.add("separated", "right", "unselectable");
market_number_title.innerText = "SIM-номер:";
// Инициализация поля ввода
const market_number_input = document.createElement("input");
market_number_input.classList.add("large");
market_number_input.setAttribute("name", "sim-number");
market_number_input.setAttribute("autocomplete", "tel");
market_number_input.setAttribute("type", "text");
market_number_input.setAttribute("minlength", "18");
market_number_input.setAttribute("maxlength", "18");
market_number_input.setAttribute(
"oninput",
`this.parentElement.parentElement.parentElement.parentElement.children[1].querySelector('[name="sim-number"]').value = this.value`
);
market_number_input.setAttribute(
"title",
"SIM-номер представителя магазина"
);
market_number_input.setAttribute("placeholder", "+7 (000) 000-00-00");
// Инициализация строки
const market_mail = document.createElement("div");
market_mail.classList.add("row", "merged");
// Инициализация оболочки для строки
const market_mail_label = document.createElement("label");
market_mail_label.setAttribute("id", "market_mail");
// Инициализация заголовка для поля ввода
const market_mail_title = document.createElement("b");
market_mail_title.classList.add("separated", "right", "unselectable");
market_mail_title.innerText = "Почта:";
// Инициализация поля ввода
const market_mail_input = document.createElement("input");
market_mail_input.classList.add("large");
market_mail_input.setAttribute("name", "mail");
market_mail_input.setAttribute("autocomplete", "email");
market_mail_input.setAttribute("type", "text");
market_mail_input.setAttribute("minlength", "3");
market_mail_input.setAttribute("maxlength", "300");
market_mail_input.setAttribute(
"oninput",
`this.parentElement.parentElement.parentElement.parentElement.children[1].querySelector('[name="mail"]').value = this.value`
);
market_mail_input.setAttribute("title", "Почта представителя магазина");
market_mail_input.setAttribute("placeholder", "name@server");
// Инициализация строки
const market_id = document.createElement("div");
market_id.classList.add("row", "merged");
// Инициализация оболочки для строки
const market_id_label = document.createElement("label");
market_id_label.setAttribute("id", "market_id");
// Инициализация заголовка для поля ввода
const market_id_title = document.createElement("b");
market_id_title.classList.add("separated", "right", "unselectable");
market_id_title.innerText = "Идентификатор:";
// Инициализация поля ввода
const market_id_input = document.createElement("input");
market_id_input.classList.add("large");
market_id_input.setAttribute("name", "id");
market_id_input.setAttribute("type", "text");
market_id_input.setAttribute("minlength", "1");
market_id_input.setAttribute("maxlength", "3");
market_id_input.setAttribute("title", "Идентификатор магазина");
market_id_input.setAttribute("placeholder", "000");
// Инициализация строки
const market_type = document.createElement("div");
market_type.classList.add("row", "divided", "merged");
// Инициализация оболочки для выпадающего списка
const market_type_label = document.createElement("label");
market_type_label.setAttribute("id", "market_type");
// Инициализация заголовка для выпадающего списка
const market_type_title = document.createElement("b");
market_type_title.classList.add("separated", "right");
market_type_title.innerText = "Тип:";
// Инициализация выпадающего списка
const market_type_select = document.createElement("select");
market_type_select.classList.add("large");
market_type_select.setAttribute("autocomplete", "address-level2");
market_type_select.setAttribute("name", "type");
market_type_select.setAttribute("title", "Тип магазина");
// Инициализация варианта для выбора
const market_type_option_1 = document.createElement("option");
market_type_option_1.classList.add("value", "Стандарт");
market_type_option_1.innerText = "Стандарт";
// Инициализация варианта для выбора
const market_type_option_2 = document.createElement("option");
market_type_option_2.classList.add("value", "Фрешмаркет");
market_type_option_2.innerText = "Фрешмаркет";
// Инициализация варианта для выбора
const market_type_option_3 = document.createElement("option");
market_type_option_3.classList.add("value", "Дискаунтер");
market_type_option_3.innerText = "Дискаунтер";
// Инициализация строки
const market_city = document.createElement("div");
market_city.classList.add("row", "divided", "merged");
// Инициализация оболочки для выпадающего списка
const market_city_label = document.createElement("label");
market_city_label.setAttribute("id", "market_city");
// Инициализация заголовка для выпадающего списка
const market_city_title = document.createElement("b");
market_city_title.classList.add("separated", "right");
market_city_title.innerText = "Город:";
// Инициализация выпадающего списка
const market_city_select = document.createElement("select");
market_city_select.classList.add("large");
market_city_select.setAttribute("autocomplete", "address-level2");
market_city_select.setAttribute("name", "city");
market_city_select.setAttribute("title", "Город магазина");
// Инициализация варианта для выбора
const market_city_option_1 = document.createElement("option");
market_city_option_1.classList.add("value", "Красноярск");
market_city_option_1.innerText = "Красноярск";
// Инициализация варианта для выбора
const market_city_option_2 = document.createElement("option");
market_city_option_2.classList.add("value", "Железногорск");
market_city_option_2.innerText = "Железногорск";
/*
// Инициализация варианта для выбора
const market_city_option_3 = document.createElement("option");
market_city_option_3.classList.add("value", "");
market_city_option_3.innerText = "";
// Инициализация варианта для выбора
const market_city_option_4 = document.createElement("option");
market_city_option_4.classList.add("value", "");
market_city_option_4.innerText = "";
// Инициализация варианта для выбора
const market_city_option_5 = document.createElement("option");
market_city_option_5.classList.add("value", "");
market_city_option_5.innerText = "";
// Инициализация варианта для выбора
const market_city_option_ = document.createElement("option");
market_city_option_.classList.add("value", "");
market_city_option_.innerText = ""; */
// Инициализация строки
const market_district = document.createElement("div");
market_district.classList.add("row", "merged");
// Инициализация оболочки для строки
const market_district_label = document.createElement("label");
market_district_label.setAttribute("id", "market_district");
// Инициализация заголовка для поля ввода
const market_district_title = document.createElement("b");
market_district_title.classList.add("separated", "right");
market_district_title.innerText = "Регион:";
// Инициализация поля ввода
const market_district_input = document.createElement("input");
market_district_input.classList.add("large");
market_district_input.setAttribute("autocomplete", "address-level3");
market_district_input.setAttribute("name", "district");
market_district_input.setAttribute("type", "text");
market_district_input.setAttribute("minlength", "0");
market_district_input.setAttribute("maxlength", "80");
market_district_input.setAttribute("title", "Регион магазина");
market_district_input.setAttribute("placeholder", "Центральный");
// Инициализация строки
const market_address = document.createElement("div");
market_address.classList.add("row", "merged");
// Инициализация оболочки для строки
const market_address_label = document.createElement("label");
market_address_label.setAttribute("id", "market_address");
// Инициализация заголовка для поля ввода
const market_address_title = document.createElement("b");
market_address_title.classList.add("separated", "right");
market_address_title.innerText = "Адрес:";
// Инициализация поля ввода
const market_address_input = document.createElement("input");
market_address_input.classList.add("large");
market_address_input.setAttribute("autocomplete", "street-address");
market_address_input.setAttribute("name", "address");
market_address_input.setAttribute("type", "text");
market_address_input.setAttribute("minlength", "0");
market_address_input.setAttribute("maxlength", "150");
market_address_input.setAttribute("title", "Адрес магазина");
market_address_input.setAttribute("placeholder", "ул. Пушкина 7");
// Инициализация колонки
const account = document.createElement("div");
account.classList.add("column");
account.setAttribute("data-column", "account");
account.style.setProperty("width", "300px");
// Инициализация строки
const account_name_first = document.createElement("div");
account_name_first.classList.add("row", "merged");
// Инициализация оболочки для строки
const account_name_first_label = document.createElement("label");
account_name_first_label.setAttribute("id", "account_first");
// Инициализация заголовка для поля ввода
const account_name_first_title = document.createElement("b");
account_name_first_title.classList.add(
"separated",
"right",
"unselectable"
);
account_name_first_title.innerText = "Имя:";
// Инициализация поля ввода
const account_name_first_input = document.createElement("input");
account_name_first_input.classList.add("medium");
account_name_first_input.setAttribute("type", "text");
account_name_first_input.setAttribute("name", "first");
account_name_first_input.setAttribute("autocomplete", "given-name");
account_name_first_input.setAttribute("minlength", "0");
account_name_first_input.setAttribute("maxlength", "100");
account_name_first_input.setAttribute(
"onclick",
"this.parentElement.parentElement.parentElement.parentElement.children[0].querySelector('[name=\"first\"]').focus()"
);
account_name_first_input.setAttribute(
"title",
"Имя аккаунта представителя магазина"
);
account_name_first_input.setAttribute("placeholder", "Иван");
account_name_first_input.setAttribute("readonly", "true");
// Инициализация строки
const account_name_second = document.createElement("div");
account_name_second.classList.add("row", "merged");
// Инициализация оболочки для строки
const account_name_second_label = document.createElement("label");
account_name_second_label.setAttribute("id", "account_second");
// Инициализация заголовка для поля ввода
const account_name_second_title = document.createElement("b");
account_name_second_title.classList.add(
"separated",
"right",
"unselectable"
);
account_name_second_title.innerText = "Фамилия:";
// Инициализация поля ввода
const account_name_second_input = document.createElement("input");
account_name_second_input.classList.add("medium");
account_name_second_input.setAttribute("autocomplete", "family-name");
account_name_second_input.setAttribute("name", "second");
account_name_second_input.setAttribute("type", "text");
account_name_second_input.setAttribute("minlength", "0");
account_name_second_input.setAttribute("maxlength", "100");
account_name_second_input.setAttribute(
"onclick",
"this.parentElement.parentElement.parentElement.parentElement.children[0].querySelector('[name=\"second\"]').focus()"
);
account_name_second_input.setAttribute(
"title",
"Фамилия аккаунта представителя магазина"
);
account_name_second_input.setAttribute("placeholder", "Иванов");
account_name_second_input.setAttribute("readonly", "true");
// Инициализация строки
const account_name_last = document.createElement("div");
account_name_last.classList.add("row", "merged");
// Инициализация оболочки для строки
const account_name_last_label = document.createElement("label");
account_name_last_label.setAttribute("id", "account_last");
// Инициализация заголовка для поля ввода
const account_name_last_title = document.createElement("b");
account_name_last_title.classList.add(
"separated",
"right",
"unselectable"
);
account_name_last_title.innerText = "Отчество:";
// Инициализация поля ввода
const account_name_last_input = document.createElement("input");
account_name_last_input.classList.add("medium");
account_name_last_input.setAttribute("name", "last");
account_name_last_input.setAttribute("autocomplete", "additional-name");
account_name_last_input.setAttribute("type", "text");
account_name_last_input.setAttribute("minlength", "0");
account_name_last_input.setAttribute("maxlength", "100");
account_name_last_input.setAttribute(
"onclick",
"this.parentElement.parentElement.parentElement.parentElement.children[0].querySelector('[name=\"last\"]').focus()"
);
account_name_last_input.setAttribute(
"title",
"Отчество/Матчество аккаунта представителя магазина"
);
account_name_last_input.setAttribute("placeholder", "Иванович");
account_name_last_input.setAttribute("readonly", "true");
// Инициализация строки
const account_number = document.createElement("div");
account_number.classList.add("row", "merged", "divided");
// Инициализация оболочки для строки
const account_number_label = document.createElement("label");
account_number_label.setAttribute("id", "account_number");
// Инициализация заголовка для поля ввода
const account_number_title = document.createElement("b");
account_number_title.classList.add("separated", "right", "unselectable");
account_number_title.innerText = "SIM-номер:";
// Инициализация поля ввода
const account_number_input = document.createElement("input");
account_number_input.classList.add("medium");
account_number_input.setAttribute("name", "sim-number");
account_number_input.setAttribute("autocomplete", "tel");
account_number_input.setAttribute("type", "text");
account_number_input.setAttribute("minlength", "18");
account_number_input.setAttribute("maxlength", "18");
account_number_input.setAttribute(
"onclick",
"this.parentElement.parentElement.parentElement.parentElement.children[0].querySelector('[name=\"sim-number\"]').focus()"
);
account_number_input.setAttribute(
"title",
"SIM-номер аккаунта представителя магазина"
);
account_number_input.setAttribute("placeholder", "+7 (000) 000-00-00");
account_number_input.setAttribute("readonly", "true");
// Инициализация строки
const account_mail = document.createElement("div");
account_mail.classList.add("row", "merged");
// Инициализация оболочки для строки
const account_mail_label = document.createElement("label");
account_mail_label.setAttribute("id", "account_mail");
// Инициализация заголовка для поля ввода
const account_mail_title = document.createElement("b");
account_mail_title.classList.add("separated", "right", "unselectable");
account_mail_title.innerText = "Почта:";
// Инициализация поля ввода
const account_mail_input = document.createElement("input");
account_mail_input.classList.add("medium");
account_mail_input.setAttribute("name", "mail");
account_mail_input.setAttribute("autocomplete", "email");
account_mail_input.setAttribute("type", "text");
account_mail_input.setAttribute("minlength", "3");
account_mail_input.setAttribute("maxlength", "300");
account_mail_input.setAttribute(
"onclick",
"this.parentElement.parentElement.parentElement.parentElement.children[0].querySelector('[name=\"mail\"]').focus()"
);
account_mail_input.setAttribute(
"title",
"Почта аккаунта представителя магазина"
);
account_mail_input.setAttribute("placeholder", "name@server");
account_mail_input.setAttribute("readonly", "true");
// Инициализация строки
const account_password = document.createElement("div");
account_password.classList.add("row", "merged");
// Инициализация оболочки для строки
const account_password_label = document.createElement("label");
account_password_label.setAttribute("id", "account_password");
// Инициализация заголовка для поля ввода
const account_password_title = document.createElement("b");
account_password_title.classList.add(
"separated",
"right",
"unselectable"
);
account_password_title.innerText = "Пароль:";
// Инициализация поля ввода
const account_password_input = document.createElement("input");
account_password_input.classList.add("medium");
account_password_input.setAttribute("name", "password");
account_password_input.setAttribute("required", "true");
account_password_input.setAttribute("autocomplete", "new-password");
account_password_input.setAttribute("type", "password");
account_password_input.setAttribute("minlength", "6");
account_password_input.setAttribute("maxlength", "100");
account_password_input.setAttribute(
"title",
"Пароль аккаунта представителя магазина"
);
account_password_input.setAttribute("placeholder", "*********");
// Инициализация строки
const account_commentary = document.createElement("div");
account_commentary.classList.add("row", "endless");
// Инициализация оболочки для строки
const account_commentary_label = document.createElement("label");
account_commentary_label.setAttribute("id", "account_commentary");
// Инициализация поля ввода
const account_commentary_textarea = document.createElement("textarea");
account_commentary_textarea.classList.add("snow");
account_commentary_textarea.setAttribute("maxlength", "800");
account_commentary_textarea.setAttribute(
"title",
"Комментарий аккаунта представителя магазина"
);
account_commentary_textarea.setAttribute(
"placeholder",
"Дополнительная информация для администраторов и операторов"
);
// Инициализация строки
const account_buttons = document.createElement("div");
account_buttons.classList.add("row", "divided", "buttons");
// Инициализация оболочки для кнопок
const account_buttons_label = document.createElement("label");
// Инициализация кнопки подтверждения даты
const account_create_button = document.createElement("button");
account_create_button.classList.add("grass", "stretched");
account_create_button.innerText = "Создать";
account_create_button.setAttribute(
"onclick",
`markets._create(this, ...this.parentElement.parentElement.parentElement.parentElement.querySelectorAll(':is(select, input, textarea)'))`
);
// Инициализация окна с ошибками
this.body.errors = document.createElement("section");
this.body.errors.classList.add(
"errors",
"window",
"list",
"calculated",
"hidden"
);
this.body.errors.setAttribute("data-errors", true);
// Инициализация элемента-тела (оболочки) окна с ошибками
const errors = document.createElement("section");
errors.classList.add("body");
// Инициализация элемента-списка ошибок
const dl = document.createElement("dl");
// Инициализация активного всплывающего окна
const old = document.getElementById("popup");
if (old instanceof HTMLElement) {
// Найдено активное окно
// Деинициализация быстрых действий по кнопкам
document.removeEventListener("keydown", this.buttons);
// Сброс блокировки
this.freeze = false;
// Удаление активного окна
old.remove();
}
// Запись в документ
popup.appendChild(title);
market_name_first_label.appendChild(market_name_first_title);
market_name_first_label.appendChild(market_name_first_input);
market_name_first.appendChild(market_name_first_label);
market.appendChild(market_name_first);
market_name_second_label.appendChild(market_name_second_title);
market_name_second_label.appendChild(market_name_second_input);
market_name_second.appendChild(market_name_second_label);
market.appendChild(market_name_second);
market_name_last_label.appendChild(market_name_last_title);
market_name_last_label.appendChild(market_name_last_input);
market_name_last.appendChild(market_name_last_label);
market.appendChild(market_name_last);
market_number_label.appendChild(market_number_title);
market_number_label.appendChild(market_number_input);
market_number.appendChild(market_number_label);
market.appendChild(market_number);
market_mail_label.appendChild(market_mail_title);
market_mail_label.appendChild(market_mail_input);
market_mail.appendChild(market_mail_label);
market.appendChild(market_mail);
market_id_label.appendChild(market_id_title);
market_id_label.appendChild(market_id_input);
market_id.appendChild(market_id_label);
market.appendChild(market_id);
market_type_label.appendChild(market_type_title);
market_type_select.appendChild(market_type_option_1);
market_type_select.appendChild(market_type_option_2);
market_type_select.appendChild(market_type_option_3);
market_type_label.appendChild(market_type_select);
market_type.appendChild(market_type_label);
market.appendChild(market_type);
market_city_label.appendChild(market_city_title);
market_city_select.appendChild(market_city_option_1);
market_city_select.appendChild(market_city_option_2);
market_city_label.appendChild(market_city_select);
market_city.appendChild(market_city_label);
market.appendChild(market_city);
market_district_label.appendChild(market_district_title);
market_district_label.appendChild(market_district_input);
market_district.appendChild(market_district_label);
market.appendChild(market_district);
market_address_label.appendChild(market_address_title);
market_address_label.appendChild(market_address_input);
market_address.appendChild(market_address_label);
market.appendChild(market_address);
main.appendChild(market);
account_name_first_label.appendChild(account_name_first_title);
account_name_first_label.appendChild(account_name_first_input);
account_name_first.appendChild(account_name_first_label);
account.appendChild(account_name_first);
account_name_second_label.appendChild(account_name_second_title);
account_name_second_label.appendChild(account_name_second_input);
account_name_second.appendChild(account_name_second_label);
account.appendChild(account_name_second);
account_name_last_label.appendChild(account_name_last_title);
account_name_last_label.appendChild(account_name_last_input);
account_name_last.appendChild(account_name_last_label);
account.appendChild(account_name_last);
account_number_label.appendChild(account_number_title);
account_number_label.appendChild(account_number_input);
account_number.appendChild(account_number_label);
account.appendChild(account_number);
account_mail_label.appendChild(account_mail_title);
account_mail_label.appendChild(account_mail_input);
account_mail.appendChild(account_mail_label);
account.appendChild(account_mail);
account_password_label.appendChild(account_password_title);
account_password_label.appendChild(account_password_input);
account_password.appendChild(account_password_label);
account.appendChild(account_password);
account_commentary_label.appendChild(account_commentary_textarea);
account_commentary.appendChild(account_commentary_label);
account.appendChild(account_commentary);
account_buttons_label.appendChild(account_create_button);
account_buttons.appendChild(account_buttons_label);
account.appendChild(account_buttons);
main.appendChild(account);
popup.appendChild(main);
this.body.wrap.appendChild(popup);
errors.appendChild(dl);
this.body.errors.appendChild(errors);
this.body.wrap.appendChild(this.body.errors);
document.body.appendChild(this.body.wrap);
// Инициализация ширины окна с ошибками
this.body.errors.style.setProperty(
"--calculated-width",
popup.offsetWidth + "px"
);
// Инициалиация масок
account_number_input.mask = IMask(account_number_input, {
mask: "+{7} (000) 000-00-00",
});
market_number_input.mask = IMask(market_number_input, {
mask: "+{7} (000) 000-00-00",
});
// Инициализация переменных для окна с ошибками (12 - это значение gap из div#popup)
function top(errors) {
errors.style.setProperty("transition", "0s");
errors.style.setProperty(
"--top",
popup.offsetTop + popup.offsetHeight + 12 + "px"
);
setTimeout(() => errors.style.removeProperty("transition"), 100);
}
top(this.body.errors);
const resize = new ResizeObserver(() => top(this.body.errors));
resize.observe(this.body.wrap);
// Инициализация функции блокировки кнопки
const block = () => {
if (account_password_input.value.length > 6)
account_create_button.removeAttribute("disabled");
else account_create_button.setAttribute("disabled", "true");
};
// Добавление функции блокировки кнопки по событиям
account_password_input.addEventListener("keyup", block);
// Первичная активация функции блокировки кнопки
block();
// Инициализация функции генерации пароля и записи в поле ввода и буфер обмена
const generate = (e) => {
// Блокировка выполнения при нажатии на поле для ввода
if (e.target.tagName === "INPUT") return;
// Инициализация поля ввода пароля
const input = e.currentTarget.getElementsByTagName("input")[0];
if (input instanceof HTMLElement) {
// Найдено поле для ввода пароля
// Инициализация буфера генерации пароля
let password = "";
// Инициализация используемых символов для генерируемого пароля
const symbols =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789------";
// Генерация пароля
for (let i = 0; i < Math.random() * 14 + 8; i++) {
password += symbols.charAt(
Math.floor(Math.random() * symbols.length)
);
}
// Запись пароля в поле для ввода пароля
input.value = password;
// Вызов функции инициализации генератора пароля
input.dispatchEvent(new KeyboardEvent("keyup"));
// Запиcь пароля в буфер обмена
navigator.clipboard.writeText(password);
// Фокусировка на поле для ввода пароля
input.focus();
}
};
// Инициализация функции инициализации генератора пароля
const generator = (e) => {
// Инициализация строки с полем для ввода пароля
const row = e.currentTarget.parentElement.parentElement;
if (row instanceof HTMLElement) {
// Найдено поле для ввода пароля
if (e.target.value.length === 0) {
// Не введён пароль
row.setAttribute("title", "Сгенерировать пароль");
row.setAttribute("data-interactive", "true");
row.addEventListener("click", generate);
} else {
// Введён пароль
row.removeAttribute("title");
row.removeAttribute("data-interactive");
row.removeEventListener("click", generate);
}
}
};
// Инициализация вызова функции инициализации генератора пароля по события нажатия клавиши
account_password_input.addEventListener("keyup", generator);
// Вызов функции инициализации генератора пароля (первичный)
account_password_input.dispatchEvent(new KeyboardEvent("keyup"));
// Инициализация функции закрытия всплывающего окна
const click = () => {
// Блокировка
if (this.freeze) return;
// Удаление всплывающего окна
this.body.wrap.remove();
// Удаление статуса активной строки
// row.removeAttribute("data-selected"); // Это окно создания строки, её ещё не существует
// Деинициализация быстрых действий по кнопкам
document.removeEventListener("keydown", this.buttons);
// Сброс блокировки
this.freeze = false;
};
// Инициализация функции добавления функции закрытия всплывающего окна
const enable = () => this.body.wrap.addEventListener("click", click);
// Инициализация функции удаления функции закрытия всплывающего окна
const disable = () => this.body.wrap.removeEventListener("click", click);
// Первичная активация функции удаления всплывающего окна
enable();
// Инициализация блокировки удаления окна при взаимодействии с select-элементом
for (const select of popup.getElementsByTagName("select")) {
// Перебор всех select-элементов
// Инициализация функции блокировки удаления окна по событию
select.addEventListener("click", () => {
// Блокировка удаления окна
this.freeze = true;
// Разблокировка удаления окна
setTimeout(() => (this.freeze = false), 100);
});
for (const option of select.getElementsByTagName("option")) {
// Перебор всех option-элементов
// Инициализация функции блокировки удаления окна по событию
option.addEventListener("click", () => {
// Блокировка удаления окна
this.freeze = true;
// Разблокировка удаления окна
setTimeout(() => (this.freeze = false), 100);
});
}
}
// Инициализация блокировки удаления окна при взаимодействии с textarea-элементом
for (const textarea of popup.getElementsByTagName("textarea")) {
// Перебор всех textarea-элементов
// Обновлять позицию окна с ошибками при изменении размера textarea (там position: absolute)
new MutationObserver(() => top(this.body.errors)).observe(textarea, {
attributes: true,
attributeFilter: ["style"],
});
// Инициализация функции игнорирования блокировки для выбранных кнопок
textarea.addEventListener("keydown", (e) => {
if (e.keyCode === 27) {
// Нажата кнопка: "escape"
// Вызов глобальной функции управления кнопками
this.buttons(e, true);
} else if (e.ctrlKey && e.keyCode === 13) {
// Нажаты кнопки: "control", "enter"
// Вызов глобальной функции управления кнопками
this.buttons(e, true);
}
});
// Добавление функции блокировки удаления окна и клавиш по событиям
textarea.addEventListener("focus", () => (this.freeze = true));
textarea.addEventListener("focusout", () => (this.freeze = false));
}
// Инициализация функции управления кнопками
this.buttons = (e, force = false) => {
// Блокировка
if (!force && this.freeze) return;
if (e.keyCode === 27) {
// Нажата кнопка: "escape"
// Удаление окна
click();
} else if (event.keyCode === 13) {
// Нажата кнопка: "enter"
// Инициализация буфера с текущим статусом блокировки закрытия окна
const freeze = this.freeze;
// Блокировка закрытия окна (чтобы не вызвался click() через событие onclick)
this.freeze = true;
// Активация виртуальной кнопки "создать"
account_create_button.click();
// Возвращение статуса блокировки закрытия окна
this.freeze = freeze;
}
};
// Инициализация быстрых действий по кнопкам
document.addEventListener("keydown", this.buttons);
// Добавление функции удаления всплывающего окна по событиям
popup.addEventListener("mouseenter", disable);
popup.addEventListener("mouseleave", enable);
// Фокусировка
market_name_first_input.focus();
}, 300);
/**
* Переключить фильтр
*
* @param {string} name Название
* @param {string|number|null} value Значение
* @param {HTMLElement|null} button Кнопка
*
* @return {void}
*/
static filter = damper(async (name, value, button) => {
if (typeof name === "string") {
// Получено название
// Инициализация сериализованного пути к директории
const path = `markets_filter_${name}`;
if (typeof value === "string" || typeof value === "number") {
// Получено значение
// Запись нового значения
buffer.write(path, value);
} else {
// Не получено значение
// Чтение текущего значения
value = +(await buffer.read(path));
// Инициализация значения по умолчанию
if (isNaN(value)) value = 0;
// Запись нового значения (инвертирование)
buffer.write(path, ++value < 3 ? value : 0);
if (button instanceof HTMLElement) {
// Получена кнопка
// Деинициализация классов статуса фильтра
button.classList.remove("earth", "sand", "river");
// Инициализация классов статуса фильтра
if (value === 1) button.classList.add("sand");
else if (value === 2) button.classList.add("river");
else button.classList.add("earth");
}
}
}
}, 300);
/**
* Записать фильтр поиска
*
* @param {HTMLElement} input Строка поиска
* @param {HTMLElement} button Кнопка отправки
*
* @return {void}
*/
static search = (input, button) => {
input.setAttribute("readonly", true);
button.setAttribute("disabled", true);
this._search(input, button);
};
/**
* Записать фильтр поиска (системное)
*
* Используется как оболочка для большей временной задержки
*
* @param {HTMLElement} input Строка поиска
* @param {HTMLElement} button Кнопка отправки
*
* @return {void}
*/
static _search = damper((input, button) => {
this.filter("search", input.value);
this.reinit(() => {
input.removeAttribute("readonly");
button.removeAttribute("disabled");
});
}, 1000);
/**
* Инициализация страниц
*
* @param {number} amount Количество страниц для генерации
* @param {number} iteration Номер итерации (системное)
*
* @return {void}
*/
static async init(amount = 3, iteration = 0) {
if (
typeof amount === "number" &&
typeof iteration === "number" &&
this.initialized === false
) {
// Получены количество страниц и номер итерации
// Инициализация страницы (написал markets потому, что оптимизатор выдаёт ошибку, что this.read не найдено, хотя всё работает)
await markets.read(++iteration);
// Проверка условий и отложенный запуск следующей итерации
if (iteration < amount) setTimeout(this.init, 1500, amount, iteration);
else this.initialized = true;
}
}
/**
* Реинициализация страниц
*
* @param {function} postprocessing Функция которая будет исполнена после реинициализации
* @param {number} amount Количество страниц для генерации при инициализации
*
* @return {void}
*/
static reinit = damper((postprocessing, amount = 3) => {
if (typeof amount === "number") {
// Получены количество страниц
// Деинициализация cookie с номером страницы
Cookies.remove("markets_page", { path: "/" });
// Инициализация оболочки
const tasks = document.getElementById("markets");
if (tasks instanceof HTMLElement) {
// Найдена оболочка
// Инициализация буфера активного элемента
const active = document.activeElement;
// Инициализация буфера элементов
const buffer = document.createElement("div");
// Перенос элементов в буфер
buffer.replaceChildren(...tasks.children);
// Удаление комментариев с индексами страниц
tasks.innerHTML = tasks.innerHTML.replace(
/<!--(?!>)[\S\s]*?-->/g,
""
);
// Перенос элементов из буфера
tasks.replaceChildren(...buffer.children);
// Деинициализация страниц
for (const element of tasks.querySelectorAll(
':scope > div[data-row="market"]'
))
element.remove();
// Сброс статуса инициализированности
this.initialized = false;
// Инициализация страниц
this.init(amount);
// Возвращение фокуса на активный элемент
active.focus();
// Постобработка
if (typeof postprocessing === "function") postprocessing();
}
}
}, 2000);
/**
* Прочитать
*
* Читает список и модифицирует документ (записывает в общий список)
*
* @param {number} page Страница
*
* @return {object} {(bool) exist, (array) errors}
*/
static read = damper(async (page) => {
if (typeof core === "function" && typeof page !== "number") {
// Не получена страница
// Инициализация страницы (если не получена, то брать из cookie и прибавлять 1)
page = Cookies.get(`markets_page`) ?? 0;
// Запись идентификатора следующей страницы
++page;
}
// Запрос к серверу
return await fetch("/markets/read", {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
body: `page=${page}`,
})
.then((response) => response.text())
.then((data) => {
// Инициализация буфера для записи в документ
const element = document.createElement("div");
// Запись пустого элемента из буфера в документ
document.getElementById("markets").appendChild(element);
// Запись в документ HTML-данных через буфер
element.outerHTML = data;
// Возврат (успех)
return data;
});
}, 50);
/**
* Сгенерировать список
*
* @return {array|null} Массив HTML-элементов <option>
*/
static async list() {
// Запрос к серверу
return await fetch(`/markets/list`, {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
})
.then((response) => response.text())
.then((data) => {
if (data.length > 0) {
// Получены данные
return data;
}
return null;
});
}
/**
* Обновить магазин (вызов демпфера)
*
* @param {HTMLElement} row Строка <div>
* @param {HTMLElement} button Кнопка <button>
* @param {HTMLElement} market_name_first Имя представителя магазина <input>
* @param {HTMLElement} market_name_second Фамилия представителя магазина <input>
* @param {HTMLElement} market_name_last Отчество представителя магазина <input>
* @param {HTMLElement} market_number SIM-номер представителя магазина <input>
* @param {HTMLElement} market_mail Почта представителя магазина <input>
* @param {HTMLElement} market_type Тип магазина <select>
* @param {HTMLElement} market_city Город магазина <select>
* @param {HTMLElement} market_district Регион магазина <input>
* @param {HTMLElement} market_address Адрес магазина <input>
*
* @return {void}
*/
static _update(
row,
button,
market_name_first,
market_name_second,
market_name_last,
market_number,
market_mail,
market_type,
market_city,
market_district,
market_address
) {
// Блокировка полей ввода
market_name_first.setAttribute("readonly", true);
market_name_second.setAttribute("readonly", true);
market_name_last.setAttribute("readonly", true);
market_number.setAttribute("readonly", true);
market_mail.setAttribute("readonly", true);
market_type.setAttribute("readonly", true);
market_city.setAttribute("readonly", true);
market_district.setAttribute("readonly", true);
market_address.setAttribute("readonly", true);
// Блокировка кнопки
button.setAttribute("disabled", true);
// Запуск выполнения
this.__update(
row,
button,
market_name_first,
market_name_second,
market_name_last,
market_number,
market_mail,
market_type,
market_city,
market_district,
market_address
);
}
/**
* Обновить сотрудника (демпфер)
*
* @param {HTMLElement} row Строка <div>
* @param {HTMLElement} button Кнопка <button>
* @param {HTMLElement} market_name_first Имя представителя магазина <input>
* @param {HTMLElement} market_name_second Фамилия представителя магазина <input>
* @param {HTMLElement} market_name_last Отчество представителя магазина <input>
* @param {HTMLElement} market_number SIM-номер представителя магазина <input>
* @param {HTMLElement} market_mail Почта представителя магазина <input>
* @param {HTMLElement} market_type Тип магазина <select>
* @param {HTMLElement} market_city Город магазина <select>
* @param {HTMLElement} market_district Регион магазина <input>
* @param {HTMLElement} market_address Адрес магазина <input>
*
* @return {void}
*/
static __update = damper(
async (
row,
button,
market_name_first,
market_name_second,
market_name_last,
market_number,
market_mail,
market_type,
market_city,
market_district,
market_address
) => {
// Инициализация функции разблокировки
function unblock() {
// Разблокировка полей ввода
market_name_first.removeAttribute("readonly");
market_name_second.removeAttribute("readonly");
market_name_last.removeAttribute("readonly");
market_number.removeAttribute("readonly");
market_mail.removeAttribute("readonly");
market_type.removeAttribute("readonly");
market_city.removeAttribute("readonly");
market_district.removeAttribute("readonly");
market_address.removeAttribute("readonly");
// Разблокировка кнопки
button.removeAttribute("disabled");
}
// Инициализация идентификатора сотрудника
const id = row.querySelector(['span[data-column="market"]']).innerText;
// Запуск отсрочки разблокировки на случай, если сервер не отвечает
const timeout = setTimeout(() => {
this.errors(["Сервер не отвечает"]);
unblock();
}, 5000);
// Запрос к серверу
return await fetch(`/market/${id}/update`, {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
body: `name_first=${market_name_first.value}&name_second=${market_name_second.value}&name_last=${market_name_last.value}&number=${market_number.mask.unmaskedValue}&mail=${market_mail.value}&type=${market_type.value}&city=${market_city.value}&district=${market_district.value}&address=${market_address.value}`,
})
.then((response) => response.json())
.then((data) => {
// Удаление отсрочки разблокировки
clearTimeout(timeout);
if (this.errors(data.errors)) {
// Сгенерированы ошибки
// Разблокировка полей ввода и кнопок
unblock();
} else {
// Не сгенерированы ошибки (подразумевается их отсутствие)
if (data.updated === true) {
// Записаны данные
// Инициализация буфера списка классов
// const buffer = [...row.classList];
// Инициализация статуса активной строки
const selected = row.getAttribute("data-selected");
// Реинициализация строки
row.outerHTML = data.row;
// Реинициализация строки (выражение странное, но правильное)
row = document.getElementById(row.getAttribute("id"));
// Копирование классов из буфера классов удалённой строки
// row.classList.add(...buffer);
// Копирование статуса активной строки
if (
typeof selected === "string" &&
selected === "true" &&
document.body.contains(document.getElementById("popup")) &&
!document.body.contains(
document.querySelector('[data-selected="true"]')
)
) {
row.setAttribute("data-selected", "true");
}
}
if (this.body.wrap instanceof HTMLElement) {
// Найдено активное окно
// Деинициализация быстрых действий по кнопкам
document.removeEventListener("keydown", this.buttons);
// Сброс блокировки
this.freeze = false;
// Деинициализация активного окна
this.body.wrap.remove();
// Удаление статуса активной строки
row.removeAttribute("data-selected");
}
}
});
},
300
);
/**
* Сгенерировать окно для редактирования магазина
*
* @param {HTMLElement} row Строка
*
* @return {void}
*/
static update = damper(async (row) => {
if (row instanceof HTMLElement) {
// Получена строка
// Инициализация идентификатора сотрудника
const id = row.querySelector(['span[data-column="market"]']).innerText;
// Запрос к серверу
return await fetch(`/market/${id}/fields`, {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
})
.then((response) => response.json())
.then((data) => {
// Инициализация буфера выбранных строк
const buffer = [
...document.querySelectorAll('div[data-selected="true"]'),
];
// Удаление статуса активной строки у остальных строк
for (const element of buffer) {
element.removeAttribute("data-selected");
}
// Инициализация статуса активной строки (обрабатываемой в данный момент)
row.setAttribute("data-selected", "true");
// Инициализация оболочки всплывающего окна
this.body.wrap = document.createElement("div");
this.body.wrap.setAttribute("id", "popup");
// Инициализация всплывающего окна
const popup = document.createElement("section");
popup.classList.add("list", "extensive", "medium");
// Инициализация заголовка всплывающего окна
const title = document.createElement("h3");
title.innerText = id;
// Инициализация оболочки с основной информацией
const main = document.createElement("section");
main.classList.add("main");
// Инициализация колонки
const market = document.createElement("div");
market.classList.add("column");
market.setAttribute("data-column", "market");
market.style.setProperty("width", "450px");
// Инициализация строки
const market_name_first = document.createElement("div");
market_name_first.classList.add("row", "merged");
// Инициализация оболочки для строки
const market_name_first_label = document.createElement("label");
market_name_first_label.setAttribute("id", "market_first");
// Инициализация заголовка для поля ввода
const market_name_first_title = document.createElement("b");
market_name_first_title.classList.add(
"separated",
"right",
"unselectable"
);
market_name_first_title.innerText = "Имя:";
// Инициализация поля ввода
const market_name_first_input = document.createElement("input");
market_name_first_input.classList.add("large");
market_name_first_input.setAttribute("type", "text");
market_name_first_input.setAttribute("name", "first");
market_name_first_input.setAttribute("autocomplete", "given-name");
market_name_first_input.setAttribute("minlength", "0");
market_name_first_input.setAttribute("maxlength", "100");
market_name_first_input.setAttribute(
"title",
"Имя представителя магазина"
);
market_name_first_input.setAttribute("placeholder", "Иван");
market_name_first_input.value = data.name.first ?? "";
// Инициализация строки
const market_name_second = document.createElement("div");
market_name_second.classList.add("row", "merged");
// Инициализация оболочки для строки
const market_name_second_label = document.createElement("label");
market_name_second_label.setAttribute("id", "market_second");
// Инициализация заголовка для поля ввода
const market_name_second_title = document.createElement("b");
market_name_second_title.classList.add(
"separated",
"right",
"unselectable"
);
market_name_second_title.innerText = "Фамилия:";
// Инициализация поля ввода
const market_name_second_input = document.createElement("input");
market_name_second_input.classList.add("large");
market_name_second_input.setAttribute(
"autocomplete",
"family-name"
);
market_name_second_input.setAttribute("name", "second");
market_name_second_input.setAttribute("type", "text");
market_name_second_input.setAttribute("minlength", "0");
market_name_second_input.setAttribute("maxlength", "100");
market_name_second_input.setAttribute(
"title",
"Фамилия представителя магазина"
);
market_name_second_input.setAttribute("placeholder", "Иванов");
market_name_second_input.value = data.name.second ?? "";
// Инициализация строки
const market_name_last = document.createElement("div");
market_name_last.classList.add("row", "merged");
// Инициализация оболочки для строки
const market_name_last_label = document.createElement("label");
market_name_last_label.setAttribute("id", "market_last");
// Инициализация заголовка для поля ввода
const market_name_last_title = document.createElement("b");
market_name_last_title.classList.add(
"separated",
"right",
"unselectable"
);
market_name_last_title.innerText = "Отчество:";
// Инициализация поля ввода
const market_name_last_input = document.createElement("input");
market_name_last_input.classList.add("large");
market_name_last_input.setAttribute("name", "last");
market_name_last_input.setAttribute(
"autocomplete",
"additional-name"
);
market_name_last_input.setAttribute("type", "text");
market_name_last_input.setAttribute("minlength", "0");
market_name_last_input.setAttribute("maxlength", "100");
market_name_last_input.setAttribute(
"title",
"Отчество/Матчество представителя магазина"
);
market_name_last_input.setAttribute("placeholder", "Иванович");
market_name_last_input.value = data.name.last ?? "";
// Инициализация строки
const market_number = document.createElement("div");
market_number.classList.add("row", "merged", "divided");
// Инициализация оболочки для строки
const market_number_label = document.createElement("label");
market_number_label.setAttribute("id", "market_number");
// Инициализация заголовка для поля ввода
const market_number_title = document.createElement("b");
market_number_title.classList.add(
"separated",
"right",
"unselectable"
);
market_number_title.innerText = "SIM-номер:";
// Инициализация поля ввода
const market_number_input = document.createElement("input");
market_number_input.classList.add("large");
market_number_input.setAttribute("name", "sim-number");
market_number_input.setAttribute("autocomplete", "tel");
market_number_input.setAttribute("type", "text");
market_number_input.setAttribute("minlength", "18");
market_number_input.setAttribute("maxlength", "18");
market_number_input.setAttribute(
"title",
"SIM-номер представителя магазина"
);
market_number_input.setAttribute(
"placeholder",
"+7 (000) 000-00-00"
);
market_number_input.value = data.number ?? "";
// Инициализация строки
const market_mail = document.createElement("div");
market_mail.classList.add("row", "merged");
// Инициализация оболочки для строки
const market_mail_label = document.createElement("label");
market_mail_label.setAttribute("id", "market_mail");
// Инициализация заголовка для поля ввода
const market_mail_title = document.createElement("b");
market_mail_title.classList.add(
"separated",
"right",
"unselectable"
);
market_mail_title.innerText = "Почта:";
// Инициализация поля ввода
const market_mail_input = document.createElement("input");
market_mail_input.classList.add("large");
market_mail_input.setAttribute("name", "mail");
market_mail_input.setAttribute("autocomplete", "email");
market_mail_input.setAttribute("type", "text");
market_mail_input.setAttribute("minlength", "3");
market_mail_input.setAttribute("maxlength", "300");
market_mail_input.setAttribute(
"title",
"Почта представителя магазина"
);
market_mail_input.setAttribute("placeholder", "name@server");
market_mail_input.value = data.mail ?? "";
// Инициализация строки
const market_type = document.createElement("div");
market_type.classList.add("row", "divided", "merged");
// Инициализация оболочки для выпадающего списка
const market_type_label = document.createElement("label");
market_type_label.setAttribute("id", "market_type");
// Инициализация заголовка для выпадающего списка
const market_type_title = document.createElement("b");
market_type_title.classList.add("separated", "right");
market_type_title.innerText = "Тип:";
// Инициализация выпадающего списка
const market_type_select = document.createElement("select");
market_type_select.classList.add("large");
market_type_select.setAttribute("autocomplete", "address-level2");
market_type_select.setAttribute("name", "type");
market_type_select.setAttribute("title", "Тип магазина");
market_type_select.value = data.type ?? "";
// Инициализация варианта для выбора
const market_type_option_1 = document.createElement("option");
market_type_option_1.classList.add("value", "Стандарт");
market_type_option_1.innerText = "Стандарт";
// Инициализация варианта для выбора
const market_type_option_2 = document.createElement("option");
market_type_option_2.classList.add("value", "Фрешмаркет");
market_type_option_2.innerText = "Фрешмаркет";
// Инициализация варианта для выбора
const market_type_option_3 = document.createElement("option");
market_type_option_3.classList.add("value", "Дискаунтер");
market_type_option_3.innerText = "Дискаунтер";
// Инициализация строки
const market_city = document.createElement("div");
market_city.classList.add("row", "divided", "merged");
// Инициализация оболочки для выпадающего списка
const market_city_label = document.createElement("label");
market_city_label.setAttribute("id", "market_city");
// Инициализация заголовка для выпадающего списка
const market_city_title = document.createElement("b");
market_city_title.classList.add("separated", "right");
market_city_title.innerText = "Город:";
// Инициализация выпадающего списка
const market_city_select = document.createElement("select");
market_city_select.classList.add("large");
market_city_select.setAttribute("autocomplete", "address-level2");
market_city_select.setAttribute("name", "city");
market_city_select.setAttribute("title", "Город магазина");
market_city_select.value = data.city ?? "";
// Инициализация варианта для выбора
const market_city_option_1 = document.createElement("option");
market_city_option_1.classList.add("value", "Красноярск");
market_city_option_1.innerText = "Красноярск";
// Инициализация варианта для выбора
const market_city_option_2 = document.createElement("option");
market_city_option_2.classList.add("value", "Железногорск");
market_city_option_2.innerText = "Железногорск";
/* // Инициализация варианта для выбора
const market_city_option_3 = document.createElement("option");
market_city_option_3.classList.add("value", "");
market_city_option_3.innerText = "";
// Инициализация варианта для выбора
const market_city_option_4 = document.createElement("option");
market_city_option_4.classList.add("value", "");
market_city_option_4.innerText = "";
// Инициализация варианта для выбора
const market_city_option_5 = document.createElement("option");
market_city_option_5.classList.add("value", "");
market_city_option_5.innerText = "";
// Инициализация варианта для выбора
const market_city_option_ = document.createElement("option");
market_city_option_.classList.add("value", "");
market_city_option_.innerText = ""; */
// Инициализация строки
const market_district = document.createElement("div");
market_district.classList.add("row", "merged");
// Инициализация оболочки для строки
const market_district_label = document.createElement("label");
market_district_label.setAttribute("id", "market_district");
// Инициализация заголовка для поля ввода
const market_district_title = document.createElement("b");
market_district_title.classList.add("separated", "right");
market_district_title.innerText = "Регион:";
// Инициализация поля ввода
const market_district_input = document.createElement("input");
market_district_input.classList.add("large");
market_district_input.setAttribute(
"autocomplete",
"address-level3"
);
market_district_input.setAttribute("name", "district");
market_district_input.setAttribute("type", "text");
market_district_input.setAttribute("minlength", "0");
market_district_input.setAttribute("maxlength", "80");
market_district_input.setAttribute("title", "Регион магазина");
market_district_input.setAttribute("placeholder", "Центральный");
market_district_input.value = data.district ?? "";
// Инициализация строки
const market_address = document.createElement("div");
market_address.classList.add("row", "merged");
// Инициализация оболочки для строки
const market_address_label = document.createElement("label");
market_address_label.setAttribute("id", "market_address");
// Инициализация заголовка для поля ввода
const market_address_title = document.createElement("b");
market_address_title.classList.add("separated", "right");
market_address_title.innerText = "Адрес:";
// Инициализация поля ввода
const market_address_input = document.createElement("input");
market_address_input.classList.add("large");
market_address_input.setAttribute("autocomplete", "street-address");
market_address_input.setAttribute("name", "address");
market_address_input.setAttribute("type", "text");
market_address_input.setAttribute("minlength", "0");
market_address_input.setAttribute("maxlength", "150");
market_address_input.setAttribute("title", "Адрес магазина");
market_address_input.setAttribute("placeholder", "ул. Пушкина 7");
market_address_input.value = data.address ?? "";
// Инициализация строки
const market_buttons = document.createElement("div");
market_buttons.classList.add("row", "divided", "buttons");
// Инициализация кнопки подтверждения даты
const market_update_button = document.createElement("button");
market_update_button.classList.add("grass", "stretched");
market_update_button.innerText = "Сохранить";
market_update_button.setAttribute(
"onclick",
`markets._update(document.getElementById(${
row.getAttribute("id") ?? ""
}), this, ...this.parentElement.parentElement.parentElement.parentElement.querySelectorAll(':is(select, input, textarea)'))`
);
// Инициализация окна с ошибками
this.body.errors = document.createElement("section");
this.body.errors.classList.add(
"errors",
"window",
"list",
"calculated",
"hidden"
);
this.body.errors.setAttribute("data-errors", true);
// Инициализация элемента-тела (оболочки) окна с ошибками
const errors = document.createElement("section");
errors.classList.add("body");
// Инициализация элемента-списка ошибок
const dl = document.createElement("dl");
// Инициализация активного всплывающего окна
const old = document.getElementById("popup");
if (old instanceof HTMLElement) {
// Найдено активное окно
// Деинициализация быстрых действий по кнопкам
document.removeEventListener("keydown", this.buttons);
// Сброс блокировки
this.freeze = false;
// Удаление активного окна
old.remove();
}
// Запись в документ
popup.appendChild(title);
market_name_first_label.appendChild(market_name_first_title);
market_name_first_label.appendChild(market_name_first_input);
market_name_first.appendChild(market_name_first_label);
market.appendChild(market_name_first);
market_name_second_label.appendChild(market_name_second_title);
market_name_second_label.appendChild(market_name_second_input);
market_name_second.appendChild(market_name_second_label);
market.appendChild(market_name_second);
market_name_last_label.appendChild(market_name_last_title);
market_name_last_label.appendChild(market_name_last_input);
market_name_last.appendChild(market_name_last_label);
market.appendChild(market_name_last);
market_number_label.appendChild(market_number_title);
market_number_label.appendChild(market_number_input);
market_number.appendChild(market_number_label);
market.appendChild(market_number);
market_mail_label.appendChild(market_mail_title);
market_mail_label.appendChild(market_mail_input);
market_mail.appendChild(market_mail_label);
market.appendChild(market_mail);
market_type_label.appendChild(market_type_title);
market_type_select.appendChild(market_type_option_1);
market_type_select.appendChild(market_type_option_2);
market_type_select.appendChild(market_type_option_3);
market_type_label.appendChild(market_type_select);
market_type.appendChild(market_type_label);
market.appendChild(market_type);
market_city_label.appendChild(market_city_title);
market_city_select.appendChild(market_city_option_1);
market_city_select.appendChild(market_city_option_2);
market_city_label.appendChild(market_city_select);
market_city.appendChild(market_city_label);
market.appendChild(market_city);
market_district_label.appendChild(market_district_title);
market_district_label.appendChild(market_district_input);
market_district.appendChild(market_district_label);
market.appendChild(market_district);
market_address_label.appendChild(market_address_title);
market_address_label.appendChild(market_address_input);
market_address.appendChild(market_address_label);
market.appendChild(market_address);
market_buttons.appendChild(market_update_button);
market.appendChild(market_buttons);
main.appendChild(market);
popup.appendChild(main);
this.body.wrap.appendChild(popup);
errors.appendChild(dl);
this.body.errors.appendChild(errors);
this.body.wrap.appendChild(this.body.errors);
document.body.appendChild(this.body.wrap);
// Инициализация ширины окна с ошибками
this.body.errors.style.setProperty(
"--calculated-width",
popup.offsetWidth + "px"
);
// Инициалиация масок
market_number_input.mask = IMask(market_number_input, {
mask: "+{7} (000) 000-00-00",
});
// Инициализация переменных для окна с ошибками (12 - это значение gap из div#popup)
function top(errors) {
errors.style.setProperty("transition", "0s");
errors.style.setProperty(
"--top",
popup.offsetTop + popup.offsetHeight + 12 + "px"
);
setTimeout(() => errors.style.removeProperty("transition"), 100);
}
top(this.body.errors);
const resize = new ResizeObserver(() => top(this.body.errors));
resize.observe(this.body.wrap);
// Инициализация функции закрытия всплывающего окна
const click = () => {
// Блокировка
if (this.freeze) return;
// Удаление всплывающего окна
this.body.wrap.remove();
// Инициализация буфера выбранных строк
const buffer = [
...document.querySelectorAll('div[data-selected="true"]'),
];
// Удаление статуса активной строки у остальных строк
for (const element of buffer) {
element.removeAttribute("data-selected");
}
// Деинициализация быстрых действий по кнопкам
document.removeEventListener("keydown", this.buttons);
// Сброс блокировки
this.freeze = false;
};
// Инициализация функции добавления функции закрытия всплывающего окна
const enable = () =>
this.body.wrap.addEventListener("click", click);
// Инициализация функции удаления функции закрытия всплывающего окна
const disable = () =>
this.body.wrap.removeEventListener("click", click);
// Первичная активация функции удаления всплывающего окна
enable();
// Инициализация блокировки удаления окна при взаимодействии с select-элементом
for (const select of popup.getElementsByTagName("select")) {
// Перебор всех select-элементов
// Инициализация функции блокировки удаления окна по событию
select.addEventListener("click", () => {
// Блокировка удаления окна
this.freeze = true;
// Разблокировка удаления окна
setTimeout(() => (this.freeze = false), 100);
});
for (const option of select.getElementsByTagName("option")) {
// Перебор всех option-элементов
// Инициализация функции блокировки удаления окна по событию
option.addEventListener("click", () => {
// Блокировка удаления окна
this.freeze = true;
// Разблокировка удаления окна
setTimeout(() => (this.freeze = false), 100);
});
}
}
// Инициализация блокировки удаления окна при взаимодействии с textarea-элементом
for (const textarea of popup.getElementsByTagName("textarea")) {
// Перебор всех textarea-элементов
// Обновлять позицию окна с ошибками при изменении размера textarea (там position: absolute)
new MutationObserver(() => top(this.body.errors)).observe(
textarea,
{
attributes: true,
attributeFilter: ["style"],
}
);
// Инициализация функции игнорирования блокировки для выбранных кнопок
textarea.addEventListener("keydown", (e) => {
if (e.keyCode === 27) {
// Нажата кнопка: "escape"
// Вызов глобальной функции управления кнопками
this.buttons(e, true);
} else if (e.ctrlKey && e.keyCode === 13) {
// Нажаты кнопки: "control", "enter"
// Вызов глобальной функции управления кнопками
this.buttons(e, true);
}
});
// Добавление функции блокировки удаления окна и клавиш по событиям
textarea.addEventListener("focus", () => (this.freeze = true));
textarea.addEventListener(
"focusout",
() => (this.freeze = false)
);
}
// Инициализация функции управления кнопками
this.buttons = (e, force = false) => {
// Блокировка
if (!force && this.freeze) return;
if (e.keyCode === 27) {
// Нажата кнопка: "escape"
// Удаление окна
click();
} else if (event.keyCode === 13) {
// Нажата кнопка: "enter"
// Инициализация буфера с текущим статусом блокировки закрытия окна
const freeze = this.freeze;
// Блокировка закрытия окна (чтобы не вызвался click() через событие onclick)
this.freeze = true;
// Активация виртуальной кнопки "сохранить"
market_update_button.click();
// Возвращение статуса блокировки закрытия окна
this.freeze = freeze;
}
};
// Инициализация быстрых действий по кнопкам
document.addEventListener("keydown", this.buttons);
// Инициализация функции удаления всплывающего окна по событиям
popup.addEventListener("mouseenter", disable);
popup.addEventListener("mouseleave", enable);
// Фокусировка
market_name_first_input.focus();
});
}
}, 300);
static account = class {
/**
* Ядро (родительский класс)
*/
static core;
/**
* Обновить аккаунт (вызов демпфера)
*
* @param {HTMLElement} row Строка <div>
* @param {HTMLElement} button Кнопка <button>
* @param {HTMLElement} account_name_first Имя аккаунта <input>
* @param {HTMLElement} account_name_second Фамилия аккаунта <input>
* @param {HTMLElement} account_name_last Отчество аккаунта <input>
* @param {HTMLElement} account_number SIM-номер аккаунта <input>
* @param {HTMLElement} account_mail Почта аккаунта<input>
* @param {HTMLElement} account_password Пароль аккаунта <input>
* @param {HTMLElement} account_commentary Комментарий аккаунта <textarea>
*
* @return {void}
*/
static _update(
row,
button,
account_name_first,
account_name_second,
account_name_last,
account_number,
account_mail,
account_password,
account_commentary
) {
// Блокировка полей ввода
account_name_first.setAttribute("readonly", true);
account_name_second.setAttribute("readonly", true);
account_name_last.setAttribute("readonly", true);
account_number.setAttribute("readonly", true);
account_mail.setAttribute("readonly", true);
account_password.setAttribute("readonly", true);
account_commentary.setAttribute("readonly", true);
// Блокировка кнопки
button.setAttribute("disabled", true);
// Запуск выполнения
this.__update(
row,
button,
account_name_first,
account_name_second,
account_name_last,
account_number,
account_mail,
account_password,
account_commentary
);
}
/**
* Обновить аккаунт (демпфер)
*
* @param {HTMLElement} row Строка <div>
* @param {HTMLElement} button Кнопка <button>
* @param {HTMLElement} account_name_first Имя аккаунта <input>
* @param {HTMLElement} account_name_second Фамилия аккаунта <input>
* @param {HTMLElement} account_name_last Отчество аккаунта <input>
* @param {HTMLElement} account_number SIM-номер аккаунта <input>
* @param {HTMLElement} account_mail Почта аккаунта<input>
* @param {HTMLElement} account_password Пароль аккаунта <input>
* @param {HTMLElement} account_commentary Комментарий аккаунта <textarea>
*
* @return {void}
*/
static __update = damper(
async (
row,
button,
account_name_first,
account_name_second,
account_name_last,
account_number,
account_mail,
account_password,
account_commentary
) => {
// Инициализация функции разблокировки
function unblock() {
// Разблокировка полей ввода
account_name_first.removeAttribute("readonly");
account_name_second.removeAttribute("readonly");
account_name_last.removeAttribute("readonly");
account_number.removeAttribute("readonly");
account_mail.removeAttribute("readonly");
account_password.removeAttribute("readonly");
account_commentary.removeAttribute("readonly");
// Разблокировка кнопки
button.removeAttribute("disabled");
}
// Инициализация идентификатора
const id = row.getAttribute("id");
// Запуск отсрочки разблокировки на случай, если сервер не отвечает
const timeout = setTimeout(() => {
this.core.errors(["Сервер не отвечает"]);
unblock();
}, 5000);
// Запрос к серверу
return await fetch(`/${id}/update`, {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
body: `name_first=${account_name_first.value}&name_second=${account_name_second.value}&name_last=${account_name_last.value}&number=${account_number.mask.unmaskedValue}&mail=${account_mail.value}&password=${account_password.value}&commentary=${account_commentary.value}`,
})
.then((response) => response.json())
.then((data) => {
// Удаление отсрочки разблокировки
clearTimeout(timeout);
if (this.core.errors(data.errors)) {
// Сгенерированы ошибки
// Разблокировка полей ввода и кнопок
unblock();
} else {
// Не сгенерированы ошибки (подразумевается их отсутствие)
if (data.updated === true) {
// Записаны данные
// Инициализация буфера списка классов
// const buffer = [...row.classList];
// Инициализация статуса активной строки
const selected = row.getAttribute("data-selected");
// Реинициализация строки
row.outerHTML = data.row;
// Реинициализация строки (выражение странное, но правильное)
row = document.getElementById(row.getAttribute("id"));
// Копирование классов из буфера классов удалённой строки
// row.classList.add(...buffer);
// Копирование статуса активной строки
if (
typeof selected === "string" &&
selected === "true" &&
document.body.contains(document.getElementById("popup")) &&
!document.body.contains(
document.querySelector('[data-selected="true"]')
)
) {
row.setAttribute("data-selected", "true");
}
}
if (
typeof data.clipboard !== "undefined" &&
data.clipboard.length > 0
) {
// Получены данные для записи в буфер обмена
// Запись в буфер обмена (подразумеваются данные созданного аккаунта)
navigator.clipboard.writeText(data.clipboard);
}
if (this.core.body.wrap instanceof HTMLElement) {
// Найдено активное окно
// Деинициализация быстрых действий по кнопкам
document.removeEventListener("keydown", this.core.buttons);
// Сброс блокировки
this.core.freeze = false;
// Деинициализация активного окна
this.core.body.wrap.remove();
// Удаление статуса активной строки
row.removeAttribute("data-selected");
}
}
});
},
300
);
/**
* Сгенерировать окно с данными аккаунта магазина
*
* @param {HTMLElement} row Строка
*
* @return {void}
*/
static update = damper(async (row) => {
if (row instanceof HTMLElement) {
// Получена строка
// Инициализация идентификатора аккаунта
const id = row.getAttribute("id");
// Запрос к серверу
return await fetch(`/${id}/fields`, {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
})
.then((response) => response.json())
.then((data) => {
// Инициализация буфера выбранных строк
const buffer = [
...document.querySelectorAll('div[data-selected="true"]'),
];
// Удаление статуса активной строки у остальных строк
for (const element of buffer) {
element.removeAttribute("data-selected");
}
// Инициализация статуса активной строки (обрабатываемой в данный момент)
row.setAttribute("data-selected", "true");
// Инициализация оболочки всплывающего окна
this.core.body.wrap = document.createElement("div");
this.core.body.wrap.setAttribute("id", "popup");
// Инициализация оболочки всплывающего окна
const popup = document.createElement("section");
popup.classList.add("list", "small");
// Инициализация заголовка всплывающего окна
const title = document.createElement("h3");
title.innerText = id;
// Инициализация оболочки с основной информацией
const main = document.createElement("section");
main.classList.add("main");
// Инициализация колонки
const account = document.createElement("div");
account.classList.add("column");
// Инициализация строки
const account_name_first = document.createElement("div");
account_name_first.classList.add("row", "merged");
// Инициализация оболочки для строки
const account_name_first_label = document.createElement("label");
account_name_first_label.setAttribute("id", "account_first");
// Инициализация заголовка для поля ввода
const account_name_first_title = document.createElement("b");
account_name_first_title.classList.add(
"separated",
"right",
"unselectable"
);
account_name_first_title.innerText = "Имя:";
// Инициализация поля ввода
const account_name_first_input = document.createElement("input");
account_name_first_input.classList.add("medium");
account_name_first_input.setAttribute("type", "text");
account_name_first_input.setAttribute("name", "first");
account_name_first_input.setAttribute(
"autocomplete",
"given-name"
);
account_name_first_input.setAttribute("minlength", "0");
account_name_first_input.setAttribute("maxlength", "100");
account_name_first_input.setAttribute("title", "Имя аккаунта");
account_name_first_input.setAttribute("placeholder", "Иван");
account_name_first_input.value = data.name.first ?? "";
// Инициализация строки
const account_name_second = document.createElement("div");
account_name_second.classList.add("row", "merged");
// Инициализация оболочки для строки
const account_name_second_label = document.createElement("label");
account_name_second_label.setAttribute("id", "account_second");
// Инициализация заголовка для поля ввода
const account_name_second_title = document.createElement("b");
account_name_second_title.classList.add(
"separated",
"right",
"unselectable"
);
account_name_second_title.innerText = "Фамилия:";
// Инициализация поля ввода
const account_name_second_input = document.createElement("input");
account_name_second_input.classList.add("medium");
account_name_second_input.setAttribute(
"autocomplete",
"family-name"
);
account_name_second_input.setAttribute("name", "second");
account_name_second_input.setAttribute("type", "text");
account_name_second_input.setAttribute("minlength", "0");
account_name_second_input.setAttribute("maxlength", "100");
account_name_second_input.setAttribute(
"title",
"Фамилия аккаунта"
);
account_name_second_input.setAttribute("placeholder", "Иванов");
account_name_second_input.value = data.name.second ?? "";
// Инициализация строки
const account_name_last = document.createElement("div");
account_name_last.classList.add("row", "merged");
// Инициализация оболочки для строки
const account_name_last_label = document.createElement("label");
account_name_last_label.setAttribute("id", "account_last");
// Инициализация заголовка для поля ввода
const account_name_last_title = document.createElement("b");
account_name_last_title.classList.add(
"separated",
"right",
"unselectable"
);
account_name_last_title.innerText = "Отчество:";
// Инициализация поля ввода
const account_name_last_input = document.createElement("input");
account_name_last_input.classList.add("medium");
account_name_last_input.setAttribute("name", "last");
account_name_last_input.setAttribute(
"autocomplete",
"additional-name"
);
account_name_last_input.setAttribute("type", "text");
account_name_last_input.setAttribute("minlength", "0");
account_name_last_input.setAttribute("maxlength", "100");
account_name_last_input.setAttribute(
"title",
"Отчество/Матчество аккаунта"
);
account_name_last_input.setAttribute("placeholder", "Иванович");
account_name_last_input.value = data.name.last ?? "";
// Инициализация строки
const account_number = document.createElement("div");
account_number.classList.add("row", "merged", "divided");
// Инициализация оболочки для строки
const account_number_label = document.createElement("label");
account_number_label.setAttribute("id", "account_number");
// Инициализация заголовка для поля ввода
const account_number_title = document.createElement("b");
account_number_title.classList.add(
"separated",
"right",
"unselectable"
);
account_number_title.innerText = "SIM-номер:";
// Инициализация поля ввода
const account_number_input = document.createElement("input");
account_number_input.classList.add("medium");
account_number_input.setAttribute("name", "sim-number");
account_number_input.setAttribute("autocomplete", "tel");
account_number_input.setAttribute("type", "text");
account_number_input.setAttribute("minlength", "18");
account_number_input.setAttribute("maxlength", "18");
account_number_input.setAttribute("title", "SIM-номер аккаунта");
account_number_input.setAttribute(
"placeholder",
"+7 (000) 000-00-00"
);
account_number_input.value = data.number ?? "";
// Инициализация строки
const account_mail = document.createElement("div");
account_mail.classList.add("row", "merged");
// Инициализация оболочки для строки
const account_mail_label = document.createElement("label");
account_mail_label.setAttribute("id", "account_mail");
// Инициализация заголовка для поля ввода
const account_mail_title = document.createElement("b");
account_mail_title.classList.add(
"separated",
"right",
"unselectable"
);
account_mail_title.innerText = "Почта:";
// Инициализация поля ввода
const account_mail_input = document.createElement("input");
account_mail_input.classList.add("medium");
account_mail_input.setAttribute("name", "mail");
account_mail_input.setAttribute("autocomplete", "email");
account_mail_input.setAttribute("type", "text");
account_mail_input.setAttribute("minlength", "3");
account_mail_input.setAttribute("maxlength", "300");
account_mail_input.setAttribute("title", "Почта аккаунта");
account_mail_input.setAttribute("placeholder", "name@server");
account_mail_input.value = data.mail ?? "";
// Инициализация строки
const account_password = document.createElement("div");
account_password.classList.add("row", "merged");
// Инициализация оболочки для строки
const account_password_label = document.createElement("label");
account_password_label.setAttribute("id", "account_password");
// Инициализация заголовка для поля ввода
const account_password_title = document.createElement("b");
account_password_title.classList.add(
"separated",
"right",
"unselectable"
);
account_password_title.innerText = "Пароль:";
// Инициализация поля ввода
const account_password_input = document.createElement("input");
account_password_input.classList.add("medium");
account_password_input.setAttribute("name", "password");
account_password_input.setAttribute("required", "true");
account_password_input.setAttribute(
"title",
"Не менее 8 символов"
);
account_password_input.setAttribute(
"autocomplete",
"new-password"
);
account_password_input.setAttribute("type", "password");
account_password_input.setAttribute("minlength", "8");
account_password_input.setAttribute("maxlength", "100");
account_password_input.setAttribute("title", "Пароль аккаунта");
account_password_input.setAttribute("placeholder", "*********");
// Инициализация строки
const account_commentary = document.createElement("div");
account_commentary.classList.add("row", "endless");
// Инициализация оболочки для строки
const account_commentary_label = document.createElement("label");
account_commentary_label.setAttribute("id", "account_commentary");
// Инициализация поля ввода
const account_commentary_textarea =
document.createElement("textarea");
account_commentary_textarea.setAttribute("maxlength", "800");
account_commentary_textarea.setAttribute(
"title",
"Комментарий аккаунта"
);
account_commentary_textarea.setAttribute(
"placeholder",
"Дополнительная информация для администраторов"
);
account_commentary_textarea.value = data.commentary ?? "";
// Инициализация строки
const account_buttons = document.createElement("div");
account_buttons.classList.add("row", "divided", "buttons");
// Инициализация кнопки обновления
const account_update_button = document.createElement("button");
account_update_button.classList.add("grass", "stretched");
account_update_button.innerText = "Сохранить";
account_update_button.setAttribute(
"onclick",
`markets.account._update(document.getElementById(${id}), this, ...this.parentElement.parentElement.parentElement.querySelectorAll(':is(input, textarea)'))`
);
// Инициализация кнопки удаления
const account_delete_button = document.createElement("button");
account_delete_button.classList.add("clay");
account_delete_button.innerText = "Удалить";
account_delete_button.setAttribute(
"onclick",
`markets.account._delete(document.getElementById(${id}), this, ...this.parentElement.parentElement.parentElement.querySelectorAll(':is(input, textarea)'))`
);
// Инициализация окна с ошибками
this.core.body.errors = document.createElement("section");
this.core.body.errors.classList.add(
"errors",
"window",
"list",
"small",
"hidden"
);
this.core.body.errors.setAttribute("data-errors", true);
// Инициализация элемента-оболочки с ошибками для всплывающего окна
const errors = document.createElement("section");
errors.classList.add("body");
// Инициализация элемента-списка ошибок
const dl = document.createElement("dl");
// Инициализация активного всплывающего окна
const old = document.getElementById("popup");
if (old instanceof HTMLElement) {
// Найдено активное окно
// Деинициализация быстрых действий по кнопкам
document.removeEventListener("keydown", this.buttons);
// Сброс блокировки
this.freeze = false;
// Удаление активного окна
old.remove();
}
// Запись в документ
popup.appendChild(title);
account_name_first_label.appendChild(account_name_first_title);
account_name_first_label.appendChild(account_name_first_input);
account_name_first.appendChild(account_name_first_label);
account.appendChild(account_name_first);
account_name_second_label.appendChild(account_name_second_title);
account_name_second_label.appendChild(account_name_second_input);
account_name_second.appendChild(account_name_second_label);
account.appendChild(account_name_second);
account_name_last_label.appendChild(account_name_last_title);
account_name_last_label.appendChild(account_name_last_input);
account_name_last.appendChild(account_name_last_label);
account.appendChild(account_name_last);
account_number_label.appendChild(account_number_title);
account_number_label.appendChild(account_number_input);
account_number.appendChild(account_number_label);
account.appendChild(account_number);
account_mail_label.appendChild(account_mail_title);
account_mail_label.appendChild(account_mail_input);
account_mail.appendChild(account_mail_label);
account.appendChild(account_mail);
account_password_label.appendChild(account_password_title);
account_password_label.appendChild(account_password_input);
account_password.appendChild(account_password_label);
account.appendChild(account_password);
account_commentary_label.appendChild(account_commentary_textarea);
account_commentary.appendChild(account_commentary_label);
account.appendChild(account_commentary);
account_buttons.appendChild(account_update_button);
account_buttons.appendChild(account_delete_button);
account.appendChild(account_buttons);
main.appendChild(account);
popup.appendChild(main);
this.core.body.wrap.appendChild(popup);
errors.appendChild(dl);
this.core.body.errors.appendChild(errors);
this.core.body.wrap.appendChild(this.core.body.errors);
document.body.appendChild(this.core.body.wrap);
// Инициалиация масок
account_number_input.mask = IMask(account_number_input, {
mask: "+{7} (000) 000-00-00",
});
// Инициализация переменных для окна с ошибками (12 - это значение gap из div#popup)
function top(errors) {
errors.style.setProperty("transition", "0s");
errors.style.setProperty(
"--top",
popup.offsetTop + popup.offsetHeight + 12 + "px"
);
setTimeout(
() => errors.style.removeProperty("transition"),
100
);
}
top(this.core.body.errors);
const resize = new ResizeObserver(() =>
top(this.core.body.errors)
);
resize.observe(this.core.body.wrap);
// Инициализация функции генерации пароля и записи в поле ввода и буфер обмена
const generate = (e) => {
// Блокировка выполнения при нажатии на поле для ввода
if (e.target.tagName === "INPUT") return;
// Инициализация поля ввода пароля
const input = e.currentTarget.getElementsByTagName("input")[0];
if (input instanceof HTMLElement) {
// Найдено поле для ввода пароля
// Инициализация буфера генерации пароля
let password = "";
// Инициализация используемых символов для генерируемого пароля
const symbols =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789------";
// Генерация пароля
for (let i = 0; i < Math.random() * 14 + 8; i++) {
password += symbols.charAt(
Math.floor(Math.random() * symbols.length)
);
}
// Запись пароля в поле для ввода пароля
input.value = password;
// Вызов функции инициализации генератора пароля
input.dispatchEvent(new KeyboardEvent("keyup"));
// Запиcь пароля в буфер обмена
navigator.clipboard.writeText(password);
// Фокусировка на поле для ввода пароля
input.focus();
}
};
// Инициализация функции инициализации генератора пароля
const generator = (e) => {
// Инициализация строки с полем для ввода пароля
const row = e.currentTarget.parentElement.parentElement;
if (row instanceof HTMLElement) {
// Найдено поле для ввода пароля
if (e.target.value.length === 0) {
// Не введён пароль
row.setAttribute("title", "Сгенерировать пароль");
row.setAttribute("data-interactive", "true");
row.addEventListener("click", generate);
} else {
// Введён пароль
row.removeAttribute("title");
row.removeAttribute("data-interactive");
row.removeEventListener("click", generate);
}
}
};
// Инициализация вызова функции инициализации генератора пароля по события нажатия клавиши
account_password_input.addEventListener("keyup", generator);
// Вызов функции инициализации генератора пароля (первичный)
account_password_input.dispatchEvent(new KeyboardEvent("keyup"));
// Инициализация функции закрытия всплывающего окна
const click = () => {
// Блокировка
if (this.core.freeze) return;
// Удаление всплывающего окна
this.core.body.wrap.remove();
// Инициализация буфера выбранных строк
const buffer = [
...document.querySelectorAll('div[data-selected="true"]'),
];
// Удаление статуса активной строки у остальных строк
for (const element of buffer) {
element.removeAttribute("data-selected");
}
// Деинициализация быстрых действий по кнопкам
document.removeEventListener("keydown", this.core.buttons);
// Сброс блокировки
this.core.freeze = false;
};
// Инициализация функции добавления функции закрытия всплывающего окна
const enable = () =>
this.core.body.wrap.addEventListener("click", click);
// Инициализация функции удаления функции закрытия всплывающего окна
const disable = () =>
this.core.body.wrap.removeEventListener("click", click);
// Первичная активация функции удаления всплывающего окна
enable();
// Инициализация блокировки удаления окна при взаимодействии с select-элементом
for (const select of popup.getElementsByTagName("select")) {
// Перебор всех select-элементов
// Инициализация функции блокировки удаления окна по событию
select.addEventListener("click", () => {
// Блокировка удаления окна
this.core.freeze = true;
// Разблокировка удаления окна
setTimeout(() => (this.core.freeze = false), 100);
});
for (const option of select.getElementsByTagName("option")) {
// Перебор всех option-элементов
// Инициализация функции блокировки удаления окна по событию
option.addEventListener("click", () => {
// Блокировка удаления окна
this.core.freeze = true;
// Разблокировка удаления окна
setTimeout(() => (this.core.freeze = false), 100);
});
}
}
// Инициализация блокировки удаления окна при взаимодействии с textarea-элементом
for (const textarea of popup.getElementsByTagName("textarea")) {
// Перебор всех textarea-элементов
// Обновлять позицию окна с ошибками при изменении размера textarea (там position: absolute)
new MutationObserver(() => top(this.core.body.errors)).observe(
textarea,
{
attributes: true,
attributeFilter: ["style"],
}
);
// Инициализация функции игнорирования блокировки для выбранных кнопок
textarea.addEventListener("keydown", (e) => {
if (e.keyCode === 27) {
// Нажата кнопка: "escape"
// Вызов глобальной функции управления кнопками
this.core.buttons(e, true);
} else if (e.ctrlKey && e.keyCode === 13) {
// Нажаты кнопки: "control", "enter"
// Вызов глобальной функции управления кнопками
this.core.buttons(e, true);
}
});
// Добавление функции блокировки удаления окна и клавиш по событиям
textarea.addEventListener(
"focus",
() => (this.core.freeze = true)
);
textarea.addEventListener(
"focusout",
() => (this.core.freeze = false)
);
}
// Инициализация функции управления кнопками
this.core.buttons = (e, force = false) => {
// Блокировка
if (!force && this.core.freeze) return;
if (e.keyCode === 27) {
// Нажата кнопка: "escape"
// Удаление окна
click();
} else if (event.keyCode === 13) {
// Нажата кнопка: "enter"
// Инициализация буфера с текущим статусом блокировки закрытия окна
const freeze = this.core.freeze;
// Блокировка закрытия окна (чтобы не вызвался click() через событие onclick)
this.core.freeze = true;
// Активация виртуальной кнопки "сохранить"
account_update_button.click();
// Возвращение статуса блокировки закрытия окна
this.core.freeze = freeze;
}
};
// Инициализация быстрых действий по кнопкам
document.addEventListener("keydown", this.core.buttons);
// Добавление функции удаления всплывающего окна по событиям
popup.addEventListener("mouseenter", disable);
popup.addEventListener("mouseleave", enable);
// Фокусировка
account_name_first_input.focus();
});
}
}, 300);
/**
* Удалить аккаунт (вызов демпфера)
*
* @param {HTMLElement} row Строка <div>
* @param {HTMLElement} button Кнопка <button>
* @param {HTMLElement} account_name_first Имя аккаунта <input>
* @param {HTMLElement} account_name_second Фамилия аккаунта <input>
* @param {HTMLElement} account_name_last Отчество аккаунта <input>
* @param {HTMLElement} account_number SIM-номер аккаунта <input>
* @param {HTMLElement} account_mail Почта аккаунта<input>
* @param {HTMLElement} account_password Пароль аккаунта <input>
* @param {HTMLElement} account_commentary Комментарий аккаунта <textarea>
*
* @return {void}
*/
static _delete(
row,
button,
account_name_first,
account_name_second,
account_name_last,
account_number,
account_mail,
account_password,
account_commentary
) {
// Блокировка полей ввода
account_name_first.setAttribute("readonly", true);
account_name_second.setAttribute("readonly", true);
account_name_last.setAttribute("readonly", true);
account_number.setAttribute("readonly", true);
account_mail.setAttribute("readonly", true);
account_password.setAttribute("readonly", true);
account_commentary.setAttribute("readonly", true);
// Блокировка кнопки
button.setAttribute("disabled", true);
// Запуск выполнения
this.__delete(
row,
button,
account_name_first,
account_name_second,
account_name_last,
account_number,
account_mail,
account_password,
account_commentary
);
}
/**
* Удалить аккаунт (демпфер)
*
* @param {HTMLElement} row Строка <div>
* @param {HTMLElement} button Кнопка <button>
* @param {HTMLElement} account_name_first Имя аккаунта <input>
* @param {HTMLElement} account_name_second Фамилия аккаунта <input>
* @param {HTMLElement} account_name_last Отчество аккаунта <input>
* @param {HTMLElement} account_number SIM-номер аккаунта <input>
* @param {HTMLElement} account_mail Почта аккаунта<input>
* @param {HTMLElement} account_password Пароль аккаунта <input>
* @param {HTMLElement} account_commentary Комментарий аккаунта <textarea>
*
* @return {void}
*/
static __delete = damper(
async (
row,
button,
account_name_first,
account_name_second,
account_name_last,
account_number,
account_mail,
account_password,
account_commentary
) => {
// Инициализация функции разблокировки
function unblock() {
// Разблокировка полей ввода
account_name_first.removeAttribute("readonly");
account_name_second.removeAttribute("readonly");
account_name_last.removeAttribute("readonly");
account_number.removeAttribute("readonly");
account_mail.removeAttribute("readonly");
account_password.removeAttribute("readonly");
account_commentary.removeAttribute("readonly");
// Разблокировка кнопки
button.removeAttribute("disabled");
}
// Инициализация идентификатора
const id = row.getAttribute("id");
// Запуск отсрочки разблокировки на случай, если сервер не отвечает
const timeout = setTimeout(() => {
this.core.errors(["Сервер не отвечает"]);
unblock();
}, 5000);
// Запрос к серверу
return await fetch(`/${id}/delete`, {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
})
.then((response) => response.json())
.then((data) => {
// Удаление отсрочки разблокировки
clearTimeout(timeout);
if (this.core.errors(data.errors)) {
// Сгенерированы ошибки
// Разблокировка полей ввода и кнопок
unblock();
} else {
// Не сгенерированы ошибки (подразумевается их отсутствие)
if (data.deleted === true) {
// Удалены данные
// Удаление строки
row.remove();
}
if (this.core.body.wrap instanceof HTMLElement) {
// Найдено активное окно
// Деинициализация быстрых действий по кнопкам
document.removeEventListener("keydown", this.core.buttons);
// Сброс блокировки
this.core.freeze = false;
// Деинициализация активного окна
this.core.body.wrap.remove();
// Удаление статуса активной строки
row.removeAttribute("data-selected");
}
}
});
},
300
);
};
/**
* Заблокировать сотрудника
*
* @param {string|int} worker Идентификатор сотрудника
* @param {HTMLElement} button Кнопка <button>
*/
static async ban(worker, button) {
console.log(button);
if ((typeof worker === "string" || typeof worker === 'number') && button instanceof HTMLElement) {
// Получены идентификатор сотрудника и кнопка
// Запрос к серверу
return await fetch(`/market/ban/${worker}`, {
method: "POST",
})
.then((response) => response.json())
.then((data) => {
if (this.errors(data.errors)) {
// Сгенерированы ошибки
} else {
// Не сгенерированы ошибки (подразумевается их отсутствие)
button.classList.remove("clay");
button.classList.add("earth");
button.innerText = "Разблокировать";
button.setAttribute(
"title",
"Сотрудник снова сможет записываться на заявки"
);
button.setAttribute("onclick", `markets.unban(${worker}, this)`);
}
});
}
}
/**
* Разблокировать сотрудника
*
* @param {string|int} worker Идентификатор сотрудника
* @param {HTMLElement} button Кнопка <button>
*/
static async unban(worker, button) {
if (typeof worker === "string" || typeof worker === 'number' && button instanceof HTMLElement) {
// Получены идентификатор сотрудника и кнопка
// Запрос к серверу
return await fetch(`/market/unban/${worker}`, {
method: "POST",
})
.then((response) => response.json())
.then((data) => {
if (this.errors(data.errors)) {
// Сгенерированы ошибки
} else {
// Не сгенерированы ошибки (подразумевается их отсутствие)
button.classList.remove("earth");
button.classList.add("clay");
button.innerText = "Заблокировать";
button.setAttribute(
"title",
"Сотрудник не сможет записываться на заявки"
);
button.setAttribute("onclick", `markets.ban(${worker}, this)`);
}
});
}
}
/**
* Проверить нахождение сотрудника в списке заблокированных
*
* @param {string|int} worker Идентификатор сотрудника
*
* @return {bool} Сотрудник заблокирован?
*/
static async banned(worker) {
if (typeof worker === "string" || typeof worker === 'number') {
// Получен идентификатор сотрудника
// Запрос к серверу
return await fetch(`/market/banned/${worker}`, {
method: "POST",
})
.then((response) => response.json())
.then((data) => {
if (this.errors(data.errors)) {
// Сгенерированы ошибки
} else {
// Не сгенерированы ошибки (подразумевается их отсутствие)
return data.banned;
}
});
}
}
/**
* Сгенерировать HTML-элемент со списком ошибок
*
* @param {object} registry Реестр ошибок
* @param {bool} render Отобразить в окне с ошибками?
* @param {bool} clean Очистить окно с ошибками перед добавлением?
*
* @return {bool} Сгенерированы ошибки?
*/
static errors(registry, render = true, clean = true) {
// Инициализация ссылки на HTML-элемент с ошибками
const wrap = document.body.contains(this.body.errors)
? this.body.errors
: document.querySelector('[data-errors="true"]');
if (wrap instanceof HTMLElement && document.body.contains(wrap)) {
// Найден HTML-элемент с ошибками
// Перерасчёт высоты элемента
function height() {
wrap.classList.remove("hidden");
wrap.classList.remove("animation");
// Реинициализация переменной с данными о высоте HTML-элемента (16 - это padding-top + padding-bottom у div#popup > section.errors)
wrap.style.setProperty("--height", wrap.offsetHeight - 16 + "px");
wrap.classList.add("animation");
wrap.classList.add("hidden");
}
// Инициализация элемента-списка ошибок
const list = wrap.getElementsByTagName("dl")[0];
// Удаление ошибок из прошлой генерации
if (clean) list.innerHTML = null;
for (const error in registry) {
// Генерация HTML-элементов с текстами ошибок
// Инициализация HTML-элемента текста ошибки
const samp = document.createElement("samp");
if (typeof registry[error] === "object") {
// Категория ошибок
// Проверка наличия ошибок
if (registry[error].length === 0) continue;
// Инициализация HTML-элемента-оболочки
const wrap = document.createElement("dt");
// Запись текста категории
samp.innerText = error;
// Запись HTML-элементов в список
wrap.appendChild(samp);
list.appendChild(wrap);
// Реинициализация высоты
height();
// Обработка вложенных ошибок (вход в рекурсию)
this.errors(registry[error], false);
} else {
// Текст ошибки (подразумевается)
// Инициализация HTML-элемента
const wrap = document.createElement("dd");
// Запись текста ошибки
samp.innerText = registry[error];
// Запись HTML-элемента в список
wrap.appendChild(samp);
list.appendChild(wrap);
// Реинициализация высоты
height();
}
}
if (render) {
// Запрошена отрисовка
if (list.childElementCount !== 0) {
// Найдены ошибки
// Сброс анимации
// УЛОВКА: таким образом не запускается анимация до взаимодействия с элементом (исправлял это в CSS, но не помню как)
wrap.classList.add("animation");
// Отображение
wrap.classList.remove("hidden");
} else {
// Не найдены ошибки
// Скрытие
wrap.classList.add("hidden");
}
}
return list.childElementCount === 0 ? false : true;
}
return false;
}
};
// Инициализация ядра
window.markets.account.core = window.markets;
}
// Вызов события: "инициализировано"
document.dispatchEvent(
new CustomEvent("markets.initialized", {
detail: { markets: window.markets },
})
);