Главная » Проза » Любимая игрушка Барона » Книга полностью
Читать онлайн полностью

Любимая игрушка Барона

Автор: Юлия Михайловна Герман

Жанр: Проза

Описание книги
Оцените книгу
0%
Страница 1 из 83 Настройки чтения
  • Тема
  • Шрифт
  • Размер
  • Поля
  • Межстрочный интервал
  • Показывать прогресс

Любимая игрушка Барона читать книгу онлайн

Автор: Юлия Михайловна Герман

обложка книги Любимая игрушка Барона

Юлия Герман

Любимая игрушка Барона

<div class="title"> <p> Глава 1 </p> </div> <p>— Еще раз прими наши соболезнования, — подходили ко мне после поминок люди, тем же черным беспрерывным потоком, что до этого шли на кладбище.</p> <p>— Спасибо, — отвечала на автомате, в то время, как баба Шура раздавала пакетики с едой, чтобы помянули Павла и Маргариту Красновых.</p> <p>— Если что нужно, обращайся, — говорили какие-то странные мужчины в темных костюмах. Но я знала, что никогда и никому не позвоню из них. Потому что даже не запоминала имен.</p> <p>— Не плачь, Сенечка, у каждого своя дорога и свой путь, — успокаивала меня соседка, когда слезы снова бесконтрольно полились из глаз.</p> <p>— Но почему у них такой короткий, баб Шур? — дрожащими руками вытерла слезы платком, когда люди разошлись.</p> <p>— Эх, девочка моя, кто ж может ответить на этот вопрос.</p> <p>— И как я без них теперь? Как жить дальше?</p> <p>— Сенечка, со временем боль притупится и дышать станет легче.</p> <p>— Да как же так? Не верю. Не верю, что их нет, — да и как можно поверить, когда самых родных и близких не стало в один день.</p> <p>Вот ты еще радуешься жизни, строишь планы и в одну секунду все обрывается.</p> <p>Родители попали в жуткую аварию. Их машину зажало между камазом и каретой скорой помощи. Выжил только водитель камаза. А мне приходится смириться с тем, что моих близких больше нет.</p> <p>— Вот и вспоминай их как живых. А пока пойдем, пойдем, моя хорошая. Больше нам здесь делать нечего, — торопила меня соседка, явно уставшая от похорон не меньше моего. — Ты забирай пальто, а я подожду тебя на улице. На свежий воздух надо.</p> <p>— Конечно, баб Шур, — взяла себя в руки. — Вы идите. Я сейчас, — развернулась в сторону гардероба, забирая пальто и сумку.</p> <p>Услышала звук открываемой двери и почувствовала как холодный воздух проник в помещение.</p> <p>— Забыли что-то? — обернулась, рассчитывая увидеть соседку, но вместо нее стояло два здоровых амбала в черных кожаных куртках.</p> <p>Лица незнакомцев совсем не напоминали тех солидных мужчин, что приходили сегодня. Один бородатый и темноволосый с острым, как кинжал взглядом. А второй лысый и с щетиной на щеках, и таким скользким взглядом, что от него хотелось спрятаться. Он жевал жвачку, что и вовсе казалось неприличным в сложившейся ситуации.</p> <p>— Вы на поминки? — заметила, как осмотрел меня с ног до головы лысый, лениво работая челюстями и внутренне сжалась. — Вы опоздали, но присаживайтесь, вас накормят.</p> <p>— А ты дочь? — кивнул в мою сторону массивным подбородком бритоголовый шкаф.</p> <p>— Да, дочь, — насторожилась. Слишком нахально и развязно он выглядел и этот вопрос, без малейшего намека на сострадание.</p> <p>— Ты-то нам и нужна! — шагнули они ко мне практически одновременно .</p> <p>— Что значит нужна? — отшатнулась назад и уперлась в вешалку для верхней одежды.</p> <p>— С нами, говорю, поедешь, — подошел вплотную лысый, схватив меня за руку.</p> <p>— Никуда я с вами не поеду! Отпустите! На помощь! — кричала, когда здоровые лапищи, схватив меня за предплечья, дернули на себя и я оказалась впечатанной в массивный торс бугая. — Что вы себе позволяете?</p> <p>— Молчи, сука, если не хочешь, чтобы мы тебя заткнули, — прорычал лысый.</p> <p>— Нет, нет, нет! Помогите! — крикнула еще громче, но столкнувшись со свирепым взглядом незнакомца, сжалась.</p> <p>— Есения! — услышала голос соседки, вернувшейся в кафе на мои крики. — Что здесь происходит?</p> <p>Меня уже тащили на выход за руки, а я упиралась ногами, наивно рассчитывая, что вот-вот кто-то появится и остановит этот беспредел.</p> <p>— Баб Шур, они меня…— не успела договорить, как бородатый подошел к моей соседке и распахнув куртку достал пистолет.</p> <p>— Что же это? — испуганно вскрикнула женщина, попятившись назад. Но бородатый настиг ее и одним ударом ударил в висок.</p> <p>— Нет! — видела, как обмякло тело соседки. Из глаз мгновенно брызнули слезы. — Что ж вы наделали, мерзавцы, — всхлипывала.</p> <p>— Заебала! Сколько можно возиться с ней, — пробубнил бородатый и всего в несколько шагов настиг нас. Он схватил меня за талию и перекинул через плечо, как мешок картошки.</p> <p>— Поставьте меня на место! — кричала, ерзая на плече.</p> <p>— Заткнись, блядь! Или вырублю как твою старуху. А пока в отключке будешь, то порезвимся с тобой, — прилетел мне по ягодице увесистый шлепок.</p> <p>Перед глазами в красках пронеслось все вышеописанное и мне стало по-настоящему страшно. Еще пятнадцать минут назад я не чувствовала себя живой, а теперь вдруг, стало так жутко лишиться той самой бессмысленной жизни, но больше пугала боль, поэтому я затихла.</p> </div> </div> <div class="navigation"> <div class="pages"><span>1</span><a href="/fb2reader/17451/2/">2</a><a href="/fb2reader/17451/3/">3</a><a href="/fb2reader/17451/4/">4</a><a href="/fb2reader/17451/5/">5</a><a href="/fb2reader/17451/6/">6</a><span class="nav_ext">...</span><a href="/fb2reader/17451/83/">83</a></div> </div> <br><div class="adfinity_block_18173"></div><div class="adfinity_block_18175"></div> <div id="reader-final-recs-slot"></div> <section class="reader-recs reader-recs--author"><h2>Другие книги автора</h2><div class="reader-rec-grid"><div class="reader-rec-card"><a class="reader-rec-card__cover" href="https://knigi.fun/31290-drug-otca-devochka-avtoriteta.html"><img src="https://knigi.fun/uploads/posts/2026-01/1767234127_70998982.webp" loading="lazy" decoding="async" alt="Друг отца. Девочка авторитета"></a><a class="reader-rec-card__title" href="https://knigi.fun/31290-drug-otca-devochka-avtoriteta.html">Друг отца. Девочка авторитета</a><a class="reader-rec-card__meta" href="https://knigi.fun/genre/romany/">Романы</a></div><div class="reader-rec-card"><a class="reader-rec-card__cover" href="https://knigi.fun/17565-sluchaynyy-podarok-dlya-dikogo.html"><img src="https://knigi.fun/uploads/posts/2025-06/sluchainyi_podarok_dlia_dikogo_german.815546.jpg" loading="lazy" decoding="async" alt="Случайный подарок для Дикого"></a><a class="reader-rec-card__title" href="https://knigi.fun/17565-sluchaynyy-podarok-dlya-dikogo.html">Случайный подарок для Дикого</a><a class="reader-rec-card__meta" href="https://knigi.fun/genre/ljubovnoe-fjentezi/">Любовное фэнтези</a></div></div></section> <section class="reader-recs reader-recs--similar"><h2>Похожие книги</h2><div class="reader-rec-grid"><div class="reader-rec-card"><a class="reader-rec-card__cover" href="https://knigi.fun/17458-izmena-molodaya-lyubovnica.html"><img src="https://knigi.fun/uploads/posts/2025-06/izmena_molodaia_liubovnitsa_kraft.791388.png" loading="lazy" decoding="async" alt="Измена. Молодая любовница"></a><a class="reader-rec-card__title" href="https://knigi.fun/17458-izmena-molodaya-lyubovnica.html">Измена. Молодая любовница</a><a class="reader-rec-card__meta" href="https://knigi.fun/genre/proza/">Проза</a></div><div class="reader-rec-card"><a class="reader-rec-card__cover" href="https://knigi.fun/23471-progulyschik.html"><img src="https://knigi.fun/uploads/posts/2025-09/progulshchik_grin.822152.png" loading="lazy" decoding="async" alt="Прогульщик"></a><a class="reader-rec-card__title" href="https://knigi.fun/23471-progulyschik.html">Прогульщик</a><a class="reader-rec-card__meta" href="https://knigi.fun/genre/proza/">Проза</a></div><div class="reader-rec-card"><a class="reader-rec-card__cover" href="https://knigi.fun/22043-perevospitaty-bandita.html"><img src="https://knigi.fun/uploads/posts/2025-09/perevospitat_bandita_lari.803848.jpg" loading="lazy" decoding="async" alt="Перевоспитать бандита"></a><a class="reader-rec-card__title" href="https://knigi.fun/22043-perevospitaty-bandita.html">Перевоспитать бандита</a><a class="reader-rec-card__meta" href="https://knigi.fun/genre/proza/">Проза</a></div><div class="reader-rec-card"><a class="reader-rec-card__cover" href="https://knigi.fun/17823-razvod-v-50-katisy-otsyuda.html"><img src="https://knigi.fun/uploads/posts/2025-06/razvod_v_50_katis_otsiuda_laks.822223.jpg" loading="lazy" decoding="async" alt="Развод в 50. Катись отсюда!"></a><a class="reader-rec-card__title" href="https://knigi.fun/17823-razvod-v-50-katisy-otsyuda.html">Развод в 50. Катись отсюда!</a><a class="reader-rec-card__meta" href="https://knigi.fun/genre/proza/">Проза</a></div><div class="reader-rec-card"><a class="reader-rec-card__cover" href="https://knigi.fun/18385-razvod-shag-v-storonu.html"><img src="https://knigi.fun/uploads/posts/2025-07/razvod_shag_v_storonu_gamaus.826908.jpg" loading="lazy" decoding="async" alt="Развод. Шаг в сторону"></a><a class="reader-rec-card__title" href="https://knigi.fun/18385-razvod-shag-v-storonu.html">Развод. Шаг в сторону</a><a class="reader-rec-card__meta" href="https://knigi.fun/genre/proza/">Проза</a></div><div class="reader-rec-card"><a class="reader-rec-card__cover" href="https://knigi.fun/18793-razvedenka-v-aktivnom-poiske.html"><img src="https://knigi.fun/uploads/posts/2025-07/razvedenka_v_aktivnom_poiske_zaikina.826511.jpg" loading="lazy" decoding="async" alt="Разведенка в активном поиске"></a><a class="reader-rec-card__title" href="https://knigi.fun/18793-razvedenka-v-aktivnom-poiske.html">Разведенка в активном поиске</a><a class="reader-rec-card__meta" href="https://knigi.fun/genre/proza/">Проза</a></div></div></section> </div> <script> (function () { var toggleBtn = document.getElementById('fb2-autoscroll-toggle'); var speedInput = document.getElementById('fb2-autoscroll-speed'); var contentWrap = document.getElementById('fb2-reader-content'); var scrollingElement = document.scrollingElement || document.documentElement; var activeScroller = scrollingElement; if (!toggleBtn || !speedInput) return; var isRunning = false; var rafId = null; var lastTime = null; var scrollRemain = 0; // накапливаем дробные пиксели var prevHtmlScrollBehavior = ''; var prevBodyScrollBehavior = ''; var cachedMaxScroll = 0; var lastMetricsUpdate = 0; var iosInnerScrollerEnabled = false; window.__fb2AutoscrollState = window.__fb2AutoscrollState || { running: false }; // простая проверка iOS var isIOS = /iP(ad|hone|od)/.test(navigator.userAgent); // читаем реальные границы слайдера var sliderMin = parseInt(speedInput.min || '1', 10); var sliderMax = parseInt(speedInput.max || '100', 10); if (isNaN(sliderMin)) sliderMin = 1; if (isNaN(sliderMax)) sliderMax = 100; // Скорость в пикселях в секунду (логика общая, но диапазон для iOS мягче) function getSpeedPxPerSec() { var raw = parseInt(speedInput.value || '40', 10); if (isNaN(raw)) raw = 40; // учитываем твой реальный слайдер 1..80 var sliderMin = parseInt(speedInput.min || '1', 10); var sliderMax = parseInt(speedInput.max || '80', 10); if (isNaN(sliderMin)) sliderMin = 1; if (isNaN(sliderMax)) sliderMax = 80; raw = Math.min(Math.max(raw, sliderMin), sliderMax); // нормируем в 0..1 var k = (raw - sliderMin) / (sliderMax - sliderMin || 1); // Для iOS оставляем более плавный старт, но делаем хвост заметно быстрее, // чтобы верхние значения ползунка реально ощущались. if (isIOS) { k = Math.pow(k, 1.25); } var minSpeed = isIOS ? 20 : 15; var maxSpeed = isIOS ? 150 : 200; return minSpeed + (maxSpeed - minSpeed) * k; } function setNativeScrollBehavior(enabled) { var html = document.documentElement; var body = document.body; if (enabled) { prevHtmlScrollBehavior = html.style.scrollBehavior; prevBodyScrollBehavior = body.style.scrollBehavior; html.style.scrollBehavior = 'auto'; body.style.scrollBehavior = 'auto'; } else { html.style.scrollBehavior = prevHtmlScrollBehavior || ''; body.style.scrollBehavior = prevBodyScrollBehavior || ''; } } function refreshScrollMetrics(force) { var now = Date.now(); if (!force && (now - lastMetricsUpdate) < 800) { return; } lastMetricsUpdate = now; if (iosInnerScrollerEnabled) { cachedMaxScroll = activeScroller.scrollHeight - activeScroller.clientHeight; } else { cachedMaxScroll = Math.max( scrollingElement.scrollHeight, document.documentElement.scrollHeight, document.body.scrollHeight ) - window.innerHeight - 2; } if (cachedMaxScroll < 0) cachedMaxScroll = 0; } function enableIOSInnerScroller() { if (!isIOS || !contentWrap || iosInnerScrollerEnabled) return; var rect = contentWrap.getBoundingClientRect(); var absoluteTop = rect.top + window.pageYOffset; var carryScroll = Math.max(0, window.pageYOffset - absoluteTop); var availableHeight = Math.floor(window.innerHeight - Math.max(rect.top, 0) - 16); if (availableHeight < 260) { availableHeight = Math.max(220, window.innerHeight - 40); } contentWrap.style.maxHeight = availableHeight + 'px'; contentWrap.style.overflowY = 'auto'; contentWrap.style.overflowX = 'hidden'; contentWrap.style.webkitOverflowScrolling = 'auto'; contentWrap.style.overscrollBehavior = 'contain'; contentWrap.style.contain = 'layout paint style'; window.scrollTo(0, absoluteTop); contentWrap.scrollTop = carryScroll; activeScroller = contentWrap; iosInnerScrollerEnabled = true; refreshScrollMetrics(true); } function disableIOSInnerScroller() { if (!iosInnerScrollerEnabled || !contentWrap) return; var absoluteTop = contentWrap.getBoundingClientRect().top + window.pageYOffset; var carryScroll = contentWrap.scrollTop; contentWrap.style.maxHeight = ''; contentWrap.style.overflowY = ''; contentWrap.style.overflowX = ''; contentWrap.style.webkitOverflowScrolling = ''; contentWrap.style.overscrollBehavior = ''; contentWrap.style.contain = ''; activeScroller = scrollingElement; iosInnerScrollerEnabled = false; window.scrollTo(0, absoluteTop + carryScroll); refreshScrollMetrics(true); } function step(timestamp) { if (!isRunning) return; if (lastTime === null) { lastTime = timestamp; } var dt = timestamp - lastTime; // мс с прошлого кадра lastTime = timestamp; var speed = getSpeedPxPerSec(); // px/сек refreshScrollMetrics(false); var current = activeScroller.scrollTop; var maxScroll = cachedMaxScroll; if (current >= maxScroll) { stopAutoscroll(); return; } // На iOS тоже считаем по реальному времени, иначе при просадках FPS // визуальная скорость получается заметно ниже выбранной. if (dt > (isIOS ? 34 : 50)) { dt = isIOS ? 34 : 50; } var distance = speed * (dt / 1000); // Накапливаем дробные пиксели, чтобы даже при маленькой скорости всё равно ползло scrollRemain += distance; var move = Math.floor(scrollRemain); if (move >= 1) { scrollRemain -= move; activeScroller.scrollTop = Math.min(current + move, maxScroll); } rafId = requestAnimationFrame(step); } function startAutoscroll() { if (isRunning) return; isRunning = true; window.__fb2AutoscrollState.running = true; lastTime = null; scrollRemain = 0; enableIOSInnerScroller(); refreshScrollMetrics(true); setNativeScrollBehavior(true); toggleBtn.classList.add('is-running'); toggleBtn.textContent = 'Остановить'; // лёгкий "пинок" странице — особенно помогает iOS try { window.scrollBy(0, 1); window.scrollBy(0, -1); } catch (e) {} rafId = requestAnimationFrame(step); } function stopAutoscroll() { if (!isRunning) return; isRunning = false; window.__fb2AutoscrollState.running = false; toggleBtn.classList.remove('is-running'); toggleBtn.textContent = 'Автопрокрутка'; if (rafId !== null) { cancelAnimationFrame(rafId); rafId = null; } setNativeScrollBehavior(false); disableIOSInnerScroller(); lastTime = null; scrollRemain = 0; } // Кнопка старт/стоп toggleBtn.addEventListener('click', function (e) { e.preventDefault(); if (isRunning) { stopAutoscroll(); } else { startAutoscroll(); } }); // iOS: touchstart -> click toggleBtn.addEventListener('touchstart', function (e) { e.preventDefault(); toggleBtn.click(); }, { passive: false }); // Любое "осознанное" действие пользователя — стоп function userStopHandler(e) { if (!isRunning) return; // Не гасим, если это внутри панели автопрокрутки if (e.target && e.target.closest && e.target.closest('.reader-autoscroll')) { return; } stopAutoscroll(); } ['wheel', 'keydown', 'mousedown'].forEach(function (ev) { document.addEventListener(ev, userStopHandler, { passive: true }); }); ['touchmove'].forEach(function (ev) { document.addEventListener(ev, userStopHandler, { passive: true }); }); window.addEventListener('resize', function () { refreshScrollMetrics(true); }, { passive: true }); })(); </script> <script> (function () { var $fb2Area = $('.fb2-area'); var ajaxMode = $fb2Area.data('ajax') == 1 || $fb2Area.data('ajax') === '1'; var $content = $('#fb2-reader-content'); var $pages = $('.navigation .pages'); var $pageInfo = $('.fb2-page-info'); var $introSlot = $('#reader-intro-slot'); var initialIntroHtml = $introSlot.html() || ''; var $finalRecsSlot = $('#reader-final-recs-slot'); var initialFinalRecsHtml = $finalRecsSlot.html() || ''; var $message = $('<div class="fb2-ajax-message" role="status"></div>'); var $loader = $('<div class="fb2-ajax-loader" role="status">Загружаем страницу...</div>'); var loading = false; var cache = {}; var prefetching = {}; var prefetchXhrs = {}; var bookId = $fb2Area.data('book-id'); if (!ajaxMode || !$fb2Area.length || !$content.length || !$pages.length || !$pageInfo.length) { return; } $pages.before($message); $content.before($loader); function normalizePage(page) { page = parseInt(page || '1', 10); return page > 0 ? page : 1; } function pageFromUrl(url) { var page = 1; var match = String(url).match(/\/fb2reader\/([0-9]+)(?:\/([0-9]+))?\//); if (match) page = normalizePage(match[2] || '1'); return page; } function ajaxUrl(page) { page = normalizePage(page); return '/index.php?do=fb2reader&news_id=' + encodeURIComponent(bookId) + '&cstart=' + page + '&fb2ajax=1'; } function pageUrl(page) { page = normalizePage(page); return page > 1 ? '/fb2reader/' + bookId + '/' + page + '/' : '/fb2reader/' + bookId + '/'; } function updateBrowserUrl(page) { var url = pageUrl(page); if (!window.history || !window.history.replaceState || !bookId) return url; window.history.replaceState(null, document.title, url); return url; } function sendMetrikaHit(page, refererUrl) { if (typeof window.ym !== 'function') return; var url = pageUrl(page); var absoluteUrl = window.location.origin + url; var title = document.title + ' — страница ' + normalizePage(page); window.ym(100046838, 'hit', absoluteUrl, { title: title, referer: refererUrl || document.referrer || '' }); } function updateIntroVisibility(page) { page = normalizePage(page); if (!$introSlot.length) return; if (page === 1 && initialIntroHtml) { $introSlot.html(initialIntroHtml).show(); } else { $introSlot.hide(); } } function updateFinalRecs(page, total, html) { page = normalizePage(page); total = normalizePage(total); if (!$finalRecsSlot.length) return; if (page >= total) { $finalRecsSlot.html(html || initialFinalRecsHtml).show(); } else { $finalRecsSlot.hide().html(''); } } function abortPrefetches(exceptPage) { $.each(prefetchXhrs, function (page, xhr) { if (parseInt(page, 10) === exceptPage) return; if (xhr && xhr.readyState !== 4) xhr.abort(); delete prefetchXhrs[page]; delete prefetching[page]; }); } function applyResponse(response, href) { updateIntroVisibility(response.page); updateFinalRecs(response.page, response.count, response.final_recs || ''); $content.html(response.content); $pages.html(response.pages || ''); $pageInfo .attr('data-page', response.page) .attr('data-count', response.count) .data('page', response.page) .data('count', response.count) .text('Страница ' + response.page + ' из ' + response.count); window.scrollTo({ top: 0, behavior: 'smooth' }); window.dispatchEvent(new CustomEvent('fb2:page-loaded', { detail: { page: parseInt(response.page || 1, 10), total: parseInt(response.count || 1, 10) } })); var refererUrl = window.location.href; updateBrowserUrl(response.page); sendMetrikaHit(response.page, refererUrl); prefetchAround(response.page, response.count); } function prefetchPage(page, total) { page = normalizePage(page); total = normalizePage(total); if (page < 1 || page > total || cache[page] || prefetching[page]) return; if (Object.keys(prefetching).length >= 1) return; prefetching[page] = true; prefetchXhrs[page] = $.ajax({ url: ajaxUrl(page), type: 'GET', dataType: 'json', cache: false, timeout: 8000 }).done(function (response) { if (response && typeof response.content !== 'undefined') { cache[page] = response; } }).always(function () { delete prefetching[page]; delete prefetchXhrs[page]; }); } function prefetchAround(page, total) { page = normalizePage(page); total = normalizePage(total); window.setTimeout(function () { if (loading) return; prefetchPage(page + 1, total); if (!prefetching[page + 1]) prefetchPage(page + 2, total); }, 250); } $(document).on('mouseenter touchstart', '.navigation .pages a', function () { var href = $(this).attr('href'); if (!href || href.indexOf('/fb2reader/') === -1) return; prefetchPage(pageFromUrl(href), normalizePage($pageInfo.data('count'))); }); $(document).on('click', '.navigation .pages a', function (e) { var href = $(this).attr('href'); if (!href || href.indexOf('/fb2reader/') === -1) return; e.preventDefault(); e.stopPropagation(); if (loading) return false; var targetPage = pageFromUrl(href); abortPrefetches(targetPage); if (cache[targetPage]) { $message.removeClass('is-visible').text(''); applyResponse(cache[targetPage], href); return false; } loading = true; $fb2Area.addClass('fb2-ajax-loading'); $message.removeClass('is-visible').text(''); $.ajax({ url: ajaxUrl(targetPage), type: 'GET', dataType: 'json', cache: false, timeout: 12000 }).done(function (response) { if (!response || typeof response.content === 'undefined') { $message .text('Не удалось быстро загрузить страницу. Попробуйте нажать ещё раз.') .addClass('is-visible'); return; } cache[targetPage] = response; applyResponse(response, href); }).fail(function () { $message .text('Страница не загрузилась за отведённое время. Попробуйте ещё раз или обновите страницу.') .addClass('is-visible'); }).always(function () { loading = false; $fb2Area.removeClass('fb2-ajax-loading'); }); return false; }); cache[normalizePage($pageInfo.data('page'))] = { content: $content.html(), pages: $pages.html(), page: normalizePage($pageInfo.data('page')), count: normalizePage($pageInfo.data('count')) }; prefetchAround($pageInfo.data('page'), $pageInfo.data('count')); })(); </script> <script> (function () { var $win = $(window); var $bar = $('#reader-progress-bar'); var $label = $('#reader-progress-label'); var $pageInfo = $('.fb2-page-info'); var $fb2Area = $('.fb2-area'); var progressEndpoint = null; if (!$bar.length || !$label.length || !$pageInfo.length || !$fb2Area.length) return; var page = parseInt($pageInfo.data('page') || '1', 10); // текущая страница var total = parseInt($pageInfo.data('count') || '1', 10); // всего страниц var pathMatch = window.location.pathname.match(/\/fb2reader\/(\d+)/); var bookId = pathMatch ? parseInt(pathMatch[1], 10) : ($fb2Area.data('book-id') || null); // news-id if (page < 1) page = 1; if (total < 1) total = 1; if (page > total) page = total; var lastSavedPercent = null; var lastSavedTime = 0; var progressTickQueued = false; function saveProgress(percent) { if (!bookId) return; var now = Date.now(); var isAutoscrolling = !!(window.__fb2AutoscrollState && window.__fb2AutoscrollState.running); var minSaveInterval = isAutoscrolling ? 4000 : 1000; // Во время автопрокрутки сохраняем реже, чтобы iPhone не дёргался // из-за частых cookie/localStorage/ajax-операций. if (lastSavedPercent !== null && lastSavedPercent === percent && (now - lastSavedTime) < minSaveInterval) { return; } if ((now - lastSavedTime) < minSaveInterval) { return; } lastSavedPercent = percent; lastSavedTime = now; try { localStorage.setItem( 'fb2_book_' + bookId, JSON.stringify({ page: page, total: total, percent: percent, // уже округлённый процент updated: now }) ); } catch (e) { // молча игнорируем } try { document.cookie = 'fb2_' + bookId + '=' + page + '-' + total + '; path=/; max-age=' + (60 * 60 * 24 * 365); } catch (e) { // молча игнорируем } if (progressEndpoint) { $.post(progressEndpoint, { news_id: bookId, page: page, total: total, percent: percent }); } } function updateProgress(forceSave) { progressTickQueued = false; var winTop = $win.scrollTop(); var winH = $win.height(); var docH = $(document).height(); var maxScroll = docH - winH; var intra = 0; // прогресс внутри текущей страницы: 0..1 if (maxScroll > 0) { intra = winTop / maxScroll; if (intra < 0) intra = 0; if (intra > 1) intra = 1; } // общий прогресс по книге: // (пройденные полные страницы + доля текущей) / всего var overall = ((page - 1) + intra) / total * 100; if (overall < 0) overall = 0; if (overall > 100) overall = 100; // 🔹 одно и то же округление используем и для отображения, и для сохранения var rounded = Math.round(overall); $bar.css('width', rounded + '%'); $label.text(rounded + '%'); if (forceSave) { lastSavedPercent = null; lastSavedTime = 0; } saveProgress(rounded); } function queueProgressUpdate() { if (window.__fb2AutoscrollState && window.__fb2AutoscrollState.running) { return; } if (progressTickQueued) return; progressTickQueued = true; window.requestAnimationFrame(updateProgress); } $win.on('scroll resize', queueProgressUpdate); updateProgress(); window.addEventListener('fb2:page-loaded', function (event) { var detail = event.detail || {}; page = parseInt(detail.page || $pageInfo.data('page') || '1', 10); total = parseInt(detail.total || $pageInfo.data('count') || '1', 10); if (page < 1) page = 1; if (total < 1) total = 1; if (page > total) page = total; lastSavedPercent = null; lastSavedTime = 0; updateProgress(true); }); setInterval(function () { if (window.__fb2AutoscrollState && window.__fb2AutoscrollState.running) { updateProgress(false); } }, 1200); // 🔹 при уходе со страницы ещё раз гарантированно сохраняем window.addEventListener('beforeunload', function () { var txt = $label.text().replace('%', '').trim(); var p = parseInt(txt, 10); if (!isNaN(p)) { updateProgress(true); saveProgress(p); } }); })(); </script> <!-- Yandex.Metrika counter --> <script type="text/javascript" > (function(m,e,t,r,i,k,a){m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)}; m[i].l=1*new Date(); for (var j = 0; j < document.scripts.length; j++) {if (document.scripts[j].src === r) { return; }} k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)}) (window, document, "script", "https://mc.yandex.ru/metrika/tag.js", "ym"); ym(100046838, "init", { clickmap:true, trackLinks:true, accurateTrackBounce:true }); </script> <noscript><div><img src="https://mc.yandex.ru/watch/100046838" style="position:absolute; left:-9999px;" alt="" /></div></noscript> <!-- /Yandex.Metrika counter --> <!--LiveInternet counter--><a href="https://www.liveinternet.ru/click" target="_blank"><img id="licnt125D" width="0" height="1" style="border:0" title="LiveInternet" src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAEALAAAAAABAAEAAAIBTAA7" alt=""/></a><script>(function(d,s){d.getElementById("licnt125D").src= "https://counter.yadro.ru/hit?t41.6;r"+escape(d.referrer)+ ((typeof(s)=="undefined")?"":";s"+s.width+"*"+s.height+"*"+ (s.colorDepth?s.colorDepth:s.pixelDepth))+";u"+escape(d.URL)+ ";h"+escape(d.title.substring(0,150))+";"+Math.random()}) (document,screen)</script><!--/LiveInternet--> <script> (function(){ var readerRecs = document.querySelectorAll('.reader-recs'); for (var i = 0; i < readerRecs.length; i++) { var grid = readerRecs[i].querySelector('.reader-rec-grid'); if (grid && !grid.textContent.replace(/\s+/g, ' ').trim()) readerRecs[i].style.display = 'none'; } })(); </script> <script>document.addEventListener("DOMContentLoaded",function readerRatingVote(){var box=document.querySelector(".reader-rating[data-news-id]");if(!box)return;var msg=box.querySelector(".reader-rating__msg");box.addEventListener("click",function(event){var btn=event.target.closest(".reader-rating__btn");if(!btn)return;event.preventDefault();var params=new URLSearchParams();params.set("news_id",box.getAttribute("data-news-id"));params.set("go_rate",btn.getAttribute("data-rate"));params.set("user_hash",box.getAttribute("data-hash"));fetch("/engine/ajax/controller.php?mod=rating",{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded; charset=UTF-8"},body:params.toString(),credentials:"same-origin"}).then(function(res){return res.json()}).then(function(data){if(data&&data.success){var like=box.querySelector("[data-rate=plus] .reader-rating__count");var dislike=box.querySelector("[data-rate=minus] .reader-rating__count");if(like)like.textContent=data.likes||0;if(dislike)dislike.textContent=data.dislikes||0;box.querySelector("[data-rate=plus]").classList.remove("is-liked");box.querySelector("[data-rate=minus]").classList.remove("is-disliked");btn.classList.add(btn.getAttribute("data-rate")==="plus"?"is-liked":"is-disliked");if(msg)msg.textContent="Спасибо, оценка учтена"}else if(msg){msg.textContent=data&&data.errorinfo?data.errorinfo:"Не удалось сохранить оценку"}}).catch(function(){if(msg)msg.textContent="Не удалось сохранить оценку"})})});</script> </body> </html>