// ==UserScript== // @name Pinterest Palooza // @description Visit a Pin's source web site by clicking the Pin's thumbnail image. Easy peasy! // @author Corey Meredith // @version 1.1.4 // @include http://*pinterest.com/* // @include https://*pinterest.com/* // @history 1.1.4 leveraging local navigation link for faster source article access // @history 1.1.3 fixed script ... Pinterest changed a class name // @history 1.1.2 only writing to new window for webkit before setting location // @history 1.1.1 fixed pin selector // @history 1.1.0 made entire pin image clickable // @history 1.0.3 replaced loading text with throbber // @history 1.0.2 moved code into IIFE // @history 1.0.1 changed button from "Visit Source" to "Visit Site" and matched icon of same button on pin details page // @history 1.0.0 initial release // @namespace https://greasyfork.org/users/2306 // @downloadURL https://update.greasyfork.icu/scripts/3075/Pinterest%20Palooza.user.js // @updateURL https://update.greasyfork.icu/scripts/3075/Pinterest%20Palooza.meta.js // ==/UserScript== (function () { function addVisitButton(e) { e.preventDefault(); e.cancelBubble = true; var pin = this, buttonWrapperN = pin.getElementsByClassName('leftSideButtonsWrapper'), pinLinkN = pin.querySelectorAll('A.pinImageWrapper'), navLinkN = pin.querySelectorAll('A.NavigateButton'); if (!buttonWrapperN.length || !pinLinkN.length) return; var buttonWrapper = buttonWrapperN[0], pinLink = pinLinkN[0]; if (buttonWrapper.getElementsByClassName('sourceLaunchButton').length) // already wired up this pin return; var href = window.location.origin + pinLink.getAttribute('href'), btn = document.createElement('a'); btn.style.cssText = 'display: inline-block; margin-left: 4px;'; btn.className = 'rounded Button likeSmall btn hasText sourceLaunchButton'; btn.innerHTML = '...'; btn.setAttribute('title', 'View Pin Details Page'); btn.href = pinLink.getAttribute('href'); buttonWrapper.appendChild(btn); pinLink.setAttribute('data-original-href', pinLink.getAttribute('href')); pinLink.setAttribute('href', '#view'); if (navLinkN.length) { var navLink = navLinkN[0], navHref = navLink.getAttribute('href'); if (navHref && navHref.length) pinLink.setAttribute('data-href', navHref); } pinLink.addEventListener('click', function (e) { e.preventDefault(); var pinLink = this, dataHref = pinLink.getAttribute('data-href'); if (dataHref && dataHref.length) { if (dataHref == 'nolink') window.location = window.location.origin + pinLink.getAttribute('data-original-href'); else window.open(dataHref); } else { var xhr = new XMLHttpRequest(), w = window.open(); if (typeof navigator.webkitPersistentStorage === 'object' || /WebKit/.test(navigator.userAgent)) w.document.write('Loading source page...'); xhr.open('GET', href); xhr.onload = function () { var container = document.implementation.createHTMLDocument().documentElement; container.innerHTML = this.responseText; var sourceLinks = container.querySelectorAll('.richPinNameLink, .paddedPinLink'); if (sourceLinks.length) { var sourceHref = sourceLinks[0].getAttribute('href'); if (sourceHref && sourceHref.length) { pinLink.setAttribute('data-href', sourceHref); w.location = sourceHref; } else { pinLink.setAttribute('title', 'View Pin Details Page'); pinLink.setAttribute('data-href', 'nolink'); pinLink.className += ' no-link'; } } } xhr.send(); } return false; }, false); } function liveWrapper(selector, method) { return function(e) { var target = e.target, ancestors = getAncestors(target), i = 0, l = ancestors.length, elem; while (i < l) { elem = ancestors[i]; if (matches(elem, selector)) { method.call(elem, e); break; } i += 1; } }; } function getAncestors(elm) { var bucket = []; do { bucket[bucket.length] = elm; elm = elm.parentNode; } while (elm); return bucket; } function matches(elm, selectors) { var possibles = document.querySelectorAll(selectors), i = possibles.length; while (i) { i -= 1; if (elm === possibles[i]) return true; } } function addStyle(style) { var head = document.getElementsByTagName('HEAD')[0], elementStyle = head.appendChild(document.createElement('style')); elementStyle.innerHTML = style; } addStyle('.Pin.summary .pinImageWrapper { cursor: pointer !important; } .Pin.summary .pinImageWrapper.no-link { cursor: zoom-in !important; }'); document.addEventListener('mouseover', liveWrapper('.Pin', addVisitButton), false); })();