NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name CatWar Mod // @name:ru Варомод // @namespace https://catwar.su/blog482084 // @version 2.3.4 // @description Полезные дополнения для catwar.su // @author Fredo14 // @copyright 2019—2020, Хвойница (https://catwar.su/cat209467) // @updateURL https://openuserjs.org/meta/Fredo14/CatWar_Mod.meta.js // @license MIT; https://opensource.org/licenses/MIT // @match https://*.catwar.su/* // @grant none // ==/UserScript== (function (window, document, $) { 'use strict'; if (typeof $ === 'undefined') return; const CONF_BLOGS_TAGS_OPEN = 'blogs_tags_open'; const CONF_SNIFF_TAGS1_OPEN = 'sniff_tags1_open'; const CONF_SNIFF_TAGS2_OPEN = 'sniff_tags2_open'; const CONF_LS_LAST_SEARCH = 'ls_last_search'; const CONF_LS_ENABLE_SAVING = 'ls_enable_saving'; const CONF_BLOGS_ANSWER_BUTTON = 'blogs_answer_btn'; const CONF_BLOGS_CITE_BUTTON = 'blogs_cite_btn'; const CONF_BLOGS_CITE_BUTTON_HIDE = 'blogs_cite_btn_hide'; const CONF_BLOGS_COMMENTS_SMILES = 'blogs_comments_smiles'; const CONF_BLOGS_AVATARS = 'blogs_avatars'; const CONF_BLOGS_AVATARS_SIZE = 'blogs_avatars_size'; const CONF_BLOGS_AVATARS_BORDER = 'blogs_avatars_border'; const CONF_BLOGS_AVATARS_NO_CROP = 'blogs_avatars_no_crop'; const CONF_BLOGS_IMAGES_MAX_WIDTH = 'blogs_img_width'; const CONF_SNIFF_IMAGES_MAX_WIDTH = 'sniff_img_width'; const CONF_INDEX_SAVE_ALERT = 'index_save_alert'; const CONF_CREATION_SAVE_ALERT = 'creation_save_alert'; const CONF_KNS_SAVE_ALERT = 'kns_save_alert'; const CONF_INDEX_EDUCATION_HIDE = 'index_education_hide'; const CONF_SETTINGS_HIDE_EMAIL = 'settings_hide_email'; const CONF_CAT_ADD_KRAFT_NUMBER = 'cat_add_kraft_number'; const CONF_CAT_ENABLE_NOTES = 'cat_enable_notes'; const CONF_FAE_SHOW_NOTES = 'fae_show_notes'; const CONF_CW3_ACT_END_IN_TITLE = 'cw3_act_end_in_title'; const CONF_CW3_ACT_END_ALERT = 'cw3_act_end_alert'; const CONF_CW3_ACT_END_ALERT_SOUND = 'cw3_act_end_alert_sound'; const CONF_CW3_ACT_END_ALERT_VOLUME = 'cw3_act_end_alert_volume'; const CONF_CW3_ACT_END_ALERT_TIME = 'cw3_act_end_alert_time'; const CONF_CW3_ACT_END_ALERT_BLUR_ONLY = 'cw3_act_end_blur_only'; const CONF_CW3_FIGHT_PANEL_HEIGHT = 'cw3_fight_panel_height'; const CONF_CW3_THEME = 'cw3_theme'; const CONF_CW3_COMPACT = 'cw3_compact'; const CONF_CW3_COMPACT_SWAP_SIDES = 'cw3_compact_swap_sides'; const CONF_CW3_COMPACT_CHAT_ON_TOP = 'cw3_compact_chat_on_top'; const CONF_CW3_COMPACT_ROUND_EDGES = 'cw3_compact_round_edges'; const CONF_CW3_COMPACT_SPLIT_INFO = 'cw3_compact_split_info'; const CONF_CW3_COMPACT_HIDE_HEADERS = 'cw3_compact_hide_headers'; const CONF_CW3_COMPACT_SPLIT_INFO_STICKY_HEADERS = 'cw3_compact_split_info_sticky_headers'; const CONF_CW3_BACKGROUND = 'cw3_bg'; const CONF_CW3_BACKGROUND_IMAGE = 'cw3_bg_image'; const CONF_CW3_BACKGROUND_SIZE = 'cw3_bg_size'; const CONF_CW3_BACKGROUND_POSITION = 'cw3_bg_position'; const CONF_CW3_WEATHER_SNOW = 'cw3_weather_snow'; const CONF_CW3_HIDE_SKY = 'cw3_hide_sky'; const CONF_CW3_CAGES_BORDERS = 'cw3_cages_borders'; const CONF_CW3_CHAT_LOUD_QUIETER = 'cw3_chat_loud_quieter'; const CONF_CW3_CHAT_QUIET_LOUDER = 'cw3_chat_quiet_louder'; const CONF_CW3_LOWER_CATS = 'cw3_lower_cats'; const CONF_CW3_LOWER_ARROWS = 'cw3_lower_arrows'; const CONF_CW3_DEAD_OPAQUE = 'cw3_dead_opaque'; const CONF_CW3_ADD_REALISM = 'cw3_add_realism'; const CONF_CW3_ALWAYS_DAY = 'cw3_always_day'; const CONF_CW3_MENU_TARGET_BLANK = 'cw3_menu_blank'; const CONF_CW3_MENU_ABOUT = 'cw3_menu_about'; const CONF_CW3_MENU_INDEX = 'cw3_menu_index'; const CONF_CW3_MENU_TOP = 'cw3_menu_top'; const CONF_CW3_MENU_CHAT = 'cw3_menu_chat'; const CONF_CW3_MENU_LS = 'cw3_menu_ls'; const CONF_CW3_MENU_LS0 = 'cw3_menu_ls0'; const CONF_CW3_MENU_BLOGS = 'cw3_menu_blogs'; const CONF_CW3_MENU_SNIFF = 'cw3_menu_sniff'; const CONF_CW3_MENU_SETTINGS = 'cw3_menu_settings'; const CONF_CW3_MENU_MOBILE = 'cw3_menu_mobile'; const CONF_CW3_HISTORY_NO_UNDERLINE = 'cw3_history_no_underline'; const CONF_CW3_CAT_INFO = 'cw3_cat_info'; const CONF_CW3_MODIFY_INVENTORY = 'cw3_modify_inventory'; const CONF_CW3_PARAMETERS_INFO = 'cw3_parameters_info'; const DEFAULTS = {}; DEFAULTS[CONF_BLOGS_TAGS_OPEN] = false; DEFAULTS[CONF_SNIFF_TAGS1_OPEN] = false; DEFAULTS[CONF_SNIFF_TAGS2_OPEN] = false; DEFAULTS[CONF_LS_LAST_SEARCH] = { folder: 0, type: 1 }; DEFAULTS[CONF_LS_ENABLE_SAVING] = true; DEFAULTS[CONF_INDEX_SAVE_ALERT] = false; DEFAULTS[CONF_INDEX_EDUCATION_HIDE] = false; DEFAULTS[CONF_CAT_ADD_KRAFT_NUMBER] = false; DEFAULTS[CONF_CAT_ENABLE_NOTES] = true; DEFAULTS[CONF_FAE_SHOW_NOTES] = true; DEFAULTS[CONF_BLOGS_ANSWER_BUTTON] = true; DEFAULTS[CONF_BLOGS_CITE_BUTTON] = true; DEFAULTS[CONF_BLOGS_CITE_BUTTON_HIDE] = false; DEFAULTS[CONF_BLOGS_COMMENTS_SMILES] = false; DEFAULTS[CONF_BLOGS_AVATARS] = false; DEFAULTS[CONF_BLOGS_AVATARS_SIZE] = 100; DEFAULTS[CONF_BLOGS_AVATARS_BORDER] = true; DEFAULTS[CONF_BLOGS_AVATARS_NO_CROP] = false; DEFAULTS[CONF_BLOGS_IMAGES_MAX_WIDTH] = 0; DEFAULTS[CONF_SNIFF_IMAGES_MAX_WIDTH] = 0; DEFAULTS[CONF_CREATION_SAVE_ALERT] = false; DEFAULTS[CONF_KNS_SAVE_ALERT] = false; DEFAULTS[CONF_SETTINGS_HIDE_EMAIL] = false; DEFAULTS[CONF_CW3_ACT_END_IN_TITLE] = false; DEFAULTS[CONF_CW3_ACT_END_ALERT] = false; DEFAULTS[CONF_CW3_ACT_END_ALERT_SOUND] = 'https://porch.website/cwmod/ding.mp3'; DEFAULTS[CONF_CW3_ACT_END_ALERT_VOLUME] = 1; DEFAULTS[CONF_CW3_ACT_END_ALERT_TIME] = 1; DEFAULTS[CONF_CW3_ACT_END_ALERT_BLUR_ONLY] = false; DEFAULTS[CONF_CW3_FIGHT_PANEL_HEIGHT] = 70; DEFAULTS[CONF_CW3_THEME] = 'default'; DEFAULTS[CONF_CW3_COMPACT] = false; DEFAULTS[CONF_CW3_COMPACT_SWAP_SIDES] = false; DEFAULTS[CONF_CW3_COMPACT_CHAT_ON_TOP] = true; DEFAULTS[CONF_CW3_COMPACT_ROUND_EDGES] = false; DEFAULTS[CONF_CW3_COMPACT_HIDE_HEADERS] = false; DEFAULTS[CONF_CW3_COMPACT_SPLIT_INFO] = true; DEFAULTS[CONF_CW3_COMPACT_SPLIT_INFO_STICKY_HEADERS] = true; DEFAULTS[CONF_CW3_BACKGROUND] = 'default'; DEFAULTS[CONF_CW3_BACKGROUND_IMAGE] = '/cw3/sky/1.png'; DEFAULTS[CONF_CW3_BACKGROUND_SIZE] = 'auto'; DEFAULTS[CONF_CW3_BACKGROUND_POSITION] = 'top left'; DEFAULTS[CONF_CW3_WEATHER_SNOW] = false; DEFAULTS[CONF_CW3_HIDE_SKY] = false; DEFAULTS[CONF_CW3_CAGES_BORDERS] = false; DEFAULTS[CONF_CW3_CHAT_LOUD_QUIETER] = false; DEFAULTS[CONF_CW3_CHAT_QUIET_LOUDER] = false; DEFAULTS[CONF_CW3_LOWER_CATS] = false; DEFAULTS[CONF_CW3_LOWER_ARROWS] = true; DEFAULTS[CONF_CW3_DEAD_OPAQUE] = false; DEFAULTS[CONF_CW3_ADD_REALISM] = false; DEFAULTS[CONF_CW3_ALWAYS_DAY] = false; DEFAULTS[CONF_CW3_HISTORY_NO_UNDERLINE] = false; DEFAULTS[CONF_CW3_CAT_INFO] = false; DEFAULTS[CONF_CW3_MODIFY_INVENTORY] = false; DEFAULTS[CONF_CW3_PARAMETERS_INFO] = true; DEFAULTS[CONF_CW3_MENU_TARGET_BLANK] = false; DEFAULTS[CONF_CW3_MENU_ABOUT] = false; DEFAULTS[CONF_CW3_MENU_INDEX] = true; DEFAULTS[CONF_CW3_MENU_TOP] = false; DEFAULTS[CONF_CW3_MENU_CHAT] = true; DEFAULTS[CONF_CW3_MENU_LS] = true; DEFAULTS[CONF_CW3_MENU_LS0] = false; DEFAULTS[CONF_CW3_MENU_BLOGS] = false; DEFAULTS[CONF_CW3_MENU_SNIFF] = false; DEFAULTS[CONF_CW3_MENU_SETTINGS] = true; DEFAULTS[CONF_CW3_MENU_MOBILE] = false; let SETTINGS = {}; let thisPageSettings = []; const months = ['января', 'февраля', 'марта', 'апреля', 'мая', 'июня', 'июля', 'августа', 'сентября', 'октября', 'ноября', 'декабря']; const catTimeStart = 1200000000000; const MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver; const isDesctop = isPage(/cw3\/(?!(kns|jagd))/) ? ($('#app').data('mobile') === 0) : ($('#branch').length); if (!Date.prototype.toISOStringLocal) { Date.prototype.toISOStringLocal = function () { const d = new Date(+this); let offset = d.getTimezoneOffset(); const sign = offset < 0 ? '+' : '-'; d.setUTCMinutes(d.getUTCMinutes() - d.getTimezoneOffset()); offset = ('0' + (offset / 60 | 0)).slice(-2) + ('0' + (offset % 60)).slice(-2); return d.toISOString().replace(/Z\s*/i, '') + sign + offset; }; } try { updateStorage(); loadSettings(); changeAllPages(); if (isPage(/cw3\/(?!(kns|jagd))/)) { changeCW3Page(); } else if (isPage('cw3/kns')) { changeKnsPage(); } else { if ((isPage('', true) || isPage('index')) && $('#act_name b').length) { changeIndexPage(); } else if (isPage(/cat(\d+|\/.+)/)) changeCatPage(); else if (isPage('fae')) changeFaePage(); else if (isPage('chat')) changeChatPage(); else if (isPage('ls')) changeLsPage(); else if (isPage('ideas', true)) changeIdeasPage(); else if (isPage(/blog(?!sea)/) || isPage('sniff') || isPage('idea')) { changeAllBlogsPages(); } else if (isPage('settings', true)) changeSettingsPage(); } } catch (err) { window.console.error('Варомод:', err); } function updateStorage() { Object.keys(window.localStorage).forEach(function (key) { const savedNotes = JSON.parse(window.localStorage.getItem('cwmod_notes') || '{}'); if (/^cwm_settings/.test(key)) delete window.localStorage[key]; if (/^cwm_note/.test(key)) { const catId = getNumber(key); savedNotes[catId] = window.localStorage[key]; saveData('notes', savedNotes); delete window.localStorage[key]; } if (key === 'cwm_saved_chat') { saveData('saved_chat', window.localStorage[key]); delete window.localStorage[key]; } }); } function changeAllPages() { const white = $('body > span').first(); if (white.length) { white.children('a').css('color', ''); white.css('background-color', $('#site_table').css('background-color')); } const footer = $('#footer'); if (footer.length) { const oldFooter = footer.html().split('<br>©'); footer.html(oldFooter[0] + ` | <a target="_blank" href="/settings#cwmod">Настройки</a><br>©` + oldFooter[1]); } let css = ` #cwmod-popup-wrap { position: fixed; left: 0; top: 0; z-index: 2; width: 100%; height: 100%; display: none; justify-content: center; align-items: center; background-color: rgba(0, 0, 0, 0.5); } #cwmod-popup { display: grid; grid-gap: 1em; max-height: 50vh; width: 300px; padding: 1em; background: white; color: black; border: 1px solid black; } .cwmod-popup-btn:hover { text-decoration: none; } .cwmod-popup-btn { display: none; text-align: center; color: #000033; text-decoration: underline; cursor: pointer; } #cwmod-popup-reload { grid-area: reload; } #cwmod-popup-cancel { grid-area: cancel; } #cwmod-popup-hide { grid-area: hide; } #cwmod-popup-text { grid-area: text; } #cwmod-popup-text a { color: #123; } #cwmod-popup-text a:hover { color: #246; } .reload #cwmod-popup { grid-template-areas: 'text text' 'reload cancel'; } .reload #cwmod-popup-reload, .reload #cwmod-popup-cancel { display: block; } .alert #cwmod-popup { grid-template-areas: 'text' 'hide'; } .alert #cwmod-popup-hide { display: block; } .usn { user-select: none; } .fs0 { font-size: 0; } `; addCSS(css); const body = $('body'); body.append(` <div class="reload" id="cwmod-popup-wrap"> <div id="cwmod-popup"> <div id="cwmod-popup-text"></div> <div class="cwmod-popup-btn" id="cwmod-popup-reload" onclick="window.location.reload()">Обновить</div> <div class="cwmod-popup-btn" id="cwmod-popup-cancel" onclick="$('#cwmod-popup-wrap').hide()">Позже</div> <div class="cwmod-popup-btn" id="cwmod-popup-hide" onclick="$('#cwmod-popup-wrap').hide()">Скрыть</div> </div> </div> `); $(window).on('storage', function (e) { if (e.originalEvent.key === 'cwmod_settings') { const oldValue = JSON.parse(e.originalEvent.oldValue); const newValue = JSON.parse(e.originalEvent.newValue); Object.keys(newValue).forEach(function (key) { if (thisPageSettings.indexOf(key) !== -1) { if (oldValue[key] !== newValue[key]) { let text = 'Настройки Варомода для этой страницы были изменены. Обновить страницу прямо сейчас, чтобы применить их?'; showCwmodPopup('reload', text); } } }); } }); body.on('click', 'summary.cwmod-settings', function () { const th = $(this); const key = th.data('conf'); setSettings(key, !th.parent().is('[open]')); }); body.on('change', 'select.cwmod-settings', function () { const th = $(this); const key = th.data('conf'); let val = th.val(); if (/^\d+$/.test(val)) val = Number(val); setSettings(key, val); $(`[data-show="${key}"]`).each(function () { let cond = $(this).data('cond'); const invert = /^!/.test(cond); cond = cond.replace(/^!/, ''); if (invert !== (cond === val)) $(this).show(); else $(this).hide(); }); }); body.on('change', 'input.cwmod-settings', function () { const th = $(this); const key = th.data('conf'); const type = th.attr('type'); let val; if (type === 'checkbox') { val = th.is(':checked'); setSettings(key, val); if (val) $(`[data-show="${key}"]`).show(); else $(`[data-show="${key}"]`).hide(); } else if (type === 'range') { val = th.val(); setSettings(key, val); } }); body.on('input', 'input.cwmod-settings', function () { const th = $(this); const key = th.data('conf'); const type = th.attr('type'); if (type === 'number') { if (th.val()) setSettings(key, Number(th.val())); } else if (type === 'text') { if (th.val()) setSettings(key, th.val()); } }); body.on('click', '.cwmod-settings-set-default', function (e) { e.preventDefault(); const th = $(this); const key = th.data('rel'); const val = DEFAULTS[key]; const input = $(`[data-conf="${key}"]`); if (input.attr('type') === 'text') input.val(val); setSettings(key, val); }); body.on('click', '.cwmod-settings-test-sound', function (e) { e.preventDefault(); const th = $(this); const audio = new Audio(); const volume = $(`[data-conf="${th.data('volume')}"]`).val(); audio.src = getSettings(th.data('audio')); audio.volume = volume; audio.pause(); audio.currentTime = 0; audio.play(); }); } function showCwmodPopup(type, text) { $('#cwmod-popup-wrap').removeClass().addClass(type); $('#cwmod-popup-text').html(text); if ($('#cwmod-popup-wrap').css('display') === 'none') { $('#cwmod-popup-wrap').css('display', 'flex'); } } function moonCalc() { if (!$('#info').length) return; addCSS(`.calc-error { color: darkred; }`); $('#info').after('<div id="calc-age"></div>'); const infoObserver = new MutationObserver(function (mutations) { mutations.forEach(function () { const infoText = $('#info').text(); if (!infoText.match('Дата')) { $('#calc-age').empty(); return; } const birthDateString = infoText.match(/\d{4}-\d\d-\d\d \d\d:\d\d/)[0].replace(' ', 'T'); const nowDateString = dateToString(new Date); const moonsNow = getMoonsFromDate(birthDateString, nowDateString); let bornWord; const sex = $('[src^="//e.catwar.su/avatar"]').first()[0].style.borderColor; const isRegDate = (/регистрац/.test(infoText) && $('#age2_icon').length); switch (sex) { case 'pink': bornWord = isRegDate ? 'Зарегистрировалась' : 'Родилась'; break; case 'blue': bornWord = isRegDate ? 'Зарегистрировался' : 'Родилcя'; break; default: bornWord = isRegDate ? 'Зарегистрировалось' : 'Родилoсь'; } const catTime = timestampToCatTime(Date.parse(birthDateString)); const catTimeString = `${catTime.day} ${months[catTime.month]} ${catTime.year} года в ${leadingZero(catTime.hour)}:${leadingZero(catTime.minute)}`; $('#calc-age').html(` <p><b>Калькулятор возраста</b></p> <label>Дата и время: <input type="datetime-local" id="calc-date" min="${birthDateString}" value="${nowDateString}" max="9999-31-12T23:59"></label> <span id="calc-error-date" class="calc-error"></span> <br><label>Возраст: <input type="number" id="calc-moons" min="0" step="0.1" value=${moonsNow} style="width: 60px"></label> <span id="moon-word">лун</span> <span id="calc-error-moons" class="calc-error"></span> <br>${bornWord} ${catTimeString} по кошачьему времени. <br><br> `); updateMoonWord(moonsNow); $('#calc-date').on('input', function () { $('#calc-error-date').empty(); const dateString = $('#calc-date').val(); const date = Date.parse(dateString); if (isNaN(date)) { if (dateString.length) $('#calc-error-date').html('Ошибка!'); return; } if (date < Date.parse(birthDateString)) { $('#calc-error-date').html('Ошибка!'); return; } const moons = getMoonsFromDate(birthDateString, dateString); $('#calc-moons').val(moons); updateMoonWord(moons); }); $('#calc-moons').on('input', function () { $('#calc-error-moons').empty(); const moons = Number($('#calc-moons').val()); if (moons < 0 || isNaN(moons)) { $('#calc-error-moons').html('Ошибка!'); return; } $('#calc-date').val(getDateStringFromMoons(birthDateString, moons)); updateMoonWord(moons); }); }); }); infoObserver.observe(document.querySelector('#info'), { childList: true }); } function updateMoonWord(moons) { $('#moon-word').html(declOfNum(moons, ['луна', 'луны', 'лун'])); } function getMoonsFromDate(birthDateString, dateString) { const birthday = Date.parse(birthDateString); const date = Date.parse(dateString); const moons = Math.floor(convertTime('ms d', date - birthday) / 4 * 10) / 10; return moons; } function getDateStringFromMoons(birthDateString, moons) { const birthday = Date.parse(birthDateString); const age = Math.round(convertTime('d ms', moons * 4)); return dateToString(birthday + age); } function changeAllBlogsPages() { addBBcode(1); let css = ` .poll-hasAnswered1 { color: black; } .tags-list { margin: 0; } .tags-list > li { list-style-type: circle; } #add-tags p, #add-tags li { line-height: 1.4em; } .add-tag { padding: 1px 5px; background-color: rgba(255, 255, 255, 0.8); color: black; border-radius: 1rem; white-space: nowrap; cursor: pointer; } .add-tag::before { content: '+ '; color: #888; } #search > p { margin-top: 0.5em; } .comment-answer, .comment-cite { display: inline-block; margin-top: 5px; } `; if (getSettings(CONF_BLOGS_CITE_BUTTON_HIDE)) { css += `.comment-cite-wrap { display: none; }`; } if (isPage('blog')) { if (getSettings(CONF_BLOGS_IMAGES_MAX_WIDTH)) { css += `img {max-width: ${getSettings(CONF_BLOGS_IMAGES_MAX_WIDTH)}px}`; } } if (isPage('sniff')) { if (getSettings(CONF_SNIFF_IMAGES_MAX_WIDTH)) { css += `img {max-width: ${getSettings(CONF_SNIFF_IMAGES_MAX_WIDTH)}px}`; } } if (getSettings(CONF_BLOGS_AVATARS)) { const width = getSettings(CONF_BLOGS_AVATARS_SIZE); const border = getSettings(CONF_BLOGS_AVATARS_BORDER); const size = getSettings(CONF_BLOGS_AVATARS_NO_CROP) ? 'contain' : 'cover'; css += ` .comment-avatar { grid-area: avatar; display: block; width: ${width}px; height: ${width}px; ${border ? 'border: 1px solid black;' : ''} background-size: ${size}; background-repeat: no-repeat; background-position: center; } .comment-info { grid-area: info; } .comment-info + p { grid-area: p; } .comment-text { grid-area: text; } .comment-answer-buttons { grid-area: btns; } .view-comment { display: grid; grid-template-areas: 'avatar info' 'avatar p' 'avatar text' 'btns btns'; grid-template-columns: ${width + 2 * border}px auto;/*я пожалею об этом*/ grid-column-gap: 10px; } `; } addCSS(css); changeMainPage(); changeViewPage(); if (isPage('blogs?creation') || isPage('sniff?creation')) { changeCreationPage(); } const viewObserver = new MutationObserver(function (mutations) { mutations.forEach(function () { if ($('#view').css('display') === 'none') { hideCommentPreview(); } }); }); const creationObserver = new MutationObserver(function (mutations) { mutations.forEach(function () { if ($('#creation').css('display') === 'none') { window.removeEventListener('beforeunload', beforeunload); } else { changeCreationPage(); } }); }); viewObserver.observe($('#view')[0], { attributes: true }); creationObserver.observe($('#creation')[0], { attributes: true }); } function changeMainPage() { $('#search > form > input[type="text"]').attr('placeholder', 'Поиск по ключевым словам'); $('#search').append(`<p><input id="search_tag" type="text" size="35" placeholder="Поиск по тегу"> <input id="search-ok" type="button" value="Искать"></p>`); $('#search-ok').click(function () { searchByTag($('#search_tag').val()); }); $('#search_tag').keypress(function (e) { if (e.which == 13) { searchByTag($('#search_tag').val()); return false; } }); } function changeViewPage() { const p = $('#send_comment_form > p:last-child'); p.prepend(`<input type="button" id="comment-preview" value="Предпросмотр"> `); $('#send_comment_form').after(` <p id="comment-preview-hide" style="display: none; margin: 0.5em 0;"><a href="#">Скрыть предпросмотр</a></p> <div id="comment-preview-div" style="display :none"></div> `); const WS = io.connect(window.location.origin, { path: '/ws/blogs/socket.io', reconnectionDelay: 10000, reconnectionDelayMax: 20000 }); WS.on('creation preview', function (data) { $('#comment-preview-div').html(data).show(); $('#comment-preview-hide').show(); }); $('#comment-preview').click(function () { WS.emit("creation preview", $('#comment').val()); }); $('#send_comment_form [type="submit"]').click(hideCommentPreview); $('#comment-preview-hide').click(function (e) { e.preventDefault(); hideCommentPreview(); }); if (getSettings(CONF_BLOGS_COMMENTS_SMILES)) { p.append(` <img src="smile/1.png" class="sticker" data-code=":sm1:"> <img src="smile/2.png" class="sticker" data-code=":sm2:"> <img src="smile/3.png" class="sticker" data-code=":sm3:"> <img src="smile/4.png" class="sticker" data-code=":sm4:"> <img src="smile/5.png" class="sticker" data-code=":sm5:"> <img src="smile/6.png" class="sticker" data-code=":sm6:"> <img src="smile/7.png" class="sticker" data-code=":sm7:"> <img src="smile/8.png" class="sticker" data-code=":sm8:"> <img src="smile/9.png" class="sticker" data-code=":sm9:"> <img src="smile/10.png" class="sticker" data-code=":sm10:"> `); } if ($('#comment').length) { const commentObserver = new MutationObserver(function (mutations) { mutations.forEach(changeComments); }); commentObserver.observe(document.querySelector('#view_comments'), { childList: true }); } let selectionInfo = {}; $('#view_comments').on('mouseup touchend', function () { if (getSettings(CONF_BLOGS_CITE_BUTTON_HIDE)) $('.comment-cite-wrap').hide(); const sel = window.getSelection(); if (!sel.isCollapsed && sel.anchorNode && sel.focusNode) { if (sel.anchorNode.parentElement.classList.contains('.comment-cite')) return; else selectionInfo = {}; const anchor = { elem: sel.anchorNode, isComment: false, id: 0 }; const focus = { elem: sel.focusNode, isComment: false, id: 0 }; while (anchor.elem = anchor.elem.parentElement) { if (anchor.elem.classList.contains('comment-text')) anchor.isComment = true; if (anchor.elem.dataset.id) { anchor.id = anchor.elem.dataset.id; break; } } while (focus.elem = focus.elem.parentElement) { if (focus.elem.classList.contains('comment-text')) focus.isComment = true; if (focus.elem.dataset.id) { focus.id = focus.elem.dataset.id; break; } } if (anchor.isComment && focus.isComment && anchor.id === focus.id) { selectionInfo.text = sel.toString(); selectionInfo.id = parseInt(anchor.id, 10); $(`[data-id="${selectionInfo.id}"] .comment-cite-wrap`).show(); } } }); $('#view_comments').on('click', '.comment-answer', function (e) { e.preventDefault(); answerComment($(this).parent().parent(), false); }); $('#view_comments').on('click', '.comment-cite', function (e) { e.preventDefault(); answerComment($(this).parent().parent().parent(), true, selectionInfo); }); } function hideCommentPreview() { $('#comment-preview-hide').hide(); $('#comment-preview-div').empty().hide(); } function changeComments() { addAnswerButtons(); if (getSettings(CONF_BLOGS_AVATARS)) { addCommentAvatars(); } } function addCommentAvatars() { $('.view-comment:not(.has-avatar)').each(function () { $(this).prepend('<div class="comment-avatar"></div>'); const commentId = $(this).data('id'); const avatarSelector = `.view-comment[data-id="${commentId}"] > .comment-avatar`; const avatarDiv = $(avatarSelector); const author = $(this).children('.comment-info').children('.author'); const catId = author.length ? getNumber(author.attr('href')) : 0; const storedAvatar = window.sessionStorage.getItem('avatar' + catId); if (catId === 0) { avatarDiv.css('background-image', `url(//e.catwar.su/avatar/0.jpg)`); } else if (storedAvatar) { avatarDiv.css('background-image', `url(${storedAvatar})`); } else { setAvatar(catId, avatarSelector); } $(this).addClass('has-avatar'); }); } function addAnswerButtons() { const answerButton = isDesctop ? 'Ответить' : '🗨'; const citeButton = isDesctop ? 'Цитировать' : '💬'; const addAnswer = getSettings(CONF_BLOGS_ANSWER_BUTTON); const addCite = getSettings(CONF_BLOGS_CITE_BUTTON); $('.view-comment:not(.has-buttons)').each(function () { let html = `<p class="comment-answer-buttons">`; const notMyComment = $(this).children('.comment-info').children('[data-candelete="0"]').css('display') !== 'none'; if (addAnswer && notMyComment) { html += `<a class="comment-answer" href="#">${answerButton}</a>`; } if (addCite) { html += '<span class="comment-cite-wrap">'; if (addAnswer && notMyComment) html += ' | ' html += `<a class="comment-cite" href="#">${citeButton}</a></span>`; } $(this).append(html).addClass('has-buttons'); }); } function answerComment(comment, cite, selectionInfo) { const commentInfo = comment.children('.comment-info'); const num = commentInfo.children('b').children('.num').text(); let author; if (commentInfo.children('.author').length) author = '[link' + getNumber(commentInfo.children('.author').attr('href')) + ']'; else author = '[b]' + commentInfo.children('span').first().text() + '[/b]'; let quote; if (cite) { let text; if (selectionInfo.id === comment.data('id')) text = selectionInfo.text; else text = bbencode(comment.children('.comment-text').children('.parsed').html()); const date = findDate(commentInfo.html()); quote = `[table][tr][td][size=10][i]Цитата:[/i] [b]#${num}[/b] ${date} @ ${author}[/size][/td][/tr][tr][td][table=0][tr][td] [/td][td]${text}[/td][/tr][/table][/td][/tr][/table]`; } else { quote = `${author} (#${num}), `; } const textarea = $('#comment'); textarea.val(textarea.val() + quote); textarea.focus(); } function changeCreationPage() { if (getSettings(CONF_CREATION_SAVE_ALERT)) addSaveAlert(); if (isPage('blogs?creation', true) || isPage('sniff?creation', true)) { const blogsTags = ` <details id="add-tags"${getSettings(CONF_BLOGS_TAGS_OPEN) ? ' open' : ''}> <summary class="cwmod-settings" data-conf="${CONF_BLOGS_TAGS_OPEN}"><b>Добавить теги</b></summary> <p> <span class="add-tag">информация</span> <span class="add-tag">новичкам</span> <span class="add-tag">племенной блог</span> </p> <p> <span class="add-tag">поздравление</span> <span class="add-tag">день рождения</span> <span class="add-tag">годовщина</span> <span class="add-tag">самопоздравление</span> </p> <p> <span class="add-tag">писательское творчество</span> <span class="add-tag">стихотворения</span> <span class="add-tag">рисунки</span> <span class="add-tag">фотографии</span> <span class="add-tag">рукоделие</span> <span class="add-tag">журнал</span> </p> <p> <span class="add-tag">неграмотно</span> <span class="add-tag">мало</span> <span class="add-tag">скопировано</span> <span class="add-tag">опасно для глаз</span> </p> <p><span class="add-tag">сходка</span></p> <p><span class="add-tag">конкурс</span></p> </details> `; const sniffTags = ` <details id="add-tags"${getSettings(CONF_SNIFF_TAGS1_OPEN) ? ' open' : ''}> <summary class="cwmod-settings" data-conf="${CONF_SNIFF_TAGS1_OPEN}"><b>Добавить теги</b></summary> <p><small>Основано на блоге <a href="/blog331589">Ликбез</a>. Инструкция по выбору тегов там, а это кнопки для тех, кому лень писать их руками.</small></p> <p><span class="add-tag">изображение</span></p> <ul class="tags-list"> <li><span class="add-tag">скриншот</span> <span class="add-tag">достижение</span> <span class="add-tag">максимальное достижение</span> <span class="add-tag">звуки в Игровой</span> <span class="add-tag">скриншот Игровой</span> <span class="add-tag">скриншот кота</span> <span class="add-tag">скриншот профиля</span></li> <li><span class="add-tag">фотография</span> <span class="add-tag">фотография автора</span> <span class="add-tag">фотография питомца</span> <span class="add-tag">фотография природы</span></li> <li><span class="add-tag">действие</span> <span class="add-tag">дизайн</span> <span class="add-tag">запах</span> <span class="add-tag">локация</span> <span class="add-tag">медалька</span> <span class="add-tag">мем</span> <span class="add-tag">небо</span> <span class="add-tag">предмет</span> <span class="add-tag">рисунок</span></li> </ul> <p><span class="add-tag">Поднюхано</span> <span class="add-tag">Замышеголовили</span></p> <ul class="tags-list"> <li><span class="add-tag">бугурт</span> <span class="add-tag">искусство</span> <span class="add-tag">Игровая</span> <span class="add-tag">критика</span> <span class="add-tag">милота</span> <span class="add-tag">обновление</span> <span class="add-tag">племенные новости</span> <span class="add-tag">творчество</span> <span class="add-tag">точка зрения</span></li> </ul> <p><span class="add-tag">Флудильня</span></p> <ul class="tags-list"> <li><span class="add-tag">кроли</span> <span class="add-tag">локации за кроли</span> <span class="add-tag">о себе за кроли</span> <span class="add-tag">предметы за кроли</span> <span class="add-tag">рисунки за кроли</span> <span class="add-tag">услуги за кроли</span></li> <li><span class="add-tag">пыль</span> <span class="add-tag">предметы за пыль</span> <span class="add-tag">рисунки за пыль</span> <span class="add-tag">услуги за пыль</span></li> <li><span class="add-tag">рисунки за деньги</span></li> <li><span class="add-tag">ролевая</span> <span class="add-tag">приглашение в ролевую</span></li> <li><span class="add-tag">72</span> <span class="add-tag">адопт</span> <span class="add-tag">аукцион</span> <span class="add-tag">битва окрасов</span> <span class="add-tag">бугурт</span> <span class="add-tag">варомявы</span> <span class="add-tag">выбор племени</span> <span class="add-tag">гиф</span> <span class="add-tag">Голодные игры</span> <span class="add-tag">желание</span> <span class="add-tag">игра</span> <span class="add-tag">Игровая</span> <span class="add-tag">имя</span> <span class="add-tag">карта</span> <span class="add-tag">квест</span> <span class="add-tag">квест-опрос</span> <span class="add-tag">клон</span> <span class="add-tag">комикс</span> <span class="add-tag">лотерея</span> <span class="add-tag">обмен</span> <span class="add-tag">обмен предметов</span> <span class="add-tag">окрас</span> <span class="add-tag">покраска лайнов</span> <span class="add-tag">рабство</span> <span class="add-tag">симулятор</span> <span class="add-tag">сторонняя игра</span> <span class="add-tag">халява</span></li> </ul> <p>Общие теги:</p> <ul class="tags-list"> <li><span class="add-tag">реальность</span> <span class="add-tag">учёба</span> <span class="add-tag">школа</span> <span class="add-tag">сон</span> <span class="add-tag">семья</span></li> <li><span class="add-tag">поиск</span> <span class="add-tag">поиск друзей</span> <span class="add-tag">поиск кота</span> <span class="add-tag">поиск напарника</span> <span class="add-tag">поиск пары</span> <span class="add-tag">поиск семьи</span> <span class="add-tag">поиск художника</span></li> <li><span class="add-tag">вопрос</span> <span class="add-tag">опрос</span> <span class="add-tag">помощь</span></li> </ul> <details${getSettings(CONF_SNIFF_TAGS2_OPEN) ? ' open' : ''}> <summary class="cwmod-settings" data-conf="${CONF_SNIFF_TAGS2_OPEN}"><b>Теги вселенных и фракций</b></summary> <p>Мёртвые: <span class="add-tag">Звёздное племя</span> <span class="add-tag">Сумрачный лес</span> <span class="add-tag">Душевая</span> </p> <p>Озёрная вселенная: <span class="add-tag">Грозовое племя</span> <span class="add-tag">племя Ветра</span> <span class="add-tag">Речное племя</span> <span class="add-tag">племя Теней</span> <span class="add-tag">клан Падающей Воды</span> <span class="add-tag">Северный клан</span> <span class="add-tag">Домашние</span> <span class="add-tag">одиночки ОВ</span> <span class="add-tag">Озёрная вселенная</span> </p> <p>Морская вселенная: <span class="add-tag">Морское племя</span> <span class="add-tag">племя Солнца</span> <span class="add-tag">племя Луны</span> <span class="add-tag">одиночки МВ</span> <span class="add-tag">Морская вселенная</span> </p> <p>Вселенная творцов: <span class="add-tag">племя Неразгаданных Тайн</span> <span class="add-tag">Крылатое племя</span> <span class="add-tag">Сплочённый Союз Свободных Республик</span> <span class="add-tag">клан Ледяного Дождя</span> <span class="add-tag">Эльфийские земли</span> <span class="add-tag">Чернолесье</span> <span class="add-tag">одиночки ВТ</span> <span class="add-tag">Вселенная творцов</span> </p> </details> </details> `; const tagsInput = $('#creation-tags'); if (!$('#add-tags').length) { if (isPage('blogs')) tagsInput.parent().after(blogsTags); else if (isPage('sniff')) tagsInput.parent().after(sniffTags); $('.add-tag').click(function () { let tags = tagsInput.val(); if (tags) tags += ', '; tags += $(this).text(); tagsInput.val(tags); tagsInput.focus(); }); } //Сохранение последнего блога/поста const creationInput = $('#creation-text'); if (creationInput.length) { const key = isPage('blogs') ? 'cwm_saved_blog' : 'cwm_saved_sniff'; const oldText = window.localStorage.getItem(key); if (oldText && !creationInput.val()) creationInput.val(oldText); creationInput.on('input', function () { window.localStorage.setItem(key, creationInput.val()); }); } } } function searchByTag(tag) { window.location.href = window.location.href.split('?') + '?tag=' + tag; } function changeCatPage() { addCSS(`#info { color: black; } #age_icon, #age2_icon, #act_icon, img[src^="medal"] { cursor: pointer; }`); moonCalc(); if ($('[src="img/icon_kraft.png"]').length) { if (getSettings(CONF_CAT_ADD_KRAFT_NUMBER)) { const kraftArr = ['блоха', 'котёночек', 'задира', 'гроза детской', 'страх барсуков', 'победитель псов', 'защитник племени', 'великий воин', 'достоин Львиного племени', 'идеальная']; const b = $('[src="img/icon_kraft.png"]').parent().siblings().children('b'); b.append(' (' + kraftArr.indexOf(b.text()) + ')'); } } if (getSettings(CONF_CAT_ENABLE_NOTES)) { let p, catId; if (isDesctop) { p = $('#branch > p').first(); catId = p.data('cat'); $('#branch').prepend(`<textarea id="note" placeholder="Заметка об игроке. Её можете видеть только вы" style="float: right; min-width: 100px; width: 250px; max-width: 500px; height: 100px;"></textarea>`); } else { p = $('#site_table > p').first(); catId = p.data('cat'); p.append(`<textarea id="note" placeholder="Заметка об игроке. Её можете видеть только вы" style="display: block; width: calc(100% - 10px); height: 50px;"></textarea>`); } const oldText = getNoteByCatId(catId); const textarea = $('#note'); if (oldText && !textarea.val()) textarea.val(oldText); const savedNotes = JSON.parse(window.localStorage.getItem('cwmod_notes') || '{}'); textarea.on('input', function () { savedNotes[catId] = textarea.val(); if (!savedNotes[catId]) delete savedNotes[catId]; saveData('notes', savedNotes); }); } const medals = $('img[src^="medal"]'); if (medals.length) { let lastpic = false; medals.last().after(`<div id="infomedal" style="display: none; margin: 5px; padding: 5px; border-radius: 10px; width: 270px; background: rgba(255, 255, 255, 0.3); color: black;"></div>`); const info = $('#infomedal'); $.getJSON('https://porch.website/get?file=medals&type=json', function (data) { let medalsList = data.data; medals.click(function () { const picURL = $(this).attr('src'); const pic = getNumber(picURL); if (pic === lastpic) { info.hide(200); lastpic = ''; } else { if (info.css('display') === 'none') info.show(200); lastpic = pic; const medalInfo = medalsList[pic]; if (medalInfo) { let status = medalInfo[1]; let transfer = medalInfo[2]; let getting = medalInfo[3]; let whose = medalInfo[4]; let about = `<br><b>${$(this).attr('alt')}</b>`; if (!(status || transfer || getting || whose === 'Сайтовая')) about += '<br><i>Нет информации</i>'; else { about += '<span style="font-size: 0.9em">'; if (status) { let color; if (status === 'выдаётся') color = 'green'; else if (status === 'не выдаётся') color = '#ba0000'; else color = 'gray'; about += `<br>Статус: <b style="color: ${color}">${status}</b>`; } if (transfer === 'возможен') about += `<br>Перенос на другого персонажа <b style="color: green">возможен</b>`; else if (transfer === 'невозможен') about += `<br>Перенос на другого персонажа <b style="color: #ba0000">невозможен</b>`; about += '</span>'; if (getting) about += `<br><span style="white-space:pre-wrap">${getting}</span>`; if (whose === 'Сайтовая') about += `<br><span style="font-size: 0.9em">Это сайтовая медаль.</span>`; } info.html(`Медаль № ${pic}${about}`); } else { info.html(`Медаль № ${pic}<br><b>${$(this).attr('alt')}</b><br><i>Нет информации</i>`); } } }); }); } } function changeChatPage() { addCSS(`.tabName, #confirm_text, .mess_tr[style^="background: rgb(255, 204, 153)"] { color: black; } .mess_tr[style^="background: rgb(255, 204, 153)"] a { color: #003; }`); addBBcode(1); const key = 'cwmod_saved_chat'; const oldText = window.localStorage.getItem(key); if (oldText) $('#mess').html(oldText); $('#mess').on('input', function () { window.localStorage.setItem(key, $('#mess').html()); }); const observer = new MutationObserver(function (mutations) { mutations.forEach(function () { if (!$('#mess').html()) window.localStorage.removeItem(key); }); }); observer.observe(document.querySelector('#mess'), { childList: true }); } function changeCW3Page() { const menu = $('.small').first(); //const isMale = /Мой кот/.test(menu.text()); const target = getSettings(CONF_CW3_MENU_TARGET_BLANK) ? 'target="_blank"' : ''; const menuButtons = {}; menuButtons[CONF_CW3_MENU_ABOUT] = `<a ${target} href="/about">Об игре</a>`; //menuButtons[CONF_CW3_MENU_INDEX] = `<a ${target} href="/">${isMale ? 'Мой кот' : 'Моя кошка'}</a>`; menuButtons[CONF_CW3_MENU_TOP] = `<a ${target} href="/top">СИ</a>`; //menuButtons[CONF_CW3_MENU_CHAT] = `<a ${target} href="/chat">Чат</a><span id="newchat"></span>`; //menuButtons[CONF_CW3_MENU_LS] = `<a ${target} href="/ls">ЛС</a><span id="newls"></span>`; menuButtons[CONF_CW3_MENU_LS0] = `<a ${target} href="/ls?id=0">Памятка</a>`; menuButtons[CONF_CW3_MENU_BLOGS] = `<a ${target} href="/blogs">Блоги</a>`; menuButtons[CONF_CW3_MENU_SNIFF] = `<a ${target} href="/sniff">Лента</a>`; menuButtons[CONF_CW3_MENU_SETTINGS] = `<a ${target} href="/settings#cwmod">Настройки</a>`; menuButtons[CONF_CW3_MENU_MOBILE] = `<a href="/mobile">Сменить версию</a>`; Object.keys(menuButtons).forEach(function (key) { if (getSettings(key)) { menu.append(' | ' + menuButtons[key]); } }); const body = $('body'); let css = ''; if (getSettings(CONF_CW3_CHAT_QUIET_LOUDER)) { css += `.vlm0, .vlm1, .vlm2, .vlm3, .vlm4 {font-size: 12px;}`; } if (getSettings(CONF_CW3_CHAT_LOUD_QUIETER)) { css += `.vlm6, .vlm7, .vlm8, .vlm9, .vlm10 {font-size: 14px;}`; } if (getSettings(CONF_CW3_LOWER_CATS)) { css += `.d, .d div {background-position: left bottom;}`; } if (getSettings(CONF_CW3_FIGHT_PANEL_HEIGHT)) { const height = getSettings(CONF_CW3_FIGHT_PANEL_HEIGHT); if (height !== 70) { css += ` #fightPanel { height: max-content; } #fightLog { overflow-y: auto; min-height: 70px; height: unset !important; max-height: ${height}px; } `; } } if (getSettings(CONF_CW3_ADD_REALISM)) { css += `.d {background-image: url(https://porch.website/cwmod/cat.png) !important;}`; } if (getSettings(CONF_CW3_CAGES_BORDERS)) { css += `.cage {box-shadow: inset 1px 1px 1px rgba(0, 0, 0, 0.33), inset -1px -1px 1px rgba(255, 255, 255, 0.33);}`; } if (getSettings(CONF_CW3_DEAD_OPAQUE)) { css += `.cat > div {opacity: 1 !important;}`; } if (getSettings(CONF_CW3_HIDE_SKY)) { css += `#tr_sky {display: none;}`; } if (getSettings(CONF_CW3_ALWAYS_DAY)) { css += `#cages_div {opacity: 1 !important;}`; } if (getSettings(CONF_CW3_HISTORY_NO_UNDERLINE)) { css += `#ist > a {text-decoration: none;}`; } if (getSettings(CONF_CW3_COMPACT)) { css += ` #app { width: 100%; height: 1000px; } #main_table { width: 100%; max-width: unset; height: 100%; border-collapse: collapse; background: none !important; } #main_table > tbody { display: grid; grid-row-gap: 5px; grid-template-columns: 1fr auto 1fr; } #app > span.small { grid-area: links; position: fixed; z-index: 1; left: 5px; top: 5px; } #tr_chat { grid-area: chat; } #tr_actions { grid-area: actions; overflow: auto; background: none !important; } #tr_tos { grid-area: tos; background: none !important; } #tr_sky { display: none; } #tr_field { grid-area: field; background: black; } #tr_mouth { grid-area: mouth; overflow: auto; background: none !important; } #tr_actions > td, #tr_mouth > td, #info_main > tbody > tr > td { background-color: #ffdead; } #tr_info { grid-area: info; max-height: 1000px; overflow-x: hidden; overflow-y: auto; } #info_main { background: none !important; } #info_main > tbody > tr > td, #tr_mouth > td > *, #tr_actions > td > *, #tr_chat { padding: 5px; } #block_mess { margin: 0; padding: 8px 0; } .infos { width: 100%; max-width: max-content; } #itemList { max-height: 75px; overflow-y: auto; } #thdey > br { display: none; } #chat_form { display: grid; grid-row-gap: 5px; margin: 10px 5px 5px 5px; } .chat_text { width: unset !important; } #chat_msg { width: auto !important; height: 350px; padding: 2px; } #volume + b { display: block; font-size: 0.75em; } #app > p:not(#error) { visibility: hidden; } #black { visibility: visible; color: white; } #black::before { content: 'ТБ: '; } .small { padding: 0 5px; background-color: #ffdead; font-size: 15px; } #history_block > div { visibility: hidden; } #location { visibility: visible; position: fixed; right: 15px; top: 5px; z-index: 5; padding: 0 5px; font-weight: bold; font-size: 1.5em; background-color: #ffdead; } h2 { font-size: 1.2em; } `; const splitInfo = (getSettings(CONF_CW3_COMPACT_SPLIT_INFO)); const sticky = (getSettings(CONF_CW3_COMPACT_SPLIT_INFO_STICKY_HEADERS)); if (isDesctop) css += ` #chat_form { grid-template-columns: auto auto; } #info_main > tbody > tr { display: grid; max-height: 1000px; grid-template-areas: 'parameter' 'history' 'family'; grid-template-rows: ${splitInfo ? '252px 1fr 1fr' : 'auto auto auto'}; grid-row-gap: 5px; } #family.infos { grid-area: family; overflow: auto; } #history.infos { grid-area: history; overflow: auto; } #parameter.infos { grid-area: parameter; overflow: auto; } `; else css += ` #chat_form { grid-template-columns: auto auto auto; } #info_main > tbody { display: grid; max-height: 1000px; grid-template-areas: 'parameter' 'history' 'family'; grid-template-rows: ${splitInfo ? '252px 1fr 1fr' : 'auto auto auto'}; grid-row-gap: 5px; } #info_main > tbody > tr:nth-child(1) { grid-area: parameter; overflow: auto; } #info_main > tbody > tr:nth-child(2) { grid-area: history; overflow: auto; } #info_main > tbody > tr:nth-child(3) { grid-area: family; overflow: auto; } `; const hideHeaders = (getSettings(CONF_CW3_COMPACT_HIDE_HEADERS)); if (hideHeaders) { css += ` #info_main h2 { visibility: hidden; } #parameters-alert { visibility: visible; } `; } else if (splitInfo && sticky) { css += `#info_main h2 { position: sticky; }`; } const swap = (getSettings(CONF_CW3_COMPACT_SWAP_SIDES)); const chatup = (getSettings(CONF_CW3_COMPACT_CHAT_ON_TOP)); if (swap && chatup) { css += `#main_table > tbody { grid-template-areas: 'info field tos' 'info field chat' 'info field actions' 'info field mouth'; grid-template-rows: 25px 425px 267.5px 267.5px; }`; } else if (swap && !chatup) { css += `#main_table > tbody { grid-template-areas: 'info field tos' 'info field actions' 'info field mouth' 'info field chat'; grid-template-rows: 25px 267.5px 267.5px 425px; }`; } else if (!swap && chatup) { css += `#main_table > tbody { grid-template-areas: 'tos field info' 'chat field info' 'actions field info' 'mouth field info'; grid-template-rows: 25px 425px 267.5px 267.5px; }`; } else { css += `#main_table > tbody { grid-template-areas: 'tos field info' 'actions field info' 'mouth field info' 'chat field info'; grid-template-rows: 25px 267.5px 267.5px 425px; }`; } if (getSettings(CONF_CW3_COMPACT_ROUND_EDGES)) { css += `.small, #tos, #tr_chat, #tr_actions > td, #tr_mouth > td, #location, #tr_field, #parameter, #cages_div { border-radius: 15px; }`; if ($('#app').data('mobile') === 1) css += `#info_main > tbody > tr { border-radius: 15px; }`; else css += `#family, #history{ border-radius: 15px; }`; } } const styleTemplate = ` #error { background-color: var(--error-bg) !important; color: var(--error-color) !important; } #main_table { background: var(--main-bg) } #tr_field { background: black !important; } hr { border: none; border-bottom: 1px solid var(--hr-color) !important; } body { background-color: var(--body-bg) !important; color: var(--text-color) !important; } a, a:hover { color: var(--a-color); } #tr_chat, #tr_actions, #tr_mouth, #info_main { background: none !important; } .small, #app > p:not(#error), #info_main > tbody > tr > td, #history_block > div, #tr_mouth > td, #tr_actions > td, #location, #black, #tr_chat { background-color: var(--table-bg) !important; color: var(--text-color) !important; border: none !important; } .myname { background: var(--myname-bg) !important; color: var(--myname-color) !important; } input, select { background-color: var(--input-bg) !important; color: var(--input-color) !important; border: 1px solid var(--input-border-color) !important; } .ui-slider { background: var(--input-bg) !important; border: 1px solid var(--input-border-color) !important; } .ui-slider .ui-slider-handle { background: var(--handle-bg) !important; border: 1px solid var(--input-border-color) !important; } .hotkey { background: white !important; } .move_name, #fightLog, #timer, .hotkey { color: #000 !important; } `; const theme = getSettings(CONF_CW3_THEME); const themes = { 'dark_grey': `:root { --table-bg: #222; --error-bg: #3c1e1e; --error-color: #ccc; --main-bg: #222; --hr-color: #282828; --body-bg: #191919; --text-color: #b2b2b2; --a-color: #b2b2b2; --myname-color: black; --myname-bg: #a73; --input-bg: #111; --handle-bg: #383838; --input-color: #aaa; --input-border-color: #282828; }`, 'black_glass': `:root { --table-bg: #000d; --error-bg: #3c1e1e; --error-color: #ccc; --main-bg: none; --hr-color: #000; --body-bg: #4d4e4f; --text-color: #b2b2b2; --a-color: #b2b2b2; --myname-color: black; --myname-bg: #a73; --input-bg: #111; --handle-bg: #333; --input-color: #ccc; --input-border-color: #000; }` }; if (theme !== 'default') { css += themes[theme] + styleTemplate; } addCSS(css); if (getSettings(CONF_CW3_BACKGROUND) !== 'default') { const bgSize = getSettings(CONF_CW3_BACKGROUND_SIZE); const bgPos = getSettings(CONF_CW3_BACKGROUND_POSITION); addCSS(`body { background-size: ${bgSize}; background-position: ${bgPos}; }`); if (getSettings(CONF_CW3_BACKGROUND) === 'location') { body.css('background-image', $('#cages_div').css('background-image')); const cagesDivObserver = new MutationObserver(function (mutations) { mutations.forEach(function () { body.css('background-image', $('#cages_div').css('background-image')); }); }); cagesDivObserver.observe($('#cages_div')[0], { attributes: true }); const pageObserver = new MutationObserver(function (mutations) { mutations.forEach(function () { if (body.text() === 'Вы открыли новую вкладку с Игровой, поэтому старая (эта) больше не работает.') { body.css('background-image', 'none'); cagesDivObserver.disconnect(); pageObserver.disconnect(); } }); }); pageObserver.observe(document.body, { childList: true }); } else { addCSS(`body { background-image: url(${getSettings(CONF_CW3_BACKGROUND_IMAGE)}); }`); } } if (getSettings(CONF_CW3_WEATHER_SNOW)) { const skyObserver = new MutationObserver(function (mutations) { let sky = $('#sky').css('background-image').match(/\d+/g)[1]; let isSnow = false; if (sky === '7' || sky === '8') { isSnow = true; setTimeout(function runSnow() { snow(); if (isSnow) setTimeout(runSnow, 250); }, 250); } mutations.forEach(function () { if (!$('#snow').length) body.prepend('<div id="snow"></div>'); const weatherObserver = new MutationObserver(function (mutations) { mutations.forEach(function () { sky = $('#sky').css('background-image').match(/\d+/g)[1]; if ((sky === '7' || sky === '8') && !isSnow) { isSnow = true; setTimeout(function runSnow() { snow(); if (isSnow) setTimeout(runSnow, 250); }, 250); } else { isSnow = false; } }); }); weatherObserver.observe($('#sky')[0], { attributes: true }); skyObserver.disconnect(); }); }); skyObserver.observe($('#main_table > tbody')[0], { childList: true }); } const cagesObserver = new MutationObserver(function (mutations) { mutations.forEach(function (mutation) { const node = mutation.addedNodes[0]; if (!node) return; if (node.nodeType !== Node.ELEMENT_NODE) return; if (isDesctop && getSettings(CONF_CW3_COMPACT)) { if (node.classList.contains('catWithArrow')) { let padding = 0; $('#cages').children('tbody').children('tr').last().children().each(function () { const tooltip = $(this).find('.cat_tooltip'); if (tooltip.length && tooltip.height() > padding) { padding = tooltip.height(); } }); padding += 50; $('body').css('padding-bottom', padding + 'px') } } if (getSettings(CONF_CW3_LOWER_CATS) && getSettings(CONF_CW3_LOWER_ARROWS)) { let arrow; if (node.classList.contains('catWithArrow')) { arrow = $(node).children('div').children('.arrow'); } else if (mutation.target.classList.contains('catWithArrow')) { arrow = $(node).children('.arrow'); } else return; if (!arrow.length) return; const oldTop = Number(getNumber(arrow.css('top'))); const catHeight = Number(getNumber(arrow.children('table').css('width'))); const newTop = oldTop + 150 - catHeight * 1.5; arrow.css('top', newTop + 'px'); } }); }); $('.cage_items').each(function () { cagesObserver.observe(this, { childList: true, subtree: true }); }); if (getSettings(CONF_CW3_ACT_END_IN_TITLE) || getSettings(CONF_CW3_ACT_END_ALERT)) { const changeTitle = getSettings(CONF_CW3_ACT_END_IN_TITLE); const blurOnly = getSettings(CONF_CW3_ACT_END_ALERT_BLUR_ONLY); const audio = new Audio(); audio.src = getSettings(CONF_CW3_ACT_END_ALERT_SOUND); audio.volume = getSettings(CONF_CW3_ACT_END_ALERT_VOLUME); let isWindowActive = true; window.addEventListener('focus', function (event) { isWindowActive = true; if (blurOnly) { audio.pause(); audio.currentTime = 0; } }); window.addEventListener('blur', function (event) { isWindowActive = false; }); const deysObserver = new MutationObserver(function (mutations) { mutations.forEach(function (mutation) { if (mutation.target.id === 'block_mess' && !$('#sek').length) { if (changeTitle) document.title = 'Игровая / CatWar'; } else if (mutation.target.id === 'sek' && mutation.addedNodes.length) { const timeLeft = $('#sek').text(); if (changeTitle) document.title = timeLeft; if (getSettings(CONF_CW3_ACT_END_ALERT)) { const alertTime = new RegExp('^' + getSettings(CONF_CW3_ACT_END_ALERT_TIME) + ' .?с'); if (alertTime.test(timeLeft) && (!isWindowActive || !blurOnly || $('#cwmod-popup-wrap').css('display') === 'flex')) { audio.play(); } } } }); }); deysObserver.observe($('#block_mess')[0], { childList: true, subtree: true }); } const DiseasesLevels = {}; DiseasesLevels.dirt = ['грязные лапы', 'грязевые пятна', 'клещи', 'блохи']; DiseasesLevels.wound = ['царапины', 'лёгкие раны', 'глубокие раны', 'смертельные раны']; DiseasesLevels.drown = ['cсадины', 'лёгкие порезы', 'глубокие царапины', 'смертельные травмы']; DiseasesLevels.trauma = ['ушибы', 'лёгкие переломы', 'сильные переломы', 'смертельные переломы']; let catInfos = []; $('body').on('mouseenter', '.cat', function () { let cat = $(this); if (getSettings(CONF_CW3_CAT_INFO)) { let html = cat.html(); let link = cat.find('a').first(); let catName = link.text(); let catId = /\d+/.exec(link.attr('href'))[0]; let sex = (/Его запах/.exec(html)); let image = /composited\/([\da-f]{16})\.png/.exec(html)[1]; let height = cat.find('.d').css('background-size'); if (height === '101%') height += ' (надута)'; let dirt = /dirt\/(\d)/.exec(html); let wound = /wound\/(\d)/.exec(html); let drown = /drown\/(\d)/.exec(html); let trauma = /trauma\/(\d)/.exec(html); wound = wound ? Number(wound[1]) : false; dirt = dirt ? Number(dirt[1]) : false; drown = drown ? Number(drown[1]) : false; trauma = trauma ? Number(trauma[1]) : false; let poisoning = (/poisoning/.exec(html)); let disease = (/disease/.exec(html)); let beddings = (/costume\/295\.png/.exec(html)); let text = `<div style="background: bottom right / 45px no-repeat url(composited/${image}.png);">`; text += `<a href="/cat${catId}"><b>${catName}</b></a> (ID ${catId})<br><a target="_blank" href="/cw3/composited/${image}.png">Окрас</a>`; text += `<br>Рост: ${height}`; text += dirt ? `<br>Грязь ${dirt} степени (${DiseasesLevels.dirt[dirt - 1]})` : ''; text += beddings ? `<br>Убирает подстилки` : ''; text += (wound || drown || trauma || poisoning || disease) ? `<br>Болезни:` : `<br>Здоров` + (sex ? '' : 'а'); text += wound ? `<br>— Раны ${wound} степени (${DiseasesLevels.wound[wound - 1]})` : ''; text += drown ? `<br>— Травмы от утопления ${drown} степени (${DiseasesLevels.drown[drown - 1]})` : ''; text += trauma ? `<br>— Переломы ${trauma} степени (${DiseasesLevels.trauma[trauma - 1]})` : ''; text += poisoning ? `<br>— Отравление` : ''; text += disease ? `<br>— Насморк` : ''; text += `</div>`; catInfos[catId] = text; if (!cat.find('.show-more').length) cat.find('.online').before(`<a class="show-more" href="#" data-id="${catId}">Подробнее</a><br>`); else cat.find('.show-more').data('id', catId); } if (getSettings(CONF_CW3_MODIFY_INVENTORY)) { let things = {}; let cats = []; let mouth = cat.find('.mouth:not(.new-mouth)').first(); if (mouth.length) { let newMouth = mouth.siblings('.new-mouth'); if (!newMouth.length) { mouth.after('<ol class="mouth new-mouth"></ol>'); newMouth = mouth.siblings('.new-mouth'); } else newMouth.show(); let mouthThings = mouth.children('li'); mouthThings.each(function () { const li = $(this); if (li.find('div').length) { cats.push(li.html()); } else { let thingId = /\d+/.exec(li.children('img').attr('src'))[0]; if (li.text() !== '') { things[thingId] = Number(li.text().slice(1)); } else if (things[thingId]) { things[thingId]++; } else things[thingId] = 1; } }); let newMouthHtml = ''; Object.keys(things).forEach(function (key) { let len = things[key] > 1 ? `×${things[key]}` : ''; newMouthHtml += `<li><img src="things/${key}.png">${len}</li>`; }); cats.forEach(function (cat) { newMouthHtml += `<li>${cat}</li>`; }); mouth.hide(); newMouth.html(newMouthHtml); } else cat.find('.new-mouth').hide(); } }); if (getSettings(CONF_CW3_CAT_INFO)) { $('body').on('click', '.show-more', function (e) { e.preventDefault(); showCwmodPopup('alert', catInfos[$(this).data('id')]); }); } if (getSettings(CONF_CW3_PARAMETERS_INFO)) { $('#parameter').children('h2').first().append(' <a id="parameters-alert" href="#" title="Параметры подробно">+</a>'); $('#parameters-alert').click(function () { let params = ['Сонливость', 'Голод', 'Жажда', 'Нужда', 'Здоровье', 'Чистота']; let text = '<center><b>Параметры</b></center>'; ['dream', 'hunger', 'thirst', 'need', 'health', 'clean'].forEach(function (param, i) { const isDream = (param === 'dream'), isHunger = (param === 'hunger'), isThirst = (param === 'thirst'), isNeed = (param === 'need'), isClean = (param === 'clean'); text += `<br><b>${params[i]}</b><br>`; let red = parseInt($('#' + param).find("td").last()[0].style.width); if (Number.isNaN(red)) text += 'Ошибка, попробуйте снова'; else if (red === 0) { if (isDream && $('.dey[data-id="1"]').length) text += `<span style="color: darkred">100 %</span><br>10 c сна`; else if (isThirst && $('.dey[data-id="5"]').length) text += `<span style="color: darkred">100 %</span><br>До 30 c питья`; else if (isNeed && $('.dey[data-id="4"]').length) text += `<span style="color: darkred">100 %</span><br>10 c дел в грязном месте`; else text += '100 %'; } else if (red === 150) { text += '<span style="color: darkred">0 %</span>'; if (isDream) text += `<br>${secToTime(150 * 20)} сна или более`; if (isThirst) text += `<br>${secToTime(150 * 60 - 30)} питья или более`; if (isNeed) text += `<br>${secToTime(150 * 30 - 10)} дел в грязном месте или более`; } else { const percent = isClean ? Math.floor((150 - red) / 1.5) : Math.round((150 - red) / 1.5 * 100) / 100; text += `<span style="color: darkred">${percent}%</span> (−${red}px)`; if (isDream) { const maxTime = red * 20 + 10; text += `<br>До ${secToTime(maxTime)} сна`; } else if (isHunger) { const time = Math.ceil((100 - percent) * 9 / 100) * 15; text += `<br>${secToTime(time)} поглощения пищи`; } else if (isThirst) { const maxTime = red * 60 + 30; text += `<br>До ${secToTime(maxTime)} питья`; } else if (isNeed) { const maxTime = red * 30 + 10; text += `<br>До ${secToTime(maxTime)} дел в грязном месте`; } else if (isClean && red <= 75) { text += `<br>Вылизываться ${secToTime((100 - percent) * 100)}`; } } }); showCwmodPopup('alert', text); }); } } function snow() { const id = Date.now(), flake = 'https://porch.website/cwmod/snow/' + Math.ceil(Math.random() * 20) + '.png', pos_x = Math.ceil(Math.random() * 98), end_x = pos_x + Math.floor(Math.random() * 31) - 15, deg = Math.ceil(Math.random() * 358), width = Math.ceil(Math.random() * 45) + 5, img = ` <img id="snow_${id}" style=" left: ${pos_x}%; top: -10%; position: fixed; pointer-events: none; z-index: 72000; transform: rotate(${deg}deg); max-width: ${width}px; " src="${flake}">`, timefall = Math.ceil(Math.random() * 12000) + 5000; $("#snow").append(img); $(`#snow_${id}`).animate({ top: '120%', left: end_x + '%' }, timefall, function () { $(`#snow_${id}`).empty().remove(); }); } function changeFaePage() { if (getSettings(CONF_FAE_SHOW_NOTES)) { const observer = new MutationObserver(function (mutations) { mutations.forEach(function () { $('.cat_span').each(function () { const t = $(this); const catId = getNumber(t.children().first().attr('href')); const noteText = getNoteByCatId(catId); if (noteText) { t.append(` <span id="${catId}" class="note" style="font-size: 0.9em"></span>`); $('#' + catId).text(noteText); } }); }); }); observer.observe(document.querySelector('#friendList'), { childList: true }); } if (getSettings(CONF_CAT_ENABLE_NOTES)) { $(isDesctop ? '#branch' : '#site_table').append(`<b>Список заметок</b><br>`); let html = ''; const notes = JSON.parse(window.localStorage.getItem('cwmod_notes') || '{}'); Object.keys(notes).forEach(function (catId) { html += `<tr><td>${catId}</td><td id="note-${catId}"></td><td>${notes[catId]}</td></tr>`;; }); if (html.length) { $(isDesctop ? '#branch' : '#site_table').append(`<table><thead><tr><td>ID</td><td>Имя</td><td>Заметка</td></tr></thead><tbody>${html}</tbody></table>`); Object.keys(notes).forEach(catId => setCatName(catId, '#note-' + catId)); } else { $(isDesctop ? '#branch' : '#site_table').append(`<i>Нет заметок об игроках</i>`); } } } function changeIdeasPage() { addCSS(` .vote[style="color:#000"] { color: inherit !important; } .idea { color: black; } .idea a, .idea a:hover { color: #005 !important; } `); } function changeIndexPage() { let css = ` #act_name b { color: black; } #info { color: black; background: rgba(255, 255, 255, 0.5); } #clan_icon, #age_icon, #age2_icon, #act_icon { cursor: pointer; } #cwmod-grats { width: fit-content; padding: 5px; background: rgba(255, 255, 255, 0.5); border-radius: 10px; } `; if (getSettings(CONF_INDEX_EDUCATION_HIDE)) { css += `#education, #education-show, #education-show + br {display: none !important}`; } addCSS(css); addBBcode(); const catId = $('[src="img/icon_id.png"]').parent().siblings().children('a').children('b').text(); activityCalc(catId); moonCalc(); if (getSettings(CONF_INDEX_SAVE_ALERT)) addSaveAlert(); } function activityCalc(catId) { const actStages = [{ name: 'пустое место', fromZero: -5000 }, { name: 'подлежащий удалению', fromZero: -5000 }, { name: 'покинувший игру', fromZero: -2000 }, { name: 'забывший про игру', fromZero: -1000 }, { name: 'забытый кот', fromZero: -750 }, { name: 'ужаснейшая', fromZero: -500 }, { name: 'ужасная', fromZero: -300 }, { name: 'ухудшающаяся', fromZero: -150 }, { name: 'отрицательная', fromZero: -50 }, { name: 'переходная', fromZero: -5 }, { name: 'положительная', fromZero: 5 }, { name: 'улучшающаяся', fromZero: 50 }, { name: 'замечательная', fromZero: 150 }, { name: 'переход 2 мин 15 с', fromZero: 225 }, { name: 'замечательнейшая', fromZero: 300 }, { name: 'переход 2 мин', fromZero: 450 }, { name: 'любимый кот', fromZero: 500 }, { name: 'переход 1 мин 45 с', fromZero: 675 }, { name: 'легенда сайта', fromZero: 750 }, { name: 'переход 1 мин 30 с', fromZero: 900 }, { name: 'ходячий миф', fromZero: 1000 }, { name: 'переход 1 мин 15 с', fromZero: 1125 }, { name: 'переход 1 мин', fromZero: 1350 }, { name: 'переход 45 c', fromZero: 1575 }, { name: 'император Игровой', fromZero: 2000 }, { name: 'частичка Игровой', fromZero: 5000 }, { name: 'хранитель Игровой', fromZero: 20000 }, { name: 'идеальная', fromZero: 75000 }, { name: 'сверхидеальная', fromZero: 150000 }]; const sets = JSON.parse(window.localStorage.getItem('cwmod_act') || '{}'); if (!sets[catId]) { sets[catId] = {}; if (window.localStorage.getItem('cwm_hours') !== null) { sets[catId].hours = Number(window.localStorage.getItem('cwm_hours')); window.localStorage.removeItem('cwm_hours'); } else sets[catId].hours = 24; sets[catId].opened = true; } /// до 2.2 if (sets[catId].actgoal) { actStages.forEach(function (stage, i) { if (i && Number(sets[catId].actgoal) === stage.fromZero) { sets[catId].goal = i; delete sets[catId].actgoal; } }); } function updateHourWord() { const hours = sets[catId].hours; $('#hour-word').text(declOfNum(hours, ['час', 'часа', 'часов'])); } function actLength(d) { const minus = sets[catId].minus || 0; if (d <= 14) return 150 - minus; else if (d >= 1575) return 45 - minus; else return Math.ceil(150 - d / 15) - minus; } function left(currentActivity, goal, hoursPerDay) { const secsPerDay = convertTime('h s', hoursPerDay); if (actLength(currentActivity) * 4 + 1 > secsPerDay) { return { actions: '∞', time: '∞', date: 'никогда' }; } const actionsWithoutDecr = goal - currentActivity; let days = 0; let secsToday; while (currentActivity < goal) { secsToday = 0; while (secsToday < secsPerDay) { currentActivity++; secsToday += actLength(currentActivity); if (currentActivity >= goal) break; } if (currentActivity >= goal) break; days++; currentActivity -= 4.8; } const actionsDecr = Math.floor(days * 4.8 + convertTime('s h', secsToday) / 5); const time = secsPerDay * days + secsToday; const now = new Date(); const tomorrow = new Date(now.getFullYear(), now.getMonth(), now.getDate() + 1); const secsToTomorrow = convertTime('ms s', tomorrow - now); if (days === 0 && secsToday > secsToTomorrow) days++; const date = new Date(Date.now() + convertTime('d ms', days)); return { actions: actionsWithoutDecr + actionsDecr, time: secToTime(time), date: date.getDate() + ' ' + months[date.getMonth()] + ' ' + date.getFullYear() }; } function updateToact() { if (progress.stage === actStages.length - 1) { $('#toact').hide(); return; } const goal = Number($('#act-list').val()); const result = left(progress.doneFromZero, actStages[goal].fromZero, sets[catId].hours); $('#toact > ul').html(` <li>${result.actions} ${declOfNum(result.actions, ['переход', 'перехода', 'переходов'])} (${result.time})</li> <li>будет достигнута ${result.date}</li> `); } const act = $('#act_name b').text().split(' ('); const progress = {}; actStages.forEach(function (stage, i) { if (act[0] === stage.name) { progress.doneFromZero = stage.fromZero + Number(act[1].split('/')[0]); } if ( (!actStages[i + 1] || actStages[i + 1].fromZero > progress.doneFromZero) && actStages[i].fromZero <= progress.doneFromZero ) { progress.stage = i; } }); const actInfoHTML = ` <details id="calc-act"${sets[catId].opened ? ' open' : ''}> <summary id="open-calc"><b>Калькулятор активности</b></summary> <p id="cwmod-grats" style="display:none"></p> <div id="actlength"><b>Переход</b>: ${secToTime(actLength(progress.doneFromZero))}</div> <div>Предметы во рту уменьшают мой переход <nobr>на <select id="minus"> <option value="0">0 секунд</option> <option value="2">2 секунды</option> <option value="4">4 секунды</option> <option value="6">6 секунд</option> </select></nobr> </div> <div>Я качаю активность <input id="hours-per-day" type="number" step="0.25" min="0" max="24" value="${sets[catId].hours}" style="width: 60px"> <span id="hour-word"></span> в сутки</div> <div id="toact"> <b>Цель: <select style="display: inline" id="act-list"></select></b>: <ul style="margin: 0.5em"></ul> </div> <div>Переход начнёт падать <span id="tofall"></span></div> </details> `; $('#info').after(actInfoHTML); for (let i = progress.stage + 1; i < actStages.length; i++) { $('#act-list').append(`<option value="${i}">${actStages[i].name}</option>`); } if (sets[catId].goal > progress.stage || sets[catId].noGrats) { $(`#act-list > [value="${sets[catId].goal}"]`).prop('selected', true); } else if (sets[catId].goal) { $(`#cwmod-grats`).html(` Цель <b>«${actStages[sets[catId].goal].name}»</b> достигнута! <center><img src="/img/stickers/systempaw3/6.png"></center> <input id="cwmod-grats-hooray" type="button" value="Скрыть"> <br><input id="cwmod-grats-never-show" type="checkbox"> Больше не поздравлять на этом персонаже `).show(); $('#cwmod-grats-hooray').click(function () { $(`#cwmod-grats`).hide(200); $(`#cwmod-grats`).hide(200); sets[catId].goal = Number($('#act-list').val()); sets[catId].noGrats = $('#cwmod-grats-never-show').is(':checked'); saveData('act', sets); }); } if (sets[catId].minus) { $(`#minus > [value="${sets[catId].minus}"]`).prop('selected', true); } updateHourWord(); updateToact(); if (actLength(progress.doneFromZero) !== 45) { $('#tofall').parent().hide(); } else { const timeFall = new Date(Date.now() + (progress.doneFromZero - 1575) * 5 * 3600000); $('#tofall').html( timeFall.getDate() + ' ' + months[timeFall.getMonth()] + ' ' + timeFall.getFullYear() ); } $('#minus').change(function () { sets[catId].minus = $(this).val(); saveData('act', sets); updateToact(); $('#actlength').html(`<b>Переход</b>: ${secToTime(actLength(progress.doneFromZero))}`); }); $('#act-list').change(function () { sets[catId].goal = Number($('#act-list').val()); saveData('act', sets); updateToact(); }); $('#hours-per-day').on('input', function () { const hours = Number($('#hours-per-day').val()); if (hours < 0 || hours > 24 || !Number.isInteger(hours * 1000)) { $('#hours-per-day').val(sets[catId].hours); return; } sets[catId].hours = hours; saveData('act', sets); updateHourWord(); updateToact(); }); $('#open-calc').click(function () { sets[catId].opened = !$('#calc-act').is('[open]'); saveData('act', sets); }); } function changeKnsPage() { if (getSettings(CONF_KNS_SAVE_ALERT)) addSaveAlert(); } function changeLsPage() { addCSS(` .msg { color: #000; background: #fff; } .msg a { color: #0000cd; } .msg_header { font-size: 1.2rem; text-align: center; } #search, #saved { display: none; } label { cursor: pointer; } .msg_deleted { color: darkred; } `); const enableSaving = getSettings(CONF_LS_ENABLE_SAVING); if (enableSaving) $('#links').append(` | <a href="ls?3" id="f3">Сохранённые (<span id="saved-number">?</span>)</a>`); $('#links').append(` | <a href="ls?search" id="s">Поиск</a>`); let html = ` <div id="search"> <form class="usn" id="search-form"> <p> Найти <label><input name="search-folder" type="radio" value="0"> входящие</label> <label><input name="search-folder" type="radio" value="1"> отправленные</label> <label><input name="search-folder" type="radio" value="2"> непрочитанные</label> </p> `; if (enableSaving) html += ` <p> <label><input name="search-type" id="search-all" type="checkbox"> во всех ЛС на этом персонаже</label> <label><input name="search-type" id="search-saved" type="checkbox"> в сохранённых ЛС</label> </p> `; html += ` <p> <input id="search-cat" type="text" placeholder="Имя или ID собеседника"> <input id="search-text" type="text" placeholder="Текст"> <input id="search-ok" type="button" value="ОК"> </p> </form> <div id="search-list"></div> </div> `; if (enableSaving) html += '<div id="saved"><div id="saved-list"></div></div>'; $(isDesctop ? '#branch' : '#site_table').append(html); const lastSearch = getSettings(CONF_LS_LAST_SEARCH); const lastFolder = lastSearch.folder; const lastType = enableSaving ? lastSearch.type : 1; $(`[name="search-folder"][value="${lastFolder}"]`).prop('checked', true); switch (lastType) { case 1: $('#search-all').prop('checked', true); break; case 2: $('#search-saved').prop('checked', true); break; case 3: $('[name="search-type"]').prop('checked', true); break; default: $('[name="search-type"]').prop('checked', false); } if (enableSaving) { updateSavedLsList(); $(window).on('storage', function (e) { if (e.originalEvent.key === 'cwmod_ls') updateSavedLsList(); }); if (isPage('ls?3')) showSavedLsList(); if (isPage(/^https:\/\/catwar.su\/ls\?id=\d+/)) changeMessagePage(); } if (isPage('ls?search')) showSearch(); if (isPage('ls?new')) addBBcode(); $('#search-ok').click(searchLs); $('[name="search-folder"]').change(function () { const folder = parseInt($('[name="search-folder"]:checked').val(), 10); lastSearch.folder = folder; setSettings(CONF_LS_LAST_SEARCH, lastSearch); }); $('[name="search-type"]').change(function () { const searchAll = $('#search-all').is(':checked'); const searchSaved = $('#search-saved').is(':checked'); if (searchAll && !searchSaved) lastSearch.type = 1; else if (!searchAll && searchSaved) lastSearch.type = 2; else if (searchAll && searchSaved) lastSearch.type = 3; else lastSearch.type = 0; setSettings(CONF_LS_LAST_SEARCH, lastSearch); }); $('#search-cat').keypress(function (e) { if (e.which == 13) { $('#search-text').focus(); return false; } }); $('#search-text').keypress(function (e) { if (e.which == 13) { searchLs(); return false; } }); $('a').click(function (e) { if ($(this).attr('id') === 'f3') { if (e.ctrlKey) { return; } e.preventDefault(); history.pushState(null, null, 'https://catwar.su/ls?3'); showSavedLsList(); } else if ($(this).attr('id') === 's') { if (e.ctrlKey) { return; } e.preventDefault(); history.pushState(null, null, 'https://catwar.su/ls?search'); showSearch(); } else { hideSavedLsList(); hideSearch(); } }); const observer = new MutationObserver(function (mutations) { mutations.forEach(function () { if (enableSaving && isPage('ls?3')) { history.pushState(null, null, 'https://catwar.su/ls?3'); showSavedLsList(); } else if (isPage('ls?search')) { history.pushState(null, null, 'https://catwar.su/ls?search'); showSearch(); } else { if (enableSaving) hideSavedLsList(); hideSearch(); } if (isPage('ls?new')) addBBcode(); if (enableSaving && isPage(/^https:\/\/catwar.su\/ls\?id=\d+/)) changeMessagePage(); }); }); observer.observe($('#main')[0], { childList: true }); } function showSearch() { $('.active').removeClass('active'); $('#s').addClass('active'); $('#main, #saved').hide(); $('#search').show(); } function hideSearch() { $('#main').show(); $('#search').hide(); } function showSavedLsList() { $('.active').removeClass('active'); $('#f3').addClass('active'); $('#main, #search').hide(); $('#saved').show(); } function hideSavedLsList() { $('#main').show(); $('#saved').hide(); } function changeMessagePage() { if ($('#delete-saved-ls').length) return; if ($('.bbcode').length) addBBcode(); const main = $('#main'); const lsId = parseInt(window.location.href.split('=')[1], 10); const ls = getSavedLsById(lsId); const btnDelete = `<input id="delete-saved-ls" type="button" value="Удалить" style="float: right">`; if ($('#msg_subject').length && lsId) { const btnSave = `<input id="savels" type="button" value="Сохранить" style="float: right">`; const subjectTd = $('#msg_subject'); subjectTd.html(`<span id="msg_subject">${subjectTd.html()}</span>${btnSave}`); subjectTd.removeAttr('id'); $('#savels').click(saveLs); if (ls) { const td = $('#msg_table > tbody > tr:last-child > td'); td.html(td.html() + `<i id="savedate">Сохранено ${ls.savedate}</i> ${btnDelete}`); } } else if (main.html() === 'ЛС не найдено.' && ls) { insertSavedLs(main, lsId, ls, btnDelete); } if ($('#delete-saved-ls').length) $('#delete-saved-ls').click(function () { if (confirm('Удалить это ЛС из сохранённых?')) { deleteSavedLs(); window.location.reload(); } }); if ($('#msg_login').length) { let myId; if (ls) myId = Number(ls.myId); else myId = Number(main.data('id')); const catId = Number(getNumber($('#msg_login').attr('href'))); const history = JSON.parse(window.localStorage.getItem('cwmod_ls_history') || '{}'); if (!history[myId]) { history[myId] = {}; } if (!history[myId][catId]) { history[myId][catId] = {}; } $('#msg_info > .msg_open').each(function () { const id = $(this).data('id'); const isMy = ($(this).text() === '-'); history[myId][catId][id] = isMy; }); saveData('ls_history', history); } } function insertSavedLs(main, lsId, ls, btnDelete) { const info = ` ${ls.type ? 'Получатель' : 'Отправитель'}: <span id="msg_login" href="/cat${ls.catId}">${ls.catName}</span> <br>${ls.date} <br>Переписка: <span id="msg-history"></span> `; if (isDesctop) { main.html(` <table id="msg_table" border="1"> <tbody> <tr><td colspan="2">${escapeHTML(ls.subject)}</td></tr> <tr><td id="msg_info" valign="top">${info}</td><td>${ls.text}</td></tr> <tr><td colspan="2"><i>${ls.type ? 'Отправитель' : 'Получатель'}: ${ls.myName} [${ls.myId}]<br>Сохранено ${ls.savedate} ${btnDelete}</i></td></tr> </tbody> </table> `); } else { main.html(` <table id="msg_table" border="1"> <tbody> <tr><td>${escapeHTML(ls.subject)}</td></tr> <tr><td id="msg_info" valign="top">${info}</td></tr> <tr><td>${ls.text}</td></tr> <tr><td><i>${ls.type ? 'Отправитель' : 'Получатель'}: ${ls.myName} [${ls.myId}]<br>Сохранено ${ls.savedate} ${btnDelete}</i></td></tr> </tbody> </table> `); } setCatName(ls.catId, `#msg_login`, ls.catName); const history = JSON.parse(window.localStorage.getItem('cwmod_ls_history'))[ls.myId][ls.catId]; const historyArray = {}; Object.keys(history).forEach(function (key) { const isMy = history[key]; $('#msg-history').prepend(`<span class="msg_deleted">${isMy ? '-' : '+'}</span> `); }); Object.keys(history).forEach(function (key) { const isMy = history[key]; $.post('/ajax/mess_show', { id: key }, function (data) { const isSaved = getSavedLsById(key); if (isSaved || !data.fail) { let lsLink = `<a href="ls?id=${key}" class="msg_open" data-id="${key}">` if (Number(key) === lsId) lsLink += `<big><b>` lsLink += isMy ? '-' : '+'; if (Number(key) === lsId) lsLink += `</b></big>` if (Number(key) === lsId) lsLink += `</b></big>` lsLink += `</a>` historyArray[key] = lsLink; } else { historyArray[key] = `<span class="msg_deleted">${isMy ? '-' : '+'}</span>`; } if (Object.keys(historyArray).length === Object.keys(history).length) { $('#msg-history').empty(); Object.keys(historyArray).forEach(function (k) { $('#msg-history').prepend(historyArray[k] + ' '); }); } }, 'json'); }); } function searchLs() { const folder = parseInt($('[name="search-folder"]:checked').val(), 10); const searchAll = $('#search-all').is(':checked'); const searchSaved = $('#search-saved').is(':checked'); if (!searchAll && searchSaved && folder === 2) { $('#search-list').html('<img src="/img/stickers/systempaw2/6.png">'); } else { $('#search-list').html(` <h2>Результаты поиска</h2> <p>Найдено: <span id="search-number">0</span></p> <table id="messList"> <tbody id="search-results"> <tr class="msg"><th>Тема</th><th>${folder === 1 ? 'Получатель' : 'Отправитель'}</th><th>Дата</th></tr> </tbody> </table> `); const cat = $('#search-cat').val(); let text = $('#search-text').val(); if (text) { text = text.match(/['_\-а-яёa-z0-9$]+/gi); text = new RegExp(text.join('|'), 'gi'); } if (searchAll || !searchSaved) searchAllLs(folder, cat, text); if (searchSaved || !searchAll) searchSavedLs(folder, cat, text); } } function searchAllLs(type, cat, text) { getCatIdByName(cat, function (catId) { $.post('/ajax/mess_folder', { folder: type, page: 1, del: 0 }, function (data) { const column = (type ? 'poluch' : 'otpr'); for (let i = 1; i <= data.page; i++) { $.post('/ajax/mess_folder', { folder: type, page: i, del: 0 }, function (data) { for (let j = 0; j < data.msg.length; j++) { const msg = data.msg[j]; const id = msg.id; const html = ` <tr class="${msg.new ? 'msg' : 'msg_notRead'}"> <td><a href="ls?id=${msg.id}" class="msg_open" data-id="${msg.id}">${msg.subject}</a></td> <td><a href="cat${msg[column]}">${msg.login}</a></td> <td>${msg.time}</td> </tr> `; $.post('/ajax/mess_show', { id: id }, function (data) { if (cat) { if (catId !== msg[column] && cat !== msg[column] && cat.toLowerCase() !== msg.login.toLowerCase()) return; } if (text) { if (!data.msg.subject.match(text) && !data.msg.text.replace(/<[^>]+>/g, '').match(text)) return; } $('#search-results').append(html); $('#search-number').html($('#search-results').children().length - 1); }, 'json'); } }, 'json'); } }, 'json'); }); } function searchSavedLs(type, cat, text) { const savedLs = JSON.parse(window.localStorage.getItem('cwmod_ls')); let result = ''; if (savedLs) { getCatIdByName(cat, function (catId) { for (let key in savedLs) { const ls = savedLs[key]; if (ls.type !== type) continue; if (cat) { if ( catId !== ls.catId && cat !== ls.catId && cat.toLowerCase() !== ls.catName.toLowerCase() ) { continue; } } if (text) { if ( !ls.subject.match(text) && !ls.text.replace(/<[^>]+>/g, '').match(text) ) { continue; } } $.post('/ajax/mess_show', { id: key }, function (data) { if (data.fail) { const html = ` <tr class="msg"> <td><a href="ls?id=${key}" class="msg_open" data-id="${key}">${escapeHTML(ls.subject)}</a></td> <td class="search-cat-name" data-id="${key}">${ls.catName}</td> <td>${ls.savedate}</td> </tr> `; $('#search-results').append(html); $('#search-number').html($('#search-results').children().length - 1); setCatName(ls.catId, `.search-cat-name[data-id="${key}"]`, ls.catName); } }, 'json'); } }); } else { result = 'Нет сохранённых сообщений'; } } function updateSavedLsList() { const savedLs = JSON.parse(window.localStorage.getItem('cwmod_ls')); if (savedLs) { $('#saved-list').html(` <h2>Входящие</h2> <table class="messList"> <tbody id="inboxLsList"> <tr class="msg"><th>Тема</th><th>Отправитель</th><th>Дата сохранения</th></tr> </tbody> </table> <h2>Отправленные</h2> <table class="messList"> <tbody id="outboxLsList"> <tr class="msg"><th>Тема</th><th>Получатель</th><th>Дата сохранения</th></tr> </tbody> </table> `); const inbox = $('#inboxLsList'); const outbox = $('#outboxLsList'); for (let key in savedLs) { const ls = savedLs[key]; const html = ` <tr class="msg"> <td><a href="ls?id=${key}" class="msg_open" data-id="${key}">${escapeHTML(ls.subject)}</a></td> <td class="cat_name" data-id="${key}">${ls.catName}</td> <td>${ls.savedate}</td> </tr> `; if (ls.type) outbox.append(html); else inbox.append(html); setCatName(ls.catId, `.cat_name[data-id="${key}"]`, ls.catName); } $('#saved-number').text(Object.keys(savedLs).length); } else { $('#saved-number').text(0); $('#saved-list').html(`Сообщений нет.`); } } function saveLs() { try { const savedLs = JSON.parse(window.localStorage.getItem('cwmod_ls') || '{}'); const main = $('#main'); const lsId = parseInt(window.location.href.split('=')[1], 10); const lsInfo = $('#msg_info').html(); const ls = {}; ls.subject = $('#msg_subject').text(); ls.text = $('#msg_table').find('.parsed').html(); ls.date = findDate(lsInfo); ls.catId = parseInt(getNumber($('#msg_login').attr('href')), 10); ls.catName = $('#msg_login').html(); ls.myId = main.data('id'); ls.myName = main.data('login'); ls.type = lsInfo.match(/Получатель/) ? 1 : 0; const now = new Date(); const saveDate = {}; saveDate.day = leadingZero(now.getDate()); saveDate.month = leadingZero(now.getMonth() + 1); saveDate.year = now.getFullYear(); saveDate.hour = leadingZero(now.getHours()); saveDate.minute = leadingZero(now.getMinutes()); saveDate.second = leadingZero(now.getSeconds()); ls.savedate = `${saveDate.year}-${saveDate.month}-${saveDate.day} ${saveDate.hour}:${saveDate.minute}:${saveDate.second}`; savedLs[lsId] = ls; saveData('ls', savedLs); if ($('#savedate').length) $('#savedate').text(`Сохранено ${ls.savedate}`); else { const td = $('#msg_table > tbody > tr:last-child > td'); td.append(`<i id="savedate">Сохранено ${ls.savedate}</i> <input id="deleteSavedLs" type="button" value="Удалить" style="float: right">`); $('#saved-number').text(Number($('#saved-number').text()) + 1); } updateSavedLsList(); $('#delete-saved-ls').click(function () { if (confirm('Удалить это ЛС из сохранённых?')) { deleteSavedLs(); window.location.reload(); } }); } catch (err) { window.console.error('Варомод:', err); } } function deleteSavedLs() { try { const savedLs = JSON.parse(window.localStorage.getItem('cwmod_ls')); if (!savedLs) return; const lsId = parseInt(window.location.href.split('=')[1], 10); delete savedLs[lsId]; saveData('ls', savedLs); } catch (err) { window.console.error('Варомод:', err); } } function getSavedLsById(lsId) { try { const savedLs = JSON.parse(window.localStorage.getItem('cwmod_ls')); if (!savedLs) return; const ls = savedLs[lsId]; return ls || false; } catch (err) { window.console.error('Варомод:', err); } } /* function changeTimePage() { const catTimeNow = timestampToCatTime(Date.now()); $(isDesctop ? '#branch' : '#site_table').append(` <div style="width: fit-content; margin: 0 auto"> <p><b>Настоящее кошачье время</b></p> <p id="real-cat-time">${catTimeNow.day} ${months[catTimeNow.month]} ${catTimeNow.year} года, ${leadingZero(catTimeNow.hour)}:${leadingZero(catTimeNow.minute)}:${leadingZero(catTimeNow.second)}</p> <p><b>Калькулятор времени</b></p> <p>Кошачье время: <input type="number" id="cat-day" min="1" max=""> <input type="time" id="cat-time"></p> <p>Время двуногих: <input type="datetime-local" id="twoleg-time" min="${dateToString(catTimeStart)}" value="${dateToString(new Date)}" max="9999-31-12T23:59"></p> </div> `); } */ function changeSettingsPage() { let css = ` .copy { cursor: pointer; } #cwmod-settings h2 { text-indent: 1.5em; } #cwmod-settings h3 { margin: 1em 0 0.5em 1em; } #cwmod-settings h4 { margin: 0; } #cwmod-settings ul { margin: 0; padding: 0 0 0 30px; list-style-type: kannada; } #cwmod-settings ul ul { padding: 0 0 0 10px; list-style-type: none; } #cwmod-settings li { padding: 0.2em 0; } .cwmod-settings[type="checkbox"] { margin-left: 0; cursor: pointer; } .cwmod-data-result { margin-bottom: 1em; max-height: 300px; overflow-y: auto; white-space: pre-line;} .cwmod-error { font-weight: bold; color: darkred; } .cwmod-done { font-weight: bold; color: darkgreen; } `; addCSS(css); if (getSettings(CONF_SETTINGS_HIDE_EMAIL)) { addCSS(`input[name="mail"]:not(:focus) { color: #333; }`, CONF_SETTINGS_HIDE_EMAIL); } const html = ` <div id="cwmod-settings"> <h2 id="cwmod">Настройки Варомода (CatWar Mod)</h2> <h3>Сайт</h3> <h4>Мой кот/моя кошка</h4> <ul> <li><input class="cwmod-settings" type="checkbox" data-conf="${CONF_INDEX_SAVE_ALERT}"> Предупреждение при уходе со страницы</li> <li><input class="cwmod-settings" type="checkbox" data-conf="${CONF_INDEX_EDUCATION_HIDE}"> Скрывать обучение</li> </ul> <h4>Профили игроков</h4> <ul> <li><input class="cwmod-settings" type="checkbox" data-conf="${CONF_CAT_ADD_KRAFT_NUMBER}"> Уровень БУ цифрой</li> <li><input class="cwmod-settings" type="checkbox" data-conf="${CONF_CAT_ENABLE_NOTES}"> Возможность создавать заметки об игроках</li> </ul> <h4>Друзья и враги</h4> <ul> <li><input class="cwmod-settings" type="checkbox" data-conf="${CONF_FAE_SHOW_NOTES}"> Показывать заметки</li> </ul> <h4>Личные сообщения</h4> <ul> <li><input class="cwmod-settings" type="checkbox" data-conf="${CONF_LS_ENABLE_SAVING}"> Возможность сохранять ЛС</li> </ul> <h4>Блоги и лента</h4> <ul> <li><input class="cwmod-settings" type="checkbox" data-conf="${CONF_CREATION_SAVE_ALERT}"> Предупреждение при уходе со страницы создания нового блога или поста</li> <li><input class="cwmod-settings" type="checkbox" data-conf="${CONF_BLOGS_AVATARS}"> Аватарки в комментариях <ul data-show="${CONF_BLOGS_AVATARS}"> <li>Размер: <input class="cwmod-settings" type="number" min="30" max="250" style="width: 45px" data-conf="${CONF_BLOGS_AVATARS_SIZE}"> px</li> <li><input class="cwmod-settings" type="checkbox" data-conf="${CONF_BLOGS_AVATARS_NO_CROP}"> Не обрезать до квадрата</li> <li><input class="cwmod-settings" type="checkbox" data-conf="${CONF_BLOGS_AVATARS_BORDER}"> Рамки у аватарок</li> </ul> </li> <li><input class="cwmod-settings" type="checkbox" data-conf="${CONF_BLOGS_COMMENTS_SMILES}"> Смайлики в комментариях</li> <li>Максимальная ширина картинок <ul> <li>в блогах: <input class="cwmod-settings" type="number" min="0" max="1000" style="width: 55px" data-conf="${CONF_BLOGS_IMAGES_MAX_WIDTH}"> px</li> <li>в Ленте: <input class="cwmod-settings" type="number" min="0" max="1000" style="width: 55px" data-conf="${CONF_SNIFF_IMAGES_MAX_WIDTH}"> px</li> <li><small>0 — значение по умолчанию (не уменьшать)</small></li> </ul> </li> <li><input class="cwmod-settings" type="checkbox" data-conf="${CONF_BLOGS_ANSWER_BUTTON}"> Кнопка «Ответить на комментарий»</li> <li><input class="cwmod-settings" type="checkbox" data-conf="${CONF_BLOGS_CITE_BUTTON}"> Кнопка «Цитировать комментарий» <ul data-show="${CONF_BLOGS_CITE_BUTTON}"> <li><input class="cwmod-settings" type="checkbox" data-conf="${CONF_BLOGS_CITE_BUTTON_HIDE}"> Показывать только при выделении текста</li> </ul> </li> </ul> <h4>Настройки</h4> <ul> <li><input class="cwmod-settings" type="checkbox" data-conf="${CONF_SETTINGS_HIDE_EMAIL}"> Спрятать адрес электронной почты</li> </ul> <h3>Игровая</h3> <ul> <li><input class="cwmod-settings" type="checkbox" data-conf="${CONF_CW3_ACT_END_IN_TITLE}"> Время до окончания действия в заголовке</li> <li><input class="cwmod-settings" type="checkbox" data-conf="${CONF_CW3_ACT_END_ALERT}"> Звук об окончании действия <ul data-show="${CONF_CW3_ACT_END_ALERT}"> <li>за <input class="cwmod-settings" type="number" min="1" max="30" style="width: 35px" data-conf="${CONF_CW3_ACT_END_ALERT_TIME}"> с до окончания</li> <li>Звук: <input class="cwmod-settings" type="text" data-conf="${CONF_CW3_ACT_END_ALERT_SOUND}"> <a href="#" class="cwmod-settings-set-default" data-rel="${CONF_CW3_ACT_END_ALERT_SOUND}">по умолчанию</a></li> <li>Громкость: <input class="cwmod-settings" type="range" min="0.05" max="1" step="0.05" data-conf="${CONF_CW3_ACT_END_ALERT_VOLUME}"> <a href="#" class="cwmod-settings-test-sound" data-audio="${CONF_CW3_ACT_END_ALERT_SOUND}" data-volume="${CONF_CW3_ACT_END_ALERT_VOLUME}">проиграть</a></li> <li><input class="cwmod-settings" type="checkbox" data-conf="${CONF_CW3_ACT_END_ALERT_BLUR_ONLY}"> Только если вкладка неактивна</li> </ul> </li> <li>Высота лога боёв: <input class="cwmod-settings" type="number" min="70" max="1000" style="width: 55px" data-conf="${CONF_CW3_FIGHT_PANEL_HEIGHT}"> px</li> <li><input class="cwmod-settings" type="checkbox" data-conf="${CONF_CW3_PARAMETERS_INFO}"> Параметры подробно <br><small>Значения в процентах и в пикселях, примерное время выполнения действий</small> </li> </ul> <h4>Меню</h4> <ul> <li><input class="cwmod-settings" type="checkbox" data-conf="${CONF_CW3_MENU_TARGET_BLANK}"> Открывать в новой вкладке</li> <li>Добавить пункты: <ul> <li><input class="cwmod-settings" type="checkbox" data-conf="${CONF_CW3_MENU_ABOUT}"> Об игре</li> <!--<li><input class="cwmod-settings" type="checkbox" data-conf="${CONF_CW3_MENU_INDEX}"> ${$('.kn1').length ? 'Мой кот' : 'Моя кошка'}</li>--> <li><input class="cwmod-settings" type="checkbox" data-conf="${CONF_CW3_MENU_TOP}"> СИ (список игроков)</li> <!--<li><input class="cwmod-settings" type="checkbox" data-conf="${CONF_CW3_MENU_CHAT}"> Чат</li>--> <!--<li><input class="cwmod-settings" type="checkbox" data-conf="${CONF_CW3_MENU_LS}"> ЛС</li>--> <li><input class="cwmod-settings" type="checkbox" data-conf="${CONF_CW3_MENU_LS0}"> Памятка</li> <li><input class="cwmod-settings" type="checkbox" data-conf="${CONF_CW3_MENU_BLOGS}"> Блоги</li> <li><input class="cwmod-settings" type="checkbox" data-conf="${CONF_CW3_MENU_SNIFF}"> Лента</li> <li><input class="cwmod-settings" type="checkbox" data-conf="${CONF_CW3_MENU_SETTINGS}"> Настройки</li> <li><input class="cwmod-settings" type="checkbox" data-conf="${CONF_CW3_MENU_MOBILE}"> Сменить версию</li> </ul> </li> </ul> <h4>Оформление</h4> <ul> <li>Тема: <select class="cwmod-settings" data-conf="${CONF_CW3_THEME}"> <option value="default">По умолчанию</option> <option value="dark_grey">Тёмно-серая</option> <option value="black_glass">Полупрозрачная чёрная</option> </select> <br><small>Больше тем в <a href="https://porch.website/scripts#cwredesign">Вароредизайне</a>. Не используйте темы Вароредизайна и Варомода одновременно!</small> </li> <li><input class="cwmod-settings" type="checkbox" data-conf="${CONF_CW3_COMPACT}"> Компактная игровая ${(($(window).width() < 1500 || $(window).height() < 700) ? ' (не рекомендуется)' : '')} <ul data-show="${CONF_CW3_COMPACT}"> <li><input class="cwmod-settings" type="checkbox" data-conf="${CONF_CW3_COMPACT_SWAP_SIDES}"> Поменять местами блоки (погода, действия, «во рту», чат справа)</li> <li><input class="cwmod-settings" type="checkbox" data-conf="${CONF_CW3_COMPACT_CHAT_ON_TOP}"> Чат наверху</li> <li><input class="cwmod-settings" type="checkbox" data-conf="${CONF_CW3_COMPACT_ROUND_EDGES}"> Скруглить углы</li> <li><input class="cwmod-settings" type="checkbox" data-conf="${CONF_CW3_COMPACT_SPLIT_INFO}"> Разделить параметры, историю и родственные связи <a href="#" id="about-split-info">(?)</a> <!--<ul data-show="${CONF_CW3_COMPACT_SPLIT_INFO}"> <li><input class="cwmod-settings" type="checkbox" data-conf="${CONF_CW3_COMPACT_SPLIT_INFO_STICKY_HEADERS}"> Закрепить заголовки</li> </ul>--> </li> </ul> </li> <li>Фон страницы: <select class="cwmod-settings" data-conf="${CONF_CW3_BACKGROUND}"> <option value="default">по умолчанию</option> <option value="location">фон локации</option> <option value="own">свой</option> </select> <ul data-show="${CONF_CW3_BACKGROUND}" data-cond="own"> <li>Картинка: <input class="cwmod-settings" type="text" data-conf="${CONF_CW3_BACKGROUND_IMAGE}"></li> </ul> <ul data-show="${CONF_CW3_BACKGROUND}" data-cond="!default"> <li>Размер: <select class="cwmod-settings" data-conf="${CONF_CW3_BACKGROUND_SIZE}"> <option value="auto">автоматически</option> <option value="cover">по размеру страницы</option> </select> </li> <li>Положение: <select class="cwmod-settings" data-conf="${CONF_CW3_BACKGROUND_POSITION}"> <option value="top left">вверху слева</option> <option value="top center">вверху по центру</option> <option value="top right">вверху справа</option> <option value="center left">по центру слева</option> <option value="center">по центру</option> <option value="center right">по центру справа</option> <option value="bottom left">внизу слева</option> <option value="bottom center">внизу по центру</option> <option value="bottom right">внизу справа</option> </select> </li> </ul> </li> <li><input class="cwmod-settings" type="checkbox" data-conf="${CONF_CW3_HISTORY_NO_UNDERLINE}"> Не подчёркивать ссылки на профили в истории</li> </ul> <h4>Окружающий мир</h4> <ul> <li><input class="cwmod-settings" type="checkbox" data-conf="${CONF_CW3_WEATHER_SNOW}"> Снежинки на странице, когда идет снег</li> <li><input class="cwmod-settings" type="checkbox" data-conf="${CONF_CW3_HIDE_SKY}"> Скрывать небо</li> </ul> <h4>Локация</h4> <ul> <li><input class="cwmod-settings" type="checkbox" data-conf="${CONF_CW3_CAGES_BORDERS}"> Обозначить границы клеток</li> <li><input class="cwmod-settings" type="checkbox" data-conf="${CONF_CW3_ALWAYS_DAY}"> Всегда день (убрать затемнение игрового поля)</li> </ul> <h4>Чат</h4> <ul> <li><input class="cwmod-settings" type="checkbox" data-conf="${CONF_CW3_CHAT_QUIET_LOUDER}"> Увеличивать шрифт тихих звуков</li> <li><input class="cwmod-settings" type="checkbox" data-conf="${CONF_CW3_CHAT_LOUD_QUIETER}"> Уменьшать шрифт громких звуков</li> </ul> <h4>Игроки</h4> <ul> <li><input class="cwmod-settings" type="checkbox" data-conf="${CONF_CW3_LOWER_CATS}"> Опустить котов вниз клеток <ul data-show="${CONF_CW3_LOWER_CATS}"> <li><input class="cwmod-settings" type="checkbox" data-conf="${CONF_CW3_LOWER_ARROWS}"> Опустить стрелки в боережиме</li> </ul> </li> <li><input class="cwmod-settings" type="checkbox" data-conf="${CONF_CW3_DEAD_OPAQUE}"> Сделать мёртвых игроков непрозрачными</li> <li> <input class="cwmod-settings" type="checkbox" data-conf="${CONF_CW3_CAT_INFO}"> Более подробная информация <br><small>То, что можно увидеть в кодах: рост, ссылка на окрас, степени грязи и болезней</small> </li> <li> <input class="cwmod-settings" type="checkbox" data-conf="${CONF_CW3_MODIFY_INVENTORY}"> Сокращать инвентарь <br><small>Вместо повторения предметов одного типа писать их количество</small> </li> <li><input class="cwmod-settings" type="checkbox" data-conf="${CONF_CW3_ADD_REALISM}"> Добавить реализма</li> </ul> <h4>Конструктор окрасов</h4> <ul> <li><input class="cwmod-settings" type="checkbox" data-conf="${CONF_KNS_SAVE_ALERT}"> Предупреждение при уходе со страницы</li> </ul> <p><input id="clear-ym-storage" type="button" value="Кнопка"> для тех, у кого ничего не сохраняется</p> <div id="clear-ym-storage-result"></div> <h3>Импорт и экспорт данных</h3> <details><summary>Как пользоваться</summary> <ol> <li>Скопируйте нужные данные в браузере, откуда вы их хотите перенести.</li> <li>Вставьте их в поле «Импорт» того же раздела в браузере, куда вы их хотите перенести.</li> <li>Нажмите на кнопку «Объединить» («Обновить» в случае настроек).</li> </ol> </details> <h4>Заметки об игроках</h4> <p>Экспорт: <input class="cwmod-data-export" data-export="notes" type="text" readonly> <img class="copy" title="Скопировать" alt="Скопировать" data-copy="notes" src="cw3/symbole/copy.png"></p> <p>Импорт: <input class="cwmod-data-import" data-import="notes" type="text"></p> <p><input class="cwmod-data-merge" data-merge="notes" type="button" value="Объединить"></p> <div class="cwmod-data-result" data-result="notes"></div> <h4>Личные сообщения</h4> <p>Экспорт: <input class="cwmod-data-export" data-export="ls" type="text" readonly> <img class="copy" title="Скопировать" alt="Скопировать" data-copy="ls" src="cw3/symbole/copy.png"></p> <p>Импорт: <input class="cwmod-data-import" data-import="ls" type="text"></p> <p><input class="cwmod-data-merge" data-merge="ls" type="button" value="Объединить"></p> <div class="cwmod-data-result" data-result="ls"></div> <h4>Настройки</h4> <p>Экспорт: <input class="cwmod-data-export" data-export="settings" type="text" readonly> <img class="copy" title="Скопировать" alt="Скопировать" data-copy="settings" src="cw3/symbole/copy.png"></p> <p>Импорт: <input class="cwmod-data-import" data-import="settings" type="text"></p> <p><input class="cwmod-data-merge" data-merge="settings" type="button" value="Обновить"></p> <div class="cwmod-data-result" data-result="settings"></div> <h3><a href="/blog482084">Блог Варомода</a></h3> </div> `; $(isDesctop ? '#branch' : '#site_table').append(html); updateSettingsInputs(); try { $('.cwmod-data-export').each(function () { const key = $(this).data('export'); $(this).val(window.localStorage.getItem('cwmod_' + key)) }); $(window).on('storage', function (e) { if (e.originalEvent.key === 'cwmod_settings') { $('[data-export="notes"]').val(e.originalEvent.newValue); } if (e.originalEvent.key === 'cwmod_ls') { $('[data-export="ls"]').val(e.originalEvent.newValue); } }); } catch (err) { window.console.error('Варомод:', err); } $('#about-split-info').click(function (e) { e.preventDefault(); showCwmodPopup('alert', '<img src="https://porch.website/cwmod/settings.png">'); }); $('.cwmod-data-import').click(function () { $(this).select(); }); $('.cwmod-data-merge').click(function () { const key = $(this).data('merge'); mergeData(key); }); $('.copy').click(function () { const key = $(this).data('copy'); $(`input[data-export="${key}"]`).select(); document.execCommand('copy'); alert('Скопировано!'); }); $(`[data-conf="${CONF_SETTINGS_HIDE_EMAIL}"]`).change(function () { if ($(this).is(':checked')) { addCSS(`input[name="mail"]:not(:focus) { color: #333; }`, CONF_SETTINGS_HIDE_EMAIL); } else removeCSS(CONF_SETTINGS_HIDE_EMAIL); }); $('#clear-ym-storage').click(function () { try { window.localStorage.setItem('storage-test', Math.pow(2, 1023).toString(2)); $('#clear-ym-storage-result').html('Вообще-то сохраняется...'); window.localStorage.removeItem('storage-test'); } catch (err) { const ymSize = window.localStorage.getItem('_ym_alt_retryReqs').length; window.localStorage.removeItem('_ym_alt_retryReqs'); $('#clear-ym-storage-result').html(`Возможно, чистка ${ymSize} байт данных Яндекс.Метрики могла помочь`); } }); } function mergeData(dataKey) { $(`[data-result]`).empty(); let exp = $(`[data-export="${dataKey}"]`).val(); let imp = $(`[data-import="${dataKey}"]`).val(); if (!imp) { mergeDataError(dataKey, null, ['С чем объединять-то?', '<img src="/img/stickers/systempaw2/6.png">']); return; } try { if (exp) exp = JSON.parse(exp); } catch (err) { window.console.error(err); mergeDataError(dataKey, 'export', ['Ошибка парсинга JSON']); return; } try { imp = JSON.parse(imp); } catch (err) { window.console.error(err); mergeDataError(dataKey, 'import', ['Ошибка парсинга JSON']); return; } const validExp = mergeDataValidate(dataKey, exp); if (validExp.error) { mergeDataError(dataKey, 'export', validExp.text); return; } const validImp = mergeDataValidate(dataKey, imp); if (validImp.error) { mergeDataError(dataKey, 'import', validImp.text); return; } let text = []; const merged = Object.assign({}, exp, imp); Object.keys(merged).forEach(function (key) { if (dataKey === 'settings') { if (DEFAULTS[key] === undefined) { delete merged[key]; return; } } if (exp[key] && imp[key]) { if (dataKey === 'ls') { if (exp[key].catName === imp[key].catName && exp[key].savedate > imp[key].savedate) { merged[key] = exp[key]; } } else if (dataKey === 'notes') { if (exp[key] === imp[key]) return; else if (exp[key].indexOf(imp[key]) !== -1) { merged[key] = exp[key]; text.push(`Заметки об игроке с ID ${key}: "${exp[key]}" и "${imp[key]}" — объединены`); } else if (imp[key].indexOf(exp[key]) === -1) { merged[key] = exp[key] + '\n' + imp[key]; text.push(`Заметки об игроке с ID ${key}: "${exp[key]}" и "${imp[key]}" — объединены в "${merged[key]}"`); } } } }); console.log(merged); saveData(dataKey, merged); $('[data-export="${dataKey}"]').val(JSON.stringify(merged)); mergeDataDone(dataKey, text); } function mergeDataValidate(dataKey, data) { let error = false, text = []; Object.keys(data).forEach(function (k) { if (dataKey === 'notes') { if (!/^\d+$/.test(k)) { error = true; text.push(`Ключ _${k}_ не ID игрока`); } if (typeof data[k] !== 'string') { error = true; text.push(`Элемент _${k}_ не заметка`); } } else if (dataKey === 'ls') { if (!/^\d+$/.test(k)) { error = true; text.push(`Ключ _${k}_ не ID сообщения`); } if (typeof data[k] !== 'object') { error = true; text.push(`Элемент _${k}_ не сообщение`); } else { const lsKeys = ['subject', 'text', 'type', 'savedate', 'catId', 'catName', 'date', 'myId', 'myName']; const thisKeys = Object.keys(data[k]); if (thisKeys.length !== lsKeys.length) { error = true; text.push(`Элемент ${k} не сообщение`); } else { let keysError = false; lsKeys.forEach(function (key) { if (thisKeys.indexOf(key) === -1) { keysError = true; } }); if (keysError) { error = true; text.push(`Элемент ${k} не сообщение`); } } } } }); return { error: error, text: text } } function mergeDataError(dataKey, type, text = []) { let errorText = 'Ошибка: '; const errors = { 'export': 'неправильный формат исходных данных (в порядке всё с ними было, зачем трогать???)', 'import': 'неправильный формат входных данных' }; errorText += errors[type] || 'Неизвестная ошибка'; $(`[data-result="${dataKey}"]`).append(`<p class="cwmod-error">${errorText}</p>${text.join('<br>')}`); } function mergeDataDone(dataKey, text = []) { let resultText = 'Данные успешно объединены'; if (dataKey === 'settings') resultText = 'Настройки успешно обновлены'; $(`[data-result="${dataKey}"]`).append(`<p class="cwmod-done">${resultText}!</p>${text.join('<br>')}`); } function updateSettingsInputs() { Object.keys(DEFAULTS).forEach(function (key) { const input = $(`[data-conf="${key}"]`); if (!input.length) return; const val = getSettings(key); if (input.is('select')) { $(`[data-conf="${key}"] > [value="${val}"]`).prop('selected', true); $(`[data-show="${key}"]`).each(function () { let cond = $(this).data('cond'); const invert = /^!/.test(cond); cond = cond.replace(/^!/, ''); if (invert !== (cond === val)) $(this).show(); else $(this).hide(); }); } else { const type = input.attr('type'); switch (type) { case 'text': case 'number': case 'range': input.val(val); break; case 'checkbox': input.prop('checked', val); if (val) $(`[data-show="${key}"]`).show(); else $(`[data-show="${key}"]`).hide(); break; default: window.console.error('я сломался зови хвойницу чинить'); } } }); } function addCSS(css, key) { const styleId = key ? 'cwmod-style-' + key : 'cwmod-style'; const style = $('#' + styleId); if (style.length) { style.append(css); } else { $('head').append(`<style id="${styleId}">${css}</style>`); } } function removeCSS(key) { $('#cwmod-style-' + key).remove(); } function getSettings(key) { thisPageSettings.push(key); const val = SETTINGS[key]; return val !== undefined ? val : DEFAULTS[key]; } function setSettings(key, val) { SETTINGS[key] = val; saveData('settings', SETTINGS); } function loadSettings() { const key = 'cwmod_settings'; try { SETTINGS = JSON.parse(window.localStorage.getItem(key) || '{}'); if (SETTINGS['cw3_location_bg'] != null) { if (SETTINGS['cw3_location_bg']) SETTINGS[CONF_CW3_BACKGROUND] = 'location'; delete SETTINGS['cw3_location_bg']; } if (SETTINGS['cw3_location_bg_size'] != null) { if (SETTINGS['cw3_location_bg_size'] === 'cover') SETTINGS[CW3_BACKGROUND_SIZE] = 'cover'; delete SETTINGS['cw3_location_bg_size']; } } catch (err) { alert(err); window.localStorage.removeItem(key); SETTINGS = {}; } } function saveData(key, data) { try { window.localStorage.setItem('cwmod_' + key, JSON.stringify(data)); } catch (err) { window.console.error('Варомод:', err); } } function addSaveAlert() { window.addEventListener('beforeunload', beforeunload); $('input[type=submit]').click(function () { window.removeEventListener('beforeunload', beforeunload); }); } function beforeunload(event) { event.preventDefault(); event.returnValue = ''; return ''; } function isPage(page, match) { if (page instanceof RegExp) return page.test(window.location.href); const re = new RegExp('catwar\.su/' + page.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&') + (match ? '(#.*)?$' : '')); return re.test(window.location.href); } function secToTime(sec) { if (!sec) return '0 c'; const d = Math.floor(convertTime('s d', sec)); sec -= convertTime('d s', d); const h = Math.floor(convertTime('s h', sec)); sec -= convertTime('h s', h); const m = Math.floor(convertTime('s m', sec)); sec -= convertTime('m s', m); const s = Math.round(sec); let result = []; if (d) result.push(`<nobr>${d} д</nobr>`); if (h) result.push(`<nobr>${h} ч</nobr>`); if (m) result.push(`<nobr>${m} мин</nobr>`); if (s) result.push(`<nobr>${s} с</nobr>`); return result.join(' '); } function leadingZero(num) { return num < 10 ? '0' + num.toString() : num; } function escapeHTML(str) { return str.replace('<', '$lt;').replace('>', '$gt;'); } function decodeHTML(str) { const doc = new DOMParser().parseFromString(str, "text/html"); return doc.documentElement.textContent; } function getNoteByCatId(catId) { try { const savedNotes = JSON.parse(window.localStorage.getItem('cwmod_notes') || '{}'); const text = savedNotes[catId]; return text || false; } catch (err) { window.console.error('Варомод:', err); } } function addBBcode(type) { const bb = $('.bbcode').parent(); if (!bb.length) return; if ($('.bbcode[data-code="ol"]').length) return; if (type) { bb.append(` <button class="bbcode" title="Перенос" data-code="br" data-parameter="0">br</button> <button class="bbcode" title="Таблица" data-code="table">table</button> <button class="bbcode" title="Строка таблицы" data-code="tr">tr</button> <button class="bbcode" title="Ячейка таблицы" data-code="td">td</button> <button class="bbcode" title="Нумерованный список" data-code="ol">ol</button> <button class="bbcode" title="Ненумерованный список" data-code="ul">ul</button> <button class="bbcode" title="Элемент списка" data-code="li">li</button> `); } else { $('[data-code="block"]').after(` <button class="bbcode" title="Раскрывающийся блок" data-code="overblock" data-parameter="1" data-text="Введите название раскрывающегося блока (то же, что и у заголовка, который раскрывает этот блок):">overblock</button> `); bb.append(` <button class="bbcode" title="Абзац" data-code="p">p</button> <button class="bbcode" title="Перенос" data-code="br" data-parameter="0">br</button> <button class="bbcode" title="Таблица" data-code="table">table</button> <button class="bbcode" title="Строка таблицы" data-code="tr">tr</button> <button class="bbcode" title="Ячейка таблицы" data-code="td">td</button> <button class="bbcode" title="Нумерованный список" data-code="ol">ol</button> <button class="bbcode" title="Ненумерованный список" data-code="ul">ul</button> <button class="bbcode" title="Элемент списка" data-code="li">li</button> `); } } function setAvatar(catId, selector) { $.get('/cat' + catId.toString(), function (data) { const temp = $('<div/>', { html: data }); let avatar = temp.find('[src*=avatar]').attr('src'); if (!avatar) avatar = '//e.catwar.su/avatar/0.jpg'; try { window.sessionStorage.setItem('avatar' + catId, avatar); } catch (err) {} $(selector).css('background-image', `url(${avatar})`); } ); } function setCatName(catId, selector, oldName) { $.post('/preview', { text: `[link${catId}]` }, function (data) { data = data.replace(/<\/?div( class="parsed")?>/, ''); $(selector).html(data); if (oldName && $(selector).text() !== oldName) { $(selector).html(data + ' (' + oldName + ')'); } }); } function getCatIdByName(name, func) { $.post('/ajax/top_cat', { name: name }, function (data) { const catId = parseInt(data, 10); func(catId); }); } function dateToString(date) { if (typeof date === 'number') date = new Date(date); const dateString = date.toISOStringLocal(); return dateString.slice(0, 16); } function declOfNum(n, titles) { n = Math.abs(n); if (isNaN(n)) return titles[2]; if (!Number.isInteger(n)) return titles[1]; n %= 100; if (n > 10 && n < 20) return titles[2]; n %= 10; if (n === 1) return titles[0]; if (n > 1 && n < 5) return titles[1]; return titles[2]; } function convertTime(units, val) { const allUnits = ['ms', 's', 'm', 'h', 'd']; units = units.split(' '); let valUnit = allUnits.indexOf(units[0]); const resultUnit = allUnits.indexOf(units[1]); const multipliers = [1000, 60, 60, 24]; if (valUnit > resultUnit) while (valUnit !== resultUnit) { val *= multipliers[valUnit - 1]; valUnit--; } else while (valUnit !== resultUnit) { val /= multipliers[valUnit]; valUnit++; } return val; } function findDate(text) { return text.match(/(\d?\d )?[а-я]+ (\d{4} )?в \d?\d:\d\d/i)[0]; } function catTimeToMs(y, m, d, h, min, s) { // отсчёт месяцев с 0, дней с 1 const result = (((((((y * 12 + m) * 28 + --d) * 24 + h) * 60) + min) * 60) + s) * 1000 / 7; return Math.round(result); } function timestampToCatTime(timestamp) { const secInYear = 12 * 28 * 24 * 60 * 60; const secInMonth = 28 * 24 * 60 * 60; const ms = timestamp - catTimeStart; let time = Math.round(ms / 1000 * 7); const year = Math.floor(time / secInYear); time -= year * secInYear; const month = Math.floor(time / secInMonth); time -= month * secInMonth; const day = Math.floor(convertTime('s d', time)); time -= convertTime('d s', day); const hour = Math.floor(convertTime('s h', time)); time -= convertTime('h s', hour); const minute = Math.floor(convertTime('s m', time)); time -= convertTime('m s', minute); const second = time; return { year: year, month: month, day: day + 1, hour: hour, minute: minute, second: second }; } function getNumber(s) { return Number(s.match(/\d+/)[0]); } function bbencode(html) { html = html.replace(/<br>/g, '[br]'); html = html.replace(/<(\/?)b>/gm, '[$1b]'); html = html.replace(/<(\/?)i>/gm, '[$1i]'); html = html.replace(/<(\/?)s>/gm, '[$1s]'); html = html.replace(/<(\/?)u>/gm, '[$1u]'); html = html.replace(/<\/?tbody>/gm, ''); html = html.replace(/<(\/?)table>/gm, '[$1table=0]'); html = html.replace(/<(\/?)table border="1">/gm, '[$1table]'); html = html.replace(/<(\/?)tr>/gm, '[$1tr]'); html = html.replace(/<td align="center" valign="top" style="height:25px">(.(?![/b]<\/td>)+)<\/td>/gm, '[td][center]$1[/center][/td]'); html = html.replace(/<(\/?)td>/gm, '[$1td]'); html = html.replace(/[td][i]Цитата:[/i](.(?![/td])+)[/td]/gm, '[td][size=10][i]Цитата:[/i]$1[/size][/td]'); html = html.replace(/<a href="([^"]+)"( target="_blank")?>/gm, '[url=$1]'); html = html.replace(/<\/a>/gm, '[/url]'); html = html.replace(/<img src="([^"]+)"( alt="([^"]+)")?( style="max-width: 4000px;")?>/gm, '[img]$1[/img]'); html = html.replace(/<iframe width="640" height="390" src="https:\/\/www\.youtube\.com\/embed\/([^"]+)" frameborder="0" allowfullscreen=""><\/iframe>/gm, '[header=$1]Видеозапись[/header][br][block=$1][video]$1[/video][/block]'); html = html.replace(/<audio controls=""><source src="([^"]+)" type="audio\/mpeg"> Воспроизведение аудиофайлов не поддерживается вашим браузером.<\/audio>/gm, '[header=$1]Аудиозапись[/header][br][block=$1][audio]$1[/audio][/block]'); html = html.replace(/<(\/?)li>/gm, '[$1li]'); html = html.replace(/<(\/?)ol( style="display:inline-block")?>/gm, '[$1ol]'); html = html.replace(/<(\/?)ul( style="display:inline-block")?>/gm, '[$1ul]'); html = html.replace(/<[^>]+>/gm, ''); html = decodeHTML(html); return html; } })(window, document, jQuery);