Greasy Fork

Greasy Fork is available in English.

Magazine Pop-up

Show magazine subscription information on hover

当前为 2023-06-28 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name        Magazine Pop-up
// @namespace   Violentmonkey Scripts
// @match       https://kbin.social/*
// @grant       GM_getValue
// @version     1.1
// @author      -
// @license MIT
// @description Show magazine subscription information on hover
// ==/UserScript==

// Select all magazine URL elements
let magazineURLs = document.querySelectorAll('a.magazine-inline');


// Create a pop-up element to display the sidebar information
const popUp = document.createElement('div');
popUp.className = 'pop-up';
popUp.style.zIndex = '9999'; // Set the desired z-index value

// Apply box styling to the pop-up element
popUp.style.border = '1px solid #363434'; // Customize the border style
popUp.style.backgroundColor = '#2c2c2c'; // Customize the background color
popUp.style.padding = '10px'; // Customize the padding
popUp.style.width = '440px';
popUp.style.height = '165px';
popUp.style.borderRadius = '8px';
popUp.style.overflow = 'none'; // Add this line to enable scrolling


// Adjust the spacing within the pop-up content
popUp.style.lineHeight = '1.0'; // Reduce line height to make content closer
popUp.style.margin = '0'; // Remove margin to reduce spacing

// Adjust the spacing for specific elements within the pop-up
popUp.querySelectorAll('p').forEach((paragraph) => {
  paragraph.style.margin = '0 0 10px'; // Adjust margin as desired
});

popUp.querySelectorAll('h1, h2, h3, h4, h5, h6').forEach((heading) => {
  heading.style.margin = '0 0 5px'; // Adjust margin as desired
});

popUp.querySelectorAll('ul, ol').forEach((list) => {
  list.style.margin = '0 0 5px'; // Adjust margin as desired
});

popUp.querySelectorAll('li').forEach((listItem) => {
  listItem.style.margin = '0 0 5px'; // Adjust margin as desired
});

// Function to fetch sidebar information for a given URL
async function fetchSidebarInfo(url) {
  const cachedContent = GM_getValue(url); // Check if content is cached

  if (cachedContent) {
    return cachedContent;
  } else {
    try {
      const response = await fetch(url);
      const html = await response.text();
      const parser = new DOMParser();
      const doc = parser.parseFromString(html, 'text/html');
      const sidebarElement = doc.querySelector('section.magazine.section'); // Adjust the selector based on the structure of the sidebar on the page
      const sidebarHTML = sidebarElement.innerHTML;

      return sidebarHTML;
    } catch (error) {
      console.error('Error fetching sidebar information:', error);
      return null;
    }
  }
}

function showPopUp(magazineURL) {
  // Check if the pop-up is already appended to the document body

  // Get the URL from the magazine link
  const url = magazineURL.getAttribute('href');

  // Fetch the sidebar information for the URL
  fetchSidebarInfo(url)
    .then((sidebarHTML) => {
      if (sidebarHTML) {
        // Create a temporary container element to manipulate the sidebar content
        const tempContainer = document.createElement('div');
        tempContainer.innerHTML = sidebarHTML;

        // Remove unnecessary items from the magazine
        const itemsToRemove = [
          'h3',
          '.magazine__description',
          '.mb-2',
          '.mt-3',
          '.meta',
          '.magazine__rules'
        ];
        itemsToRemove.forEach((selector) => {
          const element = tempContainer.querySelector(selector);
          if (element && element.parentNode) {
            element.parentNode.removeChild(element);
          }
        });

        if (!document.body.contains(popUp)) {
          // Clear the previous content of the pop-up
          popUp.innerHTML = '';

          // Move the magazine's image figure to the top of the pop-up
          const figureElement = tempContainer.querySelector('img');
          if (figureElement) {
            figureElement.style.maxWidth = '145px'; // Adjust the desired maximum width for the image
            figureElement.style.width = 'auto'; // Allow the image to resize while maintaining aspect ratio
            figureElement.style.borderRadius = '8px'; // Add border radius to the image

            const popUpContent = document.createElement('div');
            popUpContent.className = 'pop-up-content';
            popUpContent.style.display = 'flex'; // Enable flexbox layout
            popUpContent.style.alignItems = 'flex-start'; // Align items at the top

            // Move the magazine header and subscribe section to the right of the image
            const headerElement = tempContainer.querySelector('header');
            const magazineName = tempContainer.querySelector('.magazine__name');
            const subscribeElement = tempContainer.querySelector('.magazine__subscribe');

            if (headerElement || magazineName || subscribeElement) {
              const infoWrapper = document.createElement('div');
              infoWrapper.style.display = 'flex'; // Enable flexbox layout
              infoWrapper.style.flexDirection = 'column'; // Stack items vertically
              infoWrapper.style.marginLeft = '25px'; // Add margin to the left side of the header and subscribe sections
              infoWrapper.style.marginTop = '-25px'; // Add margin to the left side of the header and subscribe sections
              infoWrapper.style.alignItems = 'center'; // Center items vertically
              infoWrapper.style.gap = '5px'; // Adjust the desired spacing between the header and subscribe sections

              if (headerElement) {
                headerElement.style.textAlign = 'center'; // Center align the header
                headerElement.style.fontFamily = 'Arial, sans-serif'; // Adjust the font family
                headerElement.style.fontSize = '12.5px'; // Adjust the font size
                headerElement.style.marginBottom = '-10px'; // Adjust the negative margin bottom value to move the figure higher
                infoWrapper.appendChild(headerElement);
              }

              if (magazineName) {
                magazineName.style.fontFamily = 'Arial, sans-serif'; // Adjust the font family
                magazineName.style.fontSize = '13.5px'; // Adjust the font size
                magazineName.style.overflow = 'hidden'; // Add this line to hide the overflowed text
                magazineName.style.textOverflow = 'ellipsis'; // Add this line to display ellipsis (...) for overflowed text
                magazineName.style.whiteSpace = 'auto'; // Add this line to prevent line wrapping
                infoWrapper.appendChild(magazineName);
              }

              if (subscribeElement) {
                subscribeElement.style.marginTop = '0'; // Remove the margin at the top of the subscribe section
                subscribeElement.style.fontFamily = 'Arial, sans-serif'; // Adjust the font family
                subscribeElement.style.fontSize = '10px'; // Adjust the font size
                infoWrapper.appendChild(subscribeElement);
              }

              popUpContent.appendChild(figureElement);
              popUpContent.appendChild(infoWrapper);
            } else {
              popUpContent.appendChild(figureElement);
            }

            // Append the pop-up content to the pop-up element
            popUp.appendChild(popUpContent);
          }

          // Position the pop-up element relative to the magazine URL
          const magazineURLRect = magazineURL.getBoundingClientRect();
          const popUpHeight = popUp.offsetHeight;
          const popUpWidth = popUp.offsetWidth;

          let popUpTop, popUpLeft;

          if (magazineURLRect.bottom + popUpHeight > window.innerHeight) {
            popUpTop = magazineURLRect.top - popUpHeight;
          } else {
            popUpTop = magazineURLRect.bottom;
          }

          if (magazineURLRect.left + popUpWidth > window.innerWidth) {
            popUpLeft = window.innerWidth - popUpWidth;
          } else {
            popUpLeft = magazineURLRect.left;
          }

          // Apply the calculated position to the pop-up element
          popUp.style.position = 'fixed';
          popUp.style.top = `${popUpTop}px`;
          popUp.style.left = `${popUpLeft}px`;

          // Add the pop-up element to the document body
          document.body.appendChild(popUp);

          // Apply fade-in animation to the pop-up
          popUp.style.opacity = '0';
          popUp.style.transition = 'opacity 0.3s';

          requestAnimationFrame(() => {
            popUp.style.opacity = '1';
          });
        }
      }
    })
    .catch((error) => {
      console.error('Error fetching sidebar information:', error);
    });
}




// Function to hide the pop-up
function hidePopUp() {
  // Check if the cursor is still inside the pop-up
  if (popUp.matches(':hover')) {
    return;
  }

  // Apply fade-out animation to the pop-up
  popUp.style.opacity = '0';
  popUp.style.transition = 'opacity 0.3s';

  // Remove the pop-up element from the document body after the animation ends
  setTimeout(() => {
    document.body.removeChild(popUp);
  }, 1000);
}

// Function to attach hover functionality to the magazine URLs
function attachHoverFunctionality() {
  magazineURLs.forEach((magazineURL) => {
    let hideTimeout; // Variable to store the timeout ID

    // Add event listener to show the pop-up when hovering over the magazine URL or the pop-up itself
    magazineURL.addEventListener('mouseenter', () => {
      // Clear the timeout if it exists (to prevent premature hiding)
      clearTimeout(hideTimeout);

      // Set a timeout of 1000ms (1 second) before showing the pop-up
      hideTimeout = setTimeout(() => {
        showPopUp(magazineURL);
      }, 2000);

      // Position the pop-up immediately above the link if near the bottom of the window
      const magazineURLRect = magazineURL.getBoundingClientRect();
      const popUpHeight = popUp.offsetHeight;

      if (magazineURLRect.bottom + popUpHeight > window.innerHeight) {
        const popUpTop = magazineURLRect.top - popUpHeight;
        const popUpLeft = magazineURLRect.left;

        // Apply the calculated position to the pop-up element
        popUp.style.position = 'fixed';
        popUp.style.top = `${popUpTop}px`;
        popUp.style.left = `${popUpLeft}px`;
      }
    });

    // Add event listener to hide the pop-up when the cursor leaves the magazine URL or the pop-up itself
    magazineURL.addEventListener('mouseleave', () => {
      // Clear the timeout to prevent the pop-up from appearing
      clearTimeout(hideTimeout);

      // Set a delay of 1000ms (1 second) before hiding the pop-up
      hideTimeout = setTimeout(() => {
        hidePopUp();
      }, 1000);
    });

    // Add event listener to hide the pop-up when the cursor leaves the pop-up
    popUp.addEventListener('mouseleave', () => {
      // Set a delay of 1000ms (1 second) before hiding the pop-up
      hideTimeout = setTimeout(() => {
        hidePopUp();
      }, 1000);
    });
  });
}


// Function to observe changes in the page and attach hover functionality to new magazine URLs
function observePageChanges() {
  const observer = new MutationObserver(() => {
    magazineURLs = document.querySelectorAll('a.magazine-inline');
    attachHoverFunctionality();
  });

  const config = { childList: true, subtree: true };
  observer.observe(document.body, config);
}

// Call the function to attach hover functionality to existing magazine URLs
attachHoverFunctionality();

// Call the function to observe page changes and attach hover functionality to newly added magazine URLs
observePageChanges();