'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();