immaletufinish / Metafilter sort comments by favorites

// ==UserScript==
// @name           Metafilter sort comments by favorites
// @description    Sort comments by favorites on some Metafilter sites for logged in users.
// @namespace
// @icon           https://d217i264rvtnq0.cloudfront.net/images/askmefi/apple-touch-icon.png
// @include        http*://www.metafilter.com/*
// @include        http*://ask.metafilter.com/*
// @include        http*://fanfare.metafilter.com/*
// @include        http*://music.metafilter.com/*
// @include        http*://metatalk.metafilter.com/*
// @grant          none
// @version        1.1
// ==/UserScript==

// Extras
$.easing.jswing = $.easing.swing; $.extend($.easing, { def: 'easeOutExpo', easeOutExpo: function (x, t, b, c, d) { return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b; } });

// Setup
var origArray = [];
var commentsArray = [];
var favSetting = 1;
var anchorsMoved = 0;
var cHash, origAnchor, origComments, favedComment, regComment = "";
var sortByfavs = '<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-heart" style="width:20px"><use xlink:href="#icon-heart"></use></svg> Sort By Favorites';
var sortBydate = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 25 25" style="width:18px; height:18px; padding-top:2px"><g fill="#ffffff"><path d="M6.546 6.095h.332c.508 0 .918-.432.918-.962V1.484c0-.53-.41-.962-.918-.962h-.332c-.506 0-.918.43-.918.962v3.647c0 .53.413.963.918.963M18.307 6.07h.334c.507 0 .917-.43.917-.962V1.462c0-.53-.41-.962-.916-.962h-.333c-.506 0-.916.43-.916.962V5.11c0 .53.41.96.917.96"/><path d="M22.657 22.937H2.345V8.667h20.312v14.27m0-20.458h-2.354v2.88c0 .962-.746 1.492-1.662 1.492h-.333c-.916 0-1.662-.782-1.662-1.744v-2.63H8.542v2.654c0 .962-.745 1.743-1.66 1.743h-.336c-.916 0-1.662-.78-1.662-1.743V2.48h-2.54c-.82 0-1.49.7-1.49 1.562v18.895c0 .862.67 1.563 1.49 1.563h20.313c.822 0 1.49-.7 1.49-1.563V4.042c0-.86-.668-1.563-1.49-1.563"/><path d="M13.27 13.454h2.678c.105 0 .19-.09.19-.202v-2.43c0-.112-.085-.202-.19-.202H13.27c-.106 0-.192.09-.192.2v2.432c0 .112.086.202.193.202M17.64 13.454h2.675c.106 0 .193-.09.193-.202v-2.43c0-.112-.087-.202-.193-.202H17.64c-.107 0-.193.09-.193.2v2.432c0 .112.086.202.192.202M4.534 17.434H7.21c.106 0 .192-.09.192-.2V14.8c0-.11-.086-.2-.192-.2H4.534c-.106 0-.192.09-.192.2v2.433c0 .11.085.2.192.2M8.902 17.434h2.678c.105 0 .19-.09.19-.2V14.8c0-.11-.085-.2-.19-.2H8.902c-.105 0-.19.09-.19.2v2.433c-.002.11.084.2.19.2M13.27 17.434h2.678c.105 0 .19-.09.19-.2V14.8c0-.11-.085-.2-.19-.2H13.27c-.105 0-.19.09-.19.2v2.433c0 .11.085.2.19.2M17.64 17.434h2.675c.106 0 .193-.09.193-.2V14.8c0-.11-.087-.2-.193-.2H17.64c-.107 0-.193.09-.193.2v2.433c0 .11.086.2.192.2M7.21 18.58H4.533c-.105 0-.19.09-.19.202v2.43c0 .112.085.202.19.202H7.21c.105 0 .19-.09.19-.2V18.78c.002-.112-.084-.202-.19-.202M11.58 18.58H8.9c-.105 0-.19.09-.19.202v2.43c0 .112.085.202.19.202h2.677c.105 0 .19-.09.19-.2V18.78c0-.112-.085-.202-.19-.202M15.947 18.58H13.27c-.106 0-.192.09-.192.202v2.43c0 .112.086.202.192.202h2.677c.106 0 .192-.09.192-.2V18.78c0-.112-.087-.202-.193-.202M20.315 18.58h-2.677c-.106 0-.192.09-.192.202v2.43c0 .112.086.202.192.202h2.677c.106 0 .192-.09.192-.2V18.78c0-.112-.086-.202-.192-.202"/></g></svg> Sort By Date';
var toggleBtn = $('<div class="text-center"><button id="toggleFavs" class="button" style="margin:1em 0; outline:0 none; cursor:pointer">' + sortBydate + '</button></div>');
var noFavs = $('<div class="text-center" style="cursor:not-allowed"><button id="toggleFavs" class="button" disabled style="margin:0; outline:0 none;">No Favorites</button></div>');
var sortOverlay = $('<div class="col-sm-10 text-center" style="position:absolute; background-color:#fff; height:100%; top:0; left:0; padding:1em; font-size:32px; opacity:.9; z-index:100"><span style="position:absolute; top:35vh">Sorting...</span></div>');

if ($("#posts").length > 0) {
	var cSite = ((/ask\.metafilter\./.test(window.top.location.href)) || (/fanfare\.metafilter\./.test(window.top.location.href))) ? "#posts > div[id^=c].comments:not(:empty)" : "#posts > div.comments:not(:empty):not(:last-of-type)";
} else {
	var cSite = ((/ask\.metafilter\./.test(window.top.location.href)) || (/fanfare\.metafilter\./.test(window.top.location.href))) ? "#page > div[id^=c].comments:not(:empty)" : "#page > div.comments:not(:empty):not(:last-of-type)";
}

// Save default order of comments
$("a[name] + div.comments").each(function(i) {
	origAnchor = $(this).closest("div.comments").prev();
	origAnchor.detach().prependTo($(this));
	origComments = $(this).html();
	origArray[i] = origComments;
});

function getFavComments() {
	if (($("li.profile").length > 0) || ($("#navoften").length > 0) || ($(".log-out .nav-label").text().toLowerCase() == "log out")) {
		if ($("span[id^=fav] > span[id^=favcnt] > a").length > 0) {
			if (window.location.hash) {
				cHash = window.location.hash.substring(1);
			}
			sortOverlay.insertAfter("div#posts");
			toggleBtn.appendTo("#threadsub:last-child");

			$("span[id^=fav] > span[id^=favcnt] > a").each(function(i) {
				favedComment = $(this).closest("div.comments").html();

				commentsArray.push({
					comment: favedComment,
					value: parseInt(textParse($(this).text()), 10)
				});
			});

			$("span[id^=fav] > span[id^=favcnt]:empty").each(function(i) {
				regComment = $(this).closest("div.comments").html();

				commentsArray.unshift({
					comment: regComment,
					value: 0
				});
			});

			commentsArray.sort(reOrder).reverse();

			$(cSite).each(function(i) {
				$(this).html(commentsArray.pop().comment);
			});

			scrollToAnchor();
		} else {
			noFavs.appendTo("#threadsub:last-child");
		}
	}
}

function textParse(n) {
	n = n.replace(" favorites", "");
	n = n.replace(" favorite", "");
	return n;
}

function reOrder(a, b) {
	return (b.value - a.value);
}

function originalSort() {
	$(cSite).each(function(i) {
		$(this).html(origArray[i]);
	});	
}

function scrollToAnchor() {
	$(window).load(function() {
		if (cHash) {
			var target = $("a[name='"+ cHash +"']");
			window.location.hash = "";

			$("html, body").animate({
				scrollTop: target.offset().top
			}, "slow", "easeOutExpo");
			window.location.hash = "#" + cHash;
		}
		sortOverlay.fadeOut();
	});
}

// Listeners
$(document).on("click", "#toggleFavs", function(e) {
	if (favSetting == 1) {
		sortOverlay.fadeIn("fast");
		originalSort();
		$("#toggleFavs").html(sortByfavs);
		favSetting = 0;
		sortOverlay.fadeOut("fast");
	} else {
		sortOverlay.fadeIn("fast");
		getFavComments();
		$("#toggleFavs").html(sortBydate);
		favSetting = 1;
		sortOverlay.fadeOut("fast");
	}
});

getFavComments();