// ==UserScript== // @name Letterboxd Bio Modifier // @namespace https://github.com/soyguijarro/userscripts // @description Adds visual bio summary and Wikipedia link to actors and directors pages // @copyright 2015, Ramón Guijarro (http://soyguijarro.com) // @homepageURL https://github.com/soyguijarro/userscripts // @supportURL https://github.com/soyguijarro/userscripts/issues // @icon https://raw.githubusercontent.com/soyguijarro/userscripts/master/img/letterboxd_icon.png // @license GPLv3; http://www.gnu.org/licenses/gpl.html // @version 1.2 // @include *://letterboxd.com/director/* // @include *://letterboxd.com/actor/* // @grant GM_addStyle // @grant GM_xmlhttpRequest // @downloadURL none // ==/UserScript== var sidebarElt = document.getElementsByClassName("sidebar")[0], bioElt = sidebarElt.getElementsByClassName("tmdb-person-bio")[0], tmdbId = bioElt.getAttribute("data-tmdb-id"), tmdbBaseUrl = "http://themoviedb.org/person/", tmdbUrl = tmdbBaseUrl + tmdbId; function showBioSummary(res) { var dom = new DOMParser().parseFromString(res.responseText, "text/html"), tmdbBirthplaceElt = dom.getElementById("place_of_birth"), tmdbBirthdayElt = dom.getElementById("birthday"), tmdbDeathdayElt = dom.getElementById("deathday"), creditsElt = dom.getElementById("leftCol").getElementsByTagName("p")[0], creditsMatch = creditsElt.textContent.match(/Known Credits: (\d+)/), gotRelevantData = isActualData(tmdbBirthplaceElt) || isActualData(tmdbBirthdayElt), bioSummaryElt = document.createElement("section"), bioSummaryElts, bioInnerElt, cssRules = "section.panel-text.bio-summary {\ border-bottom: 1px solid #456;\ }\ section.panel-text.bio-summary p {\ padding-left: 25px;\ display: block;\ }"; function getFormattedDate(date) { var monthNum = date.getMonth(), dayNum = date.getDate(), yearNum = date.getFullYear(), monthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; return monthNames[monthNum] + " " + dayNum + ", " + yearNum; } function isActualData(elt) { var data = elt.textContent, exp = /^-$/; return !(exp.test(data)); } function showBirthplace() { var birthplace = tmdbBirthplaceElt.textContent, birthplaceElt = document.createElement("p"), birthplaceIconElt = document.createElement("span"); // Fill element with data and apply styles birthplaceElt.classList.add("icon-location"); birthplaceElt.textContent = birthplace.replace(/ - /g, ", "); birthplaceIconElt.style.marginLeft = "2px"; // Insert element in section birthplaceElt.appendChild(birthplaceIconElt); bioSummaryElt.appendChild(birthplaceElt); } function showBornDeathDate() { var birthday = new Date(tmdbBirthdayElt.firstElementChild.textContent), dateElt = document.createElement("p"), dateIconElt = document.createElement("span"), msPerYear = 1000 * 60 * 60 * 24 * 365, refDate, date, age; // Fill element with data and apply styles if (tmdbDeathdayElt) { // Person is dead // Use death date as reference to calculate age refDate = new Date(tmdbDeathdayElt.firstElementChild.textContent); date = refDate; // Show death date dateElt.classList.add("icon-hidden"); dateIconElt.style.marginLeft = "3px"; } else { // Person is alive // Use today as reference to calculate age refDate = new Date(); date = birthday; // Show birthday dateElt.classList.add("icon-people"); } age = Math.floor((refDate - birthday.getTime()) / msPerYear); dateElt.textContent = getFormattedDate(date) + " (age" + ((tmdbDeathdayElt) ? "d " : " ") + age + ")"; // Insert element in section dateElt.appendChild(dateIconElt); bioSummaryElt.appendChild(dateElt); } function showNumCredits() { var numCredits = creditsMatch[1], creditsElt = document.createElement("p"), creditsIconElt = document.createElement("span"); // Fill element with data and apply styles creditsElt.classList.add("icon-list-all"); creditsElt.textContent = numCredits + " known credits"; creditsIconElt.style.backgroundPosition = "-740px -110px"; // Insert element in section creditsElt.appendChild(creditsIconElt); bioSummaryElt.appendChild(creditsElt); } // Set up section to be inserted in page bioSummaryElt.className = "section panel-text bio-summary"; // Fill section with available data if (gotRelevantData) { if (isActualData(tmdbBirthplaceElt)) { showBirthplace(); } if (isActualData(tmdbBirthdayElt)) { showBornDeathDate(); } if (creditsMatch) { showNumCredits(); } } else { return; // Abort if no relevant data at all is available } // Apply common styles to section elements bioSummaryElts = bioSummaryElt.children; for (var i = 0; i < bioSummaryElts.length; i++) { bioSummaryElts[i].classList.add("has-icon") bioSummaryElts[i].classList.add("icon-16"); bioSummaryElts[i].firstElementChild.className = "icon"; } // Insert section in page bioInnerElt = bioElt.getElementsByClassName("panel-text condensed")[0] || bioElt.getElementsByClassName("panel-text")[0]; if (bioInnerElt) { // Already existing bio section bioInnerElt.insertBefore(bioSummaryElt, bioInnerElt.firstElementChild.nextSibling); } else { // No bio section, add missing header var bioHeaderElt = document.createElement("h2"); bioHeaderElt.className = "section-heading"; bioHeaderElt.textContent = "Bio"; bioElt.appendChild(bioHeaderElt); bioElt.appendChild(bioSummaryElt); } GM_addStyle(cssRules); } function showWikiLink() { var linksElt = document.getElementsByClassName("bio-link")[0], headerElt = document.getElementsByClassName("page-header")[0], personNameElt = headerElt.querySelector("h1.inline-heading.prettify em"), wikiLinkElt = document.createElement("li"), wikiLinkInnerElt = document.createElement("a"), personName = personNameElt.textContent, wikiBaseUrl = "https://en.wikipedia.org/wiki/", wikiUrl = wikiBaseUrl + personName, linksInnerElt; // Fill element with data and apply styles wikiLinkInnerElt.className = "box-link"; wikiLinkInnerElt.href = wikiUrl; wikiLinkInnerElt.textContent = "Search on Wikipedia"; wikiLinkElt.appendChild(wikiLinkInnerElt); // Insert section in page if (linksElt) { // Already existing link section linksInnerElt = linksElt.getElementsByTagName("ul")[0]; linksInnerElt.insertBefore(wikiLinkElt, linksInnerElt.firstElementChild); } else { // No link section, create first linksElt = document.createElement("section"); linksInnerElt = document.createElement("ul"); linksElt.className = "section bio-link"; linksInnerElt.className = "box-link-list box-links"; linksInnerElt.appendChild(wikiLinkElt); linksElt.appendChild(linksInnerElt); sidebarElt.insertBefore(linksElt, sidebarElt.getElementsByClassName("progresspanel")[0]); } } GM_xmlhttpRequest({ method: "GET", url: tmdbUrl, onload: showBioSummary }); showWikiLink();