Greasy Fork

Greasy Fork is available in English.

Letterboxd Titles

Force titles to be displayed above movie posters (on some pages only)

当前为 2025-05-17 提交的版本,查看 最新版本

// ==UserScript==
// @name         Letterboxd Titles
// @namespace    https://letterboxd.com/
// @version      3.21
// @description  Force titles to be displayed above movie posters (on some pages only)
// @author       n00bCod3r
// @match        https://letterboxd.com/*
// @grant        GM_addStyle
// ==/UserScript==

GM_addStyle(`
:root {
  --w: 50px;
}

.fancy-title {
  text-align: center;
  overflow-wrap: break-word;
  width: var(--w);
  font-size: 10px;
}

ul.poster-list, ul.grid {
  align-items: flex-end; //force elements to be vertically aligned at the end
}
`);

'use strict';

const body = document.querySelector('body');
const r = document.querySelector(':root');
const config = {
  childList: true,
  subtree: true
}

let titlesLoaded = false;

const observer = new MutationObserver(mutationRecords => {
  // While every title has not been loaded
  if (!titlesLoaded) {
    const movies = [...document.querySelectorAll('li>div.film-poster')]; // NodeList to Array

    const allMoviesLoaded = movies.length > 0 && movies.every(elem => { // Every movie has a title
      const spanElem = elem.querySelector('span.frame-title');
      return Boolean(spanElem.textContent);
    });

    if (allMoviesLoaded) {
      addTitles();
      titlesLoaded = true;
      observer.disconnect();
    }

  }
});

observer.observe(body, config);

document.addEventListener('scroll', () => {
  if (!titlesLoaded) {
    addTitles()
  }
}, false);

function addTitles() {

  const maxTitleLength = 23;
  let movieInfo = "";


  document.querySelectorAll('li>div.film-poster')
    .forEach(divFilmPoster => {
      r.style.setProperty('--w', `${divFilmPoster.offsetWidth}px`)

      let spanElem = divFilmPoster.querySelector('span.frame-title');

      //prevent the script to break on scrolling
      if (spanElem.textContent && !divFilmPoster.dataset.tweaked) {
        //mark tweaked posters for when user will scroll
        divFilmPoster.dataset.tweaked = 'true';

        let text = `${spanElem.textContent}`;

        // Get title and year
        const [title, year] = text.split(' (');

        // Trim title when too long
        const shortenedTitle = title.length > maxTitleLength ? `${title.substring(0, maxTitleLength-3) + '...'}` : title;

        const movieInfo = `${shortenedTitle} (${year.slice(0, -1)})`;

        // Create elem, add classes, content and place it
        const divNode = document.createElement("div");
        divNode.classList.add('fancy-title');
        divNode.textContent = movieInfo;
        divFilmPoster.parentNode.insertBefore(divNode, divFilmPoster); //insert div above the poster image
      }
    });
}