Search code examples
javascriptjquerygoogle-chrome-extensionnetflix

Netfix QueueSorter (chrome) - Help with modifying script to sort groups alphabetically


I have the Netflix Queue sorter installed as an extension. However, it randomly assigns an order to the movies within a genre. I want it to sort by name within the genre.

I open C:\Users\MyUserName\AppData\Local\Google\Chrome\User Data\Default\Extensions\ExtensionId\1.13_0\script.js and I can see that the javascript still needs some work. Here is the my modified method which sorts on title and genre.

function sortByTitleAndGenre() {
    var articles;
    sortInfo = [];
    var pos = 1;

    var articlesKey = 'sortByTitle.articles';
    var ignoreArticlesKey = 'sortByTitle.ignoreArticles';
    var ignoreArticles = GM_getValue(ignoreArticlesKey);
    if (undefined === ignoreArticles) {
        // Use true as default as Netflix ignores articles too.
        ignoreArticles = true;

        // Store keys so that users can change it via about:config.
        GM_setValue(ignoreArticlesKey, ignoreArticles);
        // The articles are used "as-is", so there must be a space after
        // each one in most cases.  To avoid typos in the default, use [].
        articles = [
            "A ",
            "AN ",
            "THE ",
            "EL ",
            "LA ",
            "LE ",
            "LES ",
            "IL ",
            "L'"
        ];
        GM_setValue(articlesKey, articles.join(',').toUpperCase());
    }

    var elts = customGetElementsByClassName(document, 'input', 'o');
    for (var idx = 0; idx < elts.length; idx++) {
        var boxName = elts[idx].name;
        var boxId = boxName.substring(2);
        // If a movie is both at home and in the queue, or a movie has been
        // watched but is still in the queue, there is both _0 and _1.
        // Here we either one works.
        var titleId = 'b0' + boxId + '_0';
        var titleElt = document.getElementById(titleId);

        var genre = $("tr[data-mid='" + boxId + "'] .gn .genre").text().toUpperCase();

        var title = titleElt.innerHTML.toUpperCase();
        if (ignoreArticles) {
            // Get the articles, but default to empty string.
            var articlesStr = GM_getValue(articlesKey, '') || '';
            articlesStr = articlesStr.toUpperCase();
            articles = articlesStr.split(',');
            for (var aa = 0; aa < articles.length; aa++) {
                var article = articles[aa].toUpperCase();
                if (0 === title.indexOf(article)) {
                    // Move article to the end of the string.
                    title = title.substring(article.length) +
                            ', ' + article;
                    break;
                }
            }
        }

        var record = {
            "id": boxId,
            "title": title,
            "genre": genre,
            "origPos": pos++
        };
        sortInfo.push(record);
    }

    var sortFn = function (a, b) {
        if (a.genre == b.genre)
            return a.title > b.title ? -1 : 1;
        else
            return a.genre > b.genre ? -1 : 1;
    };
    sortInfo.sort(sortFn);

    setOrder("origPos", elts);
}

My problem is that while it sorts fine, it's not ignoring the articles. Is my sort function off? I think it can be defined more succinctly (in one line).

    var sortFn = function (a, b) {
        if (a.genre == b.genre)
            return a.title > b.title ? -1 : 1;
        else
            return a.genre > b.genre ? -1 : 1;
    };

Solution

  • I figured it out. The code was built to set the articles array to empty. It's a small WTF, but I fixed it with a few commented lines.

    //var articlesStr = GM_getValue(articlesKey, '') || '';
    //articlesStr = articlesStr.toUpperCase();
    //articles = articlesStr.split(',');
    

    for anyone who uses this extension, I fixed it by adding the jquery library to the extension. I added a reference to it in manifest.json.

    Then just replace the existing sortByGenre with this method

    function sortByGenre() {
        var articles;
        sortInfo = [];
        var pos = 1;
    
        var articlesKey = 'sortByTitle.articles';
        var ignoreArticlesKey = 'sortByTitle.ignoreArticles';
        var ignoreArticles = GM_getValue(ignoreArticlesKey);
        if (undefined === ignoreArticles) {
            // Use true as default as Netflix ignores articles too.
            ignoreArticles = true;
    
            // Store keys so that users can change it via about:config.
            GM_setValue(ignoreArticlesKey, ignoreArticles);
            // The articles are used "as-is", so there must be a space after
            // each one in most cases.  To avoid typos in the default, use [].
            articles = [
                "A ",
                "AN ",
                "THE ",
                "EL ",
                "LA ",
                "LE ",
                "LES ",
                "IL ",
                "L'"
            ];
            //GM_setValue(articlesKey, articles.join(',').toUpperCase());
        }
    
        var elts = customGetElementsByClassName(document, 'input', 'o');
        for (var idx = 0; idx < elts.length; idx++) {
            var boxName = elts[idx].name;
            var boxId = boxName.substring(2);
            // If a movie is both at home and in the queue, or a movie has been
            // watched but is still in the queue, there is both _0 and _1.
            // Here we either one works.
            var titleId = 'b0' + boxId + '_0';
            var titleElt = document.getElementById(titleId);
    
            var genre = $("tr[data-mid='" + boxId + "'] .gn .genre").text().toUpperCase();
    
            var title = titleElt.innerHTML.toUpperCase();
            if (ignoreArticles) {
                // Get the articles, but default to empty string.
                //var articlesStr = GM_getValue(articlesKey, '') || '';
                //articlesStr = articlesStr.toUpperCase();
                //articles = articlesStr.split(',');
                for (var aa = 0; aa < articles.length; aa++) {
                    var article = articles[aa].toUpperCase();
                    if (0 === title.indexOf(article)) {
                        // Move article to the end of the string.
                        title = title.substring(article.length) +
                                ', ' + article;
                        break;
                    }
                }
            }
    
            var record = {
                "id": boxId,
                "title": title,
                "genre": genre,
                "origPos": pos++
            };
            sortInfo.push(record);
        }
    
        var sortFn = function (a, b) {
            if (a.genre == b.genre)
                return a.title > b.title ? -1 : 1;
            else
                return a.genre > b.genre ? -1 : 1;
        };
        sortInfo.sort(sortFn);
    
        setOrder("origPos", elts);
    }
    

    once you do that you can go into developer mode in chrome and either load it unpacked or pack it as a crx, navigate to the file within chrome, and install the extension.