VG Thumbnails

Show thumbnails in ViperGirls thread listings

// ==UserScript==
// @name         VG Thumbnails
// @namespace    http://tampermonkey.net/
// @version      0.13
// @description  Show thumbnails in ViperGirls thread listings
// @author       derux; based on the original script by metafox12345
// @match        https://viper.to/search.php?searchid=*
// @match        https://viper.to/forumdisplay.php?f=*
// @match        https://viper.to/forums/*/page*?prefixid=*
// @match        https://viper.to/forums/*
// @grant        none
// @license      MIT
// ==/UserScript==

(function() {
  'use strict';
  const $$ = document.querySelectorAll.bind(document);

  function addStyles() {
    const css = document.createElement('style');
    css.innerHTML = `
    .vg-preview-section {
      background: #eee;
      display: flex;
      align-items: flex-start;
      width: 100%;
      justify-content: center;
      padding: 16px 0;
      flex-wrap: wrap;
      gap: 8px;
    }

    .vg-preview-section img {
      max-width: 240px;
      max-height: 240px;
      box-shadow: 0 0 5px 0px #adadad;
    }
    `;
    document.head.appendChild(css);
  }

  function happy() {
    addStyles();

    // Find all thread links with data-images attribute
    const anchors = $$('a.title[data-images]');

    if (anchors === null || anchors.length === 0) {
      return;
    }

    for (const anchor of anchors) {
      // Get the JSON array from data-images attribute
      const dataImages = anchor.getAttribute('data-images');

      if (!dataImages) {
        continue;
      }

      // Parse the JSON array of image URLs
      let thumbUrls;
      try {
        thumbUrls = JSON.parse(dataImages);
      } catch (e) {
        console.error('Failed to parse data-images:', e);
        continue;
      }

      if (!thumbUrls || thumbUrls.length === 0) {
        continue;
      }

      // Find the parent element to append the preview section
      // Go up to find the list item or appropriate parent
      let thread = anchor.closest('li');
      if (!thread) {
        thread = anchor.parentElement;
      }

      if (!thread) {
        continue;
      }

      // Check if we already added previews to this thread
      if (thread.querySelector('.vg-preview-section')) {
        continue;
      }

      // Disable the tooltip on this anchor since we're showing thumbnails inline
      if (anchor._tippy) {
        anchor._tippy.destroy();
      }
      anchor.removeAttribute('data-images');
      anchor.classList.remove('thread-preview');

      // Generate the preview section for the thread
      const thumbsPreview = document.createElement('div');
      thumbsPreview.className = "vg-preview-section";

      for (const thumbUrl of thumbUrls) {
        // preview > a > img
        const thumb = document.createElement('img');
        thumb.src = thumbUrl;

        const thumbAnchor = document.createElement('a');
        thumbAnchor.href = thumbUrl;
        thumbAnchor.target = "_blank";

        thumbAnchor.appendChild(thumb);
        thumbsPreview.appendChild(thumbAnchor);
      }

      thread.appendChild(thumbsPreview);
    }
  }

  happy();
})();