// ==UserScript==
// @name Steam Custom Layout, Sorting and Filtering
// @namespace http://null.frisch-live.de/
// @version 0.27
// @description Allows to custom filter (min/max Price and min Discount) the search results on Steam
// @author frisch
// @match http://store.steampowered.com/search/*
// @match http://store.steampowered.com/app/*
// @match http://steamcommunity.com/id/frisch85/wishlist/
// @grant none
// ==/UserScript==
/*
position: absolute;
top: 0;
right: -102px;
float: right;
width: 100px;
height: 85px;
text-align: center;
vertical-align: middle;
border: 1px solid white;
font-size: 56pt;
margin: 0;
padding: 0;
*/
console.log("Initializing Steam Custom Layout and Sorting...");
var jq = document.fExt.jq;
if(location.href.indexOf("wishlist") >= 0){
jq("a:contains('Remove')").each(function(){
var jqThis = jq(this);
jqThis.text('X');
jqThis.css('position','absolute');
jqThis.css('top','0');
jqThis.css('right','-102px');
jqThis.css('float','right');
jqThis.css('width','100px');
jqThis.css('height','85px');
jqThis.css('text-align','center');
jqThis.css('vertical-align','middle');
jqThis.css('border','1px solid white');
jqThis.css('font-size','56pt');
jqThis.css('margin','0');
jqThis.css('padding','0');
});
}
else if(location.href.indexOf("search") >= 0) {
var loading = 0;
var loadingStep, loadingPages;
var jqSearchResultItems = [];
// Custom Elements
var sortContainer = jq("<div id='customSortContainer'>Sort by:</div>");
sortContainer.appendTo("div.searchbar");
var srtPrice = jq("<a href='#' id='srtPrice'>Price</a>");
srtPrice.data("sort-type","Price");
srtPrice.appendTo(sortContainer);
var srtDiscount = jq("<a href='#' id='srtDiscount'>Discount</a>");
srtDiscount.attr("active","true");
srtDiscount.data("sort-type","Discount");
srtDiscount.addClass("ASC");
srtDiscount.appendTo(sortContainer);
var srtDate = jq("<a href='#' id='srtDate'>Release Date</a>");
srtDate.data("sort-type","Date");
srtDate.appendTo(sortContainer);
var filterContainer = jq("<div id='customFilter' style='margin: 8px 0;'></div>");
filterContainer.insertBefore(sortContainer);
jq("<label for='filterPriceMin' class='filterLabel'>Minimum Price</label><input id='filterPriceMin' type='number' class='floatInput filterInput' value='0.00' /> €").appendTo(filterContainer);
jq("<label for='filterPriceMax' class='filterLabel'>Maximum Price</label><input id='filterPriceMax' type='number' class='floatInput filterInput' value='0.00' /> €").appendTo(filterContainer);
jq("<label for='filterDiscount' class='filterLabel'>Minimum Discount</label><input id='filterDiscount' type='number' class='intInput filterInput' value='0' /> %").appendTo(filterContainer);
jq('<button type="submit" class="btnv6_blue_hoverfade btn_small" id="customRefresh" style="float: right;"><span>Refresh</span></button>').appendTo(filterContainer);
// Styles
document.fExt.createStyle("#customSortContainer { display: block; width: 90%; padding: 4px; text-align: center; font-size: larger; }");
document.fExt.createStyle("#customSortContainer a { margin: 10px; }");
document.fExt.createStyle(".search_name { width: 58% !important; }");
document.fExt.createStyle(".search_capsule { width: 40% !important; }");
document.fExt.createStyle(".search_result_row { width: 267px !important; float: left !important; border: 2px groove rgba(28, 73, 101, 0.5); margin: 2px; }");
document.fExt.createStyle(".search_result_row:hover { border: 2px groove rgba(28, 73, 101, 0.5); margin: 2px; }");
document.fExt.createStyle("#search_result_container { width: 100%; max-width: 100% !important; }");
document.fExt.createStyle(".responsive_search_name_combined { width: 100%; height: 45px; }");
document.fExt.createStyle(".search_price_discount_combined { float: right; margin-right: 10px; width: 59%; }");
document.fExt.createStyle(".search_price { float: right; }");
document.fExt.createStyle(".leftcol.large { width: 1100px !important; }");
document.fExt.createStyle(".filterLabel { width: 110px; float: left; }");
document.fExt.createStyle(".filterInput { width: 100px; float: left; margin-right: 14px; text-align: right; }");
document.fExt.createStyle(".page_content { width: 1400px !important; } ");
document.fExt.createStyle(".search_discount.col span { position: absolute; top: 0; right: 20px; }");
document.fExt.createStyle(".search_review_summary { position: absolute; top: 40px; right: 20px; }");
document.fExt.createStyle(".search_price { position: absolute; top: 0; right: 80px;}");
document.fExt.createStyle("#customSortContainer a:after { content: ''; border-left: 5px solid transparent; border-right: 5px solid transparent; bottom: 12px; position: absolute; }");
document.fExt.createStyle("#customSortContainer a.ASC:after { border-top: 12px solid #fff; }");
document.fExt.createStyle("#customSortContainer a.DESC:after { border-bottom: 12px solid #fff; }");
// Functions
function sort(srtType){
var direction = "ASC";
var modifier = 1;
var jqSortElement;
if(srtType !== undefined){
jq("#customSortContainer a").each(function(){
var jqThis = jq(this);
var jqHtml = jqThis.html();
if(jqThis.data("sort-type") === srtType){
jqThis.attr("active","true");
direction = jqThis.hasClass("ASC") ? "ASC" : "DESC";
if(direction === "ASC") {
jqThis.removeClass("ASC");
direction = "DESC";
}
else {
jqThis.removeClass("DESC");
direction = "ASC";
}
jqSortElement = jqThis;
jqSortElement.addClass(direction);
}
else {
jqThis.removeClass("ASC");
jqThis.removeClass("DESC");
jqThis.removeAttr("active");
}
});
}
else {
jqSortElement = jq("#customSortContainer a[active=true]");
srtType = jqSortElement.data("sort-type");
if(!srtType)
return;
}
var container = jq("div#search_result_container");
if(!container || jqSearchResultItems.length === 0)
return;
if(direction === "DESC")
modifier = -1;
jqSearchResultItems.each(function(itm,ind){ itm.item.prepend(); });
jqSearchResultItems.sort(function(a,b){
var compValA, compValB;
switch(srtType){
case "Price":
return (direction === "DESC") ? a.price > b.price : a.price < b.price;
case "Release Date":
return (direction === "DESC") ? a.releaseDate > b.releaseDate : a.releaseDate < b.releaseDate;
case "Discount":
return (direction === "ASC") ? a.discount > b.discount : a.discount < b.discount;
}
});
jqSearchResultItems.each(function(itm,ind){ itm.item.appendTo("#search_result_container"); });
}
function Initialize(){
jq("a.search_result_row").remove();
jq("div.search_name").each(function(){
var jqThis = jq(this);
var jqParent = jqThis.parent().parent("a");
var jqAppImg = jqParent.find("div.search_capsule");
jqThis.detach();
jqThis.insertAfter(jqAppImg);
});
//jq("div.search_pagination").clone().insertBefore("div#search_result_container");
// http://store.steampowered.com/search/?sort_by=&sort_order=0&category1=998&special_categories=&specials=1&page=pageID
var lastPage = document.fExt.jq("div.search_pagination a:last");
if(lastPage.length === 1 && (lastPage.text() === '>' || lastPage.text() === '>'))
lastPage = lastPage.prev();
if(lastPage.length === 1){
var rx = new RegExp(/(page=[0-9]+)/g);
var matches = rx.exec(document.fExt.jq(location)[0].href);
loadingPages = parseInt(lastPage.text());
var pageLink = lastPage.attr('href').replace("page=" + loadingPages, "page=PAGENUMBER");
jqSearchResultItems.each(function(item,index){
item.item.remove();
});
jqSearchResultItems = [];
if(loadingPages > 25)
loadingPages = 25;
loadingStep = 0;
document.fExt.message("Loading pages (" + loadingStep + "/" + loadingPages + ")...");
var step = 0;
while(step < loadingPages){
step++;
var link = pageLink.replace("PAGENUMBER", step);
loadPageAsync(link);
}
}
else {
loadingStep = 0;
loadingPages = 1;
document.fExt.message("Loading pages (" + loadingStep + "/" + loadingPages + ")...");
loadPageAsync(window.location.href);
}
}
function reInit(){
if(jq("div.search_pagination").length === 2)
setTimeout(function(){ reInit(); }, 500);
else {
jq("#search_result_container").unbind("DOMSubtreeModified");
Initialize();
}
}
function loadPageAsync(link){
jq.ajax({
url: link,
type: 'GET',
error: function(data){
loadingStep++;
console.log("Error loading page #" + loadingStep + ": " + data);
},
complete: function(data){
loadingStep++;
loading--;
jq(data.responseText).find("a.search_result_row").each(function(){
var jqItem = jq(this);
var game = jqItem.find("span.title").text();
var isUnique = jq.grep(jqSearchResultItems, function(itm){ return itm.game === game; }).length === 0;
jqItem.css("display","none");
if(isUnique) {
var itemPrice = parsePrice(jqItem.find(".search_price").html().replace(/.*>/, ''));
var itemDiscount = parseDiscount(jqItem.find(".search_discount span").text());
var itemRelease = jqItem.find("div.search_released").text();
if(isNaN(itemPrice))
itemPrice = 0;
if(isNaN(itemDiscount))
itemDiscount = 0;
if(itemRelease)
itemRelease = Date.parse(itemRelease);
jqItem.appendTo("#search_result_container");
jqSearchResultItems.push({
game: game,
item: jqItem,
discount: itemDiscount,
price: itemPrice,
releaseDate: itemRelease,
});
}
});
if (loadingStep === loadingPages){
sort();
filter();
document.fExt.popup("Loading completed.");
document.fExt.message(undefined);
}
else document.fExt.message("Loading pages (" + loadingStep + "/" + loadingPages + ")(" + jqSearchResultItems.length + " uniqueItems found)...");
},
});
}
function parsePrice(text){
return parseFloat(text.replace("€","").trim().replace(",","."));
}
function parseDiscount(text){
return parseInt(text.replace("%","").trim());
}
function filter() {
var priceMin = parsePrice(jq("#filterPriceMin").val());
var priceMax = parsePrice(jq("#filterPriceMax").val());
var discountMin = parseDiscount(jq("#filterDiscount").val()) * -1;
var displayingItems = 0;
var totalDisplayingItems = 100;
var exceedingItems = 0;
jqSearchResultItems.each(function(item, ind){
var displayItem = true;
if(priceMin > 0)
displayItem = displayItem && item.price >= priceMin;
if(priceMax > 0)
displayItem = displayItem && item.price <= priceMax;
if(discountMin < 0)
displayItem = displayItem && item.discount <= discountMin;
item.item.css("display", displayingItems < totalDisplayingItems && displayItem ? "block" : "none");
if(displayItem) {
if(displayingItems === totalDisplayingItems)
exceedingItems++;
else
displayingItems++;
}
});
if(exceedingItems > 0)
document.fExt.popup("Too many items to display. (" + exceedingItems + " more items)");
}
// Events
jq("#srtPrice, #srtDiscount, #srtDate").click(function(e) {
e.preventDefault();
sort(jq(this).data("sort-type"));
return false;
});
jq(document).on('click', 'div.search_pagination_right a', function(e){
jq("#search_result_container").bind("DOMSubtreeModified", reInit());
});
jq("input.floatInput").keyup(function(e){
if(e.keyCode === 13){
e.preventDefault();
jq(".filterInput").trigger("keyup");
return false;
}
else {
var jqThis = jq(this);
var val = jqThis.val().replace(/[^0-9,.]/g,'');
if (val !== jqThis.val())
jqThis.val(val);
}
});
jq("input.intInput").keyup(function(e){
if(e.keyCode === 13){
e.preventDefault();
jq(".filterInput").trigger("keyup");
return false;
}
else {
var jqThis = jq(this);
var val = jqThis.val().replace(/[^0-9]/g,'');
if (val !== jqThis.val())
jqThis.val(val);
}
});
var filterChangeID = 0;
jq(".filterInput").keyup(function(e){
if(e.keyCode === 13)
e.preventDefault();
filterChangeID++;
var myChangeID = filterChangeID;
setTimeout(function(){
if (filterChangeID === myChangeID) {
filterChangeID = 0;
filter();
}
}, 1000);
});
jq("#customRefresh").click(function(e){
e.preventDefault();
reInit();
return false;
});
// Init
jq("form#advsearchform").on("submit", function(e){
setTimeout(function(){
Initialize();
}, 500);
});
Initialize();
}