Greasy Fork

Greasy Fork is available in English.

Netflix Ratings

View various website ratings while in netflix

目前为 2014-06-08 提交的版本。查看 最新版本

// ==UserScript==
// @name        Netflix Ratings
// @namespace   lecapitan
// @description View various website ratings while in netflix
// @include     http://*.netflix.com/*
// @version     1.0.0.0
// ==/UserScript==

document.netflixRatingsObject = 
{
    load: function()
    {
        // If the page is a movie page
        var mdpOverview = document.getElementById("mdp-overview");
        if (mdpOverview)
        {
            var titleElement = this.getTitleElement(mdpOverview);
            // Get Rotten Tomatoes ratings
            var dataElement = this.getRTMainDataElement(mdpOverview);
            if (titleElement && dataElement)
            {
                // Load ratings
                if (!this.hasClass(dataElement, "nrLoading") && !this.hasClass(dataElement, "nrLoaded"))
                {
                    // Start the search
                    this.getRatings("RottenTomatoes", this.getTitle(titleElement), this.getYear(mdpOverview), dataElement);
                }
            }
            // Get IMDb ratings
            dataElement = this.getIMDbMainDataElement(mdpOverview);
            if (titleElement && dataElement)
            {
                // Load ratings
                if (!this.hasClass(dataElement, "nrLoading") && !this.hasClass(dataElement, "nrLoaded"))
                {
                    // Start the search
                    this.getRatings("IMDb", this.getTitle(titleElement), this.getYear(mdpOverview), dataElement);
                }
            }
            // Get metacritic ratings
            dataElement = this.getmetacriticMainDataElement(mdpOverview);
            if (titleElement && dataElement)
            {
                // Load ratings
                if (!this.hasClass(dataElement, "nrLoading") && !this.hasClass(dataElement, "nrLoaded"))
                {
                    // Start the search
                    this.getRatings("metacritic", this.getTitle(titleElement), this.getYear(mdpOverview), dataElement);
                }
            }
        }
    },
    
    getTitleElement: function(element)
    {
        if (element.id && element.id == "mdp-overview")
        {
            if (element.getElementsByClassName("title").length > 0)
            {
                return element.getElementsByClassName("title")[0];
            }
        }
        return undefined;
    },
    
    getRTMainDataElement: function(element)
    {
        if (element.getElementsByClassName("nrRTMainData").length > 0)
        {
            return element.getElementsByClassName("nrRTMainData")[0];
        }
        else
        {
            if (document.getElementsByTagName("dl").length > 0)
            {
                var dlElement = document.getElementsByTagName("dl")[0];
                var dtElement = document.createElement("dt");
                dtElement.innerHTML = "Rotten Tomatoes: ";
                dlElement.appendChild(dtElement);
                var ddElement = document.createElement("dd");
                var linkElement = document.createElement("a");
                linkElement.className = "nrRTMainData";
                ddElement.appendChild(linkElement);
                dlElement.appendChild(ddElement);
                return linkElement;
            }                
        }
        return undefined;
    },
    
    getIMDbMainDataElement: function(element)
    {
        if (element.id && element.id == "mdp-overview")
        {
            if (element.getElementsByClassName("nrIMDbMainData").length > 0)
            {
                return element.getElementsByClassName("nrIMDbMainData")[0];
            }
            else
            {
                if (document.getElementsByTagName("dl").length > 0)
                {
                    var dlElement = document.getElementsByTagName("dl")[0];
                    var dtElement = document.createElement("dt");
                    dtElement.innerHTML = "IMDb: ";
                    dlElement.appendChild(dtElement);
                    var ddElement = document.createElement("dd");
                    var linkElement = document.createElement("a");
                    linkElement.className = "nrIMDbMainData";
                    ddElement.appendChild(linkElement);
                    dlElement.appendChild(ddElement);
                    return linkElement;
                }                
            }
        }
        return undefined;
    },
    
    getmetacriticMainDataElement: function(element)
    {
        if (element.id && element.id == "mdp-overview")
        {
            if (element.getElementsByClassName("nrmetacriticMainData").length > 0)
            {
                return element.getElementsByClassName("nrmetacriticMainData")[0];
            }
            else
            {
                if (document.getElementsByTagName("dl").length > 0)
                {
                    var dlElement = document.getElementsByTagName("dl")[0];
                    var dtElement = document.createElement("dt");
                    dtElement.innerHTML = "metacritic: ";
                    dlElement.appendChild(dtElement);
                    var ddElement = document.createElement("dd");
                    var linkElement = document.createElement("a");
                    linkElement.className = "nrmetacriticMainData";
                    ddElement.appendChild(linkElement);
                    dlElement.appendChild(ddElement);
                    return linkElement;
                }                
            }
        }
        return undefined;
    },
    
    getRatings: function(type, title, year, dataElement)
    {
        dataElement.innerHTML = "...";
        // Get the rotten tomatoes rating
        if (type == "RottenTomatoes")
        {
            dataElement.className = "nrRTMainData nrLoading";
            this.fetchRating(type, this.getRTUrl(title), title, year, dataElement);
        }
        else if (type == "IMDb")
        {
            dataElement.className = "nrIMDbMainData nrLoading";
            this.fetchRating(type, this.getIMDbUrl(title), title, year, dataElement);
        }
        else if (type == "metacritic")
        {
            dataElement.className = "nrmetacriticMainData nrLoading";
            this.fetchRating(type, this.getmetacriticUrl(title), title, year, dataElement);
        }
    },
    
    getRTUrl: function(title)
    {
        return "http://www.rottentomatoes.com/search/?search=" + title.replace(/-/g, " ").replace(/ /g, "+");
    },
    
    getIMDbUrl: function(title)
    {
        return "http://www.imdb.com/find?q=" + title.replace(/-/g, " ").replace(/ /g, "+").replace(/&/g, "%26") + "&s=all";
    },
    
    getmetacriticUrl: function(title)
    {
        return "http://www.metacritic.com/search/movie/" + title.replace(/-/g, " ").replace(/ /g, "+") + "/results";
    },
    
    fetchRating: function(type, url, title, year, dataElement)
    {
        // Send the request
        if (url && url != "")
        {
            // Set the link
            dataElement.href = url;
            // Make a cross-domain request for this url
            if (type == "RottenTomatoes")
            {
                GM_xmlhttpRequest({
                    method: "GET",
                    url: url,
                    onload: function(responseDetails)
                    {
                        // Get the HTML document that we received
                        var responseDoc = document.netflixRatingsObject.getDom(responseDetails.responseText);
                        // Parse the response
                        document.netflixRatingsObject.parseRTResponse(responseDoc, title, year, dataElement);
                    },
                    onerror: function(responseDetails)
                    {
                        console.log("failure");
                    }
                });
            }
            else if (type == "IMDb")
            {
                GM_xmlhttpRequest({
                    method: "GET",
                    url: url,
                    onload: function(responseDetails)
                    {
                        // Get the HTML document that we received
                        var responseDoc = document.netflixRatingsObject.getDom(responseDetails.responseText);
                        // Parse the response
                        document.netflixRatingsObject.parseIMDbResponse(responseDoc, title, year, dataElement);
                    },
                    onerror: function(responseDetails)
                    {
                        console.log("failure");
                    }
                });
            }
            else if (type == "metacritic")
            {
                GM_xmlhttpRequest({
                    method: "GET",
                    url: url,
                    onload: function(responseDetails)
                    {
                        // Get the HTML document that we received
                        var responseDoc = document.netflixRatingsObject.getDom(responseDetails.responseText);
                        // Parse the response
                        document.netflixRatingsObject.parsemetacriticResponse(responseDoc, title, year, dataElement);
                    },
                    onerror: function(responseDetails)
                    {
                        console.log("failure");
                    }
                });
            }
        }
    },
    
    // -----------------------------------
    // Parsing functions
    // -----------------------------------
    parseRTResponse: function(responseDoc, title, year, dataElement)
    {
        // Check for no results
        if (responseDoc.getElementsByClassName("noresults").length > 0)
        {
            dataElement.innerHTML = "no results";
            // Set the loaded flag
            dataElement.className = "nrRTMainData nrLoaded";
        }
        // Check for search results list
        else if (responseDoc.getElementById("movie_results_ul"))
        {
            // Get all list items
            var movieItems = responseDoc.getElementsByClassName("media_block_content");
            // Check search results for a full match (title and year)
            for (var i = 0; i < movieItems.length; i++)
            {
                if (movieItems[i].getElementsByTagName("h3").length <= 0)
                {
                    continue; // This is some menu element on the page
                }
                var parsedTitle;
                var parsedYear;
                var newUrl;
                // Get the title and url
                var linkList = movieItems[i].getElementsByTagName("a");
                for (var ii = 0; ii < linkList.length; ii++)
                {
                    if (linkList[ii].href.indexOf("/m/") >= 0)
                    {
                        parsedTitle = linkList[ii].innerHTML;
                        newUrl = "http://www.rottentomatoes.com" + linkList[ii].href;
                    }
                }
                // Get the year
                var yearList = movieItems[i].getElementsByClassName("movie_year");
                if (yearList.length > 0)
                {
                    parsedYear = yearList[0].innerHTML.replace(/ /g, "").replace(/\(/, "").replace(/\)/, "");
                }
                // Check the title and year
                if (parsedTitle.toLowerCase().replace(/[^a-z0-9]/g, "") == title.toLowerCase().replace(/[^a-z0-9]/g, "") && parsedYear == year)
                {
                    document.netflixRatingsObject.fetchRating("RottenTomatoes", newUrl, title, year, dataElement);
                    return;
                }
            }
            // Did not find a full match, check search results for just a title match
            for (var i = 0; i < movieItems.length; i++)
            {
                if (movieItems[i].getElementsByTagName("h3").length <= 0)
                {
                    continue; // This is some menu element on the page
                }
                var parsedTitle;
                var newUrl;
                // Get the title and url
                var linkList = movieItems[i].getElementsByTagName("a");
                for (var ii = 0; ii < linkList.length; ii++)
                {
                    if (linkList[ii].href.indexOf("m/") >= 0)
                    {
                        parsedTitle = linkList[ii].innerHTML;
                        newUrl = "http://www.rottentomatoes.com" + linkList[ii].href;
                    }
                }
                // Similar title
                if (parsedTitle.toLowerCase().replace(/[^a-z0-9]/g, "") == title.toLowerCase().replace(/[^a-z0-9]/g, ""))
                {
                    document.netflixRatingsObject.fetchRating("RottenTomatoes", newUrl, title, year, dataElement);
                    return;                                
                }
            }
            // Did not find a title match, check search results for just a year match
            for (var i = 0; i < movieItems.length; i++)
            {
                if (movieItems[i].getElementsByTagName("h3").length <= 0)
                {
                    continue; // This is some menu element on the page
                }
                var parsedYear;
                var newUrl;
                // Get the title and url
                var linkList = movieItems[i].getElementsByTagName("a");
                for (var ii = 0; ii < linkList.length; ii++)
                {
                    if (linkList[ii].href.indexOf("/m/") >= 0)
                    {
                        newUrl = "http://www.rottentomatoes.com" + linkList[ii].href;
                    }
                }
                // Get the year
                var yearList = movieItems[i].getElementsByClassName("movie_year");
                if (yearList.length > 0)
                {
                    parsedYear = yearList[0].innerHTML.replace(/ /g, "").replace(/\(/, "").replace(/\)/, "");
                }
                // Same year
                if (parsedYear == year)
                {
                    document.netflixRatingsObject.fetchRating("RottenTomatoes", newUrl, title, year, dataElement);
                    return;
                }
            }
            // Did not find any matches
            dataElement.innerHTML = "..?";
            // Set the loaded flag
            dataElement.className = "nrRTMainData nrLoaded";
        }
        // Got a movie's page
        else
        {
            // Set the element text, if we cannot parse critic or user ratings
            dataElement.innerHTML = "..?";
            // Set the loaded flag
            dataElement.className = "nrRTMainData nrLoaded";
            // Get the critics rating
            var criticsRating = responseDoc.getElementById('all-critics-meter');
            if (criticsRating)
            {
                dataElement.innerHTML = criticsRating.innerHTML;
            }
            // Get the users rating
            var usersRating = responseDoc.getElementsByClassName('meter popcorn numeric');
            if (usersRating && usersRating.length > 0)
            {
                dataElement.innerHTML += " | " + usersRating[0].innerHTML;
            }
            else
            {
                usersRating = responseDoc.getElementsByClassName('meter spilled numeric');
                if (usersRating && usersRating.length > 0)
                {
                    dataElement.innerHTML += " | " + usersRating[0].innerHTML;
                }   
            }
        }
    },
    
    parseIMDbResponse: function(responseDoc, title, year, dataElement)
    {
        // Check for no results - IMDb seems to always provide some results...
        if (responseDoc.getElementsByClassName("noresults").length > 0)
        {
            dataElement.innerHTML = "no results";
            // Set the loaded flag
            dataElement.className = "nrIMDbMainData nrLoaded";
        }
        // Check for search results list
        else if (responseDoc.getElementsByClassName("findList").length > 0)
        {
            // Get all list items
            var movieItems = responseDoc.getElementsByClassName("result_text");
            // Check search results for a full match (title and year)
            for (var i = 0; i < movieItems.length; i++)
            {
                var parsedTitle;
                var parsedYear;
                var newUrl;
                // Get the title and url
                var linkList = movieItems[i].getElementsByTagName("a");
                for (var ii = 0; ii < linkList.length; ii++)
                {
                    if (linkList[ii].href.indexOf("/title/") >= 0)
                    {
                        parsedTitle = linkList[ii].innerHTML;
                        newUrl = "http://www.imdb.com" + linkList[ii].href;
                    }
                }
                // Get the year
                var yearMatch = movieItems[i].innerHTML.match(/\(([0-9]*)\)/);
                if (yearMatch.length > 0)
                {
                    parsedYear = yearMatch[1];
                }
                // Same title and year
                if (parsedTitle.toLowerCase().replace(/[^a-z0-9]/g, "") == title.toLowerCase().replace(/[^a-z0-9]/g, "") && parsedYear == year)
                {
                    document.netflixRatingsObject.fetchRating("IMDb", newUrl, title, year, dataElement);
                    return;
                }
            }
            // Did not find a full match, check search results for just a title match
            for (var i = 0; i < movieItems.length; i++)
            {
                var parsedTitle;
                var newUrl;
                // Get the title and url
                var linkList = movieItems[i].getElementsByTagName("a");
                for (var ii = 0; ii < linkList.length; ii++)
                {
                    if (linkList[ii].href.indexOf("/title/") >= 0)
                    {
                        parsedTitle = linkList[ii].innerHTML;
                        newUrl = "http://www.imdb.com" + linkList[ii].href;
                    }
                }
                // Same title
                if (parsedTitle.toLowerCase().replace(/[^a-z0-9]/g, "") == title.toLowerCase().replace(/[^a-z0-9]/g, ""))
                {
                    document.netflixRatingsObject.fetchRating("IMDb", newUrl, title, year, dataElement);
                    return;
                }
            }
            // Did not find a title match, check search results for just a year match
            for (var i = 0; i < movieItems.length; i++)
            {
                var parsedYear;
                var newUrl;
                // Get the title and url
                var linkList = movieItems[i].getElementsByTagName("a");
                for (var ii = 0; ii < linkList.length; ii++)
                {
                    if (linkList[ii].href.indexOf("/title/") >= 0)
                    {
                        newUrl = "http://www.imdb.com" + linkList[ii].href;
                    }
                }
                // Get the year
                var yearMatch = movieItems[i].innerHTML.match(/\(([0-9]*)\)/);
                if (yearMatch.length > 0)
                {
                    parsedYear = yearMatch[1];
                }
                // Same year
                if (parsedYear == year)
                {
                    document.netflixRatingsObject.fetchRating("IMDb", newUrl, title, year, dataElement);
                    return;
                }
            }
            // Did not find a match
            dataElement.innerHTML = "..?";
            // Set the loaded flag
            dataElement.className = "nrIMDbMainData nrLoaded";
        }
        else
        {
            // Set the element text, if we cannot parse ratings
            dataElement.innerHTML = "..?";
            // Set the loaded flag
            dataElement.className = "nrIMDbMainData nrLoaded";
            // Get the IMDb rating
            var elementList = responseDoc.getElementsByClassName("star-box-giga-star");
            if (elementList.length >= 0)
            {
                dataElement.innerHTML = elementList[0].innerHTML;
            }
        }
    },
    
    parsemetacriticResponse: function(responseDoc, title, year, dataElement)
    {
        // Check for no results - IMDb seems to always provide some results...
        if (responseDoc.getElementsByClassName("noresults").length > 0)
        {
            dataElement.innerHTML = "no results";
            // Set the loaded flag
            dataElement.className = "nrmetacriticMainData nrLoaded";
        }
        // Check for search results list
        else if (responseDoc.getElementsByClassName("search_results").length > 0)
        {
            // Get all list items
            var movieItems = responseDoc.getElementsByClassName("result");
            // Check search results for a full match (title and year)
            for (var i = 0; i < movieItems.length; i++)
            {
                // Check the result type
                var resultTypeElements = movieItems[0].getElementsByClassName("result_type");
                if (resultTypeElements.length <= 0 || resultTypeElements[0].childNodes[1].innerHTML != "Movie")
                {
                    continue; // Not a movie result type
                }
                var parsedTitle;
                var parsedYear;
                var newUrl;
                // Get the title and url
                var linkList = movieItems[i].getElementsByTagName("a");
                for (var ii = 0; ii < linkList.length; ii++)
                {
                    if (linkList[ii].href.indexOf("/movie/") >= 0)
                    {
                        parsedTitle = linkList[ii].innerHTML;
                        newUrl = "http://www.metacritic.com" + linkList[ii].href;
                    }
                }
                // Get the year
                var releaseDateElements = movieItems[i].getElementsByClassName("release_date");
                if (releaseDateElements.length > 0)
                {
                    var yearMatches = releaseDateElements[0].childNodes[3].innerHTML.match(/[A-Za-z0-9 ]*[,][ ]([0-9][0-9][0-9][0-9])/);
                    if (yearMatches)
                    {
                        parsedYear = yearMatches[1];
                    }
                }
                // Same title and year
                if (parsedTitle.toLowerCase().replace(/[^a-z0-9]/g, "") == title.toLowerCase().replace(/[^a-z0-9]/g, "") && parsedYear == year)
                {
                    document.netflixRatingsObject.fetchRating("metacritic", newUrl, title, year, dataElement);
                    return;
                }
            }
            // Did not find a full match, check search results for just a title match
            for (var i = 0; i < movieItems.length; i++)
            {
                // Check the result type
                var resultTypeElements = movieItems[0].getElementsByClassName("result_type");
                if (resultTypeElements.length <= 0 || resultTypeElements[0].childNodes[1].innerHTML != "Movie")
                {
                    continue; // Not a movie result type
                }
                var parsedTitle;
                var newUrl;
                // Get the title and url
                var linkList = movieItems[i].getElementsByTagName("a");
                for (var ii = 0; ii < linkList.length; ii++)
                {
                    if (linkList[ii].href.indexOf("/movie/") >= 0)
                    {
                        parsedTitle = linkList[ii].innerHTML;
                        newUrl = "http://www.metacritic.com" + linkList[ii].href;
                    }
                }
                // Same title
                if (parsedTitle.toLowerCase().replace(/[^a-z0-9]/g, "") == title.toLowerCase().replace(/[^a-z0-9]/g, ""))
                {
                    document.netflixRatingsObject.fetchRating("metacritic", newUrl, title, year, dataElement);
                    return;
                }
            }
            // Did not find a title match, check search results for just a year match
            for (var i = 0; i < movieItems.length; i++)
            {
                // Check the result type
                var resultTypeElements = movieItems[0].getElementsByClassName("result_type");
                if (resultTypeElements.length <= 0 || resultTypeElements[0].childNodes[1].innerHTML != "Movie")
                {
                    continue; // Not a movie result type
                }
                var parsedYear;
                var newUrl;
                // Get the title and url
                var linkList = movieItems[i].getElementsByTagName("a");
                for (var ii = 0; ii < linkList.length; ii++)
                {
                    if (linkList[ii].href.indexOf("/movie/") >= 0)
                    {
                        newUrl = "http://www.metacritic.com" + linkList[ii].href;
                    }
                }
                // Get the year
                var releaseDateElements = movieItems[i].getElementsByClassName("release_date");
                if (releaseDateElements.length > 0)
                {
                    var yearMatches = releaseDateElements[0].childNodes[3].innerHTML.match(/[A-Za-z0-9 ]*[,][ ]([0-9][0-9][0-9][0-9])/);
                    if (yearMatches)
                    {
                        parsedYear = yearMatches[1];
                    }
                }
                // Same title and year
                if (parsedYear == year)
                {
                    document.netflixRatingsObject.fetchRating("metacritic", newUrl, title, year, dataElement);
                    return;
                }
            }
            // Did not find a match
            dataElement.innerHTML = "..?";
            // Set the loaded flag
            dataElement.className = "nrmetacriticMainData nrLoaded";
        }
        else
        {
            // Set the element text, if we cannot parse ratings
            dataElement.innerHTML = "..?";
            // Set the loaded flag
            dataElement.className = "nrmetacriticMainData nrLoaded";
            // Get the metacritic rating
            var criticsRating, usersRating;
            var elementList = responseDoc.getElementsByClassName("score_value");
            if (elementList.length >= 0)
            {
                for (var i = 0; i < elementList.length; i++)
                {
                    if (elementList[i].parentNode.tagName.toLowerCase() == "a" && elementList[i].parentNode.href.indexOf("critic-reviews") >= 0)
                    {
                        criticsRating =  elementList[i].innerHTML;
                    }
                    if (elementList[i].parentNode.tagName.toLowerCase() == "a" && elementList[i].parentNode.href.indexOf("user-reviews") >= 0)
                    {
                        usersRating = elementList[i].innerHTML;
                    }
                }
                if (criticsRating)
                {
                    dataElement.innerHTML = criticsRating;
                }
                if (usersRating)
                {
                    dataElement.innerHTML += " | " + usersRating;
                }
            }
        }
    },
    
    // -----------------------------------
    // Helper functions
    // -----------------------------------
    hasClass: function(element, cls)
    {
        return (' ' + element.className + ' ').indexOf(' ' + cls + ' ') > -1;
    },

    insertAfter: function(referenceNode, newNode)
    {
        referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
    },
    
    getTitle: function(element)
    {
        return element.innerHTML;
    },
    
    getYear: function(element)
    {
        var year;
        if (element.getElementsByClassName("year"))
        {
            year = element.getElementsByClassName("year")[0].innerHTML;
        }
        return year;
    },
    
    getDom: function(responseHTML)
    {
        var dt = document.implementation.createDocumentType("html", "-//W3C//DTD HTML 4.01 Transitional//EN", "http://www.w3.org/TR/html4/loose.dtd");
        var doc = document.implementation.createDocument('', '', dt);
        var html = doc.createElement('html');
        html.innerHTML = responseHTML;
        doc.appendChild(html);
        return doc;
    }
};

// Inject CSS
var styleElement = document.createElement('style');
styleElement.type = 'text/css';
styleElement.innerHTML =  '#mdp-metadata dl dt { width:25% !important; }';
styleElement.innerHTML += '#mdp-metadata dl dd { width:70% !important; }';
document.head.appendChild(styleElement);

// Load ratings
document.netflixRatingsObject.load();