您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Show thumbnails for all listings in TradeMe
/* TradeMe PhotoView //Shows thumbnails for all listings in TradeMe Version 0.37.14 (07 August 2018) Author: tbird81 / JimBob Baggins Licence: Will be free to edit as you choose, but i'd like to sort it out a bit first Gui: {333eb056-63c4-4e4b-9589-85a0d46d22b0} // Future improvements For me to think about: - DieNicelies for GM functions. - Convert to normal xmlhttprequest - More resilience Fix the pop ups since TradeMe's changes. // Risks Risks of using this software: - Your incoming traffic may slightly increase because more pictures are loaded. - This software may slow down the loading of TradeMe listings pages. - You might forget that other people don't have this script, so may under-promote your auction. - TradeMe may change its site without notice, rendering this script useless. Changes: - v0.37.14 Let's put the flags back - v0.37.11 TM have switched to a peculiar list layout - v0.37 Switched to https - v0.36.1 Grr... - v0.36 Bug fix... - v0.35 Pop-ups in gallery view of clothing/home & living fixed. - v0.32 New asynchronous clothing not showing pop-ups. Had to finally use jquery... - v0.30 Obvious speed fix made. Property slowness should be eliminated. - v0.29 Big changes people! - v0.28.3 Chrome strikes again... - v0.28.2 Double D'oh! - v0.28.1 D'oh! - v0.28 Property and Flatmates were causing issues. Should be good now. - v0.27 Fixed my shennanigans. - v0.26 Fixed TradeMe shennanigans. - v0.25 Fixed clothing issue. - v0.23 Open homes bug fixed. - v0.22 Big Zooms! - v0.21 TM Server change... - v0.20 Chrome's GM_xmlhttpRequest issue bypassed (will probably be resolved by them in due course)... - v0.15 Stuffed up the href link on the image brought forward. - v0.08 Sorry about the vary slow update!!! Should work with new trademe. I'm not sure what I was doing wrong. - v0.07 Fixed snippets. - v0.06 Updated image folder. Prior versions will not work. - v0.05 Displays an enlarged image when the mouse hovers over a thumbnail - v0.04 Now adds snippets of information about items. - v0.04 Uses maxHeight and maxWidth styles to confine picture to 85x64px - v0.03 Remove an unneeded loop! - v0.02 Made the User-agent the same as the browser. - v0.02 Exits search for images once first thumbnail has been found . - v0.02 Exits search for images once matching icon is found. - v0.02 Changed some variable names to make more sense. */ // ==UserScript== // @name TradeMe PhotoView // @namespace http://www.girlza.com/ // @include https://www.trademe.co.nz/* // @description Show thumbnails for all listings in TradeMe // @grant metadata // @version 0.37.14 // ==/UserScript== //This allows you to turn off unnecessary features var showThumbs = true; var showSnippets = true; var showZoom = true; function addCustomSearchResult (jNode) { //Open Homes were bugging out var z = document.getElementsByClassName('openhomes') for (var i = 0; i < z.length; i++) { if (z[i].tagName == "LI") { z[i].style.width = '170px'; z[i].style.textAlign = 'center'; z[i].childNodes[1].style.width = '170px'; z[i].childNodes[1].style.textAlign = 'center'; } } //The prototype for the callback function that allows me to remember what link I was loading! Function.prototype.bind = function(thisObject) { var method = this; var oldargs = [].slice.call(arguments, 1); return function() { var newargs = [].slice.call(arguments); return method.apply(thisObject, oldargs.concat(newargs)); }; } var allImgs, thisImg; var globalTimer; //First we load all the images of that little camera allImgs = document.evaluate( "//img | //div[@class='image'] | //div[@class='image ']", //the name of the little camera icon document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null); //Then we go through them one-by-one for (var i = 0; i < allImgs.snapshotLength; i++) { var n = allImgs.snapshotItem(i).src; var bgIm = false if(typeof n === 'undefined'){n = allImgs.snapshotItem(i).style.backgroundImage; n = n.substring(4,n.length-1).replace(/["']/g, ""); //console.log(n) //n = n.substring(5,n.length-2); bgIm = true; } if (n.indexOf('hasPhoto_160x120.png') > -1) { thisImg = allImgs.snapshotItem(i); //the photos exist but no thumbnail thisImg.setAttribute('thumbnailnumber', i); //We need to request the page that the icon links to, to get it's thumbnail if (thisImg.parentNode.href) { var oReq = new XMLHttpRequest(); oReq.open("GET", thisImg.parentNode.href); oReq.addEventListener("load", cbReplaceWithPhoto.bind({ specificIcon: thisImg.parentNode }), false); oReq.send(); } } else if (n.indexOf('/lv2/') > -1 || n.indexOf('/gv/') > -1 || n.indexOf('/med/') > -1 || n.indexOf('/tq/') > -1 || bgIm){ thisImg = allImgs.snapshotItem(i); thisImg.setAttribute('thumbnailnumber', i); addHover(thisImg, bgIm) } } //Curious design decision from TM in getting rid of the flag, so we've added the flags back... this is just for me really, so if you don't like it then tough! :-) allImgs = document.evaluate("//div[@class='reserve-text']/../..",document,null,XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,null); for (var i = 0; i < allImgs.snapshotLength; i++) { if (allImgs.snapshotItem(i).querySelector(".icon").innerText.trim() == "Reserve Met"){ //reserve met var current = allImgs.snapshotItem(i).querySelector(".listingBidPrice").innerText; allImgs.snapshotItem(i).querySelector(".listingBidPrice").innerHTML = current + "<img src='/images/NewSearchCards/LVIcons/reserveMet.gif' style='padding-left:3px;' alt='' height='14'>" } else { //reserve not met var current = allImgs.snapshotItem(i).querySelector(".listingBidPrice").innerText; allImgs.snapshotItem(i).querySelector(".listingBidPrice").innerHTML = current + "<img src='/images/NewSearchCards/LVIcons/noReserve.gif' style='padding-left:3px;' alt='' height='14'>" } }; /* //the original buy now colours, switched off for the time being allImgs = document.evaluate("//div[@class='listingBuyNowPrice'] | //div[@class='listingBuyNowText']",document,null,XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,null); for (var i = 0; i < allImgs.snapshotLength; i++) { allImgs.snapshotItem(i).style.color = "#cc6600"; };*/ //Set the style up in the <HEAD> tag var head = document.getElementsByTagName('head')[0]; style = document.createElement('style'); style.type = 'text/css'; style.innerHTML = '.enlargement {visibility:hidden;position:absolute;z-index:100;top:20px;}\r\n.enlargement img {}'; head.appendChild(style); var dimsz = document.getElementById("container").offsetLeft + document.getElementById("mainContent").offsetLeft style = document.createElement('style'); style.type = 'text/css'; style.innerHTML = ".imgBig {top:50px;position:absolute;max-width:100%;min-height:100%;margin-left:20px;left:0px;border:1px solid #000;box-shadow:0 0 17px #000;-moz-box-shadow:0 0 17px #000;-webkit-box-shadow:0 0 17px #000;}"; head.appendChild(style); String.prototype.trim = function() { return this.replace(/^\s+|\s+$/g, ""); } function hasClass(element, cls) { return (' ' + element.className + ' ').indexOf(' ' + cls + ' ') > -1; } function addHover(imgUse, bgIm){ //This handles the tooltip-like zoom function var zoomDiv = document.createElement('div'); zoomDiv.setAttribute('id', "enlargement" + imgUse.getAttribute('thumbnailnumber')); zoomDiv.setAttribute('class', 'enlargement'); document.body.appendChild(zoomDiv); //When mouse goes over it starts a timer. imgUse.addEventListener( 'mouseover', function(event) { var x = event.pageX; var y = event.pageY var divId = 'enlargement' + this.getAttribute('thumbnailnumber'); obj = document.getElementById(divId); var n = this.src; if (bgIm){ n = this.style.backgroundImage; n = n.substring(4,n.length-1).replace(/["']/g, "") var x1 = n.indexOf('photoserver') var x2 = n.indexOf('/',x1+13) n = n.substring(0,x1+12)+"full"+n.substring(x2,n.length) } obj.innerHTML = "<img src='" + n.replace('/gv/', '/full/') + "'>"; obj.innerHTML = obj.innerHTML.replace('/lv2/', '/full/') obj.innerHTML = obj.innerHTML.replace('/med/', '/full/') obj.style.width = (dimsz - 20) + 'px' obj.style.top = (window.pageYOffset + 100) + 'px'; document.getElementById(divId).childNodes[0].className="imgBig" globalTimer = window.setTimeout( //after 700msec the pic will become visible function() { showPopupDiv(x, y, divId); }, 200); }, true); //Hide image and reset timer once mouse moves out imgUse.addEventListener('mouseout', function(event) { window.clearTimeout(globalTimer); document.getElementById('enlargement' + this.getAttribute('thumbnailnumber')).style.visibility = 'hidden'; }, true); } //This is the callback function that gets run when the itemDetailsPage has loaded //It grabs the filename of the thumbnail, and replaces the icon with it. function cbReplaceWithPhoto(rD) { //Borrowed some code from Gallery+. Thanks :-) var imgtag = /<img.*mainImage.*\/>/g.exec(rD.target.responseText); var imgsrc = /.*src="([^"]*)"/.exec(imgtag) if (imgsrc !== null) { replacementImg = document.createElement("img"); //replace it with this replacementImg.src = imgsrc[1].replace("\/tq\/", "\/lv2\/") var useThis = 0 var foundIt = false while (foundIt == false) { if (useThis < this.specificIcon.childNodes.length) { if (this.specificIcon.childNodes[useThis].nodeName.toUpperCase() == "IMG") { if (this.specificIcon.childNodes[useThis].hasAttribute("thumbnailnumber")) { foundIt = true } } } if (foundIt == false) { useThis = useThis + 1 } } var iconH = Number(this.specificIcon.childNodes[useThis].style.height.replace(/[^\d\.\-]/g, '')) + "px" var iconW = Number(this.specificIcon.childNodes[useThis].style.width.replace(/[^\d\.\-]/g, '')) + "px" if (iconH == "0px") {iconH = "120px"} if (iconW == "0px") {iconW = "160px"} replacementImg.style.maxHeight = iconH replacementImg.style.maxWidth = iconW replacementImg.setAttribute('thumbnailnumber', this.specificIcon.childNodes[useThis].getAttribute('thumbnailnumber')); if (this.specificIcon.childNodes[useThis].id.indexOf("GalleryView")>-1) { replacementImg = this.specificIcon.childNodes[useThis] } //replace the icon with the thumbnail this.specificIcon.replaceChild(replacementImg, this.specificIcon.childNodes[useThis]); addHover(replacementImg) } } /* Function to popup the hidden div */ function showPopupDiv(triggerX, triggerY, divId) { obj = document.getElementById(divId); obj.style.visibility = "visible"; //make it visible } } addCustomSearchResult(); waitForKeyElements (".supergrid-overlord, #ListViewList", addCustomSearchResult); function waitForKeyElements ( selectorTxt, /* Required: The jQuery selector string that specifies the desired element(s). */ actionFunction, /* Required: The code to run when elements are found. It is passed a jNode to the matched element. */ bWaitOnce, /* Optional: If false, will continue to scan for new elements even after the first match is found. */ iframeSelector /* Optional: If set, identifies the iframe to search. */ ) { var targetNodes, btargetsFound; if (typeof iframeSelector == "undefined") targetNodes = $(selectorTxt); else targetNodes = $(iframeSelector).contents () .find (selectorTxt); if (targetNodes && targetNodes.length > 0) { btargetsFound = true; /*--- Found target node(s). Go through each and act if they are new. */ targetNodes.each ( function () { var jThis = $(this); var alreadyFound = jThis.data ('alreadyFound') || false; if (!alreadyFound) { //--- Call the payload function. var cancelFound = actionFunction (jThis); if (cancelFound) btargetsFound = false; else jThis.data ('alreadyFound', true); } } ); } else { btargetsFound = false; } //--- Get the timer-control variable for this selector. var controlObj = waitForKeyElements.controlObj || {}; var controlKey = selectorTxt.replace (/[^\w]/g, "_"); var timeControl = controlObj [controlKey]; //--- Now set or clear the timer as appropriate. if (btargetsFound && bWaitOnce && timeControl) { //--- The only condition where we need to clear the timer. clearInterval (timeControl); delete controlObj [controlKey] } else { //--- Set a timer, if needed. if ( ! timeControl) { timeControl = setInterval ( function () { waitForKeyElements ( selectorTxt, actionFunction, bWaitOnce, iframeSelector ); }, 300 ); controlObj [controlKey] = timeControl; } } waitForKeyElements.controlObj = controlObj; }