transit from nadrez, added panel
This commit is contained in:
parent
5e3e42ebe7
commit
d8c41863a8
|
@ -130,3 +130,4 @@ dist
|
||||||
.yarn/install-state.gz
|
.yarn/install-state.gz
|
||||||
.pnp.*
|
.pnp.*
|
||||||
|
|
||||||
|
web-ext-artifacts
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
web-ext -s firefox run -f "C:\Program Files\Firefox Developer Edition\firefox.exe" -p "C:\Users\MIRZAEV\AppData\Roaming\Mozilla\Firefox\Profiles\dev.mirzaev" --profile-create-if-missing --keep-profile-changes --verbose
|
|
@ -0,0 +1,52 @@
|
||||||
|
{
|
||||||
|
"extensionName": {
|
||||||
|
"message": "Menu demo",
|
||||||
|
"description": "Name of the extension."
|
||||||
|
},
|
||||||
|
|
||||||
|
"extensionDescription": {
|
||||||
|
"message": "Demonstrates the menus API.",
|
||||||
|
"description": "Description of the add-on."
|
||||||
|
},
|
||||||
|
|
||||||
|
"menuItemSelectionLogger": {
|
||||||
|
"message": "Log '%s' to the browser console",
|
||||||
|
"description": "Title of context menu item that logs the selected text when clicked."
|
||||||
|
},
|
||||||
|
|
||||||
|
"menuItemRemoveMe": {
|
||||||
|
"message": "Remove me!",
|
||||||
|
"description": "Title of context menu item that removes itself when clicked."
|
||||||
|
},
|
||||||
|
|
||||||
|
"menuItemGreenify": {
|
||||||
|
"message": "Greenify",
|
||||||
|
"description": "Title of context menu item that adds a green border when clicked."
|
||||||
|
},
|
||||||
|
|
||||||
|
"menuItemBluify": {
|
||||||
|
"message": "Bluify",
|
||||||
|
"description": "Title of context menu item that adds a green border when clicked."
|
||||||
|
},
|
||||||
|
|
||||||
|
"menuItemCheckMe": {
|
||||||
|
"message": "Check me",
|
||||||
|
"description": "Title of context menu item when the item is checked."
|
||||||
|
},
|
||||||
|
|
||||||
|
"menuItemUncheckMe": {
|
||||||
|
"message": "Uncheck me",
|
||||||
|
"description": "Title of context menu item when the item is unchecked."
|
||||||
|
},
|
||||||
|
|
||||||
|
"menuItemOpenSidebar": {
|
||||||
|
"message": "Open sidebar",
|
||||||
|
"description": "Title of context menu item that opens a sidebar."
|
||||||
|
},
|
||||||
|
|
||||||
|
"menuItemToolsMenu": {
|
||||||
|
"message": "Click me!",
|
||||||
|
"description": "Title of tools menu item."
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ядро
|
||||||
|
*
|
||||||
|
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||||
|
*/
|
||||||
|
class core {
|
||||||
|
/**
|
||||||
|
* Префикс в журнале
|
||||||
|
*/
|
||||||
|
prefix = 'ядро';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Инициализация
|
||||||
|
*/
|
||||||
|
init() {
|
||||||
|
// Инициализация маршрутизатора
|
||||||
|
window.addEventListener("popstate", this.router);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Маршрутизатор
|
||||||
|
*/
|
||||||
|
router() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Запись в журнал
|
||||||
|
*
|
||||||
|
* @param {string} text
|
||||||
|
*
|
||||||
|
* @return {bool} Статус записи в журнал
|
||||||
|
*/
|
||||||
|
log(text) {
|
||||||
|
if (typeof text === 'string') {
|
||||||
|
// Передана строка
|
||||||
|
|
||||||
|
// Запись в журнал
|
||||||
|
return log.write(this.prefix, text);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Запуск
|
||||||
|
new core().init();
|
|
@ -0,0 +1,36 @@
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||||
|
*/
|
||||||
|
class log {
|
||||||
|
/**
|
||||||
|
* Запись в журнал
|
||||||
|
*
|
||||||
|
* @param {string} prefix Префикс
|
||||||
|
* @param {string} text Текст для записи
|
||||||
|
*
|
||||||
|
* @return {Promise|bool} Статус записи в журнал
|
||||||
|
*/
|
||||||
|
static async write(prefix, text) {
|
||||||
|
if (typeof prefix === 'string' && typeof text === 'string') {
|
||||||
|
// Переданы строки
|
||||||
|
|
||||||
|
// Инициализация статуса отладки
|
||||||
|
let debug = await settings.read('debug');
|
||||||
|
|
||||||
|
// truetruetruetruetruetruetruetrue
|
||||||
|
|
||||||
|
if (debug === true || debug === '1' || true) {
|
||||||
|
// Активен режим отладки
|
||||||
|
|
||||||
|
// Запись в журнал
|
||||||
|
console.log('[надрез мозжечка][' + prefix + '] ' + text);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,80 @@
|
||||||
|
{
|
||||||
|
"version": "1.0",
|
||||||
|
"manifest_version": 2,
|
||||||
|
"name": "микроволновка",
|
||||||
|
"description": "Массовая раскрутка и прогрев аккаунтов ВКонтакте",
|
||||||
|
"applications": {
|
||||||
|
"gecko": {
|
||||||
|
"id": "microwave@mirzaev.sexy",
|
||||||
|
"strict_min_version": "95.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"default_locale": "en",
|
||||||
|
"permissions": [
|
||||||
|
"*://*.vk.com/*",
|
||||||
|
"<all_urls>",
|
||||||
|
"activeTab",
|
||||||
|
"alarms",
|
||||||
|
"background",
|
||||||
|
"browserSettings",
|
||||||
|
"browsingData",
|
||||||
|
"clipboardRead",
|
||||||
|
"clipboardWrite",
|
||||||
|
"contentSettings",
|
||||||
|
"contextMenus",
|
||||||
|
"contextualIdentities",
|
||||||
|
"cookies",
|
||||||
|
"debugger",
|
||||||
|
"dns",
|
||||||
|
"downloads",
|
||||||
|
"downloads.open",
|
||||||
|
"find",
|
||||||
|
"geolocation",
|
||||||
|
"history",
|
||||||
|
"identity",
|
||||||
|
"idle",
|
||||||
|
"management",
|
||||||
|
"menus",
|
||||||
|
"menus.overrideContext",
|
||||||
|
"nativeMessaging",
|
||||||
|
"notifications",
|
||||||
|
"pageCapture",
|
||||||
|
"pkcs11",
|
||||||
|
"privacy",
|
||||||
|
"proxy",
|
||||||
|
"search",
|
||||||
|
"sessions",
|
||||||
|
"storage",
|
||||||
|
"tabHide",
|
||||||
|
"tabs",
|
||||||
|
"topSites",
|
||||||
|
"unlimitedStorage",
|
||||||
|
"webNavigation",
|
||||||
|
"webRequest",
|
||||||
|
"webRequestBlocking"
|
||||||
|
],
|
||||||
|
"options_ui": {
|
||||||
|
"page": "/settings/index.html"
|
||||||
|
},
|
||||||
|
"background": {
|
||||||
|
"scripts": [
|
||||||
|
"/core.js"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"content_scripts": [
|
||||||
|
{
|
||||||
|
"matches": [
|
||||||
|
"https://*.vk.com/*"
|
||||||
|
],
|
||||||
|
"js": [
|
||||||
|
"/log.js",
|
||||||
|
"/settings.js",
|
||||||
|
"/modules/module.js",
|
||||||
|
"/pages/panel/index.js"
|
||||||
|
],
|
||||||
|
"all_frames": true,
|
||||||
|
"match_about_blank": true,
|
||||||
|
"run_at": "document_end"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||||
|
*/
|
||||||
|
class module {
|
||||||
|
/**
|
||||||
|
* Префикс в журнале
|
||||||
|
*/
|
||||||
|
prefix = this.name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Запись в журнал
|
||||||
|
*
|
||||||
|
* @param {string} text
|
||||||
|
*
|
||||||
|
* @return {bool} Статус записи в журнал
|
||||||
|
*/
|
||||||
|
log(text) {
|
||||||
|
if (typeof text === 'string') {
|
||||||
|
// Передана строка
|
||||||
|
|
||||||
|
// Запись в журнал
|
||||||
|
return log.write(this.prefix, text);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,877 @@
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Страница настроек ВКонтакте
|
||||||
|
*/
|
||||||
|
class panel {
|
||||||
|
constructor() {
|
||||||
|
/**
|
||||||
|
* Идентификатор (https://vk.com/settings?act=ЗНАЧЕНИЕ)
|
||||||
|
*/
|
||||||
|
this.id = 'microwave';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Инициализация
|
||||||
|
*/
|
||||||
|
this.init = function () {
|
||||||
|
// Инициализация кнопки в боковом меню
|
||||||
|
this.button();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Сгенерировать панель управления
|
||||||
|
*
|
||||||
|
* Рекурсивно проверяет открытие страницы "Игры"
|
||||||
|
*
|
||||||
|
* @return {bool} Метод выполнен без ошибок?
|
||||||
|
*/
|
||||||
|
this.generate = function () {
|
||||||
|
// Генерация уникального идентификатора для элемента загрузки
|
||||||
|
const id = Math.random().toString(36).replace(/[^A-z]+ /g, '').slice(2);
|
||||||
|
|
||||||
|
// Инициализация элемента загрузки (пока что просто проверочный)
|
||||||
|
const loading = document.createElement('div');
|
||||||
|
loading.id = id;
|
||||||
|
loading.style.display = 'none';
|
||||||
|
|
||||||
|
// Запись в документ
|
||||||
|
panel.body().appendChild(loading);
|
||||||
|
|
||||||
|
function check(iterator = 0) {
|
||||||
|
// Инициализация оболочки страницы "Игры"
|
||||||
|
|
||||||
|
if (window.location.pathname === '/apps' && !(document.getElementById(id) instanceof HTMLElement)) {
|
||||||
|
// Загружена страница "Игры" (или перезагружена)
|
||||||
|
|
||||||
|
// Инициализация страницы
|
||||||
|
panel.clean();
|
||||||
|
|
||||||
|
panel.blocks.group(
|
||||||
|
'test',
|
||||||
|
panel.blocks.menu(),
|
||||||
|
panel.blocks.tab('Тест', function () { alert('хихи') })
|
||||||
|
);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (iterator > 300) return false;
|
||||||
|
else setTimeout(check, 100, ++iterator);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Запуск проверки
|
||||||
|
check();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Инициализация кнопки в боковом меню
|
||||||
|
*/
|
||||||
|
this.button = function () {
|
||||||
|
if (document.getElementById('l_mw') instanceof HTMLElement) return;
|
||||||
|
|
||||||
|
// Инициализация оболочки кнопки
|
||||||
|
const li = document.createElement('li');
|
||||||
|
li.id = 'l_mw'
|
||||||
|
|
||||||
|
// Инициализация ссылки кнопки
|
||||||
|
const a = document.createElement('a');
|
||||||
|
a.classList.add('left_row');
|
||||||
|
a.setAttribute('type', 'button');
|
||||||
|
a.setAttribute('onclick', "return nav.go(document.getElementById('l_ap').firstElementChild, event, { noback: true, params: { _ref: 'left_nav' } });");
|
||||||
|
a.addEventListener('click', this.generate, this);
|
||||||
|
|
||||||
|
// Инициализация иконки кнопки
|
||||||
|
const div = document.createElement('div');
|
||||||
|
div.classList.add('LeftMenu__icon');
|
||||||
|
|
||||||
|
// Инициализация svg иконки
|
||||||
|
const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
|
||||||
|
svg.setAttribute('fill', 'none');
|
||||||
|
svg.setAttribute('height', '20');
|
||||||
|
svg.setAttribute('viewBox', '0 0 20 20');
|
||||||
|
svg.setAttribute('width', '20');
|
||||||
|
svg.setAttribute('xmlns', 'http://www.w3.org/2000/svg');
|
||||||
|
|
||||||
|
// Инициализация path для svg
|
||||||
|
const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
|
||||||
|
path.setAttribute('clip-rule', 'evenodd');
|
||||||
|
path.setAttribute('d', 'M10 7.75a1.25 1.25 0 1 1 0-2.5 1.25 1.25 0 0 1 0 2.5zM7.25 6.5a2.75 2.75 0 1 1 5.5 0 2.75 2.75 0 0 1-5.5 0zm-.5 7.25c0-.42.23-.83.8-1.17A4.81 4.81 0 0 1 10 12c1.03 0 1.88.23 2.45.58.57.34.8.75.8 1.17 0 .3-.1.44-.22.54-.14.11-.4.21-.78.21h-4.5c-.39 0-.64-.1-.78-.21-.12-.1-.22-.25-.22-.54zM10 10.5c-1.22 0-2.37.27-3.23.8-.88.53-1.52 1.37-1.52 2.45 0 .7.28 1.3.78 1.71.48.39 1.1.54 1.72.54h4.5c.61 0 1.24-.15 1.72-.54.5-.4.78-1 .78-1.71 0-1.08-.64-1.92-1.52-2.45-.86-.53-2-.8-3.23-.8zm4-5.59c.06-.4.44-.7.85-.64a2.5 2.5 0 0 1-.35 4.98.75.75 0 0 1 0-1.5 1 1 0 0 0 .14-1.99.75.75 0 0 1-.63-.85zM15.76 10a.75.75 0 0 0 0 1.5c1.16 0 1.75.67 1.75 1.25 0 .22-.07.41-.19.55-.1.12-.24.2-.46.2a.75.75 0 0 0 0 1.5c1.43 0 2.15-1.21 2.15-2.25 0-1.71-1.6-2.75-3.25-2.75zM5 10.75a.75.75 0 0 0-.75-.75C2.61 10 1 11.04 1 12.75 1 13.79 1.72 15 3.15 15a.75.75 0 0 0 0-1.5.57.57 0 0 1-.47-.2.86.86 0 0 1-.18-.55c0-.58.6-1.25 1.75-1.25.41 0 .75-.34.75-.75zm.14-6.47a.75.75 0 0 1 .22 1.48 1 1 0 0 0 .14 1.99.75.75 0 1 1 0 1.5 2.5 2.5 0 0 1-.36-4.97z');
|
||||||
|
path.setAttribute('fill', 'currentColor');
|
||||||
|
path.setAttribute('fill-rule', 'evenodd');
|
||||||
|
|
||||||
|
// Инициализация текста кнопки
|
||||||
|
const text = document.createElement('span');
|
||||||
|
text.classList.add('left_label', 'inl_bl');
|
||||||
|
text.innerText = 'Микроволновка';
|
||||||
|
|
||||||
|
// Инициализация оболочки количества уведомлений
|
||||||
|
const notifications = document.createElement('span');
|
||||||
|
notifications.classList.add('left_count_wrap', 'fl_r', 'left_void');
|
||||||
|
|
||||||
|
// Инициализация текста количества уведомлений
|
||||||
|
const amount = document.createElement('span');
|
||||||
|
amount.classList.add('inl_bl', 'left_count_sign');
|
||||||
|
|
||||||
|
// Инициализация оболочки кнопки настроек
|
||||||
|
const settings = document.createElement('div');
|
||||||
|
settings.classList.add('left_settings');
|
||||||
|
settings.setAttribute('onclick', 'menuSettings(0)');
|
||||||
|
|
||||||
|
// Инициализация кнопки настроек
|
||||||
|
const button = document.createElement('div');
|
||||||
|
button.classList.add('left_settings_inner');
|
||||||
|
|
||||||
|
// Генерация архитектуры
|
||||||
|
settings.appendChild(button);
|
||||||
|
notifications.appendChild(amount);
|
||||||
|
svg.appendChild(path);
|
||||||
|
div.appendChild(svg);
|
||||||
|
a.appendChild(div);
|
||||||
|
a.appendChild(text);
|
||||||
|
a.appendChild(notifications);
|
||||||
|
li.appendChild(a);
|
||||||
|
li.appendChild(settings);
|
||||||
|
|
||||||
|
// Запись в документ
|
||||||
|
panel.menu().getElementsByClassName('more_div l_main')[0].insertAdjacentElement('beforebegin', li);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Блоки
|
||||||
|
*/
|
||||||
|
static blocks = {
|
||||||
|
/**
|
||||||
|
* Запись верхнего колонтинула оболочки в формате меню
|
||||||
|
*
|
||||||
|
* @return {Function} Функция для выполнения в генераторе группы
|
||||||
|
*/
|
||||||
|
menu() {
|
||||||
|
/**
|
||||||
|
* Запись в группу (подразумевается выполнение в функции генерирующей группу)
|
||||||
|
*
|
||||||
|
* @param {string} group Группа
|
||||||
|
*
|
||||||
|
* @return {bool} Статус выполнения
|
||||||
|
*/
|
||||||
|
return function (group) {
|
||||||
|
if (typeof group === 'string') {
|
||||||
|
// Пройдена проверка входных параметров
|
||||||
|
|
||||||
|
// Инициализация блока куда надо записать заголовок
|
||||||
|
const block = document.getElementById('block_' + group);
|
||||||
|
|
||||||
|
// Инициализация верхнего колонтинула
|
||||||
|
const header = document.createElement('h2');
|
||||||
|
header.classList.add('page_block_h2');
|
||||||
|
|
||||||
|
// Инициализация меню
|
||||||
|
const menu = document.createElement('ul');
|
||||||
|
menu.id = 'block_' + group + '_menu';
|
||||||
|
menu.classList.add('ui_tabs', 'clear_fix', 'ui_tabs_header', 'GamesCatalogNav');
|
||||||
|
|
||||||
|
// Инициализация баланса
|
||||||
|
const money = document.createElement('a');
|
||||||
|
money.classList.add('GamesCatalogNav__balanceLink');
|
||||||
|
money.innerText = 'Баланс: 0 рублей';
|
||||||
|
|
||||||
|
// Инициализация ползунка
|
||||||
|
const slider = document.createElement('div');
|
||||||
|
slider.classList.add('ui_tabs_slider', '_ui_tabs_slider');
|
||||||
|
|
||||||
|
// Запись в документ
|
||||||
|
menu.appendChild(money);
|
||||||
|
menu.appendChild(slider);
|
||||||
|
header.appendChild(menu);
|
||||||
|
block.appendChild(header);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Запись верхнего колонтинула оболочки
|
||||||
|
*
|
||||||
|
* @param {string} text Название вкладки
|
||||||
|
* @param {Function} onclick Событие при нажатии на кнопку открытия вкладки
|
||||||
|
*
|
||||||
|
* @return {Function} Функция для выполнения в генераторе группы
|
||||||
|
*/
|
||||||
|
tab(text = '', onclick) {
|
||||||
|
/**
|
||||||
|
* Запись в группу (подразумевается выполнение в функции генерирующей группу)
|
||||||
|
*
|
||||||
|
* @param {string} group Группа
|
||||||
|
*
|
||||||
|
* @return {bool} Статус выполнения
|
||||||
|
*/
|
||||||
|
return function (group) {
|
||||||
|
if (typeof group === 'string' && typeof text === 'string' && typeof onclick === 'function') {
|
||||||
|
// Пройдена проверка входных параметров
|
||||||
|
|
||||||
|
// Инициализация блока куда надо записать заголовок
|
||||||
|
const menu = document.getElementById('block_' + group + '_menu');
|
||||||
|
|
||||||
|
if (menu instanceof HTMLElement) {
|
||||||
|
// Найдено меню
|
||||||
|
|
||||||
|
// Инициализация кнопки
|
||||||
|
const button = document.createElement('li');
|
||||||
|
button.classList.add('games_tab_catalog');
|
||||||
|
|
||||||
|
// Инициализация меню
|
||||||
|
const link = document.createElement('a');
|
||||||
|
link.classList.add('ui_tab', 'ui_tab_sel');
|
||||||
|
link.setAttribute('type', 'button');
|
||||||
|
link.innerText = text ?? 'Без названия';
|
||||||
|
link.addEventListener('click', onclick);
|
||||||
|
|
||||||
|
// Запись в документ
|
||||||
|
button.appendChild(link);
|
||||||
|
|
||||||
|
// Инициализация списка вкладок
|
||||||
|
const list = menu.getElementsByTagName('li');
|
||||||
|
|
||||||
|
// Запись кнопки после других, либо запись первой кнопки
|
||||||
|
if (list instanceof HTMLCollection && list.length > 0) list[list.length - 1].insertAdjacentElement('afterend', button);
|
||||||
|
else menu.insertAdjacentElement('afterbegin', button);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Генерация HTML-элемента-оболочки
|
||||||
|
*
|
||||||
|
* @param {string} id Идентификатор
|
||||||
|
* @param {...function} functions Содержимое
|
||||||
|
*
|
||||||
|
* @return {integer} Количество ошибок
|
||||||
|
*/
|
||||||
|
group(id, ...functions) {
|
||||||
|
if (typeof id === 'string' && typeof functions === 'object') {
|
||||||
|
// Пройдена проверка входных параметров
|
||||||
|
|
||||||
|
// Инициализация названия идентификатора элемента
|
||||||
|
const name = 'block_' + id;
|
||||||
|
|
||||||
|
// Поиск блока с данным идентификатором
|
||||||
|
if (document.getElementById(name) instanceof HTMLElement) return errors;
|
||||||
|
|
||||||
|
// Инициализация оболочки
|
||||||
|
const block = document.createElement('div');
|
||||||
|
block.id = name;
|
||||||
|
block.classList.add('GamesCatalogHead', 'page_block');
|
||||||
|
|
||||||
|
// Запись в документ
|
||||||
|
panel.body().appendChild(block);
|
||||||
|
|
||||||
|
// Инициализация счётчика ошибок
|
||||||
|
let errors = 0;
|
||||||
|
|
||||||
|
functions.forEach(function (entry) {
|
||||||
|
// Перебор переданных функций
|
||||||
|
|
||||||
|
// Вызов функции
|
||||||
|
if (typeof entry === 'function' && !entry(id)) ++errors;
|
||||||
|
});
|
||||||
|
|
||||||
|
return errors;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Поля
|
||||||
|
*/
|
||||||
|
fields: {
|
||||||
|
macroses: {
|
||||||
|
/**
|
||||||
|
* Шаблон для инициализации элементов строки с полем
|
||||||
|
*
|
||||||
|
* @param {string} group Группа
|
||||||
|
* @param {string|null} icon Иконка
|
||||||
|
* @param {function} content Функция которая будет обрабатывать содержимое макроса
|
||||||
|
*/
|
||||||
|
row(group, icon, content) {
|
||||||
|
// Инициализация блока
|
||||||
|
const block = document.getElementById('block_' + group);
|
||||||
|
|
||||||
|
// Инициализация головного элемента блока
|
||||||
|
const header = block.getElementsByClassName('page_block_header')[0];
|
||||||
|
|
||||||
|
// Инициализация элемента со статусом
|
||||||
|
const status = header.getElementsByClassName('page_block_saved')[0];
|
||||||
|
|
||||||
|
// Инициализация тела блока
|
||||||
|
const body = block.getElementsByClassName('settings_panel clear_fix settings_' + this.core.id + ' settings_section_' + this.core.id)[0];
|
||||||
|
|
||||||
|
// Инициализация оболочки кнопки активации
|
||||||
|
const wrap = document.createElement('div');
|
||||||
|
wrap.classList.add('settings_separated_row', this.core.icons[icon] ?? this.core.icons['lightning'], 'settings_separated_row_iconed');
|
||||||
|
|
||||||
|
// Инициализация разделителя
|
||||||
|
const separator = document.createElement('div');
|
||||||
|
separator.classList.add('settings_separated_row_extra');
|
||||||
|
|
||||||
|
// Генерация содержимого строки
|
||||||
|
return content(status, body, wrap, separator);
|
||||||
|
},
|
||||||
|
|
||||||
|
dropdown(active, rows) {
|
||||||
|
if (typeof active === 'string' && typeof rows === 'object') {
|
||||||
|
// Пройдена проверка входных параметров
|
||||||
|
|
||||||
|
// Инициализация оболочки
|
||||||
|
const wrap = document.createElement('div');
|
||||||
|
wrap.classList.add('privacy_dropdown', 'privacy_dropdown_mail', 'pdd_ralign');
|
||||||
|
wrap.setAttribute('style', 'opacity: 1; display: none;');
|
||||||
|
|
||||||
|
// Инициализация списка строк
|
||||||
|
const list = document.createElement('div');
|
||||||
|
list.classList.add('rows', 'rows__flex');
|
||||||
|
wrap.setAttribute('style', 'font-size: 13px;');
|
||||||
|
|
||||||
|
// Инициализация головной строки
|
||||||
|
const header = document.createElement('div');
|
||||||
|
header.classList.add('header');
|
||||||
|
wrap.setAttribute('onclick', 'Privacy.hide(-1)');
|
||||||
|
|
||||||
|
// Инициализация активной строки (выбранного параметра)
|
||||||
|
const active = document.createElement('div');
|
||||||
|
active.classList.add('header_label');
|
||||||
|
active.innerHTML = active;
|
||||||
|
|
||||||
|
// Инициализация основной группы строк
|
||||||
|
const body = document.createElement('div');
|
||||||
|
body.classList.add('body', 'body__flex');
|
||||||
|
body.setAttribute('role', 'list');
|
||||||
|
body.setAttribute('aria-labelledby', 'privacy_who_can_view');
|
||||||
|
|
||||||
|
for (const row in rows) {
|
||||||
|
// Перебор строк для генерации списка
|
||||||
|
|
||||||
|
// Инициализация кнопки
|
||||||
|
const button = document.createElement('button');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Генерация HTML-элемента настройки с кнопкой активации
|
||||||
|
*
|
||||||
|
* @param {string} id Идентификатор
|
||||||
|
* @param {string|null} icon Иконка
|
||||||
|
* @param {string|null} name Название
|
||||||
|
* @param {string|null} description Описание
|
||||||
|
* @param {string|null} hint Всплывающая подсказка (иконка с вопросительным знаком возле верхнего колонтинула)
|
||||||
|
* @param {string|null} onchange Код который выполняется после изменения состояния
|
||||||
|
*
|
||||||
|
* @return {function} Функция для выполнения в генераторе группы
|
||||||
|
*
|
||||||
|
* @todo 1. Добавить проверку на существование нижнего колонтинула и записывать перед ним, вместо конца блока
|
||||||
|
*/
|
||||||
|
checkbox(id, icon, name, description, hint, onchange) {
|
||||||
|
// Инициализация ядра
|
||||||
|
const core = this.core;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Запись в группу (подразумевается выполнение в функции генерирующей группу)
|
||||||
|
*
|
||||||
|
* @param {string} group Группа
|
||||||
|
*
|
||||||
|
* @return {bool} Статус выполнения
|
||||||
|
*/
|
||||||
|
return function (group) {
|
||||||
|
if (typeof id === 'string' && typeof core === 'object' && typeof group === 'string') {
|
||||||
|
// Пройдена проверка входных параметров
|
||||||
|
|
||||||
|
return core.blocks.fields.macros(group, icon,
|
||||||
|
function (status, body, wrap, separator) {
|
||||||
|
wrap.addEventListener("click", fn => {
|
||||||
|
// Инициализация кнопки
|
||||||
|
const button = wrap.getElementsByClassName('ui_toggler')[0];
|
||||||
|
|
||||||
|
if (button.classList.contains('on')) {
|
||||||
|
// Активирована
|
||||||
|
if (settings.write(group + '_' + id, false)) {
|
||||||
|
// Записан статус активации
|
||||||
|
|
||||||
|
// Запуск анимации и переход в состояние деактивации
|
||||||
|
button.classList.remove('on');
|
||||||
|
|
||||||
|
settings.read(group + '_' + id).then(result => {
|
||||||
|
if (result === false) {
|
||||||
|
// Сохранены изменения
|
||||||
|
|
||||||
|
// Запуск анимации
|
||||||
|
status.style.transition = '0.5s';
|
||||||
|
status.style.opacity = 1;
|
||||||
|
setTimeout(fn => {
|
||||||
|
status.style.transition = '1.5s';
|
||||||
|
status.style.opacity = 0;
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Деактивирована
|
||||||
|
if (settings.write(group + '_' + id, true)) {
|
||||||
|
// Записан статус активации
|
||||||
|
|
||||||
|
// Запуск анимации и переход в состояние активации
|
||||||
|
button.classList.add('on');
|
||||||
|
|
||||||
|
settings.read(group + '_' + id).then(result => {
|
||||||
|
if (result === true) {
|
||||||
|
// Сохранены изменения
|
||||||
|
|
||||||
|
// Запуск анимации
|
||||||
|
status.style.transition = '0.5s';
|
||||||
|
status.style.opacity = 1;
|
||||||
|
setTimeout(fn => {
|
||||||
|
status.style.transition = '1.5s';
|
||||||
|
status.style.opacity = 0;
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Инициализация кнопки активации
|
||||||
|
const button = document.createElement('div');
|
||||||
|
button.classList.add('ui_toggler_wrap');
|
||||||
|
|
||||||
|
// Инициализация элемента-иконки
|
||||||
|
const checkbox = document.createElement('div');
|
||||||
|
checkbox.classList.add('_ui_toggler', 'ui_toggler', '_settings_ienable');
|
||||||
|
if (typeof onchange === 'string') checkbox.setAttribute('onchange', onchange);
|
||||||
|
|
||||||
|
settings.read(group + '_' + id).then(result => {
|
||||||
|
// Получены данные о значении настройки
|
||||||
|
|
||||||
|
// Запись состояния
|
||||||
|
if (result) checkbox.classList.add('on');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Инициализация элемента-иконки
|
||||||
|
const label = document.createElement('div');
|
||||||
|
label.classList.add('ui_toggler_label');
|
||||||
|
|
||||||
|
// Инициализация названия
|
||||||
|
const header = document.createElement('div');
|
||||||
|
header.classList.add('settings_separated_row_text');
|
||||||
|
|
||||||
|
// Инициализация текста названия
|
||||||
|
const colonic = document.createElement('div');
|
||||||
|
colonic.classList.add('settings_separated_row_text_inner');
|
||||||
|
colonic.innerText = name !== undefined && typeof name === 'string' ? name : id;
|
||||||
|
|
||||||
|
// Инициализация архитектуры
|
||||||
|
button.appendChild(checkbox);
|
||||||
|
separator.appendChild(button);
|
||||||
|
wrap.appendChild(separator);
|
||||||
|
header.appendChild(colonic);
|
||||||
|
|
||||||
|
if (typeof hint === 'string') {
|
||||||
|
// Получена подсказка
|
||||||
|
|
||||||
|
// Инициализация текста-подсказки
|
||||||
|
const question = document.createElement('span');
|
||||||
|
question.classList.add('hint_icon');
|
||||||
|
question.setAttribute('data-title', hint);
|
||||||
|
question.setAttribute('onmouseover', 'showHint(this);');
|
||||||
|
|
||||||
|
// Инициализация архитектуры
|
||||||
|
colonic.appendChild(question);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (description !== undefined && typeof description === 'string') {
|
||||||
|
// Получено описание
|
||||||
|
|
||||||
|
// Инициализация текста описания
|
||||||
|
const text = document.createElement('div');
|
||||||
|
text.classList.add('settings_separated_row_hint');
|
||||||
|
text.innerText = description;
|
||||||
|
|
||||||
|
// Инициализация архитектуры
|
||||||
|
colonic.appendChild(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Инициализация архитектуры
|
||||||
|
wrap.appendChild(header);
|
||||||
|
|
||||||
|
// Запись в блок
|
||||||
|
body.appendChild(wrap);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Генерация HTML-элемента настройки с полем для ввода текста
|
||||||
|
*
|
||||||
|
* @param {string} id Идентификатор
|
||||||
|
* @param {string|null} icon Иконка
|
||||||
|
* @param {string|null} name Название
|
||||||
|
* @param {string|null} description Описание
|
||||||
|
* @param {string|null} hint Всплывающая подсказка (иконка с вопросительным знаком возле верхнего колонтинула)
|
||||||
|
* @param {string|null} type Тип поля для ввода (HTML-категории: text, password, email, number)
|
||||||
|
* @param {number|null} min Ограничение по минимальному количеству символов
|
||||||
|
* @param {number|null} max Ограничение по максимальному количеству символов
|
||||||
|
* @param {string|null} title Текст выводимый во всплывающем окне при наведении курсора
|
||||||
|
* @param {string|null} placeholder Текст отображаемый в поле для ввода если оно пустое
|
||||||
|
* @param {string|null} pattern Шаблон значений которые позволено вводить в поле
|
||||||
|
* @param {boolean|null} readonly Запретить редактирование
|
||||||
|
* @param {boolean|null} spellcheck Использовать проверку орфографии
|
||||||
|
* @param {object|null} options Массив со строками для автозаполнения поля
|
||||||
|
* @param {string|null} onchange Код который выполняется после изменения состояния
|
||||||
|
* @param {string|null} oninput Код который выполняется при вводе текста
|
||||||
|
*
|
||||||
|
* @return {function} Функция для выполнения в генераторе группы
|
||||||
|
*
|
||||||
|
* @todo 1. Добавить проверку на существование нижнего колонтинула и записывать перед ним, вместо конца блока
|
||||||
|
*/
|
||||||
|
text(id, icon, name, description, hint, type = 'text', min = 0, max = 100, title, placeholder, pattern, readonly, spellcheck, options, onchange, oninput) {
|
||||||
|
// Инициализация ядра
|
||||||
|
const core = this.core;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Запись в группу (подразумевается выполнение в функции генерирующей группу)
|
||||||
|
*
|
||||||
|
* @param {string} group Группа
|
||||||
|
*
|
||||||
|
* @return {bool} Статус выполнения
|
||||||
|
*/
|
||||||
|
return function (group) {
|
||||||
|
if (typeof id === 'string' && typeof icon === 'string' && typeof core === 'object' && typeof group === 'string') {
|
||||||
|
// Пройдена проверка входных параметров
|
||||||
|
|
||||||
|
return core.blocks.fields.macros(group, icon,
|
||||||
|
function (status, body, wrap, separator) {
|
||||||
|
wrap.addEventListener("input", fn => {
|
||||||
|
// Инициализация поля ввода
|
||||||
|
const input = wrap.getElementsByTagName('input')[0];
|
||||||
|
|
||||||
|
if (settings.write(group + '_' + id, input.value)) {
|
||||||
|
// Записано значение поля
|
||||||
|
|
||||||
|
// Запуск анимации
|
||||||
|
settings.read(group + '_' + id).then(result => {
|
||||||
|
if (result === input.value) {
|
||||||
|
// Сохранены изменения
|
||||||
|
|
||||||
|
// Запуск анимации
|
||||||
|
status.style.transition = '0.5s';
|
||||||
|
status.style.opacity = 1;
|
||||||
|
setTimeout(fn => {
|
||||||
|
status.style.transition = '1.5s';
|
||||||
|
status.style.opacity = 0;
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Инициализация элемента для ввода текста
|
||||||
|
const input = document.createElement('input');
|
||||||
|
input.classList.add('dark');
|
||||||
|
input.setAttribute('type', type);
|
||||||
|
input.setAttribute(type === 'number' ? 'min' : 'minlength', min);
|
||||||
|
input.setAttribute(type === 'number' ? 'max' : 'maxlength', max);
|
||||||
|
if (typeof title === 'string') input.setAttribute('title', title);
|
||||||
|
if (typeof placeholder === 'string') input.setAttribute('placeholder', placeholder);
|
||||||
|
if (typeof pattern === 'string') input.setAttribute('pattern', pattern);
|
||||||
|
if (readonly === true) input.setAttribute('readonly', readonly);
|
||||||
|
if (spellcheck === true) input.setAttribute('spellcheck', spellcheck);
|
||||||
|
input.setAttribute('list', group + '_' + id + '_datalist');
|
||||||
|
settings.read(group + '_' + id).then(result => {
|
||||||
|
// Получены данные о значении настройки
|
||||||
|
|
||||||
|
// Запись значения в поле
|
||||||
|
if (result) input.value = result;
|
||||||
|
});
|
||||||
|
if (typeof onchange === 'string') input.setAttribute('onchange', onchange);
|
||||||
|
if (typeof oninput === 'string') input.setAttribute('oninput', oninput);
|
||||||
|
|
||||||
|
|
||||||
|
if (typeof options === 'object' && options.length > 0) {
|
||||||
|
// Инициализация элемента-списка для выбора значений автозаполнения
|
||||||
|
const datalist = document.createElement('datalist');
|
||||||
|
datalist.id = group + '_' + id + '_datalist';
|
||||||
|
|
||||||
|
for (const option of options) {
|
||||||
|
// Перебор значений для автозаполнения поля
|
||||||
|
|
||||||
|
// Инициализация элемента со значением автозаполнения
|
||||||
|
const element = document.createElement('option');
|
||||||
|
element.setAttribute('value', option);
|
||||||
|
|
||||||
|
// Запись в список
|
||||||
|
datalist.appendChild(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Инициализация элемента-иконки
|
||||||
|
const label = document.createElement('div');
|
||||||
|
label.classList.add('ui_toggler_label');
|
||||||
|
|
||||||
|
// Инициализация названия
|
||||||
|
const header = document.createElement('div');
|
||||||
|
header.classList.add('settings_separated_row_text');
|
||||||
|
|
||||||
|
// Инициализация текста названия
|
||||||
|
const colonic = document.createElement('div');
|
||||||
|
colonic.classList.add('settings_separated_row_text_inner');
|
||||||
|
colonic.innerText = name !== undefined && typeof name === 'string' ? name : id;
|
||||||
|
|
||||||
|
// Инициализация архитектуры
|
||||||
|
separator.appendChild(input);
|
||||||
|
if (typeof datalist === 'object') separator.appendChild(datalist);
|
||||||
|
wrap.appendChild(separator);
|
||||||
|
header.appendChild(colonic);
|
||||||
|
|
||||||
|
if (typeof hint === 'string') {
|
||||||
|
// Получена подсказка
|
||||||
|
|
||||||
|
// Инициализация текста-подсказки
|
||||||
|
const question = document.createElement('span');
|
||||||
|
question.classList.add('hint_icon');
|
||||||
|
question.setAttribute('data-title', hint);
|
||||||
|
question.setAttribute('onmouseover', 'showHint(this);');
|
||||||
|
|
||||||
|
// Инициализация архитектуры
|
||||||
|
colonic.appendChild(question);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (description !== undefined && typeof description === 'string') {
|
||||||
|
// Получено описание
|
||||||
|
|
||||||
|
// Инициализация текста описания
|
||||||
|
const text = document.createElement('div');
|
||||||
|
text.classList.add('settings_separated_row_hint');
|
||||||
|
text.innerText = description;
|
||||||
|
|
||||||
|
// Инициализация архитектуры
|
||||||
|
colonic.appendChild(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Инициализация архитектуры
|
||||||
|
wrap.appendChild(header);
|
||||||
|
|
||||||
|
// Запись в блок
|
||||||
|
body.appendChild(wrap);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Генерация HTML-элемента настройки с всплывающим списком
|
||||||
|
*
|
||||||
|
* @param {string} id Идентификатор
|
||||||
|
* @param {string|null} icon Иконка
|
||||||
|
* @param {string|null} name Название
|
||||||
|
* @param {string|null} description Описание
|
||||||
|
* @param {string|null} hint Всплывающая подсказка (иконка с вопросительным знаком возле верхнего колонтинула)
|
||||||
|
* @param {string|null} type
|
||||||
|
* @param {string|null} button
|
||||||
|
* @param {object|null} options Массив со строками для автозаполнения поля
|
||||||
|
* @param {string|null} onclick
|
||||||
|
* @param {string|null} onchange Код который выполняется после изменения состояния
|
||||||
|
* @param {string|null} oninput Код который выполняется при вводе текста
|
||||||
|
*
|
||||||
|
* @return {function} Функция для выполнения в генераторе группы
|
||||||
|
*
|
||||||
|
* @todo 1. Добавить проверку на существование нижнего колонтинула и записывать перед ним, вместо конца блока
|
||||||
|
*/
|
||||||
|
button(id, icon, name, description, hint, type = 'dropdown', value = 'Выбрать', onclick, onchange, oninput) {
|
||||||
|
// Инициализация ядра
|
||||||
|
const core = this.core;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Запись в группу (подразумевается выполнение в функции генерирующей группу)
|
||||||
|
*
|
||||||
|
* @param {string} group Группа
|
||||||
|
*
|
||||||
|
* @return {bool} Статус выполнения
|
||||||
|
*/
|
||||||
|
return function (group) {
|
||||||
|
if (typeof id === 'string' && typeof icon === 'string' && typeof core === 'object' && typeof group === 'string') {
|
||||||
|
// Пройдена проверка входных параметров
|
||||||
|
|
||||||
|
return core.blocks.fields.macroses.row(group, icon,
|
||||||
|
function (status, body, wrap, separator) {
|
||||||
|
wrap.addEventListener("input", fn => {
|
||||||
|
// Инициализация поля ввода
|
||||||
|
const input = wrap.getElementsByTagName('input')[0];
|
||||||
|
|
||||||
|
if (settings.write(group + '_' + id, input.value)) {
|
||||||
|
// Записано значение поля
|
||||||
|
|
||||||
|
// Запуск анимации
|
||||||
|
settings.read(group + '_' + id).then(result => {
|
||||||
|
if (result === input.value) {
|
||||||
|
// Сохранены изменения
|
||||||
|
|
||||||
|
// Запуск анимации
|
||||||
|
status.style.transition = '0.5s';
|
||||||
|
status.style.opacity = 1;
|
||||||
|
setTimeout(fn => {
|
||||||
|
status.style.transition = '1.5s';
|
||||||
|
status.style.opacity = 0;
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Инициализация элемента-кнопки
|
||||||
|
const button = document.createElement('a');
|
||||||
|
button.innerText = value;
|
||||||
|
if (typeof onchange === 'string') button.setAttribute('onchange', onchange);
|
||||||
|
if (typeof oninput === 'string') button.setAttribute('oninput', oninput);
|
||||||
|
|
||||||
|
if (type === 'dropdown') {
|
||||||
|
// Инициализация всплывающего списка
|
||||||
|
|
||||||
|
// Инициализация элемента-кнопки
|
||||||
|
button.setAttribute('onclick', 'return Privacy.show(this, event, \'mail\');' + typeof onclick === 'string' ? ' ' + onclick : '');
|
||||||
|
|
||||||
|
// Инициализация элемента-списка
|
||||||
|
const dropdown = core.blocks.fields.macroses.dropdown();
|
||||||
|
|
||||||
|
|
||||||
|
// Инициализация архитектуры
|
||||||
|
separator.appendChild(button);
|
||||||
|
} else if (type === 'popup') {
|
||||||
|
// Инициализация всплывающего окна
|
||||||
|
|
||||||
|
// Инициализация элемента-кнопки
|
||||||
|
button.setAttribute('href', '#');
|
||||||
|
button.setAttribute('onclick', 'return Settings.showGroupMessagesNotifyBox(event, \'settings\');' + typeof onclick === 'string' ? ' ' + onclick : '');
|
||||||
|
|
||||||
|
// Инициализация архитектуры
|
||||||
|
separator.appendChild(button);
|
||||||
|
} else if (type === 'button') {
|
||||||
|
// Инициализация кнопки
|
||||||
|
|
||||||
|
// Инициализация элемента-кнопки
|
||||||
|
if (typeof onclick === 'string') button.setAttribute('onclick', onclick);
|
||||||
|
|
||||||
|
// Инициализация архитектуры
|
||||||
|
separator.appendChild(button);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Инициализация элемента-иконки
|
||||||
|
const label = document.createElement('div');
|
||||||
|
label.classList.add('ui_toggler_label');
|
||||||
|
|
||||||
|
// Инициализация названия
|
||||||
|
const header = document.createElement('div');
|
||||||
|
header.classList.add('settings_separated_row_text');
|
||||||
|
|
||||||
|
// Инициализация текста названия
|
||||||
|
const colonic = document.createElement('div');
|
||||||
|
colonic.classList.add('settings_separated_row_text_inner');
|
||||||
|
colonic.innerText = name !== undefined && typeof name === 'string' ? name : id;
|
||||||
|
|
||||||
|
// Инициализация архитектуры
|
||||||
|
separator.appendChild(button);
|
||||||
|
wrap.appendChild(separator);
|
||||||
|
header.appendChild(colonic);
|
||||||
|
|
||||||
|
if (typeof hint === 'string') {
|
||||||
|
// Получена подсказка
|
||||||
|
|
||||||
|
// Инициализация текста-подсказки
|
||||||
|
const question = document.createElement('span');
|
||||||
|
question.classList.add('hint_icon');
|
||||||
|
question.setAttribute('data-title', hint);
|
||||||
|
question.setAttribute('onmouseover', 'showHint(this);');
|
||||||
|
|
||||||
|
// Инициализация архитектуры
|
||||||
|
colonic.appendChild(question);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (description !== undefined && typeof description === 'string') {
|
||||||
|
// Получено описание
|
||||||
|
|
||||||
|
// Инициализация текста описания
|
||||||
|
const text = document.createElement('div');
|
||||||
|
text.classList.add('settings_separated_row_hint');
|
||||||
|
text.innerText = description;
|
||||||
|
|
||||||
|
// Инициализация архитектуры
|
||||||
|
colonic.appendChild(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Инициализация архитектуры
|
||||||
|
wrap.appendChild(header);
|
||||||
|
|
||||||
|
// Запись в блок
|
||||||
|
body.appendChild(wrap);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Найти оболочку
|
||||||
|
*
|
||||||
|
* @return {HTMLElement} Оболочка
|
||||||
|
*/
|
||||||
|
static body() {
|
||||||
|
return document.getElementById('wrap3');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Найти боковое меню
|
||||||
|
*
|
||||||
|
* @returns {HTMLElement} Меню
|
||||||
|
*/
|
||||||
|
static menu() {
|
||||||
|
return document.getElementById('side_bar_inner');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Очистка оболочки от HTML-элементов ВКонтакте
|
||||||
|
*/
|
||||||
|
static clean() {
|
||||||
|
// Инициализация тела оболочки
|
||||||
|
let main = panel.body();
|
||||||
|
|
||||||
|
// Очистка тела оболочки
|
||||||
|
main.innerHTML = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Запуск выполнения
|
||||||
|
new panel().init();
|
|
@ -0,0 +1,857 @@
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Страница настроек ВКонтакте
|
||||||
|
*/
|
||||||
|
class page {
|
||||||
|
constructor() {
|
||||||
|
/**
|
||||||
|
* Идентификатор (https://vk.com/settings?act=ЗНАЧЕНИЕ)
|
||||||
|
*/
|
||||||
|
this.id = 'microwave';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Иконки ВКонтакте для полей
|
||||||
|
*/
|
||||||
|
this.icons = {
|
||||||
|
lightning: 'icon_type_ienable',
|
||||||
|
sound: 'icon_type_isounds',
|
||||||
|
text: 'icon_type_itexts',
|
||||||
|
bell: 'icon_type_notification',
|
||||||
|
group: 'icon_type_group_messages ',
|
||||||
|
message: 'icon_type_message',
|
||||||
|
reminder: 'icon_type_message_reminders',
|
||||||
|
like: 'icon_type_like',
|
||||||
|
repost: 'icon_type_repost',
|
||||||
|
comment: 'icon_type_comment',
|
||||||
|
discussion: 'icon_type_discussions',
|
||||||
|
wall: 'icon_type_wall',
|
||||||
|
reply: 'icon_type_story_reply',
|
||||||
|
question: 'icon_type_story_question',
|
||||||
|
voting: 'icon_type_voting',
|
||||||
|
clips: 'icon_type_clips',
|
||||||
|
mention: 'icon_type_mention',
|
||||||
|
follow: 'icon_type_follow',
|
||||||
|
friend: 'icon_type_friend_found',
|
||||||
|
invite: 'icon_type_invite_group',
|
||||||
|
tag: 'icon_type_photo_tag',
|
||||||
|
birthday: 'icon_type_birthday',
|
||||||
|
event: 'icon_type_event',
|
||||||
|
group: 'icon_type_group',
|
||||||
|
promo: 'icon_type_feed_promo',
|
||||||
|
advice: 'icon_type_advice',
|
||||||
|
post: 'icon_type_new_post',
|
||||||
|
private: 'icon_type_private_post',
|
||||||
|
gift: 'icon_type_gift',
|
||||||
|
app: 'icon_type_invite_app',
|
||||||
|
live: 'icon_type_live',
|
||||||
|
playlists: 'icon_type_video_playlists',
|
||||||
|
podcast: 'icon_type_podcast',
|
||||||
|
ads: 'icon_type_ads',
|
||||||
|
achievements: 'icon_type_content_achievements',
|
||||||
|
services: 'icon_type_services',
|
||||||
|
installation: 'icon_type_service_installation',
|
||||||
|
bookmarks: 'icon_type_bookmarks',
|
||||||
|
box: 'icon_type_market_orders',
|
||||||
|
announcement: 'icon_type_tear_off_flyer_fill_blue',
|
||||||
|
hearts: 'icon_type_hearts_2_circle_fill_twilight',
|
||||||
|
email: 'icon_type_email',
|
||||||
|
clock: 'icon_type_clock'
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Инициализация
|
||||||
|
*/
|
||||||
|
this.init = function () {
|
||||||
|
// Инициализация страницы
|
||||||
|
this.clean();
|
||||||
|
|
||||||
|
// Инициализация модулей
|
||||||
|
let modules = {
|
||||||
|
killer: new killer()
|
||||||
|
};
|
||||||
|
|
||||||
|
// Инициализация блоков
|
||||||
|
this.blocks.group(
|
||||||
|
'nadrez',
|
||||||
|
this.blocks.header('надрез мозжечка'),
|
||||||
|
// text('Системные настройки'),
|
||||||
|
this.blocks.fields.checkbox('activate', 'lightning', 'Активировать')
|
||||||
|
);
|
||||||
|
this.blocks.group(
|
||||||
|
'killer',
|
||||||
|
this.blocks.header('Убийца'),
|
||||||
|
// text('Удаление активности выбранных пользователей'),
|
||||||
|
this.blocks.fields.checkbox('activate', 'lightning', 'Активировать'),
|
||||||
|
this.blocks.fields.text('asdasdasd', 'lightning', 'Активировать', 'asdasdasdasd', 'Тестирование всплывающей подсказки', 'text', 0, 8, 'фффф', 'сюда писать'),
|
||||||
|
this.blocks.fields.checkbox('list', 'group', 'Заблокированные ВКонтакте', 'Удалять тех кто находится в списке заблокированных ВКонтакте', 'Тестирование всплывающей подсказки'),
|
||||||
|
this.blocks.fields.checkbox('target', 'list', 'Отдельный список на удаление', 'Выбрать пользователей вручную'),
|
||||||
|
this.blocks.fields.dropdown('targetasdasd', 'promo', 'Какаято хуитень', 'Выбфывелей вручную', 'Тестирование всплывающей подсказки'),
|
||||||
|
modules.killer.list('asdasd'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Найти оболочку
|
||||||
|
*
|
||||||
|
* @return {Element} Оболочка
|
||||||
|
*/
|
||||||
|
this.body = function () {
|
||||||
|
return document.getElementById('wide_column');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Очистка оболочки от HTML-элементов ВКонтакте
|
||||||
|
*/
|
||||||
|
this.clean = function () {
|
||||||
|
// Инициализация тела оболочки
|
||||||
|
let main = this.body();
|
||||||
|
|
||||||
|
// Очистка тела оболочки
|
||||||
|
main.innerHTML = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Блоки
|
||||||
|
*/
|
||||||
|
this.blocks = {
|
||||||
|
/**
|
||||||
|
* Запись верхнего колонтинула оболочки (обычный)
|
||||||
|
*
|
||||||
|
* @param {string} text
|
||||||
|
*
|
||||||
|
* @return {Function} Функция для выполнения в генераторе группы
|
||||||
|
*/
|
||||||
|
header(text = '') {
|
||||||
|
/**
|
||||||
|
* Запись в группу (подразумевается выполнение в функции генерирующей группу)
|
||||||
|
*
|
||||||
|
* @param {string} group Группа
|
||||||
|
*
|
||||||
|
* @return {bool} Статус выполнения
|
||||||
|
*/
|
||||||
|
return function (group) {
|
||||||
|
if (typeof group === 'string' && typeof text === 'string') {
|
||||||
|
// Пройдена проверка входных параметров
|
||||||
|
|
||||||
|
// Инициализация блока куда надо записать заголовок
|
||||||
|
const block = document.getElementById('block_' + group);
|
||||||
|
|
||||||
|
// Инициализация оболочки заголовка
|
||||||
|
const title = block.getElementsByTagName('h2')[0].getElementsByClassName('page_block_header')[0];
|
||||||
|
|
||||||
|
// Запись содержимого в буфер
|
||||||
|
const buffer = title.cloneNode(true);
|
||||||
|
|
||||||
|
// Запись заголовка
|
||||||
|
title.innerText = text;
|
||||||
|
|
||||||
|
// Запись содержимого заголовка из буфера
|
||||||
|
for (let element of buffer.children) title.appendChild(element);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Запись верхнего колонтинула оболочки (дополненный)
|
||||||
|
*
|
||||||
|
* @param {string} left Содержимое элемента с классами: "page_block_header_extra_left _header_extra_left"
|
||||||
|
* @param {string} center Содержимое элемента с классами: "page_block_header_inner _header_inner"
|
||||||
|
* @param {string} right Содержимое элемента с классами: "page_block_header_extra _header_extra"
|
||||||
|
*
|
||||||
|
* @return {Function} Функция для выполнения в генераторе группы
|
||||||
|
*/
|
||||||
|
header_extra(left = '', center = '', right = '') {
|
||||||
|
/**
|
||||||
|
* Запись в группу (подразумевается выполнение в функции генерирующей группу)
|
||||||
|
*
|
||||||
|
* @param {string} group Группа
|
||||||
|
*
|
||||||
|
* @return {bool} Статус выполнения
|
||||||
|
*/
|
||||||
|
return function (group) {
|
||||||
|
if (typeof group === 'string' && typeof left === 'string' && typeof center === 'string' && typeof right === 'string') {
|
||||||
|
// Пройдена проверка входных параметров
|
||||||
|
|
||||||
|
// Инициализация блока
|
||||||
|
const block = document.getElementById('block_' + group);
|
||||||
|
|
||||||
|
// Инициализация оболочки заголовка
|
||||||
|
const title = block.getElementsByTagName('h2')[0].getElementsByClassName('page_block_header')[0];
|
||||||
|
|
||||||
|
// Запись заголовков
|
||||||
|
title.getElementsByClassName('page_block_header_extra_left _header_extra_left')[0].innerText = left;
|
||||||
|
title.getElementsByClassName('page_block_header_inner _header_inner')[0].innerText = center;
|
||||||
|
title.getElementsByClassName('page_block_header_extra _header_extra')[0].innerText = right;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Запись нижнего колонтинула оболочки
|
||||||
|
*
|
||||||
|
* @param {string} value
|
||||||
|
*
|
||||||
|
* @return {Function} Функция для выполнения в генераторе группы
|
||||||
|
*/
|
||||||
|
footer() {
|
||||||
|
/**
|
||||||
|
* Запись в группу (подразумевается выполнение в функции генерирующую группу)
|
||||||
|
*
|
||||||
|
* @param {string} group Группа
|
||||||
|
*
|
||||||
|
* @return {bool} Статус выполнения
|
||||||
|
*/
|
||||||
|
return function (group) {
|
||||||
|
if (typeof left === 'string' && typeof center === 'string' && typeof right === 'string') {
|
||||||
|
// Пройдена проверка входных параметров
|
||||||
|
// // Инициализация нижнего колонтинула оболочки
|
||||||
|
// let footer = document.getElementsByClassName('settings_block_footer')[0];
|
||||||
|
// // Очистка нижнего колонтинула оболочки
|
||||||
|
// // footer.innerHTML = null;
|
||||||
|
// footer.remove();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Генерация HTML-элемента-оболочки
|
||||||
|
*
|
||||||
|
* @param {string} id Идентификатор
|
||||||
|
* @param {...function} functions Содержимое
|
||||||
|
*
|
||||||
|
* @return {integer} Количество ошибок
|
||||||
|
*/
|
||||||
|
group(id, ...functions) {
|
||||||
|
if (typeof id === 'string' && typeof functions === 'object') {
|
||||||
|
// Пройдена проверка входных параметров
|
||||||
|
|
||||||
|
// Инициализация названия идентификатора элемента
|
||||||
|
let name = 'block_' + id;
|
||||||
|
|
||||||
|
if (document.getElementById(name) === null) {
|
||||||
|
// Не найден блок с данным идентификатором
|
||||||
|
// Инициализация оболочки
|
||||||
|
let block = document.createElement('div');
|
||||||
|
block.id = name;
|
||||||
|
block.classList.add('page_block', 'clear_fix');
|
||||||
|
|
||||||
|
// Инициализация верхнего колонтинула
|
||||||
|
let header = document.createElement('h2');
|
||||||
|
header.classList.add('page_block_h2');
|
||||||
|
|
||||||
|
// Инициализация заголовка
|
||||||
|
let title = document.createElement('div');
|
||||||
|
title.classList.add('page_block_header');
|
||||||
|
title.innerText = id;
|
||||||
|
|
||||||
|
// Инициализация статуса
|
||||||
|
let status = document.createElement('div');
|
||||||
|
status.classList.add('page_block_saved');
|
||||||
|
status.innerText = 'Изменения сохранены';
|
||||||
|
|
||||||
|
// Инициализация оболочки содержимого
|
||||||
|
let main = document.createElement('div');
|
||||||
|
main.classList.add('settings_panel', 'clear_fix', 'settings_' + this.core.id, 'settings_section_' + this.core.id);
|
||||||
|
|
||||||
|
// Инициализация архитектуры
|
||||||
|
title.appendChild(status);
|
||||||
|
header.appendChild(title);
|
||||||
|
block.appendChild(header);
|
||||||
|
block.appendChild(main);
|
||||||
|
|
||||||
|
// Запись в документ
|
||||||
|
this.core.body().appendChild(block);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Инициализация счётчика ошибок
|
||||||
|
let errors = 0;
|
||||||
|
|
||||||
|
functions.forEach(function (entry) {
|
||||||
|
// Перебор переданных функций
|
||||||
|
if (typeof entry === 'function') {
|
||||||
|
// Пройдена проверка входных параметров
|
||||||
|
|
||||||
|
// Генерация
|
||||||
|
if (!entry(id)) ++errors;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return errors;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Поля
|
||||||
|
*/
|
||||||
|
fields: {
|
||||||
|
macroses: {
|
||||||
|
/**
|
||||||
|
* Шаблон для инициализации элементов строки с полем
|
||||||
|
*
|
||||||
|
* @param {string} group Группа
|
||||||
|
* @param {string|null} icon Иконка
|
||||||
|
* @param {function} content Функция которая будет обрабатывать содержимое макроса
|
||||||
|
*/
|
||||||
|
row(group, icon, content) {
|
||||||
|
// Инициализация блока
|
||||||
|
const block = document.getElementById('block_' + group);
|
||||||
|
|
||||||
|
// Инициализация головного элемента блока
|
||||||
|
const header = block.getElementsByClassName('page_block_header')[0];
|
||||||
|
|
||||||
|
// Инициализация элемента со статусом
|
||||||
|
const status = header.getElementsByClassName('page_block_saved')[0];
|
||||||
|
|
||||||
|
// Инициализация тела блока
|
||||||
|
const body = block.getElementsByClassName('settings_panel clear_fix settings_' + this.core.id + ' settings_section_' + this.core.id)[0];
|
||||||
|
|
||||||
|
// Инициализация оболочки кнопки активации
|
||||||
|
const wrap = document.createElement('div');
|
||||||
|
wrap.classList.add('settings_separated_row', this.core.icons[icon] ?? this.core.icons['lightning'], 'settings_separated_row_iconed');
|
||||||
|
|
||||||
|
// Инициализация разделителя
|
||||||
|
const separator = document.createElement('div');
|
||||||
|
separator.classList.add('settings_separated_row_extra');
|
||||||
|
|
||||||
|
// Генерация содержимого строки
|
||||||
|
return content(status, body, wrap, separator);
|
||||||
|
},
|
||||||
|
|
||||||
|
dropdown(active, rows) {
|
||||||
|
if (typeof active === 'string' && typeof rows === 'object') {
|
||||||
|
// Пройдена проверка входных параметров
|
||||||
|
|
||||||
|
// Инициализация оболочки
|
||||||
|
const wrap = document.createElement('div');
|
||||||
|
wrap.classList.add('privacy_dropdown', 'privacy_dropdown_mail', 'pdd_ralign');
|
||||||
|
wrap.setAttribute('style', 'opacity: 1; display: none;');
|
||||||
|
|
||||||
|
// Инициализация списка строк
|
||||||
|
const list = document.createElement('div');
|
||||||
|
list.classList.add('rows', 'rows__flex');
|
||||||
|
wrap.setAttribute('style', 'font-size: 13px;');
|
||||||
|
|
||||||
|
// Инициализация головной строки
|
||||||
|
const header = document.createElement('div');
|
||||||
|
header.classList.add('header');
|
||||||
|
wrap.setAttribute('onclick', 'Privacy.hide(-1)');
|
||||||
|
|
||||||
|
// Инициализация активной строки (выбранного параметра)
|
||||||
|
const active = document.createElement('div');
|
||||||
|
active.classList.add('header_label');
|
||||||
|
active.innerHTML = active;
|
||||||
|
|
||||||
|
// Инициализация основной группы строк
|
||||||
|
const body = document.createElement('div');
|
||||||
|
body.classList.add('body', 'body__flex');
|
||||||
|
body.setAttribute('role', 'list');
|
||||||
|
body.setAttribute('aria-labelledby', 'privacy_who_can_view');
|
||||||
|
|
||||||
|
for (const row in rows) {
|
||||||
|
// Перебор строк для генерации списка
|
||||||
|
|
||||||
|
// Инициализация кнопки
|
||||||
|
const button = document.createElement('button');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Генерация HTML-элемента настройки с кнопкой активации
|
||||||
|
*
|
||||||
|
* @param {string} id Идентификатор
|
||||||
|
* @param {string|null} icon Иконка
|
||||||
|
* @param {string|null} name Название
|
||||||
|
* @param {string|null} description Описание
|
||||||
|
* @param {string|null} hint Всплывающая подсказка (иконка с вопросительным знаком возле верхнего колонтинула)
|
||||||
|
* @param {string|null} onchange Код который выполняется после изменения состояния
|
||||||
|
*
|
||||||
|
* @return {function} Функция для выполнения в генераторе группы
|
||||||
|
*
|
||||||
|
* @todo 1. Добавить проверку на существование нижнего колонтинула и записывать перед ним, вместо конца блока
|
||||||
|
*/
|
||||||
|
checkbox(id, icon, name, description, hint, onchange) {
|
||||||
|
// Инициализация ядра
|
||||||
|
const core = this.core;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Запись в группу (подразумевается выполнение в функции генерирующей группу)
|
||||||
|
*
|
||||||
|
* @param {string} group Группа
|
||||||
|
*
|
||||||
|
* @return {bool} Статус выполнения
|
||||||
|
*/
|
||||||
|
return function (group) {
|
||||||
|
if (typeof id === 'string' && typeof core === 'object' && typeof group === 'string') {
|
||||||
|
// Пройдена проверка входных параметров
|
||||||
|
|
||||||
|
return core.blocks.fields.macros(group, icon,
|
||||||
|
function (status, body, wrap, separator) {
|
||||||
|
wrap.addEventListener("click", fn => {
|
||||||
|
// Инициализация кнопки
|
||||||
|
const button = wrap.getElementsByClassName('ui_toggler')[0];
|
||||||
|
|
||||||
|
if (button.classList.contains('on')) {
|
||||||
|
// Активирована
|
||||||
|
if (settings.write(group + '_' + id, false)) {
|
||||||
|
// Записан статус активации
|
||||||
|
|
||||||
|
// Запуск анимации и переход в состояние деактивации
|
||||||
|
button.classList.remove('on');
|
||||||
|
|
||||||
|
settings.read(group + '_' + id).then(result => {
|
||||||
|
if (result === false) {
|
||||||
|
// Сохранены изменения
|
||||||
|
|
||||||
|
// Запуск анимации
|
||||||
|
status.style.transition = '0.5s';
|
||||||
|
status.style.opacity = 1;
|
||||||
|
setTimeout(fn => {
|
||||||
|
status.style.transition = '1.5s';
|
||||||
|
status.style.opacity = 0;
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Деактивирована
|
||||||
|
if (settings.write(group + '_' + id, true)) {
|
||||||
|
// Записан статус активации
|
||||||
|
|
||||||
|
// Запуск анимации и переход в состояние активации
|
||||||
|
button.classList.add('on');
|
||||||
|
|
||||||
|
settings.read(group + '_' + id).then(result => {
|
||||||
|
if (result === true) {
|
||||||
|
// Сохранены изменения
|
||||||
|
|
||||||
|
// Запуск анимации
|
||||||
|
status.style.transition = '0.5s';
|
||||||
|
status.style.opacity = 1;
|
||||||
|
setTimeout(fn => {
|
||||||
|
status.style.transition = '1.5s';
|
||||||
|
status.style.opacity = 0;
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Инициализация кнопки активации
|
||||||
|
const button = document.createElement('div');
|
||||||
|
button.classList.add('ui_toggler_wrap');
|
||||||
|
|
||||||
|
// Инициализация элемента-иконки
|
||||||
|
const checkbox = document.createElement('div');
|
||||||
|
checkbox.classList.add('_ui_toggler', 'ui_toggler', '_settings_ienable');
|
||||||
|
if (typeof onchange === 'string') checkbox.setAttribute('onchange', onchange);
|
||||||
|
|
||||||
|
settings.read(group + '_' + id).then(result => {
|
||||||
|
// Получены данные о значении настройки
|
||||||
|
|
||||||
|
// Запись состояния
|
||||||
|
if (result) checkbox.classList.add('on');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Инициализация элемента-иконки
|
||||||
|
const label = document.createElement('div');
|
||||||
|
label.classList.add('ui_toggler_label');
|
||||||
|
|
||||||
|
// Инициализация названия
|
||||||
|
const header = document.createElement('div');
|
||||||
|
header.classList.add('settings_separated_row_text');
|
||||||
|
|
||||||
|
// Инициализация текста названия
|
||||||
|
const colonic = document.createElement('div');
|
||||||
|
colonic.classList.add('settings_separated_row_text_inner');
|
||||||
|
colonic.innerText = name !== undefined && typeof name === 'string' ? name : id;
|
||||||
|
|
||||||
|
// Инициализация архитектуры
|
||||||
|
button.appendChild(checkbox);
|
||||||
|
separator.appendChild(button);
|
||||||
|
wrap.appendChild(separator);
|
||||||
|
header.appendChild(colonic);
|
||||||
|
|
||||||
|
if (typeof hint === 'string') {
|
||||||
|
// Получена подсказка
|
||||||
|
|
||||||
|
// Инициализация текста-подсказки
|
||||||
|
const question = document.createElement('span');
|
||||||
|
question.classList.add('hint_icon');
|
||||||
|
question.setAttribute('data-title', hint);
|
||||||
|
question.setAttribute('onmouseover', 'showHint(this);');
|
||||||
|
|
||||||
|
// Инициализация архитектуры
|
||||||
|
colonic.appendChild(question);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (description !== undefined && typeof description === 'string') {
|
||||||
|
// Получено описание
|
||||||
|
|
||||||
|
// Инициализация текста описания
|
||||||
|
const text = document.createElement('div');
|
||||||
|
text.classList.add('settings_separated_row_hint');
|
||||||
|
text.innerText = description;
|
||||||
|
|
||||||
|
// Инициализация архитектуры
|
||||||
|
colonic.appendChild(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Инициализация архитектуры
|
||||||
|
wrap.appendChild(header);
|
||||||
|
|
||||||
|
// Запись в блок
|
||||||
|
body.appendChild(wrap);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Генерация HTML-элемента настройки с полем для ввода текста
|
||||||
|
*
|
||||||
|
* @param {string} id Идентификатор
|
||||||
|
* @param {string|null} icon Иконка
|
||||||
|
* @param {string|null} name Название
|
||||||
|
* @param {string|null} description Описание
|
||||||
|
* @param {string|null} hint Всплывающая подсказка (иконка с вопросительным знаком возле верхнего колонтинула)
|
||||||
|
* @param {string|null} type Тип поля для ввода (HTML-категории: text, password, email, number)
|
||||||
|
* @param {number|null} min Ограничение по минимальному количеству символов
|
||||||
|
* @param {number|null} max Ограничение по максимальному количеству символов
|
||||||
|
* @param {string|null} title Текст выводимый во всплывающем окне при наведении курсора
|
||||||
|
* @param {string|null} placeholder Текст отображаемый в поле для ввода если оно пустое
|
||||||
|
* @param {string|null} pattern Шаблон значений которые позволено вводить в поле
|
||||||
|
* @param {boolean|null} readonly Запретить редактирование
|
||||||
|
* @param {boolean|null} spellcheck Использовать проверку орфографии
|
||||||
|
* @param {object|null} options Массив со строками для автозаполнения поля
|
||||||
|
* @param {string|null} onchange Код который выполняется после изменения состояния
|
||||||
|
* @param {string|null} oninput Код который выполняется при вводе текста
|
||||||
|
*
|
||||||
|
* @return {function} Функция для выполнения в генераторе группы
|
||||||
|
*
|
||||||
|
* @todo 1. Добавить проверку на существование нижнего колонтинула и записывать перед ним, вместо конца блока
|
||||||
|
*/
|
||||||
|
text(id, icon, name, description, hint, type = 'text', min = 0, max = 100, title, placeholder, pattern, readonly, spellcheck, options, onchange, oninput) {
|
||||||
|
// Инициализация ядра
|
||||||
|
const core = this.core;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Запись в группу (подразумевается выполнение в функции генерирующей группу)
|
||||||
|
*
|
||||||
|
* @param {string} group Группа
|
||||||
|
*
|
||||||
|
* @return {bool} Статус выполнения
|
||||||
|
*/
|
||||||
|
return function (group) {
|
||||||
|
if (typeof id === 'string' && typeof icon === 'string' && typeof core === 'object' && typeof group === 'string') {
|
||||||
|
// Пройдена проверка входных параметров
|
||||||
|
|
||||||
|
return core.blocks.fields.macros(group, icon,
|
||||||
|
function (status, body, wrap, separator) {
|
||||||
|
wrap.addEventListener("input", fn => {
|
||||||
|
// Инициализация поля ввода
|
||||||
|
const input = wrap.getElementsByTagName('input')[0];
|
||||||
|
|
||||||
|
if (settings.write(group + '_' + id, input.value)) {
|
||||||
|
// Записано значение поля
|
||||||
|
|
||||||
|
// Запуск анимации
|
||||||
|
settings.read(group + '_' + id).then(result => {
|
||||||
|
if (result === input.value) {
|
||||||
|
// Сохранены изменения
|
||||||
|
|
||||||
|
// Запуск анимации
|
||||||
|
status.style.transition = '0.5s';
|
||||||
|
status.style.opacity = 1;
|
||||||
|
setTimeout(fn => {
|
||||||
|
status.style.transition = '1.5s';
|
||||||
|
status.style.opacity = 0;
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Инициализация элемента для ввода текста
|
||||||
|
const input = document.createElement('input');
|
||||||
|
input.classList.add('dark');
|
||||||
|
input.setAttribute('type', type);
|
||||||
|
input.setAttribute(type === 'number' ? 'min' : 'minlength', min);
|
||||||
|
input.setAttribute(type === 'number' ? 'max' : 'maxlength', max);
|
||||||
|
if (typeof title === 'string') input.setAttribute('title', title);
|
||||||
|
if (typeof placeholder === 'string') input.setAttribute('placeholder', placeholder);
|
||||||
|
if (typeof pattern === 'string') input.setAttribute('pattern', pattern);
|
||||||
|
if (readonly === true) input.setAttribute('readonly', readonly);
|
||||||
|
if (spellcheck === true) input.setAttribute('spellcheck', spellcheck);
|
||||||
|
input.setAttribute('list', group + '_' + id + '_datalist');
|
||||||
|
settings.read(group + '_' + id).then(result => {
|
||||||
|
// Получены данные о значении настройки
|
||||||
|
|
||||||
|
// Запись значения в поле
|
||||||
|
if (result) input.value = result;
|
||||||
|
});
|
||||||
|
if (typeof onchange === 'string') input.setAttribute('onchange', onchange);
|
||||||
|
if (typeof oninput === 'string') input.setAttribute('oninput', oninput);
|
||||||
|
|
||||||
|
|
||||||
|
if (typeof options === 'object' && options.length > 0) {
|
||||||
|
// Инициализация элемента-списка для выбора значений автозаполнения
|
||||||
|
const datalist = document.createElement('datalist');
|
||||||
|
datalist.id = group + '_' + id + '_datalist';
|
||||||
|
|
||||||
|
for (const option of options) {
|
||||||
|
// Перебор значений для автозаполнения поля
|
||||||
|
|
||||||
|
// Инициализация элемента со значением автозаполнения
|
||||||
|
const element = document.createElement('option');
|
||||||
|
element.setAttribute('value', option);
|
||||||
|
|
||||||
|
// Запись в список
|
||||||
|
datalist.appendChild(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Инициализация элемента-иконки
|
||||||
|
const label = document.createElement('div');
|
||||||
|
label.classList.add('ui_toggler_label');
|
||||||
|
|
||||||
|
// Инициализация названия
|
||||||
|
const header = document.createElement('div');
|
||||||
|
header.classList.add('settings_separated_row_text');
|
||||||
|
|
||||||
|
// Инициализация текста названия
|
||||||
|
const colonic = document.createElement('div');
|
||||||
|
colonic.classList.add('settings_separated_row_text_inner');
|
||||||
|
colonic.innerText = name !== undefined && typeof name === 'string' ? name : id;
|
||||||
|
|
||||||
|
// Инициализация архитектуры
|
||||||
|
separator.appendChild(input);
|
||||||
|
if (typeof datalist === 'object') separator.appendChild(datalist);
|
||||||
|
wrap.appendChild(separator);
|
||||||
|
header.appendChild(colonic);
|
||||||
|
|
||||||
|
if (typeof hint === 'string') {
|
||||||
|
// Получена подсказка
|
||||||
|
|
||||||
|
// Инициализация текста-подсказки
|
||||||
|
const question = document.createElement('span');
|
||||||
|
question.classList.add('hint_icon');
|
||||||
|
question.setAttribute('data-title', hint);
|
||||||
|
question.setAttribute('onmouseover', 'showHint(this);');
|
||||||
|
|
||||||
|
// Инициализация архитектуры
|
||||||
|
colonic.appendChild(question);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (description !== undefined && typeof description === 'string') {
|
||||||
|
// Получено описание
|
||||||
|
|
||||||
|
// Инициализация текста описания
|
||||||
|
const text = document.createElement('div');
|
||||||
|
text.classList.add('settings_separated_row_hint');
|
||||||
|
text.innerText = description;
|
||||||
|
|
||||||
|
// Инициализация архитектуры
|
||||||
|
colonic.appendChild(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Инициализация архитектуры
|
||||||
|
wrap.appendChild(header);
|
||||||
|
|
||||||
|
// Запись в блок
|
||||||
|
body.appendChild(wrap);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Генерация HTML-элемента настройки с всплывающим списком
|
||||||
|
*
|
||||||
|
* @param {string} id Идентификатор
|
||||||
|
* @param {string|null} icon Иконка
|
||||||
|
* @param {string|null} name Название
|
||||||
|
* @param {string|null} description Описание
|
||||||
|
* @param {string|null} hint Всплывающая подсказка (иконка с вопросительным знаком возле верхнего колонтинула)
|
||||||
|
* @param {string|null} type
|
||||||
|
* @param {string|null} button
|
||||||
|
* @param {object|null} options Массив со строками для автозаполнения поля
|
||||||
|
* @param {string|null} onclick
|
||||||
|
* @param {string|null} onchange Код который выполняется после изменения состояния
|
||||||
|
* @param {string|null} oninput Код который выполняется при вводе текста
|
||||||
|
*
|
||||||
|
* @return {function} Функция для выполнения в генераторе группы
|
||||||
|
*
|
||||||
|
* @todo 1. Добавить проверку на существование нижнего колонтинула и записывать перед ним, вместо конца блока
|
||||||
|
*/
|
||||||
|
button(id, icon, name, description, hint, type = 'dropdown', value = 'Выбрать', onclick, onchange, oninput) {
|
||||||
|
// Инициализация ядра
|
||||||
|
const core = this.core;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Запись в группу (подразумевается выполнение в функции генерирующей группу)
|
||||||
|
*
|
||||||
|
* @param {string} group Группа
|
||||||
|
*
|
||||||
|
* @return {bool} Статус выполнения
|
||||||
|
*/
|
||||||
|
return function (group) {
|
||||||
|
if (typeof id === 'string' && typeof icon === 'string' && typeof core === 'object' && typeof group === 'string') {
|
||||||
|
// Пройдена проверка входных параметров
|
||||||
|
|
||||||
|
return core.blocks.fields.macroses.row(group, icon,
|
||||||
|
function (status, body, wrap, separator) {
|
||||||
|
wrap.addEventListener("input", fn => {
|
||||||
|
// Инициализация поля ввода
|
||||||
|
const input = wrap.getElementsByTagName('input')[0];
|
||||||
|
|
||||||
|
if (settings.write(group + '_' + id, input.value)) {
|
||||||
|
// Записано значение поля
|
||||||
|
|
||||||
|
// Запуск анимации
|
||||||
|
settings.read(group + '_' + id).then(result => {
|
||||||
|
if (result === input.value) {
|
||||||
|
// Сохранены изменения
|
||||||
|
|
||||||
|
// Запуск анимации
|
||||||
|
status.style.transition = '0.5s';
|
||||||
|
status.style.opacity = 1;
|
||||||
|
setTimeout(fn => {
|
||||||
|
status.style.transition = '1.5s';
|
||||||
|
status.style.opacity = 0;
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Инициализация элемента-кнопки
|
||||||
|
const button = document.createElement('a');
|
||||||
|
button.innerText = value;
|
||||||
|
if (typeof onchange === 'string') button.setAttribute('onchange', onchange);
|
||||||
|
if (typeof oninput === 'string') button.setAttribute('oninput', oninput);
|
||||||
|
|
||||||
|
if (type === 'dropdown') {
|
||||||
|
// Инициализация всплывающего списка
|
||||||
|
|
||||||
|
// Инициализация элемента-кнопки
|
||||||
|
button.setAttribute('onclick', 'return Privacy.show(this, event, \'mail\');' + typeof onclick === 'string' ? ' ' + onclick : '');
|
||||||
|
|
||||||
|
// Инициализация элемента-списка
|
||||||
|
const dropdown = core.blocks.fields.macroses.dropdown();
|
||||||
|
|
||||||
|
|
||||||
|
// Инициализация архитектуры
|
||||||
|
separator.appendChild(button);
|
||||||
|
} else if (type === 'popup') {
|
||||||
|
// Инициализация всплывающего окна
|
||||||
|
|
||||||
|
// Инициализация элемента-кнопки
|
||||||
|
button.setAttribute('href', '#');
|
||||||
|
button.setAttribute('onclick', 'return Settings.showGroupMessagesNotifyBox(event, \'settings\');' + typeof onclick === 'string' ? ' ' + onclick : '');
|
||||||
|
|
||||||
|
// Инициализация архитектуры
|
||||||
|
separator.appendChild(button);
|
||||||
|
} else if (type === 'button') {
|
||||||
|
// Инициализация кнопки
|
||||||
|
|
||||||
|
// Инициализация элемента-кнопки
|
||||||
|
if (typeof onclick === 'string') button.setAttribute('onclick', onclick);
|
||||||
|
|
||||||
|
// Инициализация архитектуры
|
||||||
|
separator.appendChild(button);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Инициализация элемента-иконки
|
||||||
|
const label = document.createElement('div');
|
||||||
|
label.classList.add('ui_toggler_label');
|
||||||
|
|
||||||
|
// Инициализация названия
|
||||||
|
const header = document.createElement('div');
|
||||||
|
header.classList.add('settings_separated_row_text');
|
||||||
|
|
||||||
|
// Инициализация текста названия
|
||||||
|
const colonic = document.createElement('div');
|
||||||
|
colonic.classList.add('settings_separated_row_text_inner');
|
||||||
|
colonic.innerText = name !== undefined && typeof name === 'string' ? name : id;
|
||||||
|
|
||||||
|
// Инициализация архитектуры
|
||||||
|
separator.appendChild(button);
|
||||||
|
wrap.appendChild(separator);
|
||||||
|
header.appendChild(colonic);
|
||||||
|
|
||||||
|
if (typeof hint === 'string') {
|
||||||
|
// Получена подсказка
|
||||||
|
|
||||||
|
// Инициализация текста-подсказки
|
||||||
|
const question = document.createElement('span');
|
||||||
|
question.classList.add('hint_icon');
|
||||||
|
question.setAttribute('data-title', hint);
|
||||||
|
question.setAttribute('onmouseover', 'showHint(this);');
|
||||||
|
|
||||||
|
// Инициализация архитектуры
|
||||||
|
colonic.appendChild(question);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (description !== undefined && typeof description === 'string') {
|
||||||
|
// Получено описание
|
||||||
|
|
||||||
|
// Инициализация текста описания
|
||||||
|
const text = document.createElement('div');
|
||||||
|
text.classList.add('settings_separated_row_hint');
|
||||||
|
text.innerText = description;
|
||||||
|
|
||||||
|
// Инициализация архитектуры
|
||||||
|
colonic.appendChild(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Инициализация архитектуры
|
||||||
|
wrap.appendChild(header);
|
||||||
|
|
||||||
|
// Запись в блок
|
||||||
|
body.appendChild(wrap);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Инициализация ядра
|
||||||
|
this.blocks.core = this.blocks.fields.core = this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Запуск выполнения
|
||||||
|
new page().init();
|
|
@ -0,0 +1,113 @@
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||||
|
*/
|
||||||
|
class settings {
|
||||||
|
/**
|
||||||
|
* Хранилище
|
||||||
|
*/
|
||||||
|
static storage = browser.storage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Префикс в журнале
|
||||||
|
*/
|
||||||
|
static prefix = 'настройки';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Записать
|
||||||
|
*
|
||||||
|
* @param {string} name
|
||||||
|
* @param {*} value
|
||||||
|
*
|
||||||
|
* @return {bool} Статус записи в базу данных
|
||||||
|
*/
|
||||||
|
static async write(name, value = null) {
|
||||||
|
if (typeof name === 'string') {
|
||||||
|
// Переданы строки
|
||||||
|
|
||||||
|
// Инициализация буфера для записи в хранилище
|
||||||
|
let buffer = {};
|
||||||
|
|
||||||
|
// Запись в буфер
|
||||||
|
buffer[name] = value;
|
||||||
|
|
||||||
|
// Запись в базу данных
|
||||||
|
await this.storage.sync.set(buffer);
|
||||||
|
|
||||||
|
// Запись в журнал
|
||||||
|
settings.log('Записана настройка: ' + name + ` (${value})`);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Запись в журнал
|
||||||
|
settings.log('Не удалось записать настройку: ' + name + ` (${value})`);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Прочитать
|
||||||
|
*
|
||||||
|
* @param {string} name
|
||||||
|
*
|
||||||
|
* @return {Promise|null} Значение, если найдено
|
||||||
|
*/
|
||||||
|
static async read(name) {
|
||||||
|
if (typeof name === 'string') {
|
||||||
|
// Передана строка
|
||||||
|
|
||||||
|
// Чтение из базы данных
|
||||||
|
let value = await this.storage.sync.get(name);
|
||||||
|
|
||||||
|
return value[name];
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Удалить
|
||||||
|
*
|
||||||
|
* @param {string} name
|
||||||
|
*
|
||||||
|
* @return {bool} Статус удаления из базы данных
|
||||||
|
*/
|
||||||
|
static async delete(name) {
|
||||||
|
if (typeof name === 'string') {
|
||||||
|
// Передана строка
|
||||||
|
|
||||||
|
// Удаление из базы данных
|
||||||
|
await this.storage.sync.remove(name);
|
||||||
|
|
||||||
|
// Запись в журнал
|
||||||
|
settings.log('Удалена настройка: ' + name);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Запись в журнал
|
||||||
|
settings.log('Не удалось удалить настройку: ' + name);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Запись в журнал
|
||||||
|
*
|
||||||
|
* @param {string} text
|
||||||
|
*
|
||||||
|
* @return {bool} Статус записи в журнал
|
||||||
|
*/
|
||||||
|
static log(text) {
|
||||||
|
if (typeof text === 'string') {
|
||||||
|
// Передана строка
|
||||||
|
|
||||||
|
// Запись в журнал
|
||||||
|
return log.write(settings.prefix, text);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,87 @@
|
||||||
|
::selection {
|
||||||
|
background: #808080;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-moz-selection {
|
||||||
|
background: #808080;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
padding: 40px 20px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
background-color: #1c1c1c;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
margin-top: -10px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
color: #fafafa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.setting:not(:last-child) {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.setting {
|
||||||
|
width: 40%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.setting>label {
|
||||||
|
margin-bottom: 4px;
|
||||||
|
display: block;
|
||||||
|
color: #c4c4c4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.setting>input:is([type="text"], [type="number"]) {
|
||||||
|
width: 100%;
|
||||||
|
padding: 5px 10px;
|
||||||
|
border-radius: 0px;
|
||||||
|
border: none;
|
||||||
|
outline: none;
|
||||||
|
color: #d0d0d0;
|
||||||
|
background-color: #2c2c2c;
|
||||||
|
}
|
||||||
|
|
||||||
|
.setting>input[type="checkbox"] {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.setting>input[type="checkbox"]+div.checkbox[type="button"] {
|
||||||
|
height: 30px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
background-color: #282828;
|
||||||
|
}
|
||||||
|
|
||||||
|
.setting>input[type="checkbox"]+div.checkbox[type="button"]:before {
|
||||||
|
content: 'Отключено';
|
||||||
|
color: #d0d0d0;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.setting>input[type="checkbox"]+div.checkbox[type="button"]:hover {
|
||||||
|
background-color: #2b2b2b;
|
||||||
|
}
|
||||||
|
|
||||||
|
.setting>input[type="checkbox"]+div.checkbox[type="button"]:active {
|
||||||
|
background-color: #252525;
|
||||||
|
}
|
||||||
|
|
||||||
|
.setting>input[type="checkbox"]:checked+div.checkbox[type="button"] {
|
||||||
|
background-color: #3c3c3c;
|
||||||
|
}
|
||||||
|
|
||||||
|
.setting>input[type="checkbox"]:checked+div.checkbox[type="button"]:before {
|
||||||
|
content: 'Включено'
|
||||||
|
}
|
||||||
|
|
||||||
|
.setting>input[type="checkbox"]:checked+div.checkbox[type="button"]:hover {
|
||||||
|
background-color: #3f3f3f;
|
||||||
|
}
|
||||||
|
|
||||||
|
.setting>input[type="checkbox"]:checked+div.checkbox[type="button"]:active {
|
||||||
|
background-color: #3a3a3a;
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
|
||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<link rel="stylesheet" href="css/settings.css">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<h1>Настройки</h1>
|
||||||
|
<script src="../settings.js" defer></script>
|
||||||
|
<script src="js/generator.js" defer></script>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
|
@ -0,0 +1,161 @@
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Генерация HTML-элемента настройки с текстовым полем
|
||||||
|
*
|
||||||
|
* @param {string} id Настройка
|
||||||
|
* @param {string|null} name Ярлык настройки (понятный пользователю)
|
||||||
|
*
|
||||||
|
* @return {bool} Статус выполнения
|
||||||
|
*/
|
||||||
|
function text(id, name) {
|
||||||
|
if (typeof id === 'string') {
|
||||||
|
settings.read(id).then(result => {
|
||||||
|
// Инициализация оболочки поля ввода
|
||||||
|
let wrap = document.createElement('div');
|
||||||
|
wrap.classList.add('setting');
|
||||||
|
|
||||||
|
// Инициализация ярлыка поля ввода
|
||||||
|
let label = document.createElement('label');
|
||||||
|
label.innerText = name !== undefined && typeof name === 'string' ? name : id;
|
||||||
|
|
||||||
|
// Инициализация поля ввода
|
||||||
|
let text = document.createElement('input');
|
||||||
|
text.setAttribute('id', id);
|
||||||
|
text.setAttribute('type', 'text');
|
||||||
|
text.value = result[id] ?? '';
|
||||||
|
|
||||||
|
// Инициализация архитектуры
|
||||||
|
wrap.appendChild(label);
|
||||||
|
wrap.appendChild(text);
|
||||||
|
|
||||||
|
// Запись в документ
|
||||||
|
document.body.appendChild(wrap);
|
||||||
|
|
||||||
|
// Инициализация созданного элемента поля ввода
|
||||||
|
text = document.getElementById(id);
|
||||||
|
|
||||||
|
// Инициализация события
|
||||||
|
text.addEventListener("change", fn => { settings.write(id, text.value); });
|
||||||
|
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Генерация HTML-элемента настройки с циферным полем
|
||||||
|
*
|
||||||
|
* @param {string} id Настройка
|
||||||
|
* @param {string|null} name Ярлык настройки (понятный пользователю)
|
||||||
|
*
|
||||||
|
* @return {bool} Статус выполнения
|
||||||
|
*/
|
||||||
|
function number(id, name, min = 0, max = 100) {
|
||||||
|
if (typeof id === 'string') {
|
||||||
|
settings.read(id).then(result => {
|
||||||
|
// Инициализация оболочки циферного поля ввода
|
||||||
|
let wrap = document.createElement('div');
|
||||||
|
wrap.classList.add('setting');
|
||||||
|
|
||||||
|
// Инициализация ярлыка циферного поля ввода
|
||||||
|
let label = document.createElement('label');
|
||||||
|
label.innerText = name !== undefined && typeof name === 'string' ? name : id;
|
||||||
|
|
||||||
|
// Инициализация поля циферного ввода
|
||||||
|
let number = document.createElement('input');
|
||||||
|
number.setAttribute('id', id);
|
||||||
|
number.setAttribute('type', 'number');
|
||||||
|
number.min = min;
|
||||||
|
number.max = max;
|
||||||
|
number.value = result[id] ?? '';
|
||||||
|
|
||||||
|
// Инициализация архитектуры
|
||||||
|
wrap.appendChild(label);
|
||||||
|
wrap.appendChild(number);
|
||||||
|
|
||||||
|
// Запись в документ
|
||||||
|
document.body.appendChild(wrap);
|
||||||
|
|
||||||
|
// Инициализация созданного элемента циферного поля ввода
|
||||||
|
number = document.getElementById(id);
|
||||||
|
|
||||||
|
// Инициализация события
|
||||||
|
number.addEventListener("change", fn => { settings.write(id, number.value); });
|
||||||
|
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Генерация HTML-элемента настройки с кнопкой активации
|
||||||
|
*
|
||||||
|
* @param {string} id Настройка
|
||||||
|
* @param {string|null} name Ярлык настройки (понятный пользователю)
|
||||||
|
*
|
||||||
|
* @return {bool} Статус выполнения
|
||||||
|
*/
|
||||||
|
function checkbox(id, name) {
|
||||||
|
if (typeof id === 'string') {
|
||||||
|
settings.read(id).then(result => {
|
||||||
|
// Инициализация оболочки кнопки активации
|
||||||
|
let wrap = document.createElement('div');
|
||||||
|
wrap.classList.add('setting');
|
||||||
|
|
||||||
|
// Инициализация ярлыка кнопки активации
|
||||||
|
let label = document.createElement('label');
|
||||||
|
label.innerText = name !== undefined && typeof name === 'string' ? name : id;
|
||||||
|
|
||||||
|
// Инициализация кнопки активации (настоящая)
|
||||||
|
let checkbox = document.createElement('input');
|
||||||
|
checkbox.setAttribute('id', id);
|
||||||
|
checkbox.setAttribute('type', 'checkbox');
|
||||||
|
checkbox.checked = result[id] === true || result[id] === 1 || result[id] === '1' ? true : false;
|
||||||
|
|
||||||
|
// Инициализация кнопки активации (видимая)
|
||||||
|
let div = document.createElement('div');
|
||||||
|
div.setAttribute('id', id + '_button');
|
||||||
|
div.classList.add('checkbox');
|
||||||
|
div.setAttribute('type', 'button');
|
||||||
|
|
||||||
|
// Инициализация архитектуры
|
||||||
|
wrap.appendChild(label);
|
||||||
|
wrap.appendChild(checkbox);
|
||||||
|
wrap.appendChild(div);
|
||||||
|
|
||||||
|
// Запись в документ
|
||||||
|
document.body.appendChild(wrap);
|
||||||
|
|
||||||
|
// Инициализация созданного элемента кнопки активации
|
||||||
|
checkbox = document.getElementById(id);
|
||||||
|
|
||||||
|
// Инициализация событий
|
||||||
|
checkbox.addEventListener("change", fn => { settings.write(id, checkbox.checked); });
|
||||||
|
document.getElementById(id + '_button').addEventListener("click", fn => { checkbox.checked = checkbox.checked ? false : true; });
|
||||||
|
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Инициализация
|
||||||
|
*/
|
||||||
|
function init() {
|
||||||
|
checkbox('debug', 'Режим отладки');
|
||||||
|
checkbox('autonom', 'Режим автономный');
|
||||||
|
number('server_connect_repeats', 'Количество попыток соединения');
|
||||||
|
checkbox('instructions', 'Инструкции');
|
||||||
|
checkbox('instruction_settings', 'Инструкция по доступу к настройкам');
|
||||||
|
checkbox('instruction_killer', 'Инструкция по доступу к удалению сообщений');
|
||||||
|
checkbox('instruction_visor', 'Инструкция по доступу к просмотру удалённых сообщений');
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener("DOMContentLoaded", init);
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"dependencies": {
|
||||||
|
"web-ext": "^7.3.1"
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue