// ==UserScript== // @name EBay: Custom Page Controls And Seller Block List // @author Scott Michaels // @description Adds more flexibility to eBay search results. Also, includes a seller block list and can filter out result items from blocked sellers. // @namespace http://se7en-soft.com // @include http*://*.ebay.*/sch/* // @include http*://*.ebay.*/dsc/* // @include http*://*.ebay.*/mbf/PurchaseHistory?MyEbay* // @include http*://*.ebay.*/ws/eBayISAPI.dll?MyEbay* // @include http*://*.ebay.com/myb/* // @version 0.0.10 // @grant metadata // @grant GM_xmlhttpRequest // @grant GM_addStyle // @grant GM_getValue // @grant GM_setValue // @grant GM_deleteValue // @grant GM_setClipboard // @downloadURL none // ==/UserScript== (function(){ var SharedObjects = { //Variables StartupInterval: 0, //Interval values Intervals : { Startup: 60, Timeout: 100 }, //local arrays Arrays : { OriginalPrices: [], ResultItems: [], FilteredItems: [], AllSellerData: [], TruncatedSellers: [] //jagged array }, //strings Constants : { ClipboardIcon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAiJJREFUeNqMU0toE1EUPRkmaYY4pBRMCYKkFQJtSF1UiriwK3WjbkSxKhbiQuhCaDeFLgpi6aa7KoiLBkRBEXUhgtSFi6wsVGgaS2msTVM/MZR+YhOM7czEe19+b0ooXji8zz3nvvuZcTzohTCHAzVLaR2uVU/oPG0PV67WA4WFt21/FnernFKpvKp1GR4RunnT8mtR7Tp3xncycsfP54/Rycz36Zej8MKocD8RbouH7/fWAsyevRLpTiQSONI/BbfbBa/3kHDkcnkUi7v48fgWwuEw3r+IcoATIgPTqqcQHJjCzJOniMWmSeyFrutwOp3IFwr4ncvBd3oIwb6rePc8WtOoplkPwGVdu3EdqZUVNLK29nbBkTW2DEzqjGVZOBoINAxgkq+kKJA1CkerwqIAp14HYRAxNjeHRDqNL9ksUpmMuGMwR9aohmV/4cOFBRjk6QmFbK8blbwdNG9ZoxqmvYT4yDBC98Yxv7xMk3BT94tiZdM0Dcf8fsga1TDsAYJ3x7BHmXRQwxr2gTiyRuFoVXAJo890ke4M9SBJPWB84x7QHYM5skbd21fCyKUN4Tje2dmwB8yRNUo6L2VAzocTE6Lbs/E4vq6t4fPSklgZfC9KqPBZq776CVxsBfyu8hgjg4MizfC+KVSnxJy/9EtlCG+y5Z9Jo41+uZkO9NlqHg8OMuZs7pB4Gz467ogABF+6gORNvQn/Y1slJFnDrfknwAA40SgApj324QAAAABJRU5ErkJggg==", CloseButtonIcon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACbklEQVR42qWTXUiTURjH/+/XPt5tbII1lokoSSAV7Cqo0UU5RkVpTIOiUqEb+6DvKKEcBhZhHxfSboS0Dy9aiyxK1rSLWNHdbkQQw5KMZUnb2N53be+7d529OpnOLqLn5jz/85zzO895nnMo/KdRxYIHbpmB2giwn8jfy9bqKoAnUWBSBM6VADRAd295+eU16TTaEok3P4FGMp1aCOttwNBjk8k5odXi1Nzc9QzQsQhggEs9Fkv3vtZWKidJ+DgwgOPJ5MgvYG8+vgp40Wc01m9qaQHFcXjW35+7EIt1ZIEbeYDOBcS8zc1azmZTj8vGYgj5/TgpCKP5BV6DYcdmtxuMxaLGpUgE7T5fOgBYClc4dNFsvn/C6WRpnp+HJBL4EAio/haXC4zJpPqKKKI3GJRvxuNtRD4qLqL7NM8Pnnc4NAWIIgjqSBsMi5t7QqHMXVE8SKS/pAvEdrVrtU+v2O36AqRg+c3XwuGUN51uIvL1im0kZrQC714aDPbqurolgS/j49gjCOHvwDYikysBTGsJeZDjHBurqgBS7SVGujM2PY0DkhSaIZmSmUQxwFQDDPtZdus6qxUUw6iTciajjqxGo465bBafZmfhluX3U8DOPEQF6IDbYzR9prKsjFSMVhdnyImH4/Efef+h2bxaU8hIUTATjWKDotwhr+ysCtADnucs2+nUE4+ikJJlNInit2GgXq0sMOLj+Qo9y5I0cgimUmiU5S4C6Cx+yp4HNH11N8NQDZL0+e385qmFcM12AhniuOpX2WzuiKJ0kct5SrpAkj9WCxydABqI/LqsQ5XryX+YBPoU4N7f2vjP9gfr3dEZbh82JAAAAABJRU5ErkJggg==", ReloadButtonIcon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAyUlEQVR42mNkoBAwkqGHHYh/EjLAGIjjgFgaquYJEC8E4nNA3ArEM4H4ETYDmIG4H4j/AfEkIL4HFVcC4jyo+l9APAWIH2IzAKTpIBCvRRMXAGJ1IA4G4gwg1sVmAMjZsUBcgMVLmkDsh8SfDsSf0A2YCMX3GEgAyAasAeIQIvXpAPEVSgyAqyXHC7AYKSAlEJHBBCBeDMRn0Q0AAVzRCAOgaLSHuoABmwGEEhITEBcC8V9cBiB7B5aUQeApEC+CORsZkJOZqGsAAKyGKhGReVeSAAAAAElFTkSuQmCC", ShowTopPager: "EBay.SellerBlockList.Property.ShowTopPager", RankByPrice: "EBay.SellerBlockList.Property.RankByPrice", FixLinks: "EBay.SellerBlockList.Property.FixLinks", FilterResults: "EBay.SellerBlockList.Property.FilterResults", UsePlaceholders: "EBay.SellerBlockList.Property.UsePlaceholders", BlockedSellerList: "EBay.SellerBlockList.Property.BlockedSellersList", StyleSheetLocation: "//mycdn.atwebpages.com/css/ebay/ebay.css", // "//se7en-soft.com/misc/gm/ebay/ebay.css", NegativeFeedbackLink: "http://feedback.ebay.com/ws/eBayISAPI.dll?ViewFeedback2&userid=[SELLERNAME]&myworld=true&items=25&iid=-1&de=off&which=negative&interval=365" }, }; //local property object var ScriptProps = {}; var EBayUsabilityEnhancer = { Initialize : function(){ //Get object properties setup for access Utilities.SetupProperties(); ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //Get the ball rollin'. var pgSetup = this.SetupPage.bind(this); SharedObjects.StartupInterval = setInterval(pgSetup, SharedObjects.Intervals.Startup); ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// }, //InjectStyles: Injects a style file from the se7en-soft.com web site. //This file contains element styles that are used througout this script. InjectStyles : function(callback){ GM_xmlhttpRequest({ method: "GET", url: SharedObjects.Constants.StyleSheetLocation + "?" + Math.random(), onload: function(r){ var css = r.responseText; GM_addStyle(css); if(callback) callback.call(this); } }); }, //SetupPage: Attaches a handler to the 'onClick' event of the DIV element containing the anchor which points to each product in the //search results page of an EBay search. The event handler opens the link in a new tab or window, depending on your browser settings. SetupPage : function() { var self = this; var winLoc = window.location.href; if(winLoc.indexOf("PurchaseHistory?MyEbay") !== -1 || winLoc.indexOf("eBayISAPI.dll?MyEbayBeta") !== -1){ var ordersDiv = document.getElementById("orders"); if(ordersDiv){ clearInterval(SharedObjects.StartupInterval); var itemsContainer = ordersDiv.querySelector("div.ajax-wrap div.result-set-r"); if(itemsContainer){ var itemContainers = itemsContainer.querySelectorAll("div.order-r"); var len = itemContainers.length, i = 0; for(i; i < len; i++){ var item = itemContainers[i]; var sellerLink = item.querySelector("div div a.seller-id"); if(sellerLink){ //append X button to allow blocking this seller... var sellerName = sellerLink.textContent.trim(); var img = new Image(); img.setAttribute("style", "height:12px;width:12px;cursor:pointer;"); img.setAttribute("Seller-ID", sellerName); sellerLink.parentNode.appendChild(img); img.onload = function(){ var seller = this.getAttribute("Seller-ID"); this.title = "Add seller '" + seller + "' to the block list."; this.addEventListener("click", function(){ SellerManager.ConfirmBlockSeller(seller); }, false); }; img.src = SharedObjects.Constants.CloseButtonIcon; } } } } } else { //find DIV elements for each product item in the search page var itmLinks = document.getElementsByClassName("sresult"); //gotz links? if(itmLinks && itmLinks.length > 0){ //remove the interval that was set when the function was first kicked off. clearInterval(SharedObjects.StartupInterval); try{ //download and inject the css styles for our elements this.InjectStyles(function(){ self.BeginOverlayConstruction(); }); } catch(e){ alert(e); } //get the item prices and stuff them into an array Utilities.GetItemPrices(); //loop through the collection of DIV elements for(var i = 0; i < itmLinks.length; i++){ //get the DIV at index 'i', from the collection var dLnk = itmLinks[i]; SharedObjects.Arrays.ResultItems.push(dLnk); } //alert(SharedObjects.Arrays.ResultItems.length); } } }, //BeginOverlayConstruction: Begins construction of the control and display it on the page. BeginOverlayConstruction : function(){ //create the top pagination bar UIBuilder.CreateTopPagerControl(); //create the overlay container var overlay = UIBuilder.BuildOverlay(); //add controls to the overlay container UIBuilder.BuildOverlayControls(overlay); var badSellerBox = document.getElementById("GM_eBayOverlay_BadSellerBox"); UIBuilder.BuildBlockedSellersBox(badSellerBox); SellerManager.AddBlockedSellers(); //setup the controls on the overlay container. UIBuilder.OverlaySetup(); //show the primary control overlay! document.getElementById('GM_eBayOverlayContainer').style.visibility = 'visible'; }, //ToggleResultOrder: Reorders items from lowest to highest, or returns them to their original order. ToggleResultOrder : function(lowToHigh){ if(SharedObjects.Arrays.OriginalPrices.length == 0) return; var pArray = SharedObjects.Arrays.OriginalPrices.slice(0); if(lowToHigh) { try{ pArray.sort(SortFunctions.SortLowToHigh); } catch(e){ alert(e); } } var results = document.getElementById("ListViewInner"); //var results = document.getElementsByClassName("rsittlref"); //var resultParent = results[0].parentNode; while(results.childNodes.length) results.removeChild(results.firstChild); for(var i = 0; i < pArray.length; i++) results.appendChild(pArray[i][0]); }, //ToggleLinkFix: Toggles links to open in a new tab/window, or not. ToggleLinkFix : function(openNew){ for(var i = 0; i < SharedObjects.Arrays.ResultItems.length; i++){ var dLnk = SharedObjects.Arrays.ResultItems[i]; //grab the anchor element from the H3 or H4 title element var anchor = dLnk.querySelector('h3 a') || dLnk.querySelector("h4 a"); if(anchor){ if(openNew){ //get the link pointer location var href = anchor.href; //attach to the 'onClick' event for the anchor element so that it opens the link in a new window/tab anchor.setAttribute('onclick',"window.open('" + href + "');return false;"); } else { anchor.removeAttribute('onclick'); } } } }, //ToggleTopPager: Toggles the visibility of the top pagination control. ToggleTopPager : function(show){ document.getElementById("Pagination2").style.visibility = show ? 'visible' : 'collapse'; }, //ToggleResultFilterBar: Toggles the display of the filtered result bar. ToggleResultFilterBar : function(result, memberName, show){ var filterBar = result.querySelector("tr.GM_eBayBadSeller_ResultFilterBarContainer"); if(memberName.lastIndexOf("..") !== -1){ var badSellers = ScriptProps.BlockedSellerList; var len = badSellers.length, i = 0; for(i; i < len; i++){ var bs = badSellers[i].toLowerCase(); var pSellerName; if(memberName.lastIndexOf("..") !== -1){ pSellerName = memberName.substring(0, memberName.lastIndexOf("..") - 1); } else pSellerName = memberName; if(bs.indexOf(pSellerName) !== -1){ memberName = bs; break; } } } if(show){ if(!filterBar){ filterBar = document.createElement("tr"); filterBar.setAttribute("class", "GM_eBayBadSeller_ResultFilterBarContainer"); var cell = document.createElement("td"); filterBar.appendChild(cell); var dvBar = document.createElement("div"); dvBar.setAttribute("class", "GM_eBayBadSeller_ResultFilterBar") cell.appendChild(dvBar); var table = document.createElement("table"); table.style.width = "100%"; var tRow = document.createElement("tr"); table.appendChild(tRow); for(var i = 0; i < 4; i++){ var tCell = document.createElement("td"); tRow.appendChild(tCell); } dvBar.appendChild(table); var span = document.createElement("span"); span.setAttribute("class", "GM_eBayBadSeller_FilterBarHeader"); span.textContent = "Filtered Result [" + memberName + "]"; tRow.childNodes[0].appendChild(span); span = document.createElement("span"); span.setAttribute("class", "GM_ebayHeader"); var link = document.createElement("a"); link.setAttribute("class", "GM_eBayBadSeller_FilterBarLink"); link.setAttribute("target", "_blank"); link.textContent = "(View Listing)"; link.title = "View item listing."; var anchor = result.querySelector("h3 a"); if(!anchor) anchor = result.querySelector("h4 a"); link.href = anchor.href; span.appendChild(link); tRow.childNodes[2].appendChild(span); span = document.createElement("span"); span.title = "Remove"; span.textContent = "X"; span.setAttribute("class", "GM_eBayBadSeller_FilterBarCloseButton"); span.addEventListener('click', function(e){ var p = e.target.parentNode; while(p != null){ if(p.getAttribute("class") == "GM_eBayBadSeller_ResultFilterBarContainer") break; if(p.parentNode != null) p = p.parentNode; else break; } p.parentNode.setAttribute("data-removed", true); p.style.visibility = 'collapse'; }); tRow.childNodes[3].appendChild(span); var tbody = result.querySelector("tbody"); var id = result.attributes["listingid"].value; var children = []; while(result.firstChild){ children.push(result.firstChild); result.removeChild(result.firstChild); } result.style.display = "none"; SharedObjects.Arrays.FilteredItems.push([children,id,memberName]); if(!ScriptProps.UsePlaceholders) filterBar.style.visibility = 'collapse'; if(!result.attributes["data-removed"]) result.appendChild(filterBar); } else { filterBar.style.visibility = ScriptProps.UsePlaceholders ? 'visible' : 'collapse'; } } else { if(filterBar) filterBar.style.visibility = 'collapse'; var id = result.attributes["listingid"].value; var len = SharedObjects.Arrays.FilteredItems.length; var sellerData, content; for(var i = 0; i < len; i++){ var fItem = SharedObjects.Arrays.FilteredItems[i]; if(fItem[1] == id){ var seller = SellerManager.GetSellerById(id); if(seller && seller.ID.lastIndexOf("...") !== -1){ var fuzzyMatch = SellerManager.FuzzyMatchedName(seller.ID); if(fuzzyMatch){ content = fItem[0]; break; } } else if(seller && seller.ID === memberName){ content = fItem[0]; break; } } } if(content){ for(var n = 0; n < content.length; n++){ var c = content[n]; result.appendChild(c); } if(filterBar) result.removeChild(filterBar); result.style.display = "block"; } } }, //ToggleFilterBlockedSellerResults: Toggles blocked seller item results. ToggleFilterBlockedSellerResults : function(filterThem){ var resultCount = SharedObjects.Arrays.OriginalPrices.length; var fiaLen = SharedObjects.Arrays.FilteredItems.length; if(fiaLen > 0){ for(var i = 0; i < fiaLen; i++){ var filteredItem = SharedObjects.Arrays.FilteredItems[i]; var itemId = filteredItem[1]; var priceItem = Utilities.GetResultItem(itemId); if(priceItem){ var memberName = filteredItem[2]; this.ToggleResultFilterBar(priceItem, memberName, filterThem); } } } if(filterThem){ for(var i = 0; i < resultCount; i++){ var resultItem = SharedObjects.Arrays.OriginalPrices[i][0]; var listingId = resultItem.attributes["listingid"].value; var skip = false; //loop through the 'SharedObjects.Arrays.FilteredItems' and see if the current 'resultItem' is contained in it. //if so, we'll not double process it. The check is based on the listingId value. for(var n = 0; n < SharedObjects.Arrays.FilteredItems.length; n++){ var fi = SharedObjects.Arrays.FilteredItems[n]; var fid = fi[1]; if(fid === listingId){ skip = true; break; } } //should we skip passed everything and continue? if(skip) continue; var sd = SellerManager.GetSellerById(listingId); if(sd){ var userName = sd.ID; if(userName.length > 0){ var fn = SellerManager.FuzzyMatchedName(userName); userName = fn || userName; if(SellerManager.IsBlockedSeller(userName, true)){ var blockedUserSpan = document.getElementById("EBayEnhancer_BlockedSeller_" + userName); blockedUserSpan.style.opacity = "1"; this.ToggleResultFilterBar(resultItem, userName, true); } } } } } else { for(var i = 0; i < resultCount; i++){ var result = SharedObjects.Arrays.OriginalPrices[i]; this.ToggleResultFilterBar(result[0], "", false); } } }, //ToggleFilteredItemPlaceholders: Toggles visibility of removed item placeholders. ToggleFilteredItemPlaceholders : function(show){ var filterBars = document.getElementsByClassName("GM_eBayBadSeller_ResultFilterBarContainer"); var len = filterBars.length; if(!show){ if(len > 0){ for(var i = 0; i < len; i++){ var fbar = filterBars[i]; fbar.style.visibility = 'collapse'; fbar.parentNode.style.display = "none"; } } } else { if(len > 0){ for(var i = 0; i < len; i++){ var fbar = filterBars[i]; var removed = fbar.parentNode.attributes["data-removed"]; if(removed == undefined){ fbar.style.visibility = 'visible'; fbar.parentNode.style.display = "block"; } } } } }, //CleanGMValues: Deletes all saved values associated with this script. CleanGMValues : function(){ GM_deleteValue(SharedObjects.Constants.BlockedSellerList); GM_deleteValue(SharedObjects.Constants.FilterResults); GM_deleteValue(SharedObjects.Constants.ShowTopPager); GM_deleteValue(SharedObjects.Constants.RankByPrice); GM_deleteValue(SharedObjects.Constants.FixLinks); GM_deleteValue(SharedObjects.Constants.UsePlaceholders); }, ResetAll : function(){ this.CleanGMValues(); location.reload(); } }; var UIBuilder = { //BuildOverlay: Builds the control overlay. BuildOverlay : function(){ var rightPanel = document.getElementById("RightPanel"); var overlayContainer = document.createElement("div"); overlayContainer.id = "GM_eBayOverlayContainer"; //set the overlay to be initially collapsed. we'll show it after the style sheet has been downloaded and applied. overlayContainer.style.visibility = 'collapse'; rightPanel.insertBefore(overlayContainer, rightPanel.firstChild); var overlay = document.createElement("div"); overlay.id = "GM_eBayOverlay"; var img = new Image(); img.src = SharedObjects.Constants.ReloadButtonIcon; img.id = "GM_eBaySettingsResetIcon"; img.title = "Reset All"; img.addEventListener('click', function(){ var result = confirm("Are you sure you want to clear and reset everything? This action cannot be undone."); if(result){ //----------------------------------- EBayUsabilityEnhancer.ResetAll(); } }); overlay.appendChild(img); var header = document.createElement("h3"); header.textContent = "Usability Settings"; header.setAttribute("class", "GM_ebayHeader"); overlay.appendChild(header); var controlBox = document.createElement("div"); controlBox.id = "GM_eBayOverlay_ControlBox"; overlay.appendChild(controlBox); header = document.createElement("h3"); header.textContent = "Seller Block List"; header.setAttribute("class", "GM_ebayHeader"); overlay.appendChild(header); var badSellerBox = document.createElement("div"); badSellerBox.id = "GM_eBayOverlay_BadSellerBox"; overlay.appendChild(badSellerBox); overlayContainer.appendChild(overlay); return controlBox; }, //BuildOverlayControls: Builds the controls for the overlay container. BuildOverlayControls : function(pOverlay){ var ul = document.createElement("ul"); ul.style.marginTop = "-8px"; for(var i = 0; i < 5; i++){ var li = document.createElement("li"); ul.appendChild(li); } // -- Top Pager var cbContainer = this.BuildCheckbox("Show Pager At Top", "GM_cbShowTopPager"); cbContainer.title = "Display a pager element at the top of the results view."; var cbShowTopPager = cbContainer.firstChild; cbShowTopPager.addEventListener('change', function(r) { var cb = r.target; ScriptProps.ShowTopPager = cb.checked; EBayUsabilityEnhancer.ToggleTopPager(cb.checked); }); ul.childNodes[0].appendChild(cbContainer); // Top Pager -- // -- Reorder Price-wise cbContainer = this.BuildCheckbox("Order Low To High", "GM_cbRankByPrice"); cbContainer.title = "Re-order results by price; lowest to highest."; var cbReorderByPrice = cbContainer.firstChild; cbReorderByPrice.addEventListener('change', function(r){ var cb = r.target; ScriptProps.RankByPrice = cb.checked; EBayUsabilityEnhancer.ToggleResultOrder(cb.checked); }); ul.childNodes[1].appendChild(cbContainer); // Reorder Price-wise -- // -- Fix Links cbContainer = this.BuildCheckbox("Open In New Tab", "GM_cbTabbedLinks"); cbContainer.title = "Open item links in a new tab."; var cbTabbedLinks = cbContainer.firstChild; cbTabbedLinks.addEventListener('change', function(r){ var cb = r.target; ScriptProps.FixLinks = cb.checked; EBayUsabilityEnhancer.ToggleLinkFix(cb.checked); }); ul.childNodes[2].appendChild(cbContainer); // -- Fix Links // -- Filter Bad Sellers var fDiv = document.createElement("div"); cbContainer = this.BuildCheckbox("Prune Results", "GM_cbFilterBlockedSellers"); cbContainer.title = "Remove items posted by blocked sellers."; var cbBlockSellers = cbContainer.firstChild; cbBlockSellers.addEventListener('change', function(r){ var cb = r.target; ScriptProps.FilterResults = cb.checked; document.getElementById('GM_cbFilterBlock_ShowPlaceholders').disabled = !cb.checked; EBayUsabilityEnhancer.ToggleFilterBlockedSellerResults(cb.checked); }); fDiv.appendChild(cbContainer); var fUl = document.createElement("ul"); var fli = document.createElement("li"); fUl.appendChild(fli); cbContainer = this.BuildCheckbox("Use Placeholders", "GM_cbFilterBlock_ShowPlaceholders"); cbContainer.title = "Show placeholders for removed items."; var cbPlaceholder = cbContainer.firstChild; cbPlaceholder.addEventListener('change', function(r){ var cb = r.target; ScriptProps.UsePlaceholders = cb.checked; EBayUsabilityEnhancer.ToggleFilteredItemPlaceholders(cb.checked); }); fli.appendChild(cbContainer); fDiv.appendChild(fUl); ul.childNodes[3].appendChild(fDiv); // Filter Bad Sellers -- //append the actual list element to the overlay pOverlay.appendChild(ul); }, //CreateTopPagerControl: Creates the top pagination control. CreateTopPagerControl : function(){ var paginator = document.getElementById("Pagination"); if(paginator){ var pager2 = paginator.cloneNode(true); if(pager2){ pager2.style.visibility = 'collapse'; pager2.id = "Pagination2"; pager2.style.marginTop = "10px"; pager2.style.marginBottom = "10px"; var msgContainer = document.getElementById("MessageContainer"); if(msgContainer) msgContainer.parentNode.insertBefore(pager2, msgContainer.nextSibling); } } }, //OverlaySetup: Sets up the controls inside the overlay container. OverlaySetup : function(){ //Checkbox setup: Show Pager At Top document.getElementById("GM_cbShowTopPager").checked = ScriptProps.ShowTopPager; setTimeout(function(){ EBayUsabilityEnhancer.ToggleTopPager(ScriptProps.ShowTopPager); }, SharedObjects.Intervals.Timeout); //Checkbox setup: Order Low To High document.getElementById("GM_cbRankByPrice").checked = ScriptProps.RankByPrice; setTimeout(function(){ EBayUsabilityEnhancer.ToggleResultOrder(ScriptProps.RankByPrice); }, SharedObjects.Intervals.Timeout); //Checkbox setup: Open In New Tab document.getElementById("GM_cbTabbedLinks").checked = ScriptProps.FixLinks; setTimeout(function(){ EBayUsabilityEnhancer.ToggleLinkFix(ScriptProps.FixLinks); }, SharedObjects.Intervals.Timeout); //Checkbox setup: Filter Results document.getElementById("GM_cbFilterBlockedSellers").checked = ScriptProps.FilterResults; setTimeout(function(){ EBayUsabilityEnhancer.ToggleFilterBlockedSellerResults(ScriptProps.FilterResults); }, SharedObjects.Intervals.Timeout); //Checkbox setup: Use Placeholders var cbPlaceHolders = document.getElementById("GM_cbFilterBlock_ShowPlaceholders"); cbPlaceHolders.checked = ScriptProps.UsePlaceholders; cbPlaceHolders.disabled = !ScriptProps.FilterResults; setTimeout(function(){ EBayUsabilityEnhancer.ToggleFilteredItemPlaceholders(ScriptProps.UsePlaceholders); }, SharedObjects.Intervals.Timeout); }, //BuildBlockedSellerNameLink: Builds a seller name element that allows for copying or removal of the seller from the black list. BuildBlockedSellerNameLink : function(sellerName){ if(!sellerName) return null; var table = document.createElement('table'); table.className = "GM_eBayTableElement"; var row = document.createElement("tr"); for(var i = 0; i < 3; i++){ var cell = document.createElement('td'); row.appendChild(cell); } table.appendChild(row); var nameSpan = document.createElement("span"); nameSpan.id = "EBayEnhancer_BlockedSeller_" + sellerName; nameSpan.style.fontWeight = "bold"; nameSpan.style.cursor = "default"; nameSpan.className = "unselectable"; var slrName = sellerName; if(slrName.length > 13) slrName = slrName.substr(0, 13) + "..."; nameSpan.textContent = slrName; nameSpan.title = sellerName; nameSpan.style.opacity = ".6"; //set to 60% opacity row.childNodes[0].appendChild(nameSpan); var copyImage = new Image(); copyImage.src = SharedObjects.Constants.ClipboardIcon; copyImage.style.cursor = "pointer"; copyImage.title = "Copy the seller name to the clipboard."; copyImage.setAttribute('data-sellerName', sellerName); copyImage.addEventListener('click', function(r){ var img = r.target; var sn = img.attributes["data-sellerName"].value; GM_setClipboard(sn); }); var cell1 = row.childNodes[1]; cell1.style.width = "16px"; cell1.appendChild(copyImage); var removeLink = new Image(); removeLink.src = SharedObjects.Constants.CloseButtonIcon; removeLink.setAttribute('data-badSellerName', sellerName); removeLink.title = "Remove blocked seller '" + sellerName + "'."; removeLink.style.cursor = "pointer"; removeLink.addEventListener('click', function(r){ var btn = r.target; var sllr = btn.getAttribute('data-badSellerName'); var result = confirm("Are you sure you want to remove '" + sllr + "' from your seller black list?"); if(result){ var badSellers = ScriptProps.BlockedSellerList; var idx = badSellers.indexOf(sllr); if(idx > -1){ var listings = SellerManager.GetListingsBySeller(sllr); for(var i = 0; i < listings.length; i++){ var listing = listings[i][0]; EBayUsabilityEnhancer.ToggleResultFilterBar(listing, sllr, false); } var remSellers = badSellers.splice(idx, 1); ScriptProps.BlockedSellerList = badSellers; var ulst = document.getElementById("GM_eBayBadSellers_UList"); while(ulst.firstChild != null) ulst.removeChild(ulst.firstChild); SellerManager.AddBlockedSellers(); } } }, false); var cell2 = row.childNodes[2]; cell2.style.width = "16px"; cell2.appendChild(removeLink); return table; }, //BuildCheckbox: Constructs a checkbox with the given title and id. BuildCheckbox : function(title, id){ var d = document.createElement("div"); d.setAttribute("class", "cbx unselectable"); var i = document.createElement("input"); i.id = id; i.type = "checkbox"; var l = document.createElement("label"); l.setAttribute('for', id); var s = document.createElement("span"); s.className = "cbx GM_cbx"; s.textContent = title; l.appendChild(s); d.appendChild(i); d.appendChild(l); return d; }, ImportFromFile : function(file){ var reader = new FileReader(); reader.onload = function(r){ var result = r.target.result; if(result){ var names = result.split("\r\n"); if(names.length > 0){ //add each name to the bad sellers list. for(var x = 0; x < names.length; x++){ var n = names[x].trim(); SellerManager.AddBlockedSeller(n, true); } } } }; reader.readAsText(file, "utf-8"); }, //BuildBlockedSellersBox: Builds the bad sellers control box. BuildBlockedSellersBox : function(pOverlay){ var self = this; var ul = document.createElement("ul"); ul.id = "GM_eBayBadSellers_UList" ul.className = "GM_eBayBadSeller_NameLinkList"; var d = document.createElement("div"); d.style.marginLeft = "8px"; d.style.display = "table"; d.style.marginBottom = "5px"; d.style.marginTop = "-8px"; var txtAddBlockedSeller = document.createElement("input"); txtAddBlockedSeller.type = "text"; txtAddBlockedSeller.id = "GM_eBayNewBadSeller_InputBox"; txtAddBlockedSeller.title = "Type or paste the name of the seller you want to block and press 'Enter'."; txtAddBlockedSeller.setAttribute("style", "width:100px;margin:0;") txtAddBlockedSeller.addEventListener('keyup', function(e){ var key = e.keyCode; if(key === 13){ var box = document.getElementById("GM_eBayNewBadSeller_InputBox"); var txt = box.value.trim(); box.value = ""; if(SellerManager.AddBlockedSeller(txt, true)){ //filter results for new seller name... var filterUser = ScriptProps.FilterResults; if(filterUser != undefined && filterUser){ EBayUsabilityEnhancer.ToggleFilterBlockedSellerResults(true); } } } }); var fileInput = document.createElement("input"); fileInput.type = "file"; fileInput.id = "GM_eBayNewBadSeller_fileInput"; fileInput.style.display = "none"; var btnImportSellers = document.createElement("input"); btnImportSellers.type = "button"; btnImportSellers.value = "I"; btnImportSellers.id = "GM_eBayNewBadSeller_btnImportBadSellers"; btnImportSellers.setAttribute("style", "height:26px;margin-left:-2px;"); btnImportSellers.title = "Import sellers from a text file."; btnImportSellers.onclick = function(){ fileInput.addEventListener("change", function(evt){ var files = evt.target.files; for(var i = 0; i < files.length; i++){ var f = files[i]; if(!f.type.match("text/plain")) continue; self.ImportFromFile(f); } }, false); fileInput.click(); }; var btnExportSellers = document.createElement("input"); btnExportSellers.type = "button"; btnExportSellers.value = "O"; btnExportSellers.id = "GM_eBayNewBadSeller_btnExportSellers"; btnExportSellers.setAttribute("style", "height:26px;margin-left:-2px;width:22px;"); btnExportSellers.title = "Export sellers to a text file."; btnExportSellers.onclick = function(){ var badSellers = ScriptProps.BlockedSellerList; var agg = ""; for(var i = 0; i < badSellers.length; i++) agg += badSellers[i] + "\r\n"; agg = agg.trim(); var dLink = document.createElement("a"); dLink.download = "EBayUsabilityEnhancer_BlockedSellersList.txt"; dLink.href = "data:text/plain," + encodeURI(agg); dLink.style.display = "none"; dLink.textContent = "download"; document.body.appendChild(dLink); dLink.click(); document.body.removeChild(dLink); }; var label = document.createElement("label"); label.textContent = "Add, Import or Export:" label.setAttribute('for', 'GM_eBayNewBadSeller_InputBox'); var table = document.createElement("table"); table.style.width = "100%"; var row = document.createElement("tr"); for(var i = 0; i < 2; i++) row.appendChild(document.createElement("td")); table.appendChild(row); var copyAllLink = document.createElement("span"); copyAllLink.textContent = "Copy All"; copyAllLink.className = "GM_eBayBadSellers_ActionLink"; copyAllLink.title = "Copy all blocked sellers to the clipboard."; copyAllLink.addEventListener('click', function(e){ //------------------------------------------ var blockedSellers = ScriptProps.BlockedSellerList; if(blockedSellers){ var sellerList = ""; for(var i = 0; i < blockedSellers.length; i++) sellerList += blockedSellers[i] + ","; sellerList = sellerList.substr(0, sellerList.lastIndexOf(",")); GM_setClipboard(sellerList); alert("All blocked sellers have been copied to the system clipboard."); } }); row.childNodes[0].appendChild(copyAllLink); var clearLink = document.createElement('span'); clearLink.textContent = "Remove All"; clearLink.className = "GM_eBayBadSellers_ActionLink"; clearLink.title = "Remove all sellers from the block list." clearLink.setAttribute("style", "float:right;margin-right:7px;"); clearLink.addEventListener('click', function(e){ var blockedSellers = ScriptProps.BlockedSellerList; if(blockedSellers){ var result = confirm("Are you sure you want to remove all sellers from your block list? This action cannot be undone."); if(result){ //----------------------------------- blockedSellers = []; ScriptProps.BlockedSellerList = blockedSellers; SellerManager.AddBlockedSellers(); } } }); row.childNodes[1].appendChild(clearLink); d.appendChild(label); d.appendChild(txtAddBlockedSeller); d.appendChild(fileInput); d.appendChild(btnImportSellers); d.appendChild(btnExportSellers); d.appendChild(table); pOverlay.appendChild(d); pOverlay.appendChild(ul); } }; var SellerManager = { //IsBlockedSeller: Returns whether or not the specified seller name is in the seller black list. IsBlockedSeller : function(sellerName, fuzzyMatch){ if(!sellerName || sellerName.length === 0) return true; var badSellers = ScriptProps.BlockedSellerList; if(fuzzyMatch && fuzzyMatch === true){ var len = badSellers.length, i = 0; for(i; i < len; i++){ var bs = badSellers[i].toLowerCase(); var pSellerName; if(sellerName.lastIndexOf("...") !== -1){ pSellerName = sellerName.substring(0, sellerName.lastIndexOf("...") - 1); } else pSellerName = sellerName; if(bs.indexOf(pSellerName) !== -1) return true; } } return badSellers.indexOf(sellerName) !== -1; }, FuzzyMatchedName : function(fuzzyName){ if(fuzzyName.lastIndexOf("...") === -1) return null; var badSellers = ScriptProps.BlockedSellerList, len = badSellers.length, n = 0, retval, tLen = SharedObjects.Arrays.TruncatedSellers.length; if(tLen > 0){ //check if we've got a match in the TruncatedSellers array. var t = 0; for(t; t < tLen; t++){ var pair = SharedObjects.Arrays.TruncatedSellers[t]; if(pair[0].toLowerCase() === fuzzyName.toLowerCase()) return pair[1]; } } for(n; n < len; n++){ var bs = badSellers[n].toLowerCase(); var pSellerName; if(fuzzyName.lastIndexOf("...") !== -1) pSellerName = fuzzyName.substring(0, fuzzyName.lastIndexOf("...")).toLowerCase(); else pSellerName = fuzzyName.toLowerCase(); if(bs.indexOf(pSellerName) !== -1){ retval = bs; break; } } return retval; }, //GetSellerById: Returns a SellerData object based on the supplied listingid parameter. GetSellerById : function(listingid){ var count = SharedObjects.Arrays.AllSellerData.length; for(var i = 0; i < count; i++){ var sellerData = SharedObjects.Arrays.AllSellerData[i]; var id = sellerData[1]; if(id === listingid) return sellerData[0]; } return null; }, //AddBlockedSeller: Creates and adds a bad seller based on the supplied seller name. AddBlockedSeller : function(sellerName, bailIfExists){ sellerName = sellerName.trim(); if(sellerName.length === 0) return false; var badSellers = ScriptProps.BlockedSellerList; if(badSellers.indexOf(sellerName) === -1){ try{ badSellers.push(sellerName); } catch(e){ alert("T: " + e); } ScriptProps.BlockedSellerList = badSellers; } else if(bailIfExists && bailIfExists === true) { return false; } var sellerLink = UIBuilder.BuildBlockedSellerNameLink(sellerName); var li = document.createElement("li"); if(sellerLink) li.appendChild(sellerLink); var uList = document.getElementById("GM_eBayBadSellers_UList"); if(uList){ var badSellers = ScriptProps.BlockedSellerList; badSellers.sort(SortFunctions.SortAlphaNum); var idx = badSellers.indexOf(sellerName); if(idx !== -1){ var liChild = uList.childNodes[idx]; uList.insertBefore(li, liChild); } else { uList.appendChild(li); } return true; } return false; }, //AddBlockedSellers: Adds the stored bad sellers to the page. AddBlockedSellers : function(){ var sellers = ScriptProps.BlockedSellerList; if(sellers == undefined) return; var uList = document.getElementById("GM_eBayBadSellers_UList"); if(uList){ while(uList.firstChild) { uList.removeChild(uList.firstChild);} } if(sellers){ sellers.sort(SortFunctions.SortAlphaNum); try{ ScriptProps.BlockedSellerList = sellers; } catch(e2){ //alert("err: " + e2) } } if(sellers.length > 0){ for(var i = 0; i < sellers.length; i++){ var seller = sellers[i]; this.AddBlockedSeller(seller); } } }, //GetListingsBySeller: Returns a collection of all listings that belong to the supplied sellerName. GetListingsBySeller : function(sellerName){ var count = SharedObjects.Arrays.AllSellerData.length; var listings = []; sellerName = sellerName.toLowerCase(); for(var i = 0; i < count; i++){ var sd = SharedObjects.Arrays.AllSellerData[i]; var id = sd[1]; var seller = sd[0].ID; if(seller.lastIndexOf("...") !== -1){ var badSellers = ScriptProps.BlockedSellerList; var len = badSellers.length, n = 0; for(n; n < len; n++){ var bs = badSellers[n].toLowerCase(); var pSellerName; if(seller.lastIndexOf("...") !== -1) pSellerName = seller.substring(0, seller.lastIndexOf("...")).toLowerCase(); else pSellerName = seller.toLowerCase(); if(bs.indexOf(pSellerName) !== -1){ seller = bs; break; } } } seller = seller.toLowerCase(); sellerName = sellerName.toLowerCase(); if(seller === sellerName){ var priceCount = SharedObjects.Arrays.OriginalPrices.length; for(var j = 0; j < priceCount; j++){ var pd = SharedObjects.Arrays.OriginalPrices[j]; var pdId = pd[0].attributes["listingid"].value; if(id === pdId){ listings.push(pd); } } } } return listings; }, GetSellerData : function(resultNode){ var sellerData = { ID: "", FeedbackScore: "", ReviewCount: "" }; var dynDiv = resultNode.querySelector("ul.lvdetails"); var listingId = resultNode.getAttribute("listingid"); var len = dynDiv.childNodes.length; var self = this; if(len > 0) { for(var m = 0; m < len; m++){ var n = dynDiv.childNodes[m]; var spns; try{ spns = n.querySelectorAll("span.selrat"); } catch (e){ continue; } if(spns){ var text = n.textContent.trim(); if(text.indexOf("Seller:") !== -1){ var idx = text.indexOf("Seller:"); var idx2 = text.indexOf("("); var idx3 = text.indexOf(")"); sellerData.ID = text.substring(idx + 8, idx2).trim(); var img = new Image(); img.setAttribute("style", "height:12px;width:12px;cursor:pointer;"); img.setAttribute("Seller-ID", sellerData.ID); try{ var revCount = spns[0].textContent.replace("(", "").replace(")", ""); while(revCount.indexOf(",") != -1) revCount = revCount.replace(",",""); sellerData.ReviewCount = parseInt(revCount); }catch(e){ //alert(e); } try{ var fbScore = parseFloat(spns[1].textContent.replace("%", "").trim()) sellerData.FeedbackScore = fbScore; var score = sellerData.FeedbackScore, color = ""; if(score >= 99.2){ //should be ok to buy from this guy. color = "green"; } else if(score >= 98 && score <= 99.1) { //better check the neg's! color = "#E8823A"; } else { //bad seller! color = "red"; } spns[1].setAttribute("style", "color:" + color + ";"); var p = spns[0]; p.parentNode.appendChild(img); } catch(e){ img.setAttribute("style", "margin-left:5px;height:12px;width:12px;cursor:pointer;"); n.appendChild(img); } try{ if(sellerData.ID.lastIndexOf("...") !== -1){ Utilities.GetFullUserName(listingId, function(lstId, resultText){ var fullUserName = Utilities.ParseNameFromTextChunk(resultText); if(fullUserName){ //add a mapping for the truncated name and the full name. SharedObjects.Arrays.TruncatedSellers.push([sellerData.ID, fullUserName]); img.onload = function(){ this.title = "Add seller '" + fullUserName + "' to the block list."; var seller = this.getAttribute("Seller-ID"); img.addEventListener("click", function(){ self.ConfirmBlockSeller(fullUserName); }, false); }; img.src = SharedObjects.Constants.CloseButtonIcon; self.SetupFeedbackLink(fullUserName, dynDiv); } }); } else { img.onload = function(){ var seller = this.getAttribute("Seller-ID"); this.title = "Add seller '" + seller + "' to the block list."; img.addEventListener("click", function(){ self.ConfirmBlockSeller(seller); }, false); }; img.src = SharedObjects.Constants.CloseButtonIcon; this.SetupFeedbackLink(sellerData.ID, dynDiv); } }catch(e){ alert(e); } } } } } return sellerData; }, ConfirmBlockSeller : function(sellerName){ if(!sellerName || sellerName.length === 0) return; if(SellerManager.IsBlockedSeller(sellerName)){ alert("Seller '" + sellerName + "' is already in your block list."); return; } var msg = "Are you sure you want to block the seller '" + sellerName + "'?"; if(confirm(msg)) { if(SellerManager.AddBlockedSeller(sellerName, true)) EBayUsabilityEnhancer.ToggleFilterBlockedSellerResults(true); } }, SetupFeedbackLink : function(sellerName, parentNode){ var fbLink = document.createElement("a"); fbLink.href = SharedObjects.Constants.NegativeFeedbackLink.replace("[SELLERNAME]", sellerName); fbLink.textContent = "Show Negative Feedback"; fbLink.title = "Opens the seller's negative feedback ratings page in a new tab."; fbLink.setAttribute('target', '_blank'); var li = document.createElement("li"); li.appendChild(fbLink); parentNode.appendChild(li); }, }; var Utilities = { //SetupProperties: Creates property get/set functions. SetupProperties : function(){ Object.defineProperty(ScriptProps, "ShowTopPager",{ get: function(){ return GM_getValue(SharedObjects.Constants.ShowTopPager); }, set: function(value){GM_setValue(SharedObjects.Constants.ShowTopPager, value); } }); Object.defineProperty(ScriptProps, "RankByPrice", { get: function() { return GM_getValue(SharedObjects.Constants.RankByPrice); }, set: function(value){ GM_setValue(SharedObjects.Constants.RankByPrice, value); } }); Object.defineProperty(ScriptProps, "FixLinks", { get: function() { return GM_getValue(SharedObjects.Constants.FixLinks); }, set: function(value) { GM_setValue(SharedObjects.Constants.FixLinks, value); } }); Object.defineProperty(ScriptProps, "FilterResults", { get: function(){ return GM_getValue(SharedObjects.Constants.FilterResults); }, set: function(value){ GM_setValue(SharedObjects.Constants.FilterResults, value); } }); Object.defineProperty(ScriptProps, 'UsePlaceholders', { get: function(){ return GM_getValue(SharedObjects.Constants.UsePlaceholders); }, set: function(value){ GM_setValue(SharedObjects.Constants.UsePlaceholders, value); } }); Object.defineProperty(ScriptProps, "BlockedSellerList", { get: function() { var blockList = GM_getValue(SharedObjects.Constants.BlockedSellerList); return blockList != null ? blockList.split(' ') : []; }, set: function(value) { var len = value.length, agg = ""; for(var i = 0; i < len; i++){ agg += value[i] + " "; } agg = agg.trim(); try{ GM_setValue(SharedObjects.Constants.BlockedSellerList, agg); } catch(e){ //alert("Err:\r\n" + e); } } }); }, //GetPageContent: Retrieves the content of the page at the supplied Url. GetPageContent : function(url, listingid, callback){ if(!url) return; GM_xmlhttpRequest({ method: "GET", url: url, onload: function(r){ var result = r.responseText; callback.call(this, listingid, result); } }); }, GetFullUserName : function(listingId, callback){ if(!listingId || listingId.length === 0) return null; var url = "http://www.ebay.com/itm/" + listingId; this.GetPageContent(url, listingId, callback /*function(l, r) { }*/); }, //GetResultItem: Returns a result item, from the 'SharedObjects.Arrays.OriginalPrices' array, that matches the supplied 'itemId' parameter value. GetResultItem : function(itemId){ if(!itemId) return null; var len = SharedObjects.Arrays.OriginalPrices.length; for(var i = 0; i < len; i++){ var result = SharedObjects.Arrays.OriginalPrices[i][0]; var id = result.attributes["listingid"].value; if(id === itemId) return result; } return null; }, //GetItemPrices: Gets an array of items and their prices. GetItemPrices : function(){ var results = document.getElementsByClassName("sresult"); if(results.length > 0 && SharedObjects.Arrays.OriginalPrices.length == 0){ var i = 0, pText, nText, result; for(i; i < results.length; i++){ try{ result = results[i]; var sd = SellerManager.GetSellerData(result); SharedObjects.Arrays.AllSellerData.push([sd, result.attributes["listingid"].value]); var prc = result.querySelector("ul.lvprices li.lvprice.prc span"); if(prc){ pText = prc.innerHTML; //the span may contain child elements. //in such case, we only want the text that preceeds any elements. if(pText.indexOf("<") !== -1) pText = pText.substring(0, pText.indexOf("<")); var price = pText.trim(); if(price.indexOf(' ') != -1) price = price.split(' ')[1].trim(); var n = price[0]; if(n){ if(!/\d/.test(n)) price = price.substring(1); nText = result; while(price.indexOf(',') > -1) price = price.replace(',',''); if(price){ SharedObjects.Arrays.OriginalPrices.push([result, price]); } } } }catch(e){ //alert(result.outerHTML); //alert(e + "\r\niteration: " + i + "\r\n" + nText); } } } }, ParseNameFromTextChunk : function(textChunk){ if(!textChunk || textChunk.length === 0) return null; var ridx = textChunk.indexOf("RightSummaryPanel"); var lidx = textChunk.indexOf("LeftSummaryPanel"); for(var s = ridx; s > 0; s--){ var chr = textChunk[s]; if(chr === "<"){ ridx = s; break; } } for(var s = lidx; s > 0; s--){ var chr = textChunk[s]; if(chr === "<"){ lidx = s; break; } } var chunk = textChunk.substring(ridx, lidx); var container = document.createElement("div"); container.style.visibility = "collapse"; container.innerHTML = chunk; document.body.appendChild(container); var cSpan = container.querySelector("div a span.mbg-nw"); return cSpan.textContent.trim(); }, }; var SortFunctions = { reA : /[^a-zA-Z]/g, reN : /[^0-9]/g, SortAlphaNum : function(a,b) { var aA = a.replace(this.reA, ""); var bA = b.replace(this.reA, ""); if(aA === bA) { var aN = parseInt(a.replace(this.reN, ""), 10); var bN = parseInt(b.replace(this.reN, ""), 10); return aN === bN ? 0 : aN > bN ? 1 : -1; } else { return aA > bA ? 1 : -1; } }, SortLowToHigh : function(a,b){ var n1 = parseFloat(a[1]); var n2 = parseFloat(b[1]); if(n1 < n2) return -1; if(n1 > n2) return 1; return 0; } }; String.prototype.splice = function( idx, rem, s ) { return (this.slice(0,idx) + s + this.slice(idx + Math.abs(rem))); }; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //Get the ball rolling... EBayUsabilityEnhancer.Initialize(); })()