// ==UserScript== // @name Query Technorati // @namespace http://www.dopiaza.org/flickr/greasemonkey/ // @description Query Technorati from Flickr photo pages // @include http://www.flickr.com/photos/* // @include http://flickr.com/photos/* // ==/UserScript== // *** Edit this *** // You need to put your Technorati API key here var technoratiAPIKey = 'YOUR-TECHNORATI-API-KEY'; var photoPagePattern = /^(.*\/photos\/[\w@-]+\/\d+\/)/; // Check that we really are on a photo page function checkPhotoPage() { var isPhotoPage = false; if (photoPagePattern.exec(window.location.href)) { isPhotoPage = true; } return isPhotoPage; } // Normalize the URL, removing any unneeded elements function normalizeUrl() { var url = window.location.href; var result = photoPagePattern.exec(url); if (result != null) { url = result[1]; } return url; } // Add the "View blogs" link after the privacy element function addLink(privacy) { var parent = privacy.parentNode; var blogContainer = document.createElement('p'); var blogLink = document.createElement('a'); blogLink.setAttribute('href', '#'); blogLink.setAttribute('class', 'Plain'); var text = document.createTextNode('View blogs'); blogLink.appendChild(text); styleElement(blogContainer); blogContainer.appendChild(blogLink); parent.insertBefore(blogContainer, privacy.nextSibling); blogLink.addEventListener("click", function(evt) { var waiting = document.createElement('span'); waiting.appendChild(document.createTextNode('Waiting for Technorati...')); blogContainer.replaceChild(waiting, blogLink); showBlogs(blogContainer, waiting); evt.preventDefault(); }, true); } // Retrieve the list of blogs and display them function showBlogs(blogContainer, message) { var url = 'http://api.technorati.com/cosmos'; var params = 'key=' + technoratiAPIKey + '&url=' + normalizeUrl() + '&limit=100'; GM_xmlhttpRequest( { method: "GET", url: url + "?" + params, headers: { "User-Agent": "Flickr-Technorati-Query" }, onload: function(response) { blogContainer.removeChild(message); var parser = new unsafeWindow.DOMParser(); var dom = parser.parseFromString(response.responseText, "application/xml"); var errors = dom.getElementsByTagName('error'); if (errors.length > 0) { var p = document.createElement('p'); p.appendChild(document.createTextNode('Error: ' + errors[0].firstChild.nodeValue)); styleElement(p); blogContainer.appendChild(p); } else { var items = dom.getElementsByTagName('item'); var filteredItems = filterItems(items); if (filteredItems.length > 0) { var list = document.createElement('ul'); for (var i = 0; i < filteredItems.length; i++) { addBlog(list, filteredItems[i]); } blogContainer.appendChild(list); } else { var p = document.createElement('p'); p.appendChild(document.createTextNode('No blogs found')); styleElement(p); blogContainer.appendChild(p); } } addTechnoratiCredit(blogContainer); }, onerror: function(response) { var p = document.createElement('p'); p.appendChild(document.createTextNode('There was an error retrieving blog information')); styleElement(p); blogContainer.appendChild(p); } }); } // Filter out the items we want to display function filterItems(items) { var filteredItems = new Array(); for (var i = 0; i < items.length; i++) { var processed = false; var itemName = items[i].getElementsByTagName('name')[0].firstChild.nodeValue; // Do we have this blog name in the list yet? for (var j = 0; j < filteredItems.length; j++) { var filteredItemName = filteredItems[j].getElementsByTagName('name')[0].firstChild.nodeValue; if (itemName == filteredItemName) { // We have a match. Let's compare the URLs var itemUrl = items[i].getElementsByTagName('nearestpermalink')[0].firstChild.nodeValue; var filteredItemUrl = filteredItems[j].getElementsByTagName('nearestpermalink')[0].firstChild.nodeValue; // We'll assume here that the longest URL is the most specific if (itemUrl.length > filteredItemUrl.length) { // The new item has a longer URL, so replace the old one. filteredItems[j] = items[i]; } processed = true; break; } } if (!processed) { // We haven't encountered this one before, so append it to the list filteredItems.push(items[i]); } } return filteredItems; } // Add this blog to the list function addBlog(list, blog) { var name = blog.getElementsByTagName('name')[0]; var url = blog.getElementsByTagName('nearestpermalink')[0]; var excerpt = blog.getElementsByTagName('excerpt')[0]; var li = document.createElement('li'); li.setAttribute('class', 'Stats'); var a = document.createElement('a'); a.setAttribute('href', url.firstChild.nodeValue); a.setAttribute('class', 'Plain'); a.appendChild(document.createTextNode(name.firstChild.nodeValue)); li.appendChild(a); li.appendChild(document.createElement('br')); li.appendChild(document.createTextNode(excerpt.firstChild.nodeValue)); list.appendChild(li); } // Add a credit line, linking back to Technorati function addTechnoratiCredit(blogContainer) { var a = document.createElement('a'); a.setAttribute('href', 'http://www.technorati.com/'); a.setAttribute('class', 'Plain'); a.appendChild(document.createTextNode('Technorati')); var p = document.createElement('p'); p.appendChild(document.createTextNode('Search results by ')); p.appendChild(a); styleElement(p); blogContainer.appendChild(p); } //Style a given node so that it matched the side bar function styleElement(node) { node.style.color = '#999999'; node.style.fontSize = '11px'; node.style.lineHeight = '15px'; } // The script itself starts here if (checkPhotoPage()) { var privacyElements = document.evaluate( "//*[@class='Privacy']", document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null); if (privacyElements.snapshotLength > 0) { addLink(privacyElements.snapshotItem(0)); } }