Netflix Rating Granulizer
— Last update Feb 9, 2009 — Installed 2,486 times.There are 5 previous versions of this script.
// ==UserScript==
// @name Netflix Rating Granulizer
// @description allows half star user ratings on Netflix
// @author mabuse
// @include http://*netflix.com/*
// ==/UserScript==
var document = unsafeWindow.document;
/* setting "overflow: visible" _dramatically_ improves performance; netflix's "overflow: hidden" isn't necessary */
var head = document.getElementsByTagName('head')[0];
if (head)
{
var style = document.createElement('style');
style.type = 'text/css';
style.innerHTML = '.stbrIl li a, .stbrOl li a, .stbrStc li a { overflow: visible; }';
head.appendChild(style);
}
var ratingStrings = [];
ratingStrings[1.5] = "Craptastic";
ratingStrings[2.5] = "Mediocre";
ratingStrings[3.5] = "Pretty pretty good";
ratingStrings[4.5] = "The shit, for reals";
var ratingWidths = [];
ratingWidths[1.5] = 27;
ratingWidths[2.5] = 46;
ratingWidths[3.5] = 65;
ratingWidths[4.5] = 84;
var niOffset = 17; /* rating width offset when not interested button is to the left */
/**
* Patches the sbHandler javascript object which netflix still uses on a few pages (instead of the
* more accessible HTML/CSS approach).
*/
function patchSbHandler()
{
var sbHandler = unsafeWindow.sbHandler;
if (!sbHandler)
return;
sbHandler.sbOffsets = [18,27,37,46,56,65,75,84,94];
sbHandler.displayStrings[1.5] = ratingStrings[1.5];
sbHandler.displayStrings[2.5] = ratingStrings[2.5];
sbHandler.displayStrings[3.5] = ratingStrings[3.5];
sbHandler.displayStrings[4.5] = ratingStrings[4.5];
for (var i=2; i<11; i++)
{
sbHandler.sbImages[i/2] = new Image();
sbHandler.sbImages[i/2].src = sbHandler.imageRoot+"stars_2_"+(Math.floor(i/2))+(i%2?"5":"0")+".gif";
}
sbHandler.getStarCount=function(evt)
{
var x = unsafeWindow.getElementMouseCoordinate(evt,this.element);
for (var i=0; i<10; i++)
if (x <= this.sbOffsets[i])
return (i+2)/2;
return 0;
};
}
/**
* Patches UL elements having the given class name by adding LI child elements with half-star
* rating widths among the existing elements.
*/
function patchUls(className, offset)
{
var uls = document.getElementsByClassName(className);
var hrefRegex = new RegExp('value=.');
for (var i=uls.length-1; i >=0; i--)
{
var ul = uls[i];
var lis = ul.childNodes;
if (ul.childNodes.length <= 6) /* only do once */
{
for (var j=4; j > 0; j--)
{
var rating = (5-j)+0.5;
var currentLi = lis[j];
var newLi = document.createElement('li');
newLi.setAttribute('class', 'rv'+rating); /* some netflix javascript parses this class name */
var newAnchor = document.createElement('a');
newLi.appendChild(newAnchor);
newAnchor.href = currentLi.childNodes[0].href.replace(hrefRegex, 'value='+rating);
newAnchor.rel = 'nofollow';
newAnchor.title = 'Click to rate the movie "'+ratingStrings[rating]+'"';
newAnchor.innerHTML = 'Rate '+rating+' stars';
newAnchor.setAttribute('style', 'width:'+(ratingWidths[rating]+offset)+'px');
ul.insertBefore(newLi, currentLi);
}
}
}
}
/**
* Patches elements displaying your current rating by setting half-star rating widths.
*/
function patchRated()
{
var maskFgs = document.getElementsByClassName('stbrMaskFg');
for (var i = maskFgs.length-1; i >= 0; i--)
{
var maskFg = maskFgs[i];
if (maskFg.childNodes.length)
{
var text = maskFg.childNodes[0].data;
if (text.indexOf('You') == 0)
{
var rating = text.replace(/.*: ([.0-9]+)/, '$1')*1.0;
if (~~rating != rating)
{
var offset = 0;
if (maskFg.parentNode.className.indexOf('stbrMaskBgIlNi') >= 0)
offset = niOffset;
maskFg.style.width = (ratingWidths[rating]+offset)+'px';
}
}
}
}
}
if (unsafeWindow.sbHandler)
patchSbHandler();
var startTime = new Date();
patchUls('stbrIlNi', niOffset);
patchUls('stbrIl', 0);
patchUls('stbrOl', 0);
patchUls('stbrStc', 0);
var endTime = new Date();
if (unsafeWindow.console)
unsafeWindow.console.log('patch time = ' + (endTime-startTime) + 'ms');
/* let DOM changes render before patching rated elements */
setTimeout(patchRated, 0);
