Tumblr Dashboard Quick Reblog

By yksk Last update Jan 20, 2010 — Installed 435 times. Daily Installs: 1, 2, 2, 1, 2, 1, 2, 4, 1, 1, 1, 6, 4, 3, 3, 2, 0, 1, 0, 1, 3, 1, 2, 4, 0, 0, 1, 4, 0, 0, 0

There are 3 previous versions of this script.

// ==UserScript==
// @name          Tumblr Dashboard Quick Reblog
// @description   Adds quick reblog link to Tumblr dashboard for Safari + GreaseKit.
// @namespace     http://codefairy.org/ns/userscripts
// @include       http://www.tumblr.com/*
// @version       0.2.1
// @license       MIT License
// @work          Greasekit
// ==/UserScript==

new function() {
	var posts = $X('id("posts")')[0];
	if (!posts) return;

	$X('./li', posts).forEach(function(li) {
		add(li);
	});

	posts.addEventListener('DOMNodeInserted', function(e) {
		var target = e.target;
		var tag = target.localName;
		if (tag && tag == 'li' && (/^post(\d+)$/.test(target.id)))
			add(target);
	}, false);

	if (window.Minibuffer) {
		window.Minibuffer.addShortcutkey({
			key        : 't',
			description: 'Reblog',
			command    : function() {
				window.Minibuffer.execute('pinned-or-current-link | reblog | clear-pin');
			}
		});
		window.Minibuffer.addCommand({
			name   : 'reblog',
			command: function(stdin) {
				if (!stdin.length) {
					var link = window.Minibuffer.execute('current-link');
					if (link) urls = [link.toString()];
				}
				// 'location | reblog'
				else if (stdin.every(function(a) { return (typeof a == 'string'); }))
					urls = stdin;
				// 'pinned-or-current-link | reblog'
				else if (stdin.every(function(a) { return (a && a.nodeName.toLowerCase() == 'a'); }))
					urls = stdin.map(function(node) { return node.href; });

				urls = urls.filter(function(url) {
					return (/^https?:\/\/[^.]+\.tumblr\.com\/post\/\d+/.test(url));
				});
				urls.map(reblog);

				return stdin;
			}
		});
	}

	function add(context) {
		var link = $X('./div[@class="post_controls"]/a[text()="reblog"]', context)[0];
		if (!link) return;
		var href = link.href;
		var a = document.createElement('a');
		a.href = href;
		a.innerHTML = ':)';
		a.addEventListener('click', function(e) {
			e.preventDefault();
			reblog(href);
		}, false);
		link.parentNode.insertBefore(a, link.nextSibling);
	}

	function reblog(url) {
		var id = /\/(?:reblog|post)\/(\d+)\//.exec(url)[1];
		var a = $X('id("post'+id+'")/div[@class="post_controls"]/a[text()="reblog"]')[0];
		if (!a) return;
		url = a.href;
		var uid = 'quick-reblog'+id;

		var link = a.nextSibling;
		link.innerHTML = '';
		link.style.padding    = '0 7px';
		link.style.background = 'url(data:image/gif;base64,R0lGODlhEAAQAPQAAP///6ixuvv8/LrByNTZ3aqyu7S8xPDx8+Dj5q+3v8/U2crP1fX299vf4uvt78DGzcXL0QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH+GkNyZWF0ZWQgd2l0aCBhamF4bG9hZC5pbmZvACH5BAAKAAAAIf8LTkVUU0NBUEUyLjADAQAAACwAAAAAEAAQAAAFUCAgjmRpnqUwFGwhKoRgqq2YFMaRGjWA8AbZiIBbjQQ8AmmFUJEQhQGJhaKOrCksgEla+KIkYvC6SJKQOISoNSYdeIk1ayA8ExTyeR3F749CACH5BAAKAAEALAAAAAAQABAAAAVoICCKR9KMaCoaxeCoqEAkRX3AwMHWxQIIjJSAZWgUEgzBwCBAEQpMwIDwY1FHgwJCtOW2UDWYIDyqNVVkUbYr6CK+o2eUMKgWrqKhj0FrEM8jQQALPFA3MAc8CQSAMA5ZBjgqDQmHIyEAIfkEAAoAAgAsAAAAABAAEAAABWAgII4j85Ao2hRIKgrEUBQJLaSHMe8zgQo6Q8sxS7RIhILhBkgumCTZsXkACBC+0cwF2GoLLoFXREDcDlkAojBICRaFLDCOQtQKjmsQSubtDFU/NXcDBHwkaw1cKQ8MiyEAIfkEAAoAAwAsAAAAABAAEAAABVIgII5kaZ6AIJQCMRTFQKiDQx4GrBfGa4uCnAEhQuRgPwCBtwK+kCNFgjh6QlFYgGO7baJ2CxIioSDpwqNggWCGDVVGphly3BkOpXDrKfNm/4AhACH5BAAKAAQALAAAAAAQABAAAAVgICCOZGmeqEAMRTEQwskYbV0Yx7kYSIzQhtgoBxCKBDQCIOcoLBimRiFhSABYU5gIgW01pLUBYkRItAYAqrlhYiwKjiWAcDMWY8QjsCf4DewiBzQ2N1AmKlgvgCiMjSQhACH5BAAKAAUALAAAAAAQABAAAAVfICCOZGmeqEgUxUAIpkA0AMKyxkEiSZEIsJqhYAg+boUFSTAkiBiNHks3sg1ILAfBiS10gyqCg0UaFBCkwy3RYKiIYMAC+RAxiQgYsJdAjw5DN2gILzEEZgVcKYuMJiEAOwAAAAAAAAAAAA==) no-repeat -1px -1px'

		if (window.Minibuffer)
			window.Minibuffer.status(uid, 'Reblogging...');

		var reblog = new XMLHttpRequest;
		reblog.onreadystatechange = function() {
			if (reblog.readyState == 4 && reblog.status == 200) {
				var p = get_param(reblog.responseText);
				
				var post = new XMLHttpRequest;
				post.onreadystatechange = function() {
					if (post.readyState == 4 && post.status == 200) {
						var span = document.createElement('span');
						span.innerHTML = ':D';
						span.style.marginLeft = '10px';
						var parent = a.parentNode;
						parent.insertBefore(span, link);
						parent.removeChild(link);
						if (window.Minibuffer)
							window.Minibuffer.status(uid, 'Reblogged', 100);
					}
				};
				post.open('POST', url, true);
				post.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
				post.send(p);
			}
		};
		reblog.open('GET', url, true);
		reblog.send(null);
	}

	function get_param (html) {
		var params = $X(
			'id("edit_post")//*[name()="input" or name()="textarea" or name()="select"]',
			createDocumentFromString(html)
		);
		var q = [];
		params.forEach(function(param) {
			var name = param.name;
			if (name == 'preview_post' || name == 'send_to_twitter') return;
			q.push(encodeURIComponent(name)+'='+encodeURIComponent(param.value));
		});
		return q.join('&');
	}

	// http://gist.github.com/198443
	// via http://github.com/hatena/hatena-bookmark-xul/blob/master/chrome/content/common/05-HTMLDocumentCreator.js
	function createDocumentFromString(source){
		var doc = document.implementation.createHTMLDocument ?
				document.implementation.createHTMLDocument('hogehoge') :
				document.implementation.createDocument(null, 'html', null);
		var range = document.createRange();
		range.selectNodeContents(document.documentElement);
		var fragment = range.createContextualFragment(source);
		var headChildNames = {title: true, meta: true, link: true, script: true, style: true, /*object: true,*/ base: true/*, isindex: true,*/};
		var child, head = doc.getElementsByTagName('head')[0] || doc.createElement('head'),
		           body = doc.getElementsByTagName('body')[0] || doc.createElement('body');
		while ((child = fragment.firstChild)) {
			if (
				(child.nodeType === doc.ELEMENT_NODE && !(child.nodeName.toLowerCase() in headChildNames)) || 
				(child.nodeType === doc.TEXT_NODE &&/\S/.test(child.nodeValue))
			   )
				break;
			head.appendChild(child);
		}
		body.appendChild(fragment);
		doc.documentElement.appendChild(head);
		doc.documentElement.appendChild(body);
		return doc;
	}

	// http://gist.github.com/29681.txt
	function $X (exp, context, resolver, result_type) {
		context || (context = document);
		var Doc = context.ownerDocument || context;
		var result = Doc.evaluate(exp, context, resolver, result_type || XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
		if (result_type) return result;
		for (var i = 0, len = result.snapshotLength, res = new Array(len); i < len; i++) {
			res[i] = result.snapshotItem(i);
		}
		return res;
	}
};