Tampermonkey script for shinier comping

For ages now I've used a Tampermonkey script to adjust the competitions page to streamline things, just a few little quick tweaks to make life easier for myself, and with the redesign I decided to expand it out a bit.  Still nothing too major, but enough I figured others might be interested.  The full feature list is:
  • Left & Right arrow keys load the prev/next pages
  • The little < and > prev/next links are now "< Prev" or "Next >" for less fiddly clicking
  • Small bugfix to remove the horizontal scroll in some browsers (the MSE nav bar is too wide, har!)
  • Tracks the last 5000 comps you've listed and highlights any new ones in yellow
  • If the "E: dd/mm" date is today or before it highlights it in red
  • Rearranges the layout a bit to use more of the width
Basically it looks like this:


So how do you get this?  Well you most likely don't, if you're baffled at the prospect of addons that run custom scripts then you shouldn't be installing ones handed out by random people on forums!  However, if you're tech-savvy enough then here it is:
// ==UserScript==
// @name         Spiffier Comp Time
// @namespace    http://tampermonkey.net/
// @version      7
// @description  Make the competitions time forum a bit more streamlined and usable
// @author       Dumdeedum
// @match        https://forums.moneysavingexpert.com/categories/competitions-time*
// @grant        none
// @require      https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js
// ==/UserScript==

(function() {
    // tiny bugfix to prevent horizonal scroll on Chrome
    $("nav.mse-navigation").css("width", "100%");

    // better prev/next links
    $("a.Previous").html("< Prev");
    $("a.Next").html("Next >");

    // right and left arrows for navigation
    $(document).keyup(function(evnt) {
       if((evnt.which == 37) || (evnt.which == 39)) {
          if(evnt.which == 37) {
              newurl = $("a.Previous").attr("href");
          }
          else {
              newurl = $("a.Next").attr("href");
          }
          evnt.preventDefault();
          document.location.assign(newurl);
       }
    });

    // get/set our seen competitions array
    var seenComps = localStorage.getItem("seenComps");
    // found it, convert to array
    if(seenComps) {
        seenComps = JSON.parse(seenComps);
    }
    // didn't find, create a new blank one
    else {
        seenComps = [];
    }

    // date object for playing with in places below
    var rightNow = new Date();

    // and another date object for today, ie. 00:00:00.0
    var today = new Date(rightNow.getTime());
    today.setHours(0, 0, 0, 0);

    // regular expression for tinkering with comp end dates found in titles
    var compEndDateRE = /^e:\s*([0-9]{1,2})\/([0-9]{1,2})(?:\/([0-9]{2}))?/i

    // run through each competition listed
    $("li.ItemDiscussion").not(".Announcement").each(function() {
        // pick out some info we might need
        var compID = $(this).attr("id");
        var compViews = $("span.ViewCount", this).first().text();
        var compReplies = $("span.CommentCount", this).first().text();
        var compLastCommentDate = $("span.LastCommentDate > time", this).first().text();
        var compLastCommentDateTime = $("span.LastCommentDate > time", this).first().attr("datetime");

        // hey look it's a comp we haven't seen before
        if(seenComps.indexOf(compID) == -1) {
            // highlight this listing
            $(this).css("background-color", "#fff2c6");

            // remember that we've seen it
            seenComps.push(compID);
        }

        // hide the info stuff on the right, it's just taking up space
        $("div.DiscussionMeta", this).hide();

        // and with the new space, stretch the main title over
        $("div.Discussion", this).css("width", "100%");

        // and bump the skipped/entered label over too
        $("span.CompetitionStatus", this).css("right", "20px");

        // hide the ugly-!!!!!! "new posts" box
        $("strong.HasNew").hide();

        // rejigger the info line
        $("span.FirstCommentBy", this).prepend("By ").append(" | " + compViews + " | " + compReplies + " | " + compLastCommentDate).css("color", "#6f6f6f");
        $("span.FirstCommentBy a", this).css({"font-size" : "14px", "font-weight" : "bold"});

        // investigate the competition title
        var compTitle = $("div.Title a", this).text();

        // if the title is following the standard "E: dd/mm" format (optional /yy), investigate further
        var compTitleMatches;
        if(compTitleMatches = compTitle.match(compEndDateRE)) {
            var compTitleDay = parseInt(compTitleMatches[1], 10);
            var compTitleMonth = parseInt(compTitleMatches[2], 10);

            // assume the end year is this year to begin with
            var compTitleYear = rightNow.getFullYear();

            // oh, unless they've specifically set it, then use that
            if(typeof compTitleMatches[3] !== "undefined") {
                compTitleYear = 2000 + parseInt(compTitleMatches[3], 10);
            }

            // wait, if it's more than 6 months behind our current month then assume they mean next year
            else if((rightNow.getMonth() + 1) - compTitleMonth > 6) {
                compTitleYear = rightNow.getFullYear() + 1;
            }

            // make an end comp date object already
            var compEndDate = new Date(compTitleYear, compTitleMonth - 1, compTitleDay);

            // if the end date is today or before
            if(compEndDate <= today) {
                // make a new title and slot it in place
                var compTitleNew = compTitle.replace(compEndDateRE, "<span style='color:red'>" + compTitleMatches[0] + "</span>");
                $("div.Title a", this).html(compTitleNew);
            }
        }

    });

    // crop the seen competitions list to, oh, 5000?  seems like enough?  Tweak down if it becomes a resource hog
    var seenCompsMax = 5000;
    if(seenComps.length > seenCompsMax) {
        seenComps = seenComps.slice(seenCompsMax * -1);
    }

    // save the seen competitions list
    localStorage.setItem("seenComps", JSON.stringify(seenComps));
})();
Use at your own risk.  Do with whatever you want.  Probably not too many horrible bugs.  Probably.  Maybe.  Install instructions deliberately not given to weed out people who shouldn't be tinkering with such things.
This discussion has been closed.
Meet your Ambassadors

🚀 Getting Started

Hi new member!

Our Getting Started Guide will help you get the most out of the Forum

Categories

  • All Categories
  • 350.1K Banking & Borrowing
  • 252.7K Reduce Debt & Boost Income
  • 453.1K Spending & Discounts
  • 243K Work, Benefits & Business
  • 597.4K Mortgages, Homes & Bills
  • 176.5K Life & Family
  • 256K Travel & Transport
  • 1.5M Hobbies & Leisure
  • 16.1K Discuss & Feedback
  • 37.6K Read-Only Boards

Is this how you want to be seen?

We see you are using a default avatar. It takes only a few seconds to pick a picture.