您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Makes like and comment counts always visible on Flickr photo thumbnails in profile pages
- // ==UserScript==
- // @name Flickr Always Visible Stats
- // @namespace http://tampermonkey.net/
- // @version 1.0
- // @description Makes like and comment counts always visible on Flickr photo thumbnails in profile pages
- // @author fapek GPT
- // @match https://*.flickr.com/people/*
- // @match https://*.flickr.com/photos/*
- // @match *.flickr.com/photos/*
- // @license MIT
- // @grant none
- // ==/UserScript==
- (function() {
- 'use strict';
- // Function to create and inject custom CSS
- function injectCustomCSS() {
- const css = `
- /* Force interaction bar to be always visible */
- .photo-list-photo-view .interaction-bar,
- .overlay-target .interaction-bar {
- display: none !important; /* Hide the original interaction bar completely */
- opacity: 0 !important;
- visibility: hidden !important;
- }
- /* Style for our custom stats bar */
- .always-visible-stats {
- display: flex !important;
- opacity: 1 !important;
- visibility: visible !important;
- position: absolute !important;
- bottom: 0 !important;
- left: 0 !important;
- right: 0 !important;
- background: rgb(0, 0, 0) !important; /* Fully opaque background */
- padding: 5px !important;
- transition: background 0.2s ease !important;
- z-index: 99 !important; /* Higher z-index to ensure it's on top */
- pointer-events: auto !important;
- }
- /* Hide the title and attribution to save space */
- .photo-list-photo-view .interaction-bar .text {
- display: none;
- }
- /* Make the engagement section take full width */
- .photo-list-photo-view .interaction-bar .engagement {
- display: flex;
- width: 100%;
- justify-content: space-around;
- }
- /* Style for engagement items */
- .photo-list-photo-view .interaction-bar .engagement-item {
- display: flex;
- align-items: center;
- color: white;
- padding: 2px 5px;
- font-weight: bold;
- }
- /* Hover effect on the bar */
- .photo-list-photo-view:hover .interaction-bar {
- background: rgba(0, 0, 0, 0.8);
- }
- /* Make engagement count more visible */
- .photo-list-photo-view .interaction-bar .engagement-count {
- margin-left: 3px;
- font-size: 14px;
- text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.8);
- }
- /* Special styling for favorite counts */
- .photo-list-photo-view .interaction-bar .fave .engagement-count {
- color: #fffc00;
- }
- /* Special styling for comment counts */
- .photo-list-photo-view .interaction-bar .comment .engagement-count {
- color: #00ffff;
- }
- /* Hide the curate button to save space */
- .photo-list-photo-view .interaction-bar .curate {
- display: none;
- }
- /* Ensure icons are visible */
- .photo-list-photo-view .interaction-bar svg,
- .photo-list-photo-view .interaction-bar i {
- filter: drop-shadow(1px 1px 1px rgba(0, 0, 0, 0.8));
- }
- `;
- const styleElement = document.createElement('style');
- styleElement.textContent = css;
- document.head.appendChild(styleElement);
- }
- // Function to parse like counts including K format (1K, 1.5K etc.)
- function parseCount(text) {
- text = text.trim();
- // Handle K format (e.g., "1K", "1.3K")
- if (text.endsWith('K')) {
- const numPart = parseFloat(text.replace('K', ''));
- return Math.round(numPart * 1000);
- }
- return parseInt(text);
- }
- // Function to stylize like counts with the same levels as your other script
- function stylizeLikeCounts() {
- // Find all engagement count elements for favorites
- const likeElements = document.querySelectorAll('.fave .engagement-count');
- likeElements.forEach(function(likeElement) {
- const originalText = likeElement.innerText.trim();
- const likeCount = parseCount(originalText);
- if (!isNaN(likeCount)) {
- // Reset existing custom styles
- likeElement.style.fontSize = '';
- likeElement.style.textShadow = '';
- // Style based on number of likes
- if (likeCount >= 1 && likeCount <= 5) {
- likeElement.style.fontSize = '14px';
- } else if (likeCount >= 6 && likeCount <= 15) {
- likeElement.style.fontSize = '16px';
- likeElement.style.textShadow = '0 0 3px #fffc00';
- } else if (likeCount >= 16 && likeCount <= 30) {
- likeElement.style.fontSize = '18px';
- likeElement.style.textShadow = '0 0 4px #fffc00';
- } else if (likeCount >= 31 && likeCount <= 60) {
- likeElement.style.fontSize = '20px';
- likeElement.style.textShadow = '0 0 5px #fffc00';
- } else if (likeCount >= 61 && likeCount <= 100) {
- likeElement.style.fontSize = '22px';
- likeElement.style.textShadow = '0 0 6px #fffc00';
- } else if (likeCount >= 101 && likeCount <= 500) {
- likeElement.style.fontSize = '24px';
- likeElement.style.textShadow = '0 0 8px #fffc00, 0 0 12px #fffc00';
- } else if (likeCount >= 501 && likeCount <= 1000) {
- likeElement.style.fontSize = '26px';
- likeElement.style.textShadow = '0 0 10px #fffc00, 0 0 15px #fffc00';
- } else if (likeCount > 1000) {
- likeElement.style.fontSize = '28px';
- likeElement.style.textShadow = '0 0 10px #fffc00, 0 0 15px #fffc00, 0 0 20px #fffc00';
- }
- }
- });
- // Also style comment counts
- const commentElements = document.querySelectorAll('.comment .engagement-count');
- commentElements.forEach(function(commentElement) {
- const originalText = commentElement.innerText.trim();
- const commentCount = parseCount(originalText);
- if (!isNaN(commentCount)) {
- // Reset existing custom styles
- commentElement.style.fontSize = '';
- commentElement.style.textShadow = '';
- // Style based on number of comments
- if (commentCount >= 1 && commentCount <= 2) {
- commentElement.style.fontSize = '14px';
- } else if (commentCount >= 3 && commentCount <= 5) {
- commentElement.style.fontSize = '16px';
- commentElement.style.textShadow = '0 0 3px #00ffff';
- } else if (commentCount >= 6 && commentCount <= 10) {
- commentElement.style.fontSize = '18px';
- commentElement.style.textShadow = '0 0 4px #00ffff';
- } else if (commentCount >= 11 && commentCount <= 30) {
- commentElement.style.fontSize = '20px';
- commentElement.style.textShadow = '0 0 6px #00ffff, 0 0 10px #00ffff';
- } else if (commentCount > 30) {
- commentElement.style.fontSize = '22px';
- commentElement.style.textShadow = '0 0 8px #00ffff, 0 0 12px #00ffff, 0 0 16px #00ffff';
- }
- }
- });
- }
- // Function to make interaction bars visible by manipulating the DOM
- function forceShowInteractionBars() {
- // Find all photo containers
- const photoContainers = document.querySelectorAll('.photo-list-photo-view');
- photoContainers.forEach(container => {
- // Find the interaction bar in this container
- const interactionBar = container.querySelector('.interaction-bar');
- if (interactionBar) {
- // Completely hide the original interaction bar
- interactionBar.style.display = 'none';
- interactionBar.style.opacity = '0';
- interactionBar.style.visibility = 'hidden';
- interactionBar.style.pointerEvents = 'none';
- // Remove any padding we might have added before
- container.style.paddingBottom = '';
- container.style.marginBottom = '';
- // Create a new div for displaying stats if it doesn't exist yet
- let statsDiv = container.querySelector('.always-visible-stats');
- if (!statsDiv) {
- statsDiv = document.createElement('div');
- statsDiv.className = 'always-visible-stats';
- // Apply explicit styles directly to the element
- statsDiv.style.position = 'absolute';
- statsDiv.style.bottom = '0';
- statsDiv.style.left = '0';
- statsDiv.style.right = '0';
- statsDiv.style.height = '25px';
- statsDiv.style.backgroundColor = 'rgba(0, 0, 0, 0.75)';
- statsDiv.style.color = '#ffffff';
- statsDiv.style.display = 'flex';
- statsDiv.style.alignItems = 'center';
- statsDiv.style.justifyContent = 'space-around';
- statsDiv.style.zIndex = '9999';
- statsDiv.style.padding = '0';
- // Get original elements
- const faveItem = interactionBar.querySelector('.engagement-item.fave');
- const commentItem = interactionBar.querySelector('.engagement-item.comment');
- if (faveItem && commentItem) {
- // Create custom fave element with working interaction
- const customFaveItem = document.createElement('div');
- customFaveItem.className = 'custom-fave-item';
- customFaveItem.style.display = 'flex';
- customFaveItem.style.alignItems = 'center';
- customFaveItem.style.cursor = 'pointer';
- customFaveItem.style.padding = '0 10px';
- // Create star icon
- const starIcon = document.createElement('span');
- starIcon.innerHTML = '★'; // Unicode star
- starIcon.style.color = '#fffc00'; // Yellow color
- starIcon.style.fontSize = '16px';
- starIcon.style.marginRight = '4px';
- starIcon.style.lineHeight = '1';
- // Get original count
- const countSpan = faveItem.querySelector('.engagement-count');
- const customCountSpan = document.createElement('span');
- customCountSpan.className = 'custom-engagement-count';
- customCountSpan.textContent = countSpan ? countSpan.textContent : '0';
- customCountSpan.style.color = '#fffc00'; // Yellow color
- // Add click event that triggers the original fave button
- customFaveItem.addEventListener('click', function(e) {
- e.stopPropagation(); // Prevent triggering photo click
- // Click the original fave button
- faveItem.click();
- // Update our custom count after a short delay
- setTimeout(() => {
- const updatedCount = faveItem.querySelector('.engagement-count');
- if (updatedCount) {
- customCountSpan.textContent = updatedCount.textContent;
- // Re-stylize after update
- stylizeCustomCounts();
- }
- }, 1000);
- });
- // Assemble fave item
- customFaveItem.appendChild(starIcon);
- customFaveItem.appendChild(customCountSpan);
- // Create custom comment element (non-interactive, just display)
- const customCommentItem = document.createElement('a');
- customCommentItem.className = 'custom-comment-item';
- customCommentItem.style.display = 'flex';
- customCommentItem.style.alignItems = 'center';
- customCommentItem.style.padding = '0 10px';
- customCommentItem.style.textDecoration = 'none';
- // Set the href to the original comment link if available
- if (commentItem.hasAttribute('href')) {
- customCommentItem.href = commentItem.getAttribute('href');
- }
- // Comment icon
- const commentIcon = document.createElement('span');
- commentIcon.innerHTML = '💬'; // Speech bubble emoji
- commentIcon.style.fontSize = '14px';
- commentIcon.style.marginRight = '4px';
- commentIcon.style.lineHeight = '1';
- // Comment count
- const commentCountSpan = commentItem.querySelector('.engagement-count');
- const customCommentCountSpan = document.createElement('span');
- customCommentCountSpan.className = 'custom-comment-count';
- customCommentCountSpan.textContent = commentCountSpan ? commentCountSpan.textContent : '0';
- customCommentCountSpan.style.color = '#00ffff'; // Cyan color
- // Assemble comment item
- customCommentItem.appendChild(commentIcon);
- customCommentItem.appendChild(customCommentCountSpan);
- // Add both items to our custom stats bar
- statsDiv.appendChild(customFaveItem);
- statsDiv.appendChild(customCommentItem);
- // Find the appropriate place to add our element
- const photoElement = container.querySelector('.photo-list-photo-container');
- if (photoElement) {
- photoElement.appendChild(statsDiv);
- } else {
- container.appendChild(statsDiv);
- }
- }
- }
- }
- });
- // Apply styling to our custom counts
- stylizeCustomCounts();
- }
- // Function to stylize our custom counts
- function stylizeCustomCounts() {
- // Style fave counts
- const customFaveCounts = document.querySelectorAll('.custom-engagement-count');
- customFaveCounts.forEach(function(countElement) {
- const originalText = countElement.textContent.trim();
- const likeCount = parseCount(originalText);
- if (!isNaN(likeCount)) {
- // Reset styles
- countElement.style.fontSize = '';
- countElement.style.textShadow = '';
- // Apply styling based on count
- if (likeCount >= 1 && likeCount <= 5) {
- countElement.style.fontSize = '14px';
- } else if (likeCount >= 6 && likeCount <= 15) {
- countElement.style.fontSize = '16px';
- countElement.style.textShadow = '0 0 3px #fffc00';
- } else if (likeCount >= 16 && likeCount <= 30) {
- countElement.style.fontSize = '18px';
- countElement.style.textShadow = '0 0 4px #fffc00';
- } else if (likeCount >= 31 && likeCount <= 60) {
- countElement.style.fontSize = '20px';
- countElement.style.textShadow = '0 0 5px #fffc00';
- } else if (likeCount >= 61 && likeCount <= 100) {
- countElement.style.fontSize = '22px';
- countElement.style.textShadow = '0 0 6px #fffc00';
- } else if (likeCount >= 101 && likeCount <= 500) {
- countElement.style.fontSize = '24px';
- countElement.style.textShadow = '0 0 8px #fffc00, 0 0 12px #fffc00';
- } else if (likeCount >= 501 && likeCount <= 1000) {
- countElement.style.fontSize = '26px';
- countElement.style.textShadow = '0 0 10px #fffc00, 0 0 15px #fffc00';
- } else if (likeCount > 1000) {
- countElement.style.fontSize = '28px';
- countElement.style.textShadow = '0 0 10px #fffc00, 0 0 15px #fffc00, 0 0 20px #fffc00';
- }
- }
- });
- // Style comment counts
- const customCommentCounts = document.querySelectorAll('.custom-comment-count');
- customCommentCounts.forEach(function(countElement) {
- const originalText = countElement.textContent.trim();
- const commentCount = parseCount(originalText);
- if (!isNaN(commentCount)) {
- // Reset styles
- countElement.style.fontSize = '';
- countElement.style.textShadow = '';
- // Apply styling based on count
- if (commentCount >= 1 && commentCount <= 2) {
- countElement.style.fontSize = '14px';
- } else if (commentCount >= 3 && commentCount <= 5) {
- countElement.style.fontSize = '16px';
- countElement.style.textShadow = '0 0 3px #00ffff';
- } else if (commentCount >= 6 && commentCount <= 10) {
- countElement.style.fontSize = '18px';
- countElement.style.textShadow = '0 0 4px #00ffff';
- } else if (commentCount >= 11 && commentCount <= 30) {
- countElement.style.fontSize = '20px';
- countElement.style.textShadow = '0 0 6px #00ffff, 0 0 10px #00ffff';
- } else if (commentCount > 30) {
- countElement.style.fontSize = '22px';
- countElement.style.textShadow = '0 0 8px #00ffff, 0 0 12px #00ffff, 0 0 16px #00ffff';
- }
- }
- });
- }
- // Main function to run on page load and after content changes
- function initialize() {
- // First, inject custom CSS to make bars visible
- injectCustomCSS();
- // Also force show by manipulating DOM directly
- forceShowInteractionBars();
- // No longer need this as we now use stylizeCustomCounts
- // stylizeLikeCounts();
- }
- // Set up observer to watch for dynamically loaded content
- function setupObserver() {
- const observer = new MutationObserver(function(mutations) {
- mutations.forEach(function(mutation) {
- if (mutation.addedNodes.length) {
- // Wait a moment to let any dynamic content fully render
- setTimeout(stylizeLikeCounts, 300);
- }
- });
- });
- // Start observing the document body for changes
- observer.observe(document.body, {
- childList: true,
- subtree: true
- });
- }
- // Initial run
- document.addEventListener('DOMContentLoaded', function() {
- initialize();
- setupObserver();
- });
- // Run immediately for already loaded content
- initialize();
- setupObserver();
- // Run multiple times with delays to ensure we catch all dynamic content
- setTimeout(initialize, 500);
- setTimeout(initialize, 1500);
- setTimeout(initialize, 3000);
- // Set up interval to periodically check and update
- setInterval(initialize, 5000);
- // Additional force refresh on page interactions
- document.addEventListener('click', function() {
- setTimeout(initialize, 100);
- });
- // Target specific events that might trigger content changes
- window.addEventListener('scroll', function() {
- // Debounce the scroll event
- clearTimeout(window.flickrStatsScrollTimer);
- window.flickrStatsScrollTimer = setTimeout(initialize, 300);
- });
- })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址