您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Добавляет кнопку для сортировки товаров по количеству отзывов
// ==UserScript== // @name Ozon Sort by Reviews // @version 0.7 // @description Добавляет кнопку для сортировки товаров по количеству отзывов // @author Jipok // @match https://www.ozon.ru/* // @grant none // @license MIT // @namespace https://gist.github.com/Jipok/cda67abb99078c85ca452a7a261384ac // ==/UserScript== (function() { 'use strict'; function extractReviewCount(element) { const reviewText = Array.from(element.querySelectorAll('*')) .map(el => el.textContent) .find(text => text && text.includes('отзыв')); if (!reviewText) return 0; const match = reviewText.match(/(\d+[\s,]?\d*)\s*отзыв/); return match ? parseInt(match[1].replace(/[\s,]/g, '')) : 0; } function sortByReviews() { const products = Array.from(document.querySelectorAll('div[data-index]')).filter(el => { return el.querySelector('img') && el.querySelector('a[href*="/product/"]') && el.textContent.includes('₽'); }); if (!products.length) { console.log('Товары не найдены'); return; } const container = products[0].parentElement; if (!container) return; const sortedProducts = [...products].sort((a, b) => { const reviewsA = extractReviewCount(a); const reviewsB = extractReviewCount(b); return reviewsB - reviewsA; }); container.innerHTML = ''; sortedProducts.forEach(product => { container.appendChild(product); }); window.scrollTo(0, 0); } // Стили для попапа const style = document.createElement('style'); style.textContent = ` .loading-popup { position: fixed; bottom: 2rem; right: 1rem; background: white; padding: 1.25rem; border-radius: 0.75rem; box-shadow: 0 0.125rem 0.625rem rgba(0,0,0,0.2); z-index: 9999; display: none; font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; font-size: 1rem; } .loading-popup.visible { display: block; } .loading-popup-content { margin-bottom: 0.75rem; } .loading-popup-cancel { background: #ff4d4d; color: white; border: none; padding: 0.5rem 1rem; border-radius: 0.375rem; cursor: pointer; font-size: 0.875rem; width: 100%; } .loading-popup-cancel:hover { background: #ff3333; } @media (min-width: 768px) { .desktop-buttons-container { display: inline-flex; align-items: center; gap: 8px; margin-left: 16px; position: absolute; right: 0; top: 50%; transform: translateY(-50%); } .desktop-buttons-container button { padding: 8px 16px !important; height: 40px !important; line-height: 20px !important; border-radius: 4px !important; font-size: 14px !important; } } @media (max-width: 767px) { .mobile-buttons-container { display: flex; justify-content: center; gap: 0.5rem; padding: 0.5rem 1rem; margin-bottom: 1rem; } } `; document.head.appendChild(style); // Создаем попап const popup = document.createElement('div'); popup.className = 'loading-popup'; popup.innerHTML = ` <div class="loading-popup-content"> Загружено товаров: <span id="pagesCount">0</span> </div> <button class="loading-popup-cancel">Отменить загрузку</button> `; document.body.appendChild(popup); let loadingCancelled = false; // Обработчики отмены popup.querySelector('.loading-popup-cancel').addEventListener('click', () => { loadingCancelled = true; }); document.addEventListener('keydown', (e) => { if (e.key === 'Escape') { loadingCancelled = true; } }); async function loadPages(pages = 7) { const loadButton = document.querySelector('#ozonLoadMore'); loadButton.disabled = true; loadButton.innerHTML = 'Загрузка...'; popup.classList.add('visible'); const pagesCount = document.getElementById('pagesCount'); let loadedPages = 0; let initialProducts = document.querySelectorAll('div[data-index]').length; pagesCount.textContent = initialProducts; const scrollInterval = setInterval(() => { if (!loadingCancelled) { window.scrollTo(0, document.body.scrollHeight); const currentProducts = document.querySelectorAll('div[data-index]').length; const newProducts = currentProducts pagesCount.textContent = newProducts; } else { clearInterval(scrollInterval); window.scrollTo(0, 0); loadButton.disabled = false; loadButton.innerHTML = 'Загрузить больше'; popup.classList.remove('visible'); } }, 500); return new Promise((resolve) => { const observer = new MutationObserver((mutations) => { const hasNewProducts = mutations.some(mutation => Array.from(mutation.addedNodes).some(node => node.nodeType === 1 && node.querySelector?.('[data-index]') ) ); if (hasNewProducts) { loadedPages++; const currentProducts = document.querySelectorAll('div[data-index]').length; const newProducts = currentProducts; pagesCount.textContent = newProducts; if (loadedPages >= pages || loadingCancelled) { clearInterval(scrollInterval); observer.disconnect(); window.scrollTo(0, 0); loadButton.disabled = false; loadButton.innerHTML = 'Загрузить больше'; popup.classList.remove('visible'); resolve(); } } }); observer.observe(document.body, { childList: true, subtree: true }); }); } function createButtons() { const buttonsContainer = document.createElement('div'); const buttonStyle = ` font-family: Sans; font-size: 0.875rem; font-weight: 400; height: 2rem; line-height: 2rem; border-radius: 1rem; padding: 0 1rem; background: #005bff; color: white; border: none; cursor: pointer; position: relative; transition: 0.2s cubic-bezier(0.4,0,0.2,1); white-space: nowrap; `; const loadButton = document.createElement('button'); loadButton.id = 'ozonLoadMore'; loadButton.innerHTML = 'Загрузить больше'; loadButton.style.cssText = buttonStyle; const sortButton = document.createElement('button'); sortButton.id = 'ozonCustomSort'; sortButton.innerHTML = 'Сортировать по отзывам'; sortButton.style.cssText = buttonStyle; [loadButton, sortButton].forEach(button => { button.addEventListener('mouseover', () => { button.style.opacity = '0.8'; }); button.addEventListener('mouseout', () => { button.style.opacity = '1'; }); }); loadButton.addEventListener('click', () => loadPages(7)); sortButton.addEventListener('click', sortByReviews); buttonsContainer.appendChild(loadButton); buttonsContainer.appendChild(sortButton); return buttonsContainer; } function addButtons() { if (document.querySelector('#ozonCustomSort')) return; const buttons = createButtons(); // Пробуем десктопное расположение const sortContainer = document.querySelector('div[data-widget="searchResultsSort"]'); if (sortContainer) { buttons.className = 'desktop-buttons-container'; const parentContainer = sortContainer; parentContainer.style.position = 'relative'; parentContainer.appendChild(buttons); return; } // Если не вышло, пробуем мобильное const paginator = document.querySelector('div#paginator'); if (paginator) { buttons.className = 'mobile-buttons-container'; paginator.parentNode.insertBefore(buttons, paginator); } } for (let i = 1; i < 5; i++) { setTimeout(addButtons, i * 550); } let lastUrl = location.href; new MutationObserver(() => { if (location.href !== lastUrl) { lastUrl = location.href; for (let i = 0; i < 5; i++) { setTimeout(addButtons, i * 550); } } }).observe(document, {subtree: true, childList: true}); })();