Greasy Fork is available in English.

1337x - UX Enhancement

Extend titles, add images to torrent list, full width site

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name         1337x - UX Enhancement
// @namespace    http://tampermonkey.net/
// @version      1.4
// @description  Extend titles, add images to torrent list, full width site
// @author       French Bond
// @match        https://1337x.to/*
// @grant        GM_xmlhttpRequest
// @grant        GM_addStyle
// @license      MIT
// ==/UserScript==

const VISIBLE_IMAGES = 4; // Number of images to show initially

(function () {
  'use strict';

  // List all torrent links on the page
  function listTorrentLinks() {
    return document.querySelectorAll('.table-list a[href^="/torrent/"]');
  }

  // Clean the page title in order to get the torrent title
  function cleanTitle(title) {
    // Remove "Download " from the beginning
    if (title.startsWith('Download ')) {
      title = title.substring('Download '.length);
    }
    // Remove anything after " |"
    let pipeIndex = title.indexOf(' Torrent |');
    if (pipeIndex !== -1) {
      title = title.substring(0, pipeIndex);
    }
    return title;
  }

  // Modify the H1 content on torrent pages to show the full title
  function modifyH1ContentOnTorrentPages() {
    if (window.location.pathname.startsWith('/torrent/')) {
      let h1Element = document.querySelector('.box-info-heading h1');
      if (h1Element) {
        let cleanedTitle = cleanTitle(document.title);
        h1Element.textContent = cleanedTitle;
      }
    }
  }

  // Fetch the content of the link
  function fetchContent(link, onSuccess) {
    GM_xmlhttpRequest({
      method: 'GET',
      url: link.href,
      onload: function (response) {
        let parser = new DOMParser();
        let doc = parser.parseFromString(response.responseText, 'text/html');
        onSuccess(doc);
      },
    });
  }

  // Process the link to update the title and add download buttons and images
  function processLink(link) {
    fetchContent(link, (doc) => {
      updateLinkTitle(link, doc);
      appendImages(link, doc);
      addDownloadButtons(link, doc);
    });
  }

  // Update the link title
  function updateLinkTitle(link, doc) {
    let title = cleanTitle(doc.querySelector('title').innerText);
    link.innerText = title;
  }

  // Add download buttons next to the link
  function addDownloadButtons(link, doc) {
    let torrentLink = doc.querySelector("a[href*='itorrents.org/torrent/']");
    let magnetLink = doc.querySelector("a[href^='magnet:?']");

    let buttonsContainer = document.createElement('div');
    buttonsContainer.style.display = 'flex';
    buttonsContainer.style.alignItems = 'center';
    buttonsContainer.style.gap = '5px';
    buttonsContainer.style.marginTop = '10px';

    // Torrent button
    let torrentButton = document.createElement('a');
    torrentButton.href = torrentLink ? torrentLink.href.replace('http:', 'https:') : '#';
    torrentButton.title = 'Download torrent file';
    torrentButton.innerHTML =
      '<i class="flaticon-torrent-download" style="color: #89ad19; font-size: 16px"></i>';

    // Magnet button
    let magnetButton = document.createElement('a');
    magnetButton.href = magnetLink ? magnetLink.href : '#';
    magnetButton.title = 'Download via magnet';
    magnetButton.innerHTML =
      '<i class="flaticon-magnet" style="color: #da3a04; font-size: 16px"></i>';

    buttonsContainer.appendChild(torrentButton);
    buttonsContainer.appendChild(magnetButton);

    link.after(buttonsContainer);
  }

  // Append images related to the torrent
  function appendImages(link, doc) {
    let images = doc.querySelectorAll('#description img');
    if (images.length > 0) {
      let flexContainer = document.createElement('div');
      flexContainer.style.display = 'flex';
      flexContainer.style.flexWrap = 'wrap';
      flexContainer.style.gap = '10px';
      flexContainer.style.marginTop = '10px';

      let clonedImages = []; // Array to store cloned images

      images.forEach((img, index) => {
        let clonedImg = img.cloneNode(true);
        if (img.hasAttribute('data-original')) {
          clonedImg.src = img.getAttribute('data-original');
        }
        clonedImg.style.maxHeight = '100px';
        clonedImg.style.setProperty('margin', '0', 'important');

        // Show only the first VISIBLE_IMAGES images initially
        clonedImg.style.display = index < VISIBLE_IMAGES ? 'block' : 'none';
        flexContainer.appendChild(clonedImg);
        clonedImages.push(clonedImg); // Store the cloned image
      });

      // Add "Show More/Less" button if there are more than VISIBLE_IMAGES images
      if (images.length > VISIBLE_IMAGES) {
        let showMoreButton = document.createElement('button');
        showMoreButton.textContent = 'Show More';

        showMoreButton.onclick = function () {
          // Toggle visibility of additional images
          let isShowingMore = showMoreButton.textContent === 'Show Less';
          clonedImages.forEach((img, index) => {
            if (index >= VISIBLE_IMAGES) {
              img.style.display = isShowingMore ? 'none' : 'block';
            }
          });
          showMoreButton.textContent = isShowingMore ? 'Show More' : 'Show Less';
        };

        flexContainer.appendChild(showMoreButton);
      }

      link.parentNode.insertBefore(flexContainer, link.nextSibling);

      clonedImages.forEach((clonedImg) => {
        // Mouseover event to show enlarged image
        clonedImg.addEventListener('mouseover', function () {
          showEnlargedImg(clonedImg.src);
        });

        // Mousemove event to update the position of the enlarged image
        clonedImg.addEventListener('mousemove', updateEnlargedImgPosition);

        // Mouseout event to remove enlarged image
        clonedImg.addEventListener('mouseout', function () {
          removeEnlargedImg();
        });
      });
    }
  }

  // Function to show an enlarged image
  function showEnlargedImg(imgSrc) {
    const enlargedImg = document.createElement('img');
    enlargedImg.src = imgSrc;
    enlargedImg.style.position = 'fixed';
    enlargedImg.style.width = '500px';
    enlargedImg.style.height = '500px';
    enlargedImg.style.pointerEvents = 'none'; // Ignore pointer events
    enlargedImg.id = 'enlargedImg';
    document.body.appendChild(enlargedImg);
  }

  // Function to update the position of the enlarged image
  function updateEnlargedImgPosition(e) {
    const enlargedImg = document.getElementById('enlargedImg');
    if (enlargedImg) {
      const viewportWidth = window.innerWidth;
      const viewportHeight = window.innerHeight;
      const imgWidth = 500; // Width of the enlarged image
      const imgHeight = 500; // Height of the enlarged image
      const offsetX = 10; // Horizontal offset from the cursor
      const offsetY = 10; // Vertical offset from the cursor

      let leftPosition = e.clientX + offsetX;
      let topPosition = e.clientY + offsetY;

      // Adjust position if the image goes out of the viewport
      if (leftPosition + imgWidth > viewportWidth) {
        leftPosition = e.clientX - imgWidth - offsetX;
      }
      if (topPosition + imgHeight > viewportHeight) {
        topPosition = e.clientY - imgHeight - offsetY;
      }

      enlargedImg.style.left = leftPosition + 'px';
      enlargedImg.style.top = topPosition + 'px';
    }
  }

  // Function to remove enlarged image
  function removeEnlargedImg() {
    const enlargedImg = document.getElementById('enlargedImg');
    if (enlargedImg) {
      document.body.removeChild(enlargedImg);
    }
  }

  // Replace the link text with the title and append images
  function replaceLinkTextWithTitlesAndAppendImages() {
    let torrentLinks = listTorrentLinks();
    torrentLinks.forEach(processLink);
  }

  function injectCustomCSS() {
    // Remove the max-width on the container
    GM_addStyle('.container { max-width: none !important; }');
  }

  // Modify the function calls accordingly
  replaceLinkTextWithTitlesAndAppendImages();
  modifyH1ContentOnTorrentPages();
  injectCustomCSS();
})();