2
\$\begingroup\$

I try keep an eye on any questions or answers that I have posted here within the StackExchange network and I like to prioritize my updates and improvements based on ones that get frequent visits.

I previously used a paper sticky note attached to the side of my monitor with question titles and view counts scribbled on them but this was less than desirable.

I created a UserScript that adds a track views button into the question summary.

track views

Once activated it will display how many views that question has had since the last time you visited it.

tracked views

Visiting the Questions or Answers tab under the user profile will also display the recent views to all tracked posts.

tracked views questions tab


As usual, everything is working but I would like to get some pointers on how I can improve. I've taken pointers from my last two posts here and tried to run with them, hopefully my implementation is improving.

Note: I didn't include all urls in the meta match tag intentionally, I didn't want to add too much clutter in this post

// ==UserScript==
// @name         Question View Tracker
// @namespace    https://stackoverflow.com/users/1454538/
// @author       enki
// @match        *://*.stackoverflow.com/questions/*
// @match        *://*.stackoverflow.com/users/*/*?tab=questions*
// @match        *://*.stackoverflow.com/users/*/*?tab=answers*
// @match        *://*.stackexchange.com/questions/*
// @match        *://*.stackexchange.com/users/*/*?tab=questions*
// @match        *://*.stackexchange.com/users/*/*?tab=answers*
// @grant        GM_getValue
// @grant        GM_setValue
// @grant        GM_deleteValue
// @run-at document-end
// ==/UserScript==
"use strict";
$(function() {
    if(tracker.isOnPost()) {
        var postid = $("input[name='_id_']:first").val(),
            $qinfo = $("#qinfo"),
            $asked = $qinfo.find("tr td p:contains('asked')"),
            $active = $qinfo.find("tr td p:contains('active')"),
            $views = $qinfo.find("tr td p:contains('times')"),
            count = $views.text().replace(" times", "");

        //create table row for recent views
        var $recentviews = $('<tr/>').append(
            $('<td/>').append(
                $('<p/>', {
                    'class': 'label-key',
                    text: 'recent'
                })
            )).append(
            $('<td/>', {style: "padding-left: 10px;"}).append(
                $('<p/>', {
                    'class': 'label-key'
                }).append(
                    $('<b/>', {
                        id: 'recent',
                        text: '0 times',
                        style: "display: none;"
                    })
                ).append(
                    $('<a/>', {
                        id: 'track',
                        text: 'track views'
                    }).on('click', function(){
                        var $link = $(this),
                            $recent = $("#recent"),
                            state = $link.text();
                        if (state == "track views"){
                            tracker.track(postid, count);
                            $link.text("untrack");
                            $recent.html("0 times &mdash; ").show();
                        } else if (state == "untrack") {
                            tracker.untrack(postid);
                            $link.text("track views");
                            $recent.hide();
                        }
                    })
                )
            )
        );

        // rearrange question info to place active stat below the asked stat
        $active.closest("tr").insertAfter($asked.closest("tr"));

        // add recent views to question info after view count
        $recentviews.closest("tr").insertAfter($views.closest("tr"));

        // check if question views are being tracked
        if (tracker.isTracked(postid)) {
            console.log("tracker - isTracked");
            // get last count before we update it
            var lastcount = tracker.lastCount(postid);

            // update view count
            tracker.track(postid, count);

            // update recent views element and change tracking link text
            $("#recent").html((count - lastcount) + " times &mdash; ").show();
            $("#track").text("untrack");
        }

    } else if (tracker.isOnTab("questions")) {
        $(".question-summary").each(function () {
            var questionid = $(this).attr("id").split("-")[2];

            if(tracker.isTracked(questionid)){
                // view counts over 1k are placed inside a span tag title attribute otherwise view count is within .mini-counts div tag
                var questionViewCount = $(this).find(".views .mini-counts span").attr("title"),
                    questionLastcount = tracker.lastCount(questionid);

                // view count must be less than <1k
                if(questionViewCount == undefined){
                    questionViewCount = $(this).find(".views .mini-counts").text();
                } else { 
                    questionViewCount = parseInt(questionViewCount); // strip ' views' from number
                }

                $(this).find("h3").append($("<div/>", {"class": "started"})
                                          .append($("<span/>", {"class":"reputation-score", text: questionViewCount - questionLastcount })
                                                  .append($("<span/>", {text: " recent views",
                                                                        style: "font-weight: 100;"})
                                                         ))

                                         );
            }

        });
    } else if(tracker.isOnTab("answers")){
        $(".answer-hyperlink").each(function() {
            var $link = $(this),
                href = $link.attr("href"),
                answerid = href.split("/")[2];

            if(tracker.isTracked(answerid)){
                var answerLastCount = tracker.lastCount(answerid);

                // fetch current view count from url
                $.ajax({ url: href, 
                        dataType: 'html', 
                        success: function(response) { 
                            // get view count and add recent view count to answer summary
                            var answerViewCount = parseInt($(response).find("#qinfo tr td p:contains('times')").text());
                            $link.closest(".answer-summary").append($("<span/>", {text: answerViewCount - answerLastCount + " recent views — ",
                                                                                  style: "padding: 6px 5px 0 0; float: right;"}));
                        }});
            }
        });
    }
});

function tracker() {};
tracker.track = function(postid, count) {
    GM_setValue(this.trackerId(postid), count);
}
tracker.untrack = function(postid) {
    GM_deleteValue(this.trackerId(postid));
}
tracker.isTracked = function(postid) {
    //if result is undefined return false (not being tracked)
    return (GM_getValue(this.trackerId(postid)) === undefined ? false : true);
}
tracker.lastCount = function(postid) {
    return GM_getValue(this.trackerId(postid));
}
tracker.isOnPost = function() {
    return ($(location).attr('href').indexOf('/questions/') > -1 ? true : false);
}
tracker.isOnTab = function(tabName) {
    return ($(location).attr('href').indexOf("?tab=" + tabName ) > -1 ? true : false);
}
tracker.trackerId = function(postid){
    // post ids are not unique across stackexchange sites so we append the sitename to the postid and make it unique..
    var site = window.location.hostname.replace(".com", "").replace(".", "");
    return postid + site;
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.