Шрифт в постах

Стиль оформления

Тема

Дополнительно

Размер элементов форума
вверх
вниз

Shadows of Old

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » Shadows of Old » Организационный раздел » Полезные материалы


Полезные материалы

Сообщений 1 страница 2 из 2

1

Тема предназначена, чтобы делиться материалами, кодами и шаблонами, полезными для игры и её организации.
Также здесь можно попросить создать некий шаблон или задать вопрос по их созданию.

+3

2

Генератор кода для акций

Рекомендации по использованию
Вы могли заметить, что в нужных внутри сообщений со временем добавляется блок blockhidden, внутри которого находится техническая информация. Она нужна, чтобы работал автосбор акций в шапку темы, и заполняет этот блок администрация.

Если взять в спойлер информацию из blockhidden (как обычно делается, когда его бронируют), то можно удалить персонажа из шапки темы.

Если хочется поменять теги, расставленные администрацией, или задать другое описание, вы можете это сделать благодаря этому генератору.

[html]

<script>
// --------- СОСТОЯНИЕ DOM ------------

let iframeDomReady = document.readyState !== 'loading';

document.addEventListener('DOMContentLoaded', function () {
    iframeDomReady = true;
    initializeIframeForm();
});

// --------- input data ------------
const Gender = {
    Male: { id: 'Male', name: 'Мужской' },
    Female: { id: 'Female', name: 'Женский' }
};

const Activity = {
    Politics: { id: 'Politics', name: 'Политики' },
    Warrior: { id: 'Warrior', name: 'Воины' },
    Gods: { id: 'Gods', name: 'Служители богов' },
    Wizard: { id: 'Wizard', name: 'Маги' },
    Kale: { id: 'Kale', name: 'Кале' },
    Criminal: { id: 'Criminal', name: 'Криминал' },
};
const Race = {
    Human: { id: 'Human', name: 'Люди' },
    Vampire: { id: 'Vampire', name: 'Вампиры' },
    Soulless: { id: 'Soulless', name: 'Бездушники' },
    Aire: { id: 'Aire', name: 'Айре' },
    Werewolf: { id: 'Werewolf', name: 'Перевертыши' },
    Beastman: { id: 'Beastman', name: 'Зверолюди' },
};
const Aim = {
    Family: { id: 'Family', name: 'Семья' },
    Love: { id: 'Love', name: 'Пара' },
    Friend: { id: 'Friend', name: 'Дружба' },
    Enemy: { id: 'Enemy', name: 'Враги' },
    Worker: { id: 'Worker', name: 'Подчиненные' },
    Plot: { id: 'Plot', name: 'Сюжет' }
};

// --------- fill containers ------------
function checkbox(text, id, name, isChecked = '') {
    return `<label class="tag"><input type="checkbox" id="${id}" name="${name}" ${isChecked} /> <span>${text}</span></label>`;
}

function radiobox(text, id, name) {
    return `<label class="tag"><input type="radio" id="${id}" name="${name}" /> <span>${text}</span></label>`;
}

function fillContainers() {
    const cont = {
        activity: document.querySelector('.activityContainer'),
        race: document.querySelector('.raceContainer'),
        gender: document.querySelector('.genderContainer'),
        aim: document.querySelector('.aimContainer')
    };

    if (!cont.gender || !cont.aim || !cont.activity || !cont.race) return;

    cont.gender.innerHTML = Object.values(Gender).map(gender => radiobox(gender.name, gender.id, 'gender')).join('');
    cont.aim.innerHTML = Object.values(Aim).map(aim => checkbox(aim.name, aim.id, 'aim')).join('');
    cont.activity.innerHTML = Object.values(Activity).map(activity => checkbox(activity.name, activity.id, 'activity')).join('');
    cont.race.innerHTML = Object.values(Race).map(race => checkbox(race.name, race.id, 'race')).join('');
}

// --------- ORIGIN CHECK ------------

function isAllowedParentOrigin(origin) {
    return /^https?:\/\/oldshadows\.rusff\.me(?::\d+)?$/.test(origin);
}

// --------- COPY RESULTS ------------

function copyResults() {
    let copyContent = '';

    const cyrillicNameField = document.getElementById('cyrillicName');
    const cyrillicDescrField = document.getElementById('cyrillicDescr');

    const cyrillicName = cyrillicNameField ? cyrillicNameField.value : '';
    const cyrillicDescr = cyrillicDescrField ? cyrillicDescrField.value : '';

    const hasRoleTags = Array.from(document.getElementsByName('gender')).some(el => el.checked) ||
                       Array.from(document.getElementsByName('aim')).some(el => el.checked) ||
                       Array.from(document.getElementsByName('activity')).some(el => el.checked) ||
                       Array.from(document.getElementsByName('race')).some(el => el.checked);

    if (hasRoleTags) {
        const currentName = cyrillicName || 'Имя персонажа';
        const currentDescr = cyrillicDescr || 'Описание персонажа';
        const gendersTags = Array.from(document.getElementsByName('gender'));
        const aimTags = Array.from(document.getElementsByName('aim'));
        const activityTags = Array.from(document.getElementsByName('activity'));
        const raceTags = Array.from(document.getElementsByName('race'));
        const allTags = gendersTags.concat(aimTags, activityTags, raceTags);
        const selectedTags = allTags
            .filter(element => element.checked)
            .map(element => element.id);

        // JSON.stringify сам корректно экранирует кавычки, переносы строк и
        // спецсимволы в name/descr — раньше здесь была ручная сборка строки
        // шаблонным литералом, и значение поля "Краткое описание" могло
        // содержать кавычку, закрывающую строку раньше времени, и вставить
        // ВТОРОЙ ключ "tags" в объект. При JSON.parse дублирующийся ключ,
        // идущий позже, перезаписывает предыдущий — то есть пользователь
        // мог подменить себе теги на произвольные, в обход чекбоксов.
        const rolesForm = JSON.stringify({
            name: currentName,
            tags: selectedTags,
            descr: currentDescr
        });

        copyContent += `${String.fromCharCode(91)}blockHidden${String.fromCharCode(93)}${rolesForm}${String.fromCharCode(91)}/blockHidden${String.fromCharCode(93)}`;
    }

    window.parent.postMessage({
        eventName: 'profileCopyInfoRequest',
        copyData: copyContent.trim()
    }, '*');
}

// --------- STYLE AND FONT ------------

let initialStyleReceived = false;
let receivedTheme = 'pink';
let styleRequestInterval = null;
let styleRequestTimeout = null;

function applyIframeStyle(style, theme) {
    let appliedStyle = style;

    if (style === 'system') {
        appliedStyle = window
            .matchMedia('(prefers-color-scheme: dark)')
            .matches
            ? 'dark'
            : 'light';
    }

    if (appliedStyle !== 'dark') {
        appliedStyle = 'light';
    }

    if (typeof theme === 'string' && theme) {
        receivedTheme = theme;
    }

    document.body.classList.remove('light', 'dark');
    document.body.classList.add(appliedStyle);

    document.body.classList.remove('pink', 'green');
    document.body.classList.add(receivedTheme);
}

function applyIframeFont(data) {
    const fontSize = Number(data.fontsize) || 12;
    const fontFamily = data.fontfam || '0';
    const allFontSize = Number(data.allFontSize) || 12;

    document.documentElement.style.setProperty(
        '--iframe-post-font-size',
        fontSize + 'px'
    );

    document.documentElement.style.setProperty(
        '--iframe-all-font-size',
        allFontSize + 'px'
    );

    document
        .querySelectorAll(
            '.post-content p, ' +
            '.post-content div, ' +
            '.instructionBlock'
        )
        .forEach(function (element) {
            element.style.fontSize = fontSize + 'px';
        });

    document
        .querySelectorAll('.post-content p')
        .forEach(function (element) {
            if (fontFamily !== '0') {
                element.style.fontFamily = fontFamily;
            } else {
                element.style.removeProperty('font-family');
            }
        });
}

function requestParentStyle() {
    window.parent.postMessage({
        eventName: 'askStyle'
    }, '*');
}

function stopStyleRequesting() {
    if (styleRequestInterval) {
        clearInterval(styleRequestInterval);
        styleRequestInterval = null;
    }

    if (styleRequestTimeout) {
        clearTimeout(styleRequestTimeout);
        styleRequestTimeout = null;
    }
}

function startStyleRequesting() {
    stopStyleRequesting();

    requestParentStyle();

    styleRequestInterval = setInterval(function () {
        if (initialStyleReceived) {
            stopStyleRequesting();
            return;
        }

        requestParentStyle();
    }, 300);

    styleRequestTimeout = setTimeout(function () {
        stopStyleRequesting();
    }, 10000);
}

// --------- MESSAGES FROM PARENT ------------

window.addEventListener('message', function (event) {
    if (!isAllowedParentOrigin(event.origin)) return;
    if (!event.data || typeof event.data !== 'object') return;

    switch (event.data.eventName) {
        case 'styleChange':
            initialStyleReceived = true;
            applyIframeStyle(event.data.style, event.data.theme);
            stopStyleRequesting();
            break;

        case 'fontChange':
            applyIframeFont(event.data);
            break;
    }
});

// --------- INITIALIZATION ------------

function initializeIframeForm() {
    fillContainers();

    const resultButton = document.getElementById('instructionResult');

    if (resultButton) {
        resultButton.addEventListener('click', copyResults);
    }

    startStyleRequesting();
}

if (iframeDomReady) {
    initializeIframeForm();
}
</script>

<div class="instructionBlock listsInstruction" id="mainUserList">
<h2 class="instructionHeading">Скопировать шаблон</h2>
<label for="cyrillicName" class="labelDescr">Имя на кириллице:</label>
<input type="text" id="cyrillicName" name="cyrillicName">
<label for="cyrillicDescr" class="labelDescr">Краткое описание:</label>
<input type="text" id="cyrillicDescr" name="cyrillicDescr">

<br><br>
<h2 class="instructionHeading">Теги</h2>
<span class="labelDescr">Выберите теги, которые характеризуют вашу заявку:</span>

<span class="labelDescr">Пол:</span>
<div class="genderContainer"></div>

<span class="labelDescr">Деятельности:</span>
<div class="activityContainer"></div>

<span class="labelDescr">Расы:</span>
<div class="raceContainer"></div>

<span class="labelDescr">Цель заявки:</span>
<div class="aimContainer"></div>
</div>

<div class="formButtons">
<input type="button" id="instructionResult" value="Скопировать код">
</div>

<style>
h2.instructionHeading {
    font-size: 16px;
    font-family: 'Palatino Linotype';
    font-weight: bold;
    letter-spacing: 1px;
}

.labelDescr {
    display: block;
    margin: 9px 0px 1px 0px;
}

.instructionBlock {
    text-align: left;
    margin: 10px 0 !important;
    padding: 14px 14px 12px 14px !important;
    border: 1px solid var(--borders);
    background: var(--beg300);
    border-radius: 4px;
}

.instructionBlock input[type="text"] {
    width: calc(100% - 10px);
}

label.hrAdd, label.npcDead {
    margin: 10px 0 0 0;
    display: block;
}

input#hrAdd, input.npcDead  {
    accent-color: var(--text2);
}

input#listsDescr {
    margin-bottom: 16px;
}

label.tag {
    border-radius: 16px;
    border: 1px solid var(--borders);
    background: var(--beg300);
    padding: 4px 8px;
    display: inline-block;
    margin: 0px 4px 5px 0px;
}

label.tag:has(input:checked) {
    background: var(--borders);
    color: #fff;
}

.tag input[type="checkbox"], .tag input[type="radio"] {
    display: none;
}

label.tag {
    cursor: pointer;
}
</style>[/html]

+4


Вы здесь » Shadows of Old » Организационный раздел » Полезные материалы