NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript==
// @name Spoilered IMDb Episodes
// @namespace http://github.com/obskyr/
// @homepageURL http://github.com/obskyr/
// @icon http://i.imgur.com/joPuTLc.png
// @description Hide spoilers on IMDb. Accidentally spoiling if a character leaves halfway through a show really sucks!
// @include *.imdb.com/name/*
// @include *.imdb.com/title/*
// @require http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js
// @version 1.2.2
// @grant none
// ==/UserScript==
// Dedicated to @freddefripp.
// CSS for button states
var epButtonCss = ".epButton, .allEpButton { \n\
display: inline-block; \n\
float: right; \n\
height: 14px; \n\
padding: 2px; \n\
border-radius: 2px; \n\
background-color: #FFFFFF; \n\
font-size: 0.8em; \n\
cursor: pointer; \n\
\n\
-webkit-touch-callout: none; \n\
-webkit-user-select: none; \n\
-khtml-user-select: none; \n\
-moz-user-select: none; \n\
-ms-user-select: none; \n\
user-select: none; \n\
}\n";
var ebPressedCss = ".ebPressed { \n\
background-color: rgb(246, 246, 245); \n\
}\n";
var charEpCss = ".charEpText { \n\
display: inline; \n\
}\n";
var allEpConCss = "#allEpContainer { \n\
display: inline-block; \n\
float: right; \n\
overflow: hidden; \n\
}\n";
var cssArr = [epButtonCss, ebPressedCss, charEpCss, allEpConCss]
var filmselector = '#filmography .filmo-category-section .filmo-row';
var charselector = '.cast_list tbody tr .character';
var fadeNHide = function($peekaboo) {
$peekaboo.fadeTo(400, 0, function(){
$peekaboo.css('visibility', 'hidden'); // For browsers that don't do opacity
});
}
var fadeNShow = function($peekaboo) {
$peekaboo.css('visibility', 'visible'); // Same here
$peekaboo.fadeTo(400, 1);
}
$(document).ready(function() {
$('html > head').append('<style type="text/css">' + cssArr.join('') + '</style>')
var $tvEntries = $(filmselector + ' .filmo-episodes').parent();
var $charEntries = $(charselector);
var $epButton = $("<div></div>", {"class": "epButton", "text": "EPISODES",});
var $allEpButton = $("<div></div>", {"class": "allEpButton", "text": "ALL EPISODES",});
var seriesNotMovie = ($('#title-overview-widget #title-overview-widget-layout tbody tr #overview-top .infobar').text().toLowerCase().match('tv series') || $('#sidebar .nobr').text().toLowerCase().match('tv series'))
var epCountRe = /\([0-9]+\sepisode[^)]+\)/
if (window.location.pathname.match('/name/')) { // Actor pages
// Lets the button take up space and resize show entries
$tvEntries.css("overflow", "hidden");
// Adds toggle to every TV series entry
$tvEntries.find('.filmo-episodes:first-of-type').before($epButton)
if (!($('#jumpto').length)) { // Adds #jumpto div needed for .allEpsButton on actor pages
$('#filmography').before($('<div></div>', {'id': 'jumpto'}));
}
$('#jumpto').css({'overflow': 'hidden'});
$('#jumpto').append($allEpButton);
$($tvEntries).children('.filmo-episodes').hide() // Starts spoilered
$('.epButton').click(function() { // Shows and hides the episode list
var $epDiv = $(this).parent().children('.filmo-episodes'); // All single-episode divs in the current filmo-row
if ($epDiv.is(':visible') && !($epDiv.is(':animated'))) {
$epDiv.hide(400);
$(this).toggleClass('ebPressed');
}
else if (!($epDiv.is(':animated'))) {
$epDiv.show(400);
$(this).toggleClass('ebPressed');
}
var allChecked = false;
if ($('.epButton.ebPressed').length == $('.epButton').length) {
allChecked = true;
}
if (allChecked) {$('.allEpButton').addClass('ebPressed')} else {$('.allEpButton').removeClass('ebPressed')} // Checks allEpButton if every epButton is checked
})
$('.allEpButton').click(function() {
if (!($('.filmo-episodes:animated').length)) {
if ($('.epButton').length > 50) { // Too many simultaneous animations cause lag.
var fadeHide = function($o) {
$o.hide();
}
var fadeShow = function($o) {
$o.show();
}
}
else {
var fadeHide = function($o) {
$o.hide(400);
}
var fadeShow = function($o) {
$o.show(400);
}
}
if (!($(this).hasClass('ebPressed'))) {
$('.epButton').not('.ebPressed').addClass('ebPressed');
fadeShow($('.filmo-episodes'));
$('.allEpButton').addClass('ebPressed');
}
else {
$('.epButton.ebPressed').removeClass('ebPressed');
fadeHide($('.filmo-episodes'));
$('.allEpButton').removeClass('ebPressed');
}
}
});
}
else if (window.location.pathname.match('/title/') && seriesNotMovie) { // TV show pages
// Only for TV series, not movies
var $nameAndEps = $charEntries.children('div:first-of-type');
$nameAndEps.css({'display': 'inline', 'overflow': 'hidden',}); // Puts episode button next to episodes, not under
$charEntries.append($epButton);
$charEntries.parent().parent().find('.castlist_label').css({'padding-right': '6px', 'padding-bottom': '8px'});
$charEntries.parent().parent().find('.castlist_label').append($allEpButton);
$nameAndEps.each(function() {
var curEpText = $(this).text().match(epCountRe);
if (curEpText) { // Puts number of episodes text in its own hideable div
curEpText = curEpText[0]
$(this).text($(this).text().replace(epCountRe, ''));
$(this).append($("<div></div>", {'text': curEpText, 'class': 'charEpText'}));
$(this).children('.charEpText').css({'visibility': 'hidden', 'opacity': '0'});
}
});
$('.epButton').click(function() {
var $textDiv = $(this).parent().find('.charEpText');
if ($textDiv.css('visibility') == 'visible' && !($textDiv.is(':animated'))) {
fadeNHide($textDiv);
$(this).toggleClass('ebPressed');
}
else if (!($textDiv.is(':animated'))) {
fadeNShow($textDiv);
$(this).toggleClass('ebPressed');
}
var allChecked = true;
$('.epButton').each(function() { // Toggles .allEpButton if all are selected
if (!($(this).hasClass('ebPressed'))) {
allChecked = false;
return false;
}
});
if (allChecked) {$('.allEpButton').addClass('ebPressed')} else {$('.allEpButton').removeClass('ebPressed')}
});
$('.allEpButton').click(function() {
if (!($charEntries.find('.charEpText:animated').length)) {
if ($('.epButton').length > 20) {
var fadeNShowTemp = function($o) {$o.css({'visibility': 'visible', 'opacity': '1'})}
var fadeNHideTemp = function($o) {$o.css({'visibility': 'hidden', 'opacity': '0'})}
}
else {
var fadeNShowTemp = fadeNShow; // So apparently JS doesn't like duplicate
var fadeNHideTemp = fadeNHide; // function names. I don't know, scope, man.
}
// Unlike in the actor pages, these animations are very cheap (processing-wise).
// No checking for number of divs is needed.
if (!($(this).hasClass('ebPressed'))) { // Shows all episode number divs
$('.epButton').not('.ebPressed').addClass('ebPressed');
fadeNShowTemp($('.charEpText'));
$('.allEpButton').addClass('ebPressed');
}
else { // Hides all episode number divs
$('.epButton.ebPressed').removeClass('ebPressed');
fadeNHideTemp($('.charEpText'));
$('.allEpButton').removeClass('ebPressed');
}
}
});
}
});