/**
* @file felexdev-theme-manager.js
* @description Минифицированная версия
* @version 0.0.1
* @author felex67 (admin@felexdev.ru)
* @license Apache2.0
* @warning Системная версия('auto') должна регистрироваться первой!!!
*/
class ThemeManager {
/** Cunfigurations */
static #config = {
btnId: 'btn-toggle', // Идентификатор кнопки переключения: `gpfx + btnid == 'flxd-tm-btn-toggle'`
btnTabIndex: 0, // Индекс табуляции кнопки переключения тем
globalPrefix: 'flxd-tm', // Глобальный префикс: `gpfx + '-' == 'flxd-tm-'`
themePrefix: 'color-scheme', // Селектор CSS: `gpfx + stdid == 'flxd-tm-color-scheme'`
svg: '',
};
static #classList = document.documentElement.classList;
static #button = document.createElement('div');
static #index = 0;
static #themes = [];
static toggle = () => {
this.#s((this.#index + 1) % this.#themes.length);
};
static /* Инициализация конфигурации */ {
const config = this.#config;
config.globalPrefix += '-';
config.themePrefix = config.globalPrefix + config.themePrefix;
this.#button.id = config.btnId = config.globalPrefix + config.btnId;
this.#button.tabIndex = config.btnTabIndex;
this.#button.setAttribute('aria-label', 'toggle color scheme');
this.#button.addEventListener('click', this.toggle);
};
/**
* Add new theme
* @param {string} themeName - Название темы используемое в селекторе CSS. 'auto' -> 'flxd-tm-color-scheme-auto'
* @param {string?} themeIcon - Текстовое векторное изображение PlainSVG, если равно нулю используется иконка по умолчанию: 2-я фаза луны.
*/
static #addTheme = (name, icon = null) => {
this.#themes.push({
name: name,
icon: icon || this.#config.svg,
selector:`${this.themePrefix}-${name}`,
});
};
static #set(index) {
if (index == this.#index)
return;
if (index && this.#index)
this.#configl.replace(this.#themes[this.#index].selector, this.#themes[index].selector);
else if (this.#index)
this.#configl.remove(this.#themes[this.#index].selector);
else this.#configl.add(this.#themes[index].selector);
this.#save(this.#index = index);
this.#button.innerHTML = this.#themes[index].icon;
this.#button.setAttribute('aria-current', this.#themes[index].name);
};
static #save = (() => {
let save = (index) => { console.error(this.#config.globalPrefix + '#save: Невозможно сохранить тему, хранилища не доступны.'); };
try {
this.#index = parseInt(localStorage.getItem(this.#config.themePrefix)) || 0;
save = (index) => {
try { localStorage.setItem(this.#config.themePrefix, index); }
catch(e) { console.error(e); }
};
}
catch(e) {
console.error(this.#config.globalPrefix + '#sv-IIFE: localStorage не доступен, пробую cookie.');
try {
let cookie = document.cookie.match(`${this.#config.themePrefix}\\s*=\\s*(\\d+)`);
this.#index = cookie ? parseInt(c[1]) || 0 : 0;
save = (i) => {
try {
document.cookie = `${this.#config.themePrefix}=${i};max-age=${31536000};path=/`;
}
catch(e) { console.error(e); }
};
}
catch(e) { console.error(this.#config.globalPrefix + `#s-IIFE: Хранилища не доступны. Настройки темы не сохраняются!`); }
}
return save;
})();
static /* Инициализация тем */ {
let addTheme = this.#addTheme;
/** @warning Системная версия('auto') должна регистрироваться первой!!! */
addTheme('auto','');
addTheme('light','');
addTheme('dark','');
/* Новые темы добавлять здесь */
addTheme('old-terminal','');
/* */
if (this.#index >= this.#themes.length || this.#index<0) {
console.error(`${this.#config.globalPrefix}bottom-static: В хранилище сохранён не валидный индекс '${this.#index}'. Сброс на системную тему`);
this.#index = 0;
}
this.#set(this.#index);
};
static set = (theme) => {
let i = -1;
for(let j=0; j < this.#themes.length; j++) {
if(this.#themes[j].name === name) {
i = j;
break;
}
}
if(i == -1) {
throw new Error(`Темы '${theme}' не существует!.`);
}
this.#set(i);
};
static #_ = () => {
window.removeEventListener('DOMContentLoaded',this.#_);
document.body.appendChild(this.#button);
};
static {
let m = this;
this.#set(this.#index);
if (!document.body)window.addEventListener('DOMContentLoaded', this.#_);
}
};