3 Commits
1.0.x ... 1.2.x

View File

@@ -4,6 +4,56 @@
* Страница настроек ВКонтакте
*/
class panel {
/**
* Иконки ВКонтакте для полей
*/
static 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'
};
constructor() {
/**
* Идентификатор (https://vk.com/settings?act=ЗНАЧЕНИЕ)
@@ -18,50 +68,6 @@ class panel {
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();
}
/**
* Инициализация кнопки в боковом меню
*/
@@ -70,13 +76,13 @@ class panel {
// Инициализация оболочки кнопки
const li = document.createElement('li');
li.id = 'l_mw'
li.id = 'l_mw';
// Инициализация ссылки кнопки
const a = document.createElement('a');
a.classList.add('left_row');
a.href = '/settings?act=notify';
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);
// Инициализация иконки кнопки
@@ -134,13 +140,203 @@ class panel {
// Запись в документ
panel.menu().getElementsByClassName('more_div l_main')[0].insertAdjacentElement('beforebegin', li);
}
/**
* Сгенерировать панель управления
*
* Рекурсивно проверяет открытие страницы "Игры"
*
* @return {bool} Метод выполнен без ошибок?
*/
this.generate = function () {
// Генерация уникального идентификатора для загрузки первой страницы
const first = Math.random().toString(36).replace(/[^A-z]+ /g, '').slice(2);
// Инициализация элемента загрузки (пока что просто проверочный)
const loading = document.createElement('div');
loading.id = first;
loading.style.display = 'none';
// Запись в документ
document.getElementById('wrap3').appendChild(loading);
// Генерация уникального идентификатора для элемента загрузки страницы "Игры"
const games = Math.random().toString(36).replace(/[^A-z]+ /g, '').slice(2);
// Инициализация элемента загрузки (пока что просто проверочный)
const script = document.createElement('script');
script.textContent = `
// Инициализация кнопки\r
button = document.getElementById('l_mw');
if (button instanceof HTMLElement) {
// Найдена кнопка\r
// Переход на страницу \"Настройка уведомлений\" для получения CSS\r
button.id = 'ui_rmenu_notifications';
nav.go(button.firstElementChild);
// Генерация уникального идентификатора для элемента загрузки\r
const id = Math.random().toString(36).replace(/[^A-z]+ /g, '').slice(2);
// Инициализация элемента загрузки (пока что просто проверочный)\r
const loading = document.createElement('div');
loading.id = id;
loading.style.display = 'none';
// Запись в документ\r
document.getElementById('wrap3').appendChild(loading);
function check(iterator = 0) {
// Инициализация оболочки страницы "Игры"\r
if (window.location.pathname === '/settings' && !(document.getElementById(id) instanceof HTMLElement)) {
// Загружена страница "Игры" (или перезагружена)\r
// Инициализация элемента загрузки (пока что просто проверочный)\r
const loading = document.createElement('div');
loading.id = '${games}';
loading.style.display = 'none';
// Запись в документ\r
document.getElementById('wrap3').appendChild(loading);
// Переход на страницу \"Игры\" для получения CSS\r
button.id = 'l_mw';
nav.go(document.getElementById('l_ap').firstElementChild, null, { noback: true, params: { _ref: 'left_nav' } });
return true;
}
else if (iterator > 300) return false;
else setTimeout(check, 100, ++iterator);
}
// Запуск проверки\r
check();
}
`;
// Запись в документ
panel.body().appendChild(script);
function check(iterator = 0) {
// Инициализация оболочки страницы "Игры"
if (window.location.pathname === '/apps' && !(document.getElementById(games) instanceof HTMLElement) && !(document.getElementById(first) instanceof HTMLElement)) {
// Загружена страница "Игры" (или перезагружена)
// Инициализация страницы
panel.clean();
panel.blocks.generate(
'test2',
'settings',
panel.blocks.fields.text('asdasdasd', 'lightning', 'Активировать', 'asdasdasdasd', 'Тестирование всплывающей подсказки', 'text', 0, 8, 'фффф', 'сюда писать')
// panel.blocks.fields.button('account_key', 'friend', 'Аккаунт', 'Анонимный режим ограничивает возможности', 'Аутентификация через аккаунт ВКонтакте', 'dropdown', 'Будет сгенерирован ключ доступа ВКонтакте', 'Подключить', function () {
// alert('ура!');
// })
);
panel.blocks.generate(
'test',
'menu',
panel.blocks.menu(),
panel.blocks.tab('Тест', function () { alert('хихи') }),
panel.blocks.fields.text('asdasdasd', 'lightning', 'Активировать', 'asdasdasdasd', 'Тестирование всплывающей подсказки', 'text', 0, 8, 'фффф', 'сюда писать')
);
return true;
}
else if (iterator > 300) return false;
else setTimeout(check, 100, ++iterator);
}
// Запуск проверки
check();
}
}
/**
* Блоки
*/
static blocks = {
/**
* Генерация HTML-элемента-оболочки
*
* @param {string} id Идентификатор
* @param {...function} functions Содержимое
*
* @return {integer} Количество ошибок
*/
generate(id, type = 'settings', ...functions) {
if (typeof id === 'string' && typeof type === 'string' && typeof functions === 'object') {
// Пройдена проверка входных параметров
// Инициализация названия идентификатора элемента
const name = 'block_' + id;
// Проверка на существование (защита от дубликатов)
if (document.getElementById(name) instanceof HTMLElement) return ++errors;
if (type === 'settings') {
// Блок: "настройки"
// Инициализация оболочки
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_' + panel.id, 'settings_section_' + panel.id);
// Инициализация архитектуры
title.appendChild(status);
header.appendChild(title);
block.appendChild(header);
block.appendChild(main);
// Запись в документ
panel.body().appendChild(block);
} else if (type === 'menu') {
// Блок: "меню"
// Инициализация оболочки
const block = document.createElement('div');
block.id = name;
block.classList.add('GamesCatalogHead', 'page_block');
// Запись в документ
panel.body().appendChild(block);
} else return ++errors;
// Инициализация счётчика ошибок
let errors = 0;
functions.forEach(function (entry) {
// Перебор переданных функций
// Вызов функции
if (typeof entry === 'function' && !entry(id, type)) ++errors;
});
return errors;
}
},
/**
* Запись верхнего колонтинула оболочки в формате меню
*
@@ -151,11 +347,12 @@ class panel {
* Запись в группу (подразумевается выполнение в функции генерирующей группу)
*
* @param {string} group Группа
* @param {string} type Тип группы
*
* @return {bool} Статус выполнения
*/
return function (group) {
if (typeof group === 'string') {
return function (group, type = 'menu') {
if (typeof group === 'string' && type === 'menu') {
// Пройдена проверка входных параметров
// Инициализация блока куда надо записать заголовок
@@ -205,11 +402,12 @@ class panel {
* Запись в группу (подразумевается выполнение в функции генерирующей группу)
*
* @param {string} group Группа
* @param {string} type Тип группы
*
* @return {bool} Статус выполнения
*/
return function (group) {
if (typeof group === 'string' && typeof text === 'string' && typeof onclick === 'function') {
return function (group, type = 'menu') {
if (typeof group === 'string' && type === 'menu' && typeof text === 'string' && typeof onclick === 'function') {
// Пройдена проверка входных параметров
// Инициализация блока куда надо записать заголовок
@@ -247,81 +445,73 @@ class panel {
};
},
/**
* Генерация 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} type Тип группы
* @param {string|null} icon Иконка
* @param {function} content Функция которая будет обрабатывать содержимое макроса
*
* @return {mixed} Результат работы content()
*/
row(group, icon, content) {
row(group, type = 'settings', icon, content) {
// Инициализация блока
const block = document.getElementById('block_' + group);
// Инициализация головного элемента блока
const header = block.getElementsByClassName('page_block_header')[0];
// Инициализация головного элемента оболочки для содержимого, и элемента со статусом
let header, main, status;
// Инициализация элемента со статусом
const status = header.getElementsByClassName('page_block_saved')[0];
if (type === 'settings') {
// Блок: "настройки"
// Инициализация тела блока
const body = block.getElementsByClassName('settings_panel clear_fix settings_' + this.core.id + ' settings_section_' + this.core.id)[0];
// Запись головного элемента блока
header = block.getElementsByClassName('page_block_header')[0];
// Инициализация оболочки кнопки активации
// Запись оболочки для содержимого блока
main = block.getElementsByClassName('settings_panel clear_fix settings_' + panel.id + ' settings_section_' + panel.id)[0];
// Запись элемента со статусом
status = header.getElementsByClassName('page_block_saved')[0];
} else if (type === 'menu') {
// Блок: "меню"
// Запись головного элемента блока
header = block.getElementsByClassName('page_block_h2')[0];
// Запись оболочки для содержимого блока
main = block.getElementsByClassName('settings_panel')[0];
if (typeof main === 'undefined' && header instanceof HTMLElement) {
// Не найдена оболочка для содержимого блока
// Инициализация элемента-оболочки для содержимого блока
const element = document.createElement('div');
element.classList.add('settings_panel');
// Запись в документ
header.insertAdjacentElement('afterend', element);
// Запись тела содержимого блока
main = element;
}
}
// Инициализация оболочки строки
const wrap = document.createElement('div');
wrap.classList.add('settings_separated_row', this.core.icons[icon] ?? this.core.icons['lightning'], 'settings_separated_row_iconed');
wrap.classList.add('settings_separated_row', panel.icons[icon] ?? panel.icons['lightning'], 'settings_separated_row_iconed');
// Инициализация разделителя
const separator = document.createElement('div');
separator.classList.add('settings_separated_row_extra');
// Генерация содержимого строки
return content(status, body, wrap, separator);
return content(status, main, wrap, separator);
},
dropdown(active, rows) {
@@ -381,21 +571,19 @@ class panel {
* @todo 1. Добавить проверку на существование нижнего колонтинула и записывать перед ним, вместо конца блока
*/
checkbox(id, icon, name, description, hint, onchange) {
// Инициализация ядра
const core = this.core;
/**
* Запись в группу (подразумевается выполнение в функции генерирующей группу)
*
* @param {string} group Группа
* @param {string} type Тип группы
*
* @return {bool} Статус выполнения
*/
return function (group) {
if (typeof id === 'string' && typeof core === 'object' && typeof group === 'string') {
return function (group, type = 'settings') {
if (typeof id === 'string' && typeof group === 'string') {
// Пройдена проверка входных параметров
return core.blocks.fields.macros(group, icon,
return panel.blocks.fields.macros(group, icon,
function (status, body, wrap, separator) {
wrap.addEventListener("click", fn => {
// Инициализация кнопки
@@ -531,7 +719,7 @@ class panel {
* @param {string|null} name Название
* @param {string|null} description Описание
* @param {string|null} hint Всплывающая подсказка (иконка с вопросительным знаком возле верхнего колонтинула)
* @param {string|null} type Тип поля для ввода (HTML-категории: text, password, email, number)
* @param {string|null} field Тип поля для ввода (HTML-категории: text, password, email, number)
* @param {number|null} min Ограничение по минимальному количеству символов
* @param {number|null} max Ограничение по максимальному количеству символов
* @param {string|null} title Текст выводимый во всплывающем окне при наведении курсора
@@ -547,24 +735,22 @@ class panel {
*
* @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;
text(id, icon, name, description, hint, field = 'text', min = 0, max = 100, title, placeholder, pattern, readonly, spellcheck, options, onchange, oninput) {
/**
* Запись в группу (подразумевается выполнение в функции генерирующей группу)
*
* @param {string} group Группа
* @param {string} type Тип группы
*
* @return {bool} Статус выполнения
*/
return function (group) {
if (typeof id === 'string' && typeof icon === 'string' && typeof core === 'object' && typeof group === 'string') {
return function (group, type = 'settings') {
if (typeof id === 'string' && typeof icon === 'string' && typeof group === 'string') {
// Пройдена проверка входных параметров
return core.blocks.fields.macros(group, icon,
return panel.blocks.fields.macroses.row(group, type, icon,
function (status, body, wrap, separator) {
wrap.addEventListener("input", fn => {
if (type === 'settings') wrap.addEventListener("input", fn => {
// Инициализация поля ввода
const input = wrap.getElementsByTagName('input')[0];
@@ -591,9 +777,9 @@ class panel {
// Инициализация элемента для ввода текста
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);
input.setAttribute('type', field);
input.setAttribute(field === 'number' ? 'min' : 'minlength', min);
input.setAttribute(field === '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);
@@ -609,7 +795,6 @@ class panel {
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');
@@ -705,10 +890,7 @@ class panel {
*
* @todo 1. Добавить проверку на существование нижнего колонтинула и записывать перед ним, вместо конца блока
*/
button(id, icon, name, description, hint, type = 'dropdown', value = 'Выбрать', onclick, onchange, oninput) {
// Инициализация ядра
const core = this.core;
button(id, icon, name, description, hint, type = 'dropdown', title, value = 'Выбрать', onclick, onchange, oninput) {
/**
* Запись в группу (подразумевается выполнение в функции генерирующей группу)
*
@@ -717,10 +899,10 @@ class panel {
* @return {bool} Статус выполнения
*/
return function (group) {
if (typeof id === 'string' && typeof icon === 'string' && typeof core === 'object' && typeof group === 'string') {
if (typeof id === 'string' && typeof icon === 'string' && typeof group === 'string') {
// Пройдена проверка входных параметров
return core.blocks.fields.macroses.row(group, icon,
return panel.blocks.fields.macroses.row(group, icon,
function (status, body, wrap, separator) {
wrap.addEventListener("input", fn => {
// Инициализация поля ввода
@@ -759,8 +941,7 @@ class panel {
button.setAttribute('onclick', 'return Privacy.show(this, event, \'mail\');' + typeof onclick === 'string' ? ' ' + onclick : '');
// Инициализация элемента-списка
const dropdown = core.blocks.fields.macroses.dropdown();
const dropdown = panel.blocks.fields.macroses.dropdown();
// Инициализация архитектуры
separator.appendChild(button);