// ==UserScript== // @name Pinterest Plus // @namespace https://greasyfork.org/users/102866 // @description Show full size + working middle click to open new tab + open original image. // @include https://*.pinterest.*/* // @require https://code.jquery.com/jquery-3.6.0.min.js // @author TiLied // @version 0.6.00 // @grant GM_openInTab // @grant GM_listValues // @grant GM_getValue // @grant GM_setValue // @grant GM_deleteValue // @require https://greasemonkey.github.io/gm4-polyfill/gm4-polyfill.js // @grant GM.openInTab // @grant GM.listValues // @grant GM.getValue // @grant GM.setValue // @grant GM.deleteValue // @downloadURL none // ==/UserScript== class PinterestPlus { constructor() { console.log("Pinterest Plus v" + GM.info.script.version + " initialization"); this.urls = [""]; this._FirstTime(); this._SetCSS(); this._HidePopup(); } _SetCSS() { $("head").append($("")); $("head").append($("").text("button.ppTrue \ { \ border:2px solid black!important; \ } \ ")); $("head").append($("").text("#myBtn \ { \ display: inherit;\ align-items: center;\ box-sizing: border-box;\ color:#fff;\ font-size: 16px;\ font-weight: 700;\ letter-spacing: -.4px;\ margin-top: -4px;\ border-style: solid;\ border-width: 0px;\ background-color: #e60023;\ border-radius: 24px;\ padding: 10px 14px;\ will-change: transform;\ margin-left: 8px;\ } \ ")); $("head").append($("").text("#myBtn:hover \ { \ background-color: #ad081b;\ } \ ")); $("head").append($("").text("#pp_divFullSize \ { \ z-index: 500;!important; \ justify-content: center;\ display: inherit; \ } \ ")); $("head").append($("")); } //Hide popup after scrolling _HidePopup() { setTimeout(function () { let button = $(" button[aria-label='close']"); if (button.length >= 1) $(button).click(); let popup = $(" div[data-test-id='giftWrap']:parent"); console.log(popup); console.log(button); $(popup).attr("style", "display:none;"); }, 1500); } async _FirstTime() { if (this.HasValueGM("ppFullSize", false)) { this.btnOn = await GM.getValue("ppFullSize"); } //Console log prefs with value console.log("*prefs:"); console.log("*-----*"); let vals = await GM.listValues(); //Find out that var in for block is not local... Seriously js? for (let i = 0; i < vals.length; i++) { console.log("*" + vals[i] + ":" + await GM.getValue(vals[i])); } console.log("*-----*"); } Main() { if (!document.URL.match("/pin/")) return; this.urls = [""]; let buttonDiv = document.createElement("div"); let buttonButton = document.createElement("button"); let buttonText = document.createTextNode("Full Size"); let parentDiv = document.querySelector("div[data-test-id='closeupActionBar']>div>div, div[data-test-id='UnauthBestPinCardBodyContainer']>div>div>div, div.UnauthStoryPinCloseupBody__container>div>div"); if (typeof parentDiv === "undefined" || parentDiv == null) { console.error("parentDiv:", parentDiv); return; } buttonButton.appendChild(buttonText); buttonDiv.appendChild(buttonButton); buttonButton.id = "myBtn"; parentDiv.appendChild(buttonDiv); // let queryCloseup = $("div[data-test-id='pin']:first, div.Closeup"); if (typeof queryCloseup === "undefined" || queryCloseup == null || queryCloseup.length === 0) { console.error("div[data-test-id='pin']:first, div.Closeup:", queryCloseup); return; } let div = document.querySelector("#pp_divFullSize"); if (div == null) { div = document.createElement("div"); div.id = "pp_divFullSize"; queryCloseup.prepend(div); } div.style.display = "none"; if (this.btnOn) { $(buttonButton).addClass("ppTrue"); } // this.Events(buttonButton); this.Core(buttonButton); this.UrlHandler(); } Core(btn) { let time = Date.now(); let url = new URL(document.URL); let regU = document.URL.match(/\/(\d+)\/|pin\/([\w].+\w+)\//); let id = regU[1]; if (typeof id === "undefined") id = regU[2]; if (typeof id === "undefined") { //TODO! not through request! } let urlRec = "https://" + url.host + "/resource/PinResource/get/?source_url=/pin/" + id + "/&data={%22options%22:{%22field_set_key%22:%22detailed%22,%22id%22:%22" + id + "%22},%22context%22:{}}&_=" + time; $.get(urlRec, async function (r) { if (r["resource_response"]["status"] === "success") { console.log(r["resource_response"]["data"]); let pin = r["resource_response"]["data"]; if (pin["videos"] != null) { let k0 = Object.keys(pin["videos"]["video_list"])[0]; pp.urls[0] = pin["videos"]["video_list"][k0]["url"]; $(btn).attr("title", "" + pin["videos"]["video_list"][k0]["width"] + "px x " + pin["videos"]["video_list"][k0]["height"] + "px"); return; } if (pin["story_pin_data"] != null) { let sp = pin["story_pin_data"]["pages"]; for (let i in sp) { if (pp.urls[0] === "") { pp.urls[0] = sp[i]["image"]["images"]["originals"]["url"]; continue; } pp.urls.push(sp[i]["image"]["images"]["originals"]["url"]); } return; } pp.urls[0] = pin["images"]["orig"]["url"]; $(btn).attr("title", "" + pin["images"]["orig"]["width"] + "px x " + pin["images"]["orig"]["height"] + "px"); if (pp.btnOn) pp.Show(pp.urls[0]); return; } else { console.error(r); } }, "json") .fail(function (e) { console.error(e); }); } Events(btn) { $(btn).on('mousedown', async function (e) { if ((e.which === 3)) { if (pp.btnOn) { GM.setValue("ppFullSize", false); $(btn).removeClass("ppTrue"); pp.btnOn = false; } else { GM.setValue("ppFullSize", true); $(btn).addClass("ppTrue"); pp.btnOn = true; } //console.log("right"); } if ((e.which === 1)) { pp.Show(pp.urls[0]); $("#pp_divFullSize").toggle(500); //console.log("left"); } if ((e.which === 2)) { for (let i in pp.urls) { GM.openInTab(pp.urls[i]); } //console.log("middle"); } e.preventDefault(); }); } Show(url) { let img = document.querySelector("#pp_img"); let div = document.querySelector("#pp_divFullSize"); if (img != null) { img.setAttribute("src", url); } else { img = document.createElement("img"); img.id = "pp_img"; img.setAttribute("src", url); div.prepend(img); } } //Handler for url UrlHandler() { this.oldHash = window.location.pathname; this.Check; var that = this; var detect = function () { if (that.oldHash !== window.location.pathname) { that.oldHash = window.location.pathname; setTimeout(function () { pp.Main(); }, 1500); } }; this.Check = setInterval(function () { detect(); }, 250); } //Start //async Methods/Functions GM_VALUE async HasValueGM(nameVal, optValue) { var vals = await GM.listValues(); if (vals.length === 0) { if (optValue !== undefined) { GM.setValue(nameVal, optValue); return true; } else { return false; } } if (typeof nameVal !== "string") { return alert("name of value: '" + nameVal + "' are not string"); } for (let i = 0; i < vals.length; i++) { if (vals[i] === nameVal) { return true; } } if (optValue !== undefined) { GM.setValue(nameVal, optValue); return true; } else { return false; } } async DeleteValuesGM(nameVal) { var vals = await GM.listValues(); if (vals.length === 0 || typeof nameVal !== "string") { return; } switch (nameVal) { case "all": for (let i = 0; i < vals.length; i++) { if (vals[i] !== "adm") { GM.deleteValue(vals[i]); } } break; case "old": for (let i = 0; i < vals.length; i++) { if (vals[i] === "debug" || vals[i] === "debugA") { GM.deleteValue(vals[i]); } } break; default: for (let i = 0; i < vals.length; i++) { if (vals[i] === nameVal) { GM.deleteValue(nameVal); } } break; } } async UpdateGM(what) { var gmVal; switch (what) { case "options": gmVal = JSON.stringify(options.values); GM.setValue("pp_options", gmVal); break; default: alert("class:Options.UpdateGM(" + what + "). default switch"); break; } } //async Methods/Functions GM_VALUE //End } let pp = new PinterestPlus(); $(window).on("load", function () { setTimeout(() => { pp.Main(); console.log(pp); }, 1000); });