您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Improves the TrueAchievements interface in various ways
当前为
// ==UserScript== // @author Mobius Evalon // @name TrueAchievements improver // @description Improves the TrueAchievements interface in various ways // @version 1.1 // @namespace mobiusevalon.tibbius.com // @license Creative Commons Attribution-ShareAlike 4.0; http://creativecommons.org/licenses/by-sa/4.0/ // @require https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js // @require https://code.jquery.com/ui/1.11.4/jquery-ui.js // @include /^https{0,1}:\/\/\w{0,}\.?trueachievements\.com.*$/ // @grant none // ==/UserScript== this.$ = this.jQuery = jQuery.noConflict(true); Date.prototype.short_date = true; Date.prototype.date_time = true; var help_topics = {tai_longdate:"The letters here are tokens that expand to date information. They use the same tokens as PHP's date() function, if you're familiar with it.<br><table>"+ "<tr><td>d</td><td>The day of the month with leading zeroes</td></tr>"+ "<tr><td>D</td><td>The name of the day, three letter abbreviation</td></tr>"+ "<tr><td>j</td><td>The day of the month, no leading zeroes</td></tr>"+ "<tr><td>l</td><td>The name of the day, full text</td></tr>"+ "<tr><td>S</td><td>Ordinal suffix for the day of the month (the 'th' in 5th or the 'st' in 1st)</td></tr>"+ "<tr><td>F</td><td>The name of the month, full text</td></tr>"+ "<tr><td>m</td><td>The month number with leading zeroes</td></tr>"+ "<tr><td>M</td><td>The name of the month, three letter abbreviation</td></tr>"+ "<tr><td>n</td><td>The month number, no leading zeroes</td></tr>"+ "<tr><td>Y</td><td>The year, four digits</td></tr>"+ "<tr><td>y</td><td>The year, two digits</td></tr>"+ "<tr><td>a</td><td>Lowercase meridiem (am/pm)</td></tr>"+ "<tr><td>A</td><td>Uppercase meridiem (AM/PM)</td></tr>"+ "<tr><td>g</td><td>The hour in the 12-hour meridiem rotation, no leading zeroes</td></tr>"+ "<tr><td>G</td><td>The hour in the 24-hour military notation, no leading zeroes</td></tr>"+ "<tr><td>h</td><td>The hour in the 12-hour meridiem rotation with leading zeroes</td></tr>"+ "<tr><td>H</td><td>The hour in the 24-hour military notation with leading zeroes</td></tr>"+ "<tr><td>i</td><td>Minutes with leading zeroes</td></tr>"+ "<tr><td>s</td><td>Seconds with leading zeroes</td></tr>"+ "<tr><td>[]</td><td>A proprietary format that 'fuzzies' the tokens inside</td></tr>"+ "</table><br>"+ "Information inside the angled brackets will be fuzzied if the date is yesterday, today, or tomorrow. For example, the token string 'D d M' would generally give you something like 'Sat 30 Apr', but if you enclose this information inside brackets such as '[D d M]' it will fuzzy this information to 'Today' if applicable. '[D d M], H:i' would give you something like 'Sat 30 Apr, 01:50' if the dat is not today, but will output something like 'Today, 01:50' if it is.<br>"+ "All unrecognized letters will be left alone, so you can insert commas or other glyphs as you please.<br>"+ ""}; Date.prototype.toString = function() { var r = ""; if(!this.short_date || script_settings.always_long_date) r += this.outputLongDate(); else r += this.outputShortDate(); if(this.date_time) r += (", "+this.outputTime()); return r; }; Date.prototype.getMonthString = function() { switch(this.getMonth()) { case 0: return "January"; case 1: return "February"; case 2: return "March"; case 3: return "April"; case 4: return "May"; case 5: return "June"; case 6: return "July"; case 7: return "August"; case 8: return "September"; case 9: return "October"; case 10: return "November"; case 11: return "December"; } }; Date.prototype.getShortMonthString = function() { return this.getMonthString().slice(0,3); }; Date.prototype.getDayString = function() { switch(this.getDay()) { case 0: return "Sunday"; case 1: return "Monday"; case 2: return "Tuesday"; case 3: return "Wednesday"; case 4: return "Thursday"; case 5: return "Friday"; case 6: return "Saturday"; } }; Date.prototype.getShortDayString = function() { return this.getDayString().slice(0,3); }; Date.prototype.getTwoDigitHours = function() { return zero_pad(this.getHours(),2); }; Date.prototype.getTwoDigitMinutes = function() { return zero_pad(this.getMinutes(),2); }; Date.prototype.getTwoDigitSeconds = function() { return zero_pad(this.getSeconds(),2); }; Date.prototype.getTwoDigitDate = function() { return zero_pad(this.getDate(),2); }; Date.prototype.getShortYear = function() { return (((""+this.getFullYear()).slice(-2))*1); }; Date.prototype.getMeridiem = function() { return ((this.getHours() > 11) ? "pm" : "am"); }; Date.prototype.getMeridiemHours = function() { var h = this.getHours(); if(h > 12) h -= 12; return h; }; Date.prototype.getTwoDigitMeridiemHours = function() { return zero_pad(this.getMeridiemHours(),2); }; Date.prototype.adjustDate = function(n) { this.setDate(this.getDate()+n); }; Date.prototype.getDateAfterAdjustment = function(n) { this.adjustDate(n); return this.getDate(); }; Date.prototype.getFuzzyDay = function() { var d = new Date(); if(d.getFullYear() === this.getFullYear() && d.getMonth() === this.getMonth()) { if(d.getDate() === this.getDate()) return "Today"; else if(d.getDateAfterAdjustment(1) === this.getDate()) return "Tomorrow"; else if(d.getDateAfterAdjustment(-2) === this.getDate()) return "Yesterday"; } return ""; }; Date.prototype.outputLongDate = function() { return this.getTokenizedOutput(script_settings.long_date_format); }; Date.prototype.outputShortDate = function() { return this.getTokenizedOutput(script_settings.short_date_format); }; Date.prototype.outputLongDateTime = function() { return (this.outputLongDate()+", "+this.outputTime()); }; Date.prototype.outputShortDateTime = function() { return (this.outputShortDate()+", "+this.outputTime()); }; Date.prototype.outputTime = function() { return this.getTokenizedOutput(script_settings.time_format); }; Date.prototype.getTokenizedOutput = function(t) { var r = "", i = -1; while(i++ < t.length) { switch(t.charAt(i)) { case 'd': {r += this.getTwoDigitDate(); break;} case 'D': {r += this.getShortDayString(); break;} case 'j': {r += this.getDate(); break;} case 'l': {r += this.getDayString(); break;} case 'S': {r += ordinal_suffix(this.getDate()); break;} case 'F': {r += this.getMonthString(); break;} case 'm': {r += zero_pad(this.getMonth()+1,2); break;} case 'M': {r += this.getShortMonthString(); break;} case 'n': {r += (this.getMonth()+1); break;} case 'Y': {r += this.getFullYear(); break;} case 'y': {r += this.getShortYear(); break;} case 'a': {r += this.getMeridiem(); break;} case 'A': {r += this.getMeridiem().toUpperCase(); break;} case 'g': {r += this.getMeridiemHours(); break;} case 'G': {r += this.getHours(); break;} case 'h': {r += this.getTwoDigitMeridiemHours(); break;} case 'H': {r += this.getTwoDigitHours(); break;} case 'i': {r += this.getTwoDigitMinutes(); break;} case 's': {r += this.getTwoDigitSeconds(); break;} case '[': var e = t.indexOf(']',i), f = this.getFuzzyDay(); if(e > i && f.length) { r += f; i = e; } break; case ']': break; default: {r += t.charAt(i); break;} } } return r; }; function ordinal_suffix(n) { n = Math.floor(n*1); var ord = "th"; switch(n) { case 1: case 21: case 31: ord = "st"; break; case 2: case 22: ord = "nd"; break; case 3: case 23: ord = "rd"; break; } return ord; } function zero_pad(a,l) { var r = (""+a); while(r.length < l) r = ("0"+r); return r; } function datetime_master(obj) { var date = new Date(), short = false, time = true; if(!obj.hasOwnProperty("hour") || obj.hour === undefined) {obj.hour = "00"; time = false;} if(!obj.hasOwnProperty("minute") || obj.minute === undefined) obj.minute = "00"; if(!obj.hasOwnProperty("year") || obj.year === undefined) {obj.year = date.getFullYear(); short = true;} else if(obj.year.length === 2) obj.year = ("20"+obj.year); if(!obj.hasOwnProperty("month") || obj.month === undefined) obj.month = date.getShortMonthString(); 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); date = new Date(obj.month+" "+obj.day+" "+obj.year+" "+obj.hour+":"+obj.minute); date.short_date = short; date.date_time = time; return date; } function short_datetime_callback() // mon, jan 1 1900 at 00:00 { var len = arguments.length, 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.toString(); } function short_date_callback() // 1 jan 1900 { var len = arguments.length, date = datetime_master({year:arguments[len-3],month:arguments[len-4],day:(arguments[len-5]||arguments[len-6])}); return date.toString(); //date.outputShortDate(); } function uri() { var m = window.location.href.match(/\/([\w-]*\.(?:aspx|htm))(?:\?|$)/i); if(m !== null) return m[1]; return ""; } function filter_settings_by_query(q) { $("div#oOptionPanel div.inputform div.innerform").each(function() { $(this).children("div.filtered-out, div:not([class]), div[class='']").each(function() { if(!q.length || $(this).html().toLowerCase().indexOf(q) > -1) $(this).removeClass("filtered-out").show(); else $(this).addClass("filtered-out").hide(); }); if(!q.length || $(this).children("div").not(".clearboth, .filtered-out").length) $(this).parent().show(); else $(this).parent().hide(); }); } function json_obj(json) { var obj; if(typeof json === "string") { try {obj = JSON.parse(json);} catch(e) {console.log("Malformed JSON object. Error message from JSON library: ["+e.message+"]");} } return obj; } function localstorage_obj(key) { var obj = json_obj(localStorage.getItem(key)); if(typeof obj !== "object") localStorage.removeItem(key); return obj; } function default_settings() { return {hide_ads:true, normalize_dates:true, improve_chat:true, session_userlinks_compare:true, session_hide_user_statuses:true, feed_permalinks:true, fix_spoilers:true, settings_page_filter:true, display_video_links:true, short_date_format:"D d M", long_date_format:"d M Y", time_format:"H:i", always_long_date:false, solution_list_filters:true, achievement_page_improvements:true}; } function store_settings() { localStorage.setItem("ta_improver_settings",JSON.stringify({hide_ads:checkbox("#tai_hide_ads"), normalize_dates:checkbox("#tai_dates"), improve_chat:checkbox("#tai_improve_chat"), session_userlinks_compare:checkbox("#tai_session_compare"), session_hide_user_statuses:checkbox("#tai_user_statuses"), feed_permalinks:checkbox("#tai_permalinks"), fix_spoilers:checkbox("#tai_spoilers"), settings_page_filter:checkbox("#tai_filter"), display_video_links:checkbox("#tai_video_links"), short_date_format:$("#tai_shortdate").val(), long_date_format:$("#tai_longdate").val(), time_format:$("#tai_time").val(), always_long_date:checkbox("#tai_always_longdate"), solution_list_filters:checkbox("#tai_solution_list_filter"), achievement_page_improvements:checkbox("#tai_improve_achievement_list") })); } function checkbox(id) { return ($("#divImprover "+id).prop("checked") === true); } function script_setting_display(id,type,value,name,tooltip) { var $element; if(type === "checkbox") $element = $("<input/>") .attr({"id":id, "type":"checkbox"}) .prop("checked",(value === true)); // fast short circuit. if the value is boolean and true, the box is checked. all other circumstances evaluate to boolean false (not checked) if(type === "textbox") $element = $("<input/>") .attr({"id":id, "type":"text"}) .val(value); var $elem = $("<div/>") .append($("<label/>") .attr("class","vlargelabel") .append($("<img/>") .attr({"src":"/images/icons/information.png", "alt":tooltip, "title":tooltip}) .css({"width":"16px", "height":"16px", "margin-right":"4px"}), $("<span/>") .text(name) ), $("<div/>") .attr("class","singleline") .append($element) ) .after($("<div/>") .attr("class","clearboth") ); /* if(help_topics.hasOwnProperty(id)) $elem.append($("<img/>") .attr("src","/images/icons/helper.png") .css({"display":"inline-block", "margin-left":"4px", "float":"left", "vertical-align":"middle", "cursor":"pointer"}) .click(function() {$("#tai_help_box") .css({"top":"15px", "left":"100px"}) .show() .find("div.content").first().html(help_topics[id]); }) ); */ return $elem; } function intersect_arrays(s,t) { var r = []; if($.type(s) === "array" && $.type(t) === "array") { for(var i=0;i<t.length;i++) { if(s.indexOf(t[i]) > -1) r.push(t[i]); } } return r; } function flag_filter() { var filter_flags = [], join = $("#tai_flag_filter input[name='filter_link']:checked").val(); $("#tai_flag_filter input[type='checkbox']:checked + div").each(function() {filter_flags.push($(this).attr("class"));}); //console.log(join+": "+flags.join(",")); $("div.achievementpanel").not(".tai_achievement_ownership_filtered").each(function() {var achievement_flags = []; $(this).find("span.achievementtypes span").each(function() {achievement_flags.push($(this).attr("class"));}); if(achievement_flags.length) { achievement_flags = intersect_arrays(achievement_flags,filter_flags); if(join === "not" && achievement_flags.length === 0) $(this).show(); else if(join === "or" && achievement_flags.length > 0) $(this).show(); else if(join === "and" && achievement_flags.length === filter_flags.length) $(this).show(); else $(this).hide(); } }); } $(document).ready(function() { $("head").append($("<style/>") .attr("type","text/css") .text("#tai_help_box {background-color: #e3e3e3; color: #000; width: 350px; height: 450px; position: absolute; z-index: 100; display: none; border-radius: 8px; border: 2px solid #000; overflow-x: hidden; overflow-y: scroll;} "+ "#tai_help_box h1 {display: block; padding: 0px; margin: 5px 0px; font-size: 125%; text-align: center;} "+ "#tai_help_box .content {padding: 4px;} "+ "div.spoiler {border: 1px solid #000 !important; border-radius: 5px !important;} "+ "div.spoiler span.tai_spoiler_header {display: inline-block; width: 100%; cursor: pointer; font-weight: bold; text-align: center;} "+ "a.tai_video_url_header {display: block; margin: 0px auto; text-align: center; font-weight: bold;} "+ "div.Comment img.tai_permalink_icon {float: right !important; width: 16px !important; height: 16px !important; border: none !important; padding: 0px !important; margin: 8px 2px 0px 5px !important;} "+ "#tai_flag_button .droparrow {margin-left: 8px;} "+ ".tai_pagetitle {margin: 0px !important;} "+ ".tai_won_options {margin: 10px 0px !important;} "+ ".tai_link_label {float: none !important; display: inline-block !important; width: 40px !important; margin: 0px 10px 0px 0px !important;} "+ ".tai_achievement_ownership_filtered {display: none !important;} " ) ); $("body").append($("<div/>") .attr("id","tai_help_box") .append($("<h1/>") .text("TrueAchievements Improver help"), $("<div/>") .attr("class","content") ) .draggable() ); script_settings = localstorage_obj("ta_improver_settings"); if(typeof script_settings !== "object") script_settings = default_settings(); else { // make sure new config options exist if the script has been updated var defaults = default_settings(); $.each(defaults,function(k,v) {if(!script_settings.hasOwnProperty(k)) script_settings[k] = v;}); } if(script_settings.hide_ads) { $("#topad-wrap, #divTAProHolder, #divGiftProPanel, #divBottomAds, .followuson, .internalad, .rightintergi, .sharepanel").remove(); $("div#sidebar").children().not(".smallpanel").remove(); } if(script_settings.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, #oGamer div.itemright p, td.author div.info").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, #oGamer div.itemright p").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(script_settings.fix_spoilers) $("div.spoiler").each(function() {$(this) .children("a").first().replaceWith($("<span/>") .text("SPOILER: click to show content") .attr("class","tai_spoiler_header") .click(function() {var $span_content = $(this).siblings("span.spoiler").first(); if($span_content.css("display") === "none") { $span_content.show(); $(this).text("SPOILER: click to hide content"); } else { $span_content.hide(); $(this).text("SPOILER: click to show content"); } }) ); }); // give videos a visible external link so script blockers can get around a blank display if(script_settings.display_video_links) $("iframe[src*='youtube.com']").each(function() {var vurl = $(this).attr("src"); vurl = ("https://www.youtube.com/watch?v="+vurl.slice(vurl.lastIndexOf("/")+1)); $(this).parent().before($("<a/>") .attr({"class":"tai_video_url_header", "href":vurl, "target":"_blank"}) .text(vurl) ); }); // friend feed permalinks if(script_settings.feed_permalinks) $("#oFriendFeed div.Comment p").each(function() {$(this).prepend($("<a/>") .attr({"href":("?gfcid="+$(this).parent().attr("id").slice(5)), "target":"_blank"}) .append($("<img/>") .attr({"class":"tai_permalink_icon", "src":"/images/icons/permalink.png", "title":"Permalink", "alt":"Permalink"}) ) ); }); switch(uri()) { case "achievements.htm": if(script_settings.achievement_page_improvements) { // remove default actions on the won status sorting radio buttons so this script can sort instead $("#rdoAllAchievements, #rdoWonAchievements, #rdoNotWonAchievements") .attr("onclick","") .prop("onclick",null) .removeAttr("onclick") .click(function() {var earned = ($(this).val() === "rdoAllAchievements" || $(this).val() === "rdoWonAchievements"), unearned = ($(this).val() === "rdoAllAchievements" || $(this).val() === "rdoNotWonAchievements"); $("div.achievementpanel").each(function() {if((earned && $(this).hasClass("green")) || (unearned && $(this).hasClass("red"))) $(this).removeClass("tai_achievement_ownership_filtered"); else $(this).addClass("tai_achievement_ownership_filtered"); flag_filter(); }); }); // add the button that toggles the flag filter dropdown $("#btnFlagFilter").before($("<a/>") .attr({"id":"tai_flag_button", "class":"button menubutton"}) .text("Filter") .click(function() {var $arrow = $(this).children("span.droparrow").first(); if($arrow.hasClass("icon-button-arrow-down")) { $arrow.removeClass("icon-button-arrow-down").addClass("icon-button-arrow-up"); $("#tai_flag_filter") .css({"left":$(this).css("left"), "top":$(this).css("bottom")}) .show(); } else { $arrow.removeClass("icon-button-arrow-up").addClass("icon-button-arrow-down"); $("#tai_flag_filter").hide(); } }) .append($("<span/>") .attr("class","droparrow icon-button-arrow-down") ), $("<ul/>") .attr({"id":"tai_flag_filter", "class":"menuitems rightaligned filterbutton"}) .hide() ); // cosmetics $("h1.pagetitle").first() .addClass("tai_pagetitle") .insertBefore("#tai_flag_button"); $("table.achievementwonoptions").first().addClass("tai_won_options"); // clone the flag filter section of the existing dropdown, then hide it so it cannot be manipulated in postback $("#btnFlagFilter_Options li.fp").eq(2).hide() .clone().appendTo("#tai_flag_filter").show() .find("*") .attr("onclick","") .prop("onclick",null) .removeAttr("id name value onclick"); // fix the check/uncheck all links $("#tai_flag_filter a[title='Select all flags']").removeAttr("href").click(function() {$("#tai_flag_filter input[type='checkbox']").prop("checked",true);}); $("#tai_flag_filter a[title='Clear all flags']").removeAttr("href").click(function() {$("#tai_flag_filter input[type='checkbox']").prop("checked",false);}); // i can't do an easy append for the NOT filter because the raw text outside of elements and floating elements makes it impossible, // so i have to clear the entire contents of this div and do it over $("#tai_flag_filter input[type=radio]").parent() .empty() .append($("<span/>") .text("Link flags:"), $("<input/>") .attr({"type":"radio", "name":"filter_link", "id":"tai_link_or", "checked":"checked", "value":"or"}), $("<label/>") .attr({"class":"tai_link_label", "for":"tai_link_or"}) .text("OR"), $("<input/>") .attr({"type":"radio", "name":"filter_link", "id":"tai_link_and", "value":"and"}), $("<label/>") .attr({"class":"tai_link_label", "for":"tai_link_and"}) .text("AND"), $("<input/>") .attr({"type":"radio", "name":"filter_link", "id":"tai_link_not", "value":"not"}), $("<label/>") .attr({"class":"tai_link_label", "for":"tai_link_not"}) .text("NOT") ); // add the apply button $("#tai_flag_filter").append($("<li/>") .attr("class","buttons") .append($("<a/>") .attr("class","button") .append($("<span/>") .attr({"class":"icon-tick", "title":"Apply", "alt":"Apply"}), $("<span/>") .text("Apply") ) .click(function() {flag_filter();}) ) ); } break; case "solutions.aspx": if(script_settings.solution_list_filters) $("table#oFilter tbody tr").first().after($("<tr/>") .append($("<td/>") .append($("<input/>") .attr({"class":"checkbox", "id":"tai_weekly_votes", "type":"checkbox"}) .click(function() {$("#tai_negative_votes, #tai_no_votes").prop("checked",false); var checked = ($(this).prop("checked") === true); $("table#oSolutionList tbody tr.myrow").each(function() {if(!checked || $(this).children().eq(9).text().trim().length) $(this).show(); else $(this).hide(); }); }), $("<label/>") .attr({"class":"checkboxcaption", "for":"tai_weekly_votes"}) .text("Votes this week") ), $("<td/>") .append($("<input/>") .attr({"class":"checkbox", "id":"tai_negative_votes", "type":"checkbox"}) .click(function() {$("#tai_weekly_votes, #tai_no_votes").prop("checked",false); var checked = ($(this).prop("checked") === true); $("table#oSolutionList tbody tr.myrow").each(function() {if(!checked || ($(this).children().eq(8).text().trim()*1) > ($(this).children().eq(7).text().trim()*1)) $(this).show(); else $(this).hide(); }); }), $("<label/>") .attr({"class":"checkboxcaption", "for":"tai_negative_votes"}) .text("Negative vote ratio") ), $("<td/>") .append($("<input/>") .attr({"class":"checkbox", "id":"tai_no_votes", "type":"checkbox"}) .click(function() {$("#tai_weekly_votes, #tai_negative_votes").prop("checked",false); var checked = ($(this).prop("checked") === true); $("table#oSolutionList tbody tr.myrow").each(function() {if(!checked || (($(this).children().eq(8).text().trim()*1) === 0 && ($(this).children().eq(7).text().trim()*1) === 0)) $(this).show(); else $(this).hide(); }); }), $("<label/>") .attr({"class":"checkboxcaption", "for":"tai_no_votes"}) .text("No votes") ) ) ); break; case "gamingsessionfeedback.aspx": $(".gsdisclaimer").remove(); break; case "gamingsession.aspx": $(".gsdisclaimer").remove(); if(script_settings.session_userlinks_compare && $("#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(script_settings.session_hide_user_statuses) $("span.sitestatus").remove(); break; case "customize.aspx": // insert the options for this script on the page $("#oOptionPanel") .before($("<div/>") .attr("class","buttons") .append($("<a/>") .attr({"class":"button", "id":"btnSaveTop", "onclick":"Postback('btnSave_click');return false;"}) .append($("<img/>") .attr({"src":"/images/icons/save.png", "alt":"Save", "title":"Save"}), $("<span/>") .css("padding-left","4px") .text("Save") ) .click(function() {store_settings();}), // the jquery click event will fire before the inline onclick event $("<div/>") .attr("class","clearboth") ) ) .prepend($("div.informationpanel"), // because this element is appended out of order due to this script's modifications $("<div/>") .attr({"class":"inputform", "id":"divImprover"}) .append($("<div/>") .attr("class","innerform") .append($("<h2/>") .text("TA Improver Script"), script_setting_display("tai_hide_ads","checkbox",script_settings.hide_ads,"Hide advertisements","This is pretty obvious."), script_setting_display("tai_dates","checkbox",script_settings.normalize_dates,"Normalize dates","TA has a bad habit of using half a dozen different date formats and further using fuzzy dates by saying something like 'tomorrow' instead of listing a calendar date. This option sets all dates to the same format."), script_setting_display("tai_improve_chat","checkbox",script_settings.improve_chat,"Improve chat interface","Rearrange the chat interface to look better and save space."), script_setting_display("tai_session_compare","checkbox",script_settings.session_userlinks_compare,"Change user session links to compare","When clicking on a gamertag in a session roster table, this option will default the link to compare your achievements with them for that game instead of linking you to their homepage."), script_setting_display("tai_user_statuses","checkbox",script_settings.session_hide_user_statuses,"Hide user statuses in sessions","User statuses are generally just stretching the size of the table for no good reason, so using this option will hide statuses in the session roster table."), script_setting_display("tai_permalinks","checkbox",script_settings.feed_permalinks,"Friend feed permalinks","Add a permalink icon to comments on the friend feed for easily linking other people to the conversation."), script_setting_display("tai_spoilers","checkbox",script_settings.fix_spoilers,"Fix spoiler tags","This option will change spoiler tags so that the header text always remains and can be clicked to collapse the spoiler content again."), script_setting_display("tai_filter","checkbox",script_settings.settings_page_filter,"Filter settings","Adds a textbox to the top of this page to easily filter out options by search query."), script_setting_display("tai_video_links","checkbox",script_settings.display_video_links,"Video links","Display a clickable hyperlink of the video URL above it. Most useful for those running ad/script blockers who block the YouTube domain when it's not first-party."), script_setting_display("tai_longdate","textbox",script_settings.long_date_format,"Long date format","A 'long date' is one that includes the year. If the script finds a calendar date with an accompanying year, then it will use this format to reconfigure the output."), script_setting_display("tai_shortdate","textbox",script_settings.short_date_format,"Short date format","A 'short date' does not include the year. Any short dates will be reconfigured using this output."), script_setting_display("tai_time","textbox",script_settings.time_format,"Time format","The format of time output to be used, if the time is included on a calendar date display."), script_setting_display("tai_always_longdate","checkbox",script_settings.always_long_date,"Always use long date","The script will not differentiate between short dates and long dates and will simply use the long date format in all circumstances."), script_setting_display("tai_solution_list_filter","checkbox",script_settings.solution_list_filters,"Solution list vote filter","I don't know about everyone else, but I check my solution list at least once a day for vote changes. Enabling this option will add checkboxes to your list of solutions to filter for solutions with votes cast in the last week and filter for zero or negative vote ratios overall."), script_setting_display("tai_improve_achievement_list","checkbox",script_settings.achievement_page_improvements,"Improve achievement list","This will reconfigure a game's achievement list page to remove all postback to the site and instead filter achievements without reloading the page. This option will also add a NOT filter.") ), $("<div/>") .attr("class","clearboth") ) ); $("#btnCancel").remove(); // the cancel button doesn't even do anything $("#btnSave").click(function() {store_settings();}); // this page has become ridiculously bloated so this simple search filter helps quickly narrow relevant options down if(script_settings.settings_page_filter) $("div#main h1.pagetitle") .css("display","inline-block") .after($("<img/>") .attr({"src":"/images/icons/information.png", "alt":"Quickly find relevant options you're looking for by typing search text in the box, then hitting Enter/Return or clicking the Find button.", "title":"Quickly find relevant options you're looking for by typing search text in the box, then hitting Enter/Return or clicking the Find button."}) .css("margin-left","8px"), $("<input/>") .attr({"type":"text", "id":"filter-text"}) .css({"margin-left":"8px", "margin-bottom":"-2px"}) .keyup(function(e) {if(e.which === 13 || !$(this).val().length) $("#execute-filter").click();}), $("<input/>") .attr({"type":"button", "value":"Find", "class":"button", "id":"execute-filter"}) .css("margin-left","8px") .click(function() {filter_settings_by_query($("#filter-text").val());}) ); break; case "chat.aspx": if(script_settings.improve_chat) { // this whole 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 // # collapses vertical space to fit the entire chat on one screen without scrolling // # 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 // # moves the clear chat button out of the display box and puts it next to the input box // # removes the large footer for the chat guidelines and makes it a tiny button by the input box instead // # removes the "TrueAchievements Chat" page header // 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", "target":"_blank"}) .append($("<img/>") .attr({"src":"/images/itemflags/MainStoryline.png", "id":"btnChatRules", "title":"Chat guidelines", "alt":"Chat guidelines"}) ) ); $("#divChatKey, #divChatInformation, h1.pagetitle, #footer-wrap").remove(); $("head").append($("<style/>") .attr("type","text/css") .text("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;} "+ "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;} ") ); } break; } });