// ==UserScript==
// @name TrueAchievements improver
// @namespace mobiusevalon.tibbius.com
// @version 0.6
// @description Improves the TrueAchievements interface in various ways
// @author Mobius Evalon
// @require https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js
// @include /^https{0,1}:\/\/\w{0,}\.?trueachievements\.com.*$/
// @grant none
// ==/UserScript==
var hide_ads = 1,
normalize_dates = 1,
improve_chat = 1,
minimalize_chat = 1,
session_user_links = 1,
session_user_status = 1,
feed_permalinks = 1,
fix_spoilers = 1;
Date.prototype.getShortMonthString = function()
{
switch(this.getMonth())
{
case 0: return "Jan";
case 1: return "Feb";
case 2: return "Mar";
case 3: return "Apr";
case 4: return "May";
case 5: return "Jun";
case 6: return "Jul";
case 7: return "Aug";
case 8: return "Sep";
case 9: return "Oct";
case 10: return "Nov";
case 11: return "Dec";
}
};
Date.prototype.getTwoDigitHours = function()
{
var n = this.getHours();
if(n < 10) return ("0"+n);
else return n.toString();
};
Date.prototype.getTwoDigitMinutes = function()
{
var n = this.getMinutes();
if(n < 10) return ("0"+n);
else return n.toString();
};
Date.prototype.getTwoDigitDate = function()
{
var n = this.getDate();
if(n < 10) return ("0"+n);
else return n.toString();
};
Date.prototype.adjustDate = function(n)
{
this.setDate(this.getDate()+n);
};
Date.prototype.getDateAfterAdjustment = function(n)
{
this.adjustDate(n);
return this.getDate();
};
Date.prototype.shortDate = function()
{
return (this.getTwoDigitDate()+" "+this.getShortMonthString()+" "+this.getFullYear());
};
Date.prototype.shortDateTime = function()
{
return (this.getTwoDigitDate()+" "+this.getShortMonthString()+" "+this.getFullYear()+", "+this.getTwoDigitHours()+":"+this.getTwoDigitMinutes());
};
function datetime_master(obj)
{
var date = new Date();
if(!obj.hasOwnProperty("minute") || obj.minute === undefined) obj.minute = "00";
if(!obj.hasOwnProperty("hour") || obj.hour === undefined) obj.hour = "00";
if($.type(obj.day) === "string") obj.day = obj.day.toLowerCase();
if(!obj.hasOwnProperty("day") || obj.day === undefined || obj.day === "today") obj.day = date.getDate();
else if(obj.day === "yesterday") obj.day = date.getDateAfterAdjustment(-1);
else if(obj.day === "tomorrow") obj.day = date.getDateAfterAdjustment(+1);
if(!obj.hasOwnProperty("month") || obj.month === undefined) obj.month = date.getShortMonthString();
if(!obj.hasOwnProperty("year") || obj.year === undefined) obj.year = date.getFullYear();
else if(obj.year.length === 2) obj.year = ("20"+obj.year);
date = new Date(obj.month+" "+obj.day+" "+obj.year+" "+obj.hour+":"+obj.minute);
return date;
}
function short_datetime_callback() // mon, jan 1 1900 at 00:00
{
var len = arguments.length;
var date = datetime_master({year:arguments[len-5],month:arguments[len-6],day:(arguments[len-7]||arguments[len-8]),hour:arguments[len-4],minute:arguments[len-3]});
return date.shortDateTime();
}
function short_date_callback() // 1 jan 1900
{
var len = arguments.length;
var date = datetime_master({year:arguments[len-3],month:arguments[len-4],day:(arguments[len-5]||arguments[len-6])});
return date.shortDate();
}
function uri()
{
var m = window.location.href.match(/\/([\w-]*\.aspx)(?:\?|$)/i);
if(m !== null) return m[1];
return "";
}
$(document).ready(function() {
if(hide_ads) $("#topad-wrap, #divTAProHolder, #divGiftProPanel, .followuson, .internalad, .rightintergi, .sharepanel").remove(); // oops, the ads disappeared
if(normalize_dates)
{
$("td.lastpostdate, td.posted, div.info, td.time, td.sentdate, div.coveritem, td.ta, div.boostingdate, div.gamingsession h3, div.subcommentinfo, td.lastpost, div.links").each(function() {
$(this).html($(this).html().replace(/(?:on )?(?:[A-Z]{1}[a-z]{2,8}, )?(today|yesterday|tomorrow|(?:\d{1,2}) ([A-Z]{1}[a-z]{2,8}) ?(\d{2,4})?) at (\d{2}):(\d{2})/g,short_datetime_callback));
});
$("div.addedby, td.hwr, table.comparison td.green, .maincolumnpanel .itemright h3").each(function() {
$(this).html($(this).html().replace(/(?:on )?(?:[A-Z]{1}[a-z]{2,8}, )?(today|yesterday|tomorrow|(\d{1,2}) ([A-Z]{1}[a-z]{2,8}) (\d{2,4}))/g,short_date_callback));
});
}
// fix spoilers
if(fix_spoilers) $("div.spoiler").each(function() {
$(this)
.css("border","1px solid #000")
.children("a").first().replaceWith($("<span/>")
.text("SPOILER: click to toggle")
.css("display","inline-block")
.css("width","100%")
.css("cursor","pointer")
.click(function() {var $span_content = $(this).siblings("span.spoiler").first();
if($span_content.css("display") === "none") $span_content.show();
else $span_content.hide();
})
);
});
// friend feed permalinks
if(feed_permalinks) $("#oFriendFeed div.Comment p").each(function() {$(this).prepend($("<a/>")
.attr("href",("?gfcid="+$(this).parent().attr("id").slice(5)))
.append($("<img/>")
.attr("src","/images/icons/permalink.png")
.attr("class","AddComment")
.attr("title","Permalink")
.attr("alt","Permalink")
)
);
});
switch(uri())
{
case "gamingsessionfeedback.aspx":
$(".gsdisclaimer").remove();
break;
case "gamingsession.aspx":
$(".gsdisclaimer").remove();
if(session_user_links && $("#mnuMyPages").length) // change gamertag links to compare page
{
var game_id = $("h4 a[title='View on session calendar']").first().attr("href"),
user_id = $("#mnuMyPages li a[href*='/gamerstats.aspx?gamerid=']").attr("href");
game_id = game_id.slice(game_id.lastIndexOf("=")+1);
user_id = user_id.slice(user_id.lastIndexOf("=")+1);
$("#oGamingSessionGamerList td.gamer").each(function() {
var $gamer_anchor = $(this).children("a").first(),
other_id = $gamer_anchor.attr("href");
other_id = other_id.slice(other_id.lastIndexOf("=")+1);
if(other_id != user_id) $gamer_anchor.attr("href",("/comparison.aspx?gameid="+game_id+"&gamerid="+user_id+"&friendid="+other_id));
$gamer_anchor.attr("target","_blank");
});
if(session_user_status) $("span.sitestatus").remove();
}
break;
case "chat.aspx":
var css = "";
if(improve_chat)
{
// this whole css section is overriding the default styling of the page when viewing the chatroom to change a whole
// bunch of things, including:
// # changing the font of the whole chat interface
// # extending the height of the userlist to be the same as the chatbox
// # shrinking the vertical display slightly so it all fits on the page at the same time (i always had to scroll a
// bit to get to the textbox)
// # extending the width of the input box
// # giving the timestamp a fixed width
// # giving the gamertag a fixed width
// # positioning the buttons we'll be adding after the text input later
// # preventing long words (spam) from adding horizontal scrolling
css = css +
"div#divChatHolder {font-family: 'Droid Sans Mono',monospace !important} "+
"div#divChatList {width: 175px !important; height: 450px !important;}" +
"div#divChatBody {margin-right: 190px !important; height: 450px !important; overflow-wrap: break-word !important;} "+
"input#txtChatMessage {width: 720px !important;} "+
"span.chattime {display: inline-block !important; width: 65px !important; font-style: normal !important;} "+
"span.gamertag {display: inline-block !important; width: 105px !important;} "+
"a#btnClearChat {position: relative !important; top: -4px !important; right: auto !important; padding-right: 8px !important;} "+
"img#btnChatRules {position: relative !important; top: -4px !important;} ";
// this section moves the clear chat button and creates a new rules button to the right of the input box at the bottom
$("#btnClearChat")
.insertBefore($("#divChatKey"))
.after($("<a/>")
.attr("href","chatpolicy.aspx")
.attr("target","_blank")
.append($("<img/>")
.attr("src","/images/itemflags/MainStoryline.png")
.attr("id","btnChatRules")
.attr("title","Chat guidelines")
.attr("alt","Chat guidelines")
)
);
$("#divChatKey, #divChatInformation").remove();
}
if(minimalize_chat)
{
// this section enforces additional options that leaves basically nothing on the page besides the chat
// elements, collapsing vertical space and removing elements from the page to even fit the whole thing
// on one screen and prevent vertical scrolling
css = css +
"div#main-holder {padding-bottom: 0 !important;} "+
"div#main {padding: 10px 10px 0px 10px !important; min-height: 0 !important;} "+
"div#page-wrap {padding-bottom: 0 !important;} "+
"div#page {min-height: 0 !important;}";
// the "header" variable points to the large bold text at the top of the page that says "TrueAchievements Chat"
// the footer is a huge bar of information that stretches the page
$("h1.pagetitle, #footer-wrap").remove();
}
// simply injecting the above css rules into the document
if(css.length) $("head").append($("<style/>")
.attr("type","text/css")
.text(css)
);
break;
}
});