NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name Unfuck IMDb // @namespace https://www.imdb.com // @version 0.4.2 // @description Enhance the existing IMDB design. Works well with reference view. // @author heyxsh // @match *://www.imdb.com/search/title/* // @match *://www.imdb.com/title/tt* // @icon https://www.google.com/s2/favicons?domain=imdb.com // @require https://code.jquery.com/jquery-3.6.0.slim.min.js // @require https://cdn.jsdelivr.net/npm/spotlight.js@0.7.8/dist/spotlight.bundle.js // @grant GM_xmlhttpRequest // @connect yandex.com // @connect self // @updateURL https://raw.githubusercontent.com/heyxsh/userscripts/master/src/unfuckimdb.user.js // @downloadURL https://raw.githubusercontent.com/heyxsh/userscripts/master/src/unfuckimdb.user.js // @license MIT // ==/UserScript== function getTitleName() { let title = document.querySelector('title').innerText.trim() title = title.substr(0, title.lastIndexOf(')') + 1) title = title.replace('(', '') title = title.replace(')', '') // return encodeURIComponent(title) return title } /* * High Quality Poster Thumbs */ async function applyToSearchPage() { const images = document.querySelectorAll('.lister-item-image a img') images.forEach((img) => { img.setAttribute('width', 72) img.setAttribute('height', 105) let imgUrl = img.getAttribute('loadlate') || img.getAttribute('src') if (imgUrl) { let lastDot = imgUrl.lastIndexOf('.') let secLastDot = imgUrl.substr(0, lastDot).lastIndexOf('.') let params = imgUrl.substr(secLastDot + 1, lastDot - secLastDot - 1) if (params.search('_V[0-9]_') > -1) { let newParams = params.replace(/67/g, "240") newParams = newParams.replace(/98/g, "323") let newUrl = imgUrl.replace(params, newParams) img.setAttribute('loadlate', newUrl) img.setAttribute('src', newUrl) } } }) } /* * High Quality Poster */ async function hdPoster() { const poster = document.querySelector('img.titlereference-primary-image') if (!poster) return const imgUrl = poster.getAttribute('src') || poster.getAttribute('loadlate') if (imgUrl.search('_V[0-9]_') > -1) { let newUrl = imgUrl.slice(0, 116 + 1) + imgUrl.substr(imgUrl.lastIndexOf('.') + 1) poster.setAttribute('src', newUrl) } } /* * High Quality Actor Images */ async function hdActorImages() { const actorPhotos = document.querySelectorAll('.primary_photo a img') actorPhotos.forEach(img => { img.style.borderRadius = "4px" const imgUrl = img.getAttribute('loadlate') || img.getAttribute('src') if (imgUrl) { img.setAttribute('width', '90') img.setAttribute('height', '121') if (imgUrl.search(/_V[0-9]_/) > -1) { let lastDot = imgUrl.lastIndexOf('.') let secLastDot = imgUrl.substr(0, lastDot).lastIndexOf('.') let params = imgUrl.substr(secLastDot + 1, lastDot - secLastDot - 1) if (params.search('_V[0-9]_') > -1) { let newParams = params.replace(/26/g, "160") newParams = newParams.replace(/35/g, "215") let newUrl = imgUrl.replace(params, newParams) img.setAttribute('loadlate', newUrl) img.setAttribute('src', newUrl) } } } }) } /* * Fetch Parental Guide for Title Page */ async function fetchParentalGuide() { const url = window.location.href.replace("/reference", "/parentalguide") fetch(url).then(res => { return res.text() }) .then(html => { const div = document.createElement("div") div.innerHTML = html.trim() const main = div.querySelector("#main > section") const subPage = main.querySelector(".subpage_title_block") const itemCount = main.querySelector(".ipl-itemcount-header") const jumpto = main.querySelector(".ipl-jumpto-container") subPage.parentNode.removeChild(subPage) itemCount.parentNode.removeChild(itemCount) jumpto.parentNode.removeChild(jumpto) const section = document.querySelector("div#main > section.content-advisories-index") if (section) section.appendChild(main) }) .catch(err => { console.log(err) }) } /* * Declutters and Makes the Title Page Compact */ async function declutterTitlePage() { const cast_list = document.querySelector(".cast_list") const sidebar = document.querySelector("#sidebar") if (!sidebar) return sidebar.innerHTML = "" sidebar.appendChild(cast_list) cast_list.style.marginBottom = "20px" const credits = document.querySelector(".titlereference-section-credits") const production = document.querySelector(".titlereference-section-credits + section") const contrib = document.querySelector("#contribute-main-section") const rvi = document.querySelector("#rvi-div") credits.parentNode.removeChild(credits) production.parentNode.removeChild(production) contrib.parentNode.removeChild(contrib) rvi.parentNode.removeChild(rvi) $("td.ellipsis").remove() const remove_rows = ["Plot Summary", "Parents Guide", "Certification", "Sound Mix", "Aspect Ratio", "Opening Weekend", "Taglines", "Gross United States", "Trivia", "Goofs"] const tr = document.querySelectorAll('.ipl-zebra-list__item') tr.forEach(t => { for (var i = 0; i < remove_rows.length; i++) { if (t.innerText.indexOf(remove_rows[i]) > -1) { t.parentNode.removeChild(t) } } }) const summary = $(".titlereference-section-overview > div:first") const summaryLink = $(summary).find('a')[0] if (summaryLink.href && $(summary).text().includes("more")) { GM_xmlhttpRequest({ method: "GET", url: summaryLink.href, onload: r => { const sum = $($.parseHTML(r.responseText)).find('#main section #plot-summaries-content p:first').text(); $(summary).text(sum) } }) } } /* * Opens Spotlight Image Viewer */ function openSpotlight(srcs) { Spotlight.show(srcs, { media: "image", infinite: true, preload: true, download: true }) document.querySelector('.spl-title').setAttribute("style", "font-size: 0.65em; margin-bottom: 0; font-weight: bold;") document.querySelector('.spl-description').setAttribute("style", "font-size: 0.55em; margin-bottom: 4px;") document.querySelector('.spl-footer').setAttribute("style", "line-height: 15px; background: rgba(0, 0, 0, 0.25); padding: 4px 4px 0 4px;") } /* * Handle the Image/GIFS Sources */ async function handleImageSrcs(html) { var d = document.createElement('div') var srcs = [] d.innerHTML = html d.querySelectorAll(".serp-item.serp-item_type_search").forEach(item => { const data = (JSON.parse(item.getAttribute('data-bem')))["serp-item"] var title = false var description = false if (data.snippet && data.snippet.title) { const e = document.createElement('div') e.innerHTML = data.snippet.title title = e.innerText.trim() } if (data.snippet && data.snippet.text) { const e = document.createElement('div') e.innerHTML = data.snippet.text description = e.innerText.trim() } if (data.img_href) { srcs.push({ src: data.img_href, description, title }) } }) openSpotlight(srcs) } /* * Binds Events for Fetching Images */ async function bindImagesFetch() { const actors = document.querySelectorAll(".primary_photo a img") const seeMore = document.querySelector(".combined-see-more.see-more") actors.forEach(actor => { const tr = actor.parentNode.parentNode.parentNode const charName = $(tr).children("td.character").text().trim() $(tr).children("td.itemprop").append("<hr><em>" + charName + "</em>") $(tr).find("td.character").remove() $(tr).css({ fontSize: "0.85em" }) tr.innerHTML += ` <td class="character" style="width: 85px;"> <div class="actor_photos" style="float: right; padding-bottom: 2px;">Photos</div> <div class="actor_gifs" style="float: right; clear: both; padding-bottom: 2px;">GIFS</div> <div class="title_photos" style="float: right; clear: both;paddin-bottom: 2px;">Title Photos</div> <div class="title_gifs" style="float: right; clear: both;">Title GIFS</div> </td>` $(tr).children('.character').children().css({ color: "#136CB2", cursor: "pointer" }) const toFetch = { actor_photos: { el: tr.querySelector('.actor_photos'), url: encodeURI("https://yandex.com/images/search?text=" + actor.getAttribute('title') + "&ncrnd=0.874686120501252") }, actor_gifs: { el: tr.querySelector('.actor_gifs'), url: encodeURI("https://yandex.com/images/search?itype=gifan&text=" + actor.getAttribute('title') + "&ncrnd=0.874686120501252") }, title_photos: { el: tr.querySelector('.title_photos'), url: encodeURI("https://yandex.com/images/search?text=" + actor.getAttribute('title') + " " + getTitleName() + "&ncrnd=0.874686120501252") }, title_gifs: { el: tr.querySelector('.title_gifs'), url: encodeURI("https://yandex.com/images/search?text=" + actor.getAttribute('title') + " " + getTitleName() + "&itype=gifan&ncrnd=0.874686120501252") } } Object.keys(toFetch).forEach(k => { toFetch[k].el.addEventListener("mousedown", function(evt) { evt.stopPropagation() evt.preventDefault() GM_xmlhttpRequest({ method: "GET", url: toFetch[k].url, onload: function(res) { handleImageSrcs(res.responseText) } }) }) }) }) if (seeMore) { seeMore.innerHTML += ` <span class="ghost">|</span> <span class="external_images">More Images</span>` seeMore.innerHTML += ` <span class="ghost">|</span> <span class="gifs">GIFS</span>` $(seeMore).children(".external_images, .gifs").css({ color: "#136CB2", cursor: "pointer" }) const toFetch = { ext_images: { el: seeMore.querySelector(".external_images"), url: encodeURI("https://yandex.com/images/search?text=" + getTitleName() + "&ncrnd=0.874686120501252") }, gifs: { el: seeMore.querySelector(".gifs"), url: encodeURI("https://yandex.com/images/search?itype=gifan&text=" + getTitleName() + "&ncrnd=0.874686120501252") } } Object.keys(toFetch).forEach(k => { toFetch[k].el.addEventListener("mousedown", function(e) { e.preventDefault() e.stopPropagation() GM_xmlhttpRequest({ method: "GET", url: toFetch[k].url, onload: function(res) { handleImageSrcs(res.responseText) } }) }) }) } } async function applyToTitlePage() { declutterTitlePage() hdPoster() hdActorImages() fetchParentalGuide() bindImagesFetch() } (function() { 'use strict'; const currentUrl = window.location.href if (currentUrl.search(/title\/tt/) > -1) { applyToTitlePage() } else { applyToSearchPage() } })();