readelicious

By Richard Crowley Last update Feb 12, 2008 — Installed 790 times. Daily Installs: 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 1, 0, 1, 2, 0, 0, 2, 2, 0, 1, 0, 0
// ==UserScript==
// @name           readelicious
// @namespace      rcrowley.org
// @description    Post to del.icio.us links in Google Reader
// @include        http://google.com/reader*
// @include        http://*.google.com/reader*
// ==/UserScript==

// $Id$

// Show a window to save the entry passed to this function into del.icio.us
//   This function is left in the global namespace for others to attach to
var readelicious = function(entry) {
	if (!(entry && entry.className &&
		entry.className.match(/(^|\s)entry($|\s)/))) {
		return;
	}

	// Hide Reader's and Immersion's scrollbars
	document.getElementById('sub-tree').style.overflowY = 'hidden';
	document.getElementById('entries').style.overflowY = 'hidden';
	var immersion = document.getElementById('immersion');
	if (immersion) {
		immersion.getElementsByTagName('iframe')[0].style.overflow = 'hidden';
	}

	// Get the title and link for the entry
	var node = entry.firstChild.firstChild.firstChild
		.nextSibling.firstChild.nextSibling.firstChild.firstChild
		.nextSibling.firstChild.nextSibling.firstChild;
	var title = node.firstChild.nodeValue;
	var link = node.getAttribute('href');

	// TODO: Resolve Feedburner's indirection URLs
	//   From my preliminary research it seems XMLHttpRequest is
	//   required to transparently follow a 302 thus never giving me
	//   an opportunity to snoop the Location header
	//   http://www.w3.org/TR/XMLHttpRequest/

	// Field labels
	var labels = [];
	for (var i = 0; i < 3; ++i) {
		labels[i] = document.createElement('label');
		labels[i].style.display = 'block';
		labels[i].style.margin = '0 10px';
	}
	labels[0].appendChild(document.createTextNode('Title:'));
	labels[1].appendChild(document.createTextNode('Note:'));
	labels[2].appendChild(document.createTextNode('Tags:'));

	// Title and tags
	var inputs = [];
	for (var i = 0; i < 2; ++i) {
		inputs[i] = document.createElement('input');
		inputs[i].setAttribute('type', 'text');
		inputs[i].setAttribute('size', 255);
		inputs[i].style.margin = '0 10px 10px 10px';
		inputs[i].style.width = '400px';
	}
	inputs[0].setAttribute('id', 'title');
	inputs[0].setAttribute('name', 'title');
	inputs[0].setAttribute('value', title);
	inputs[1].setAttribute('id', 'tags');
	inputs[1].setAttribute('name', 'tags');

	// Note
	var textarea = document.createElement('textarea');
	textarea.setAttribute('id', 'note');
	textarea.setAttribute('name', 'note');
	textarea.setAttribute('rows', 3);
	textarea.setAttribute('cols', 48);
	textarea.style.width = '400px';
	textarea.style.margin = '0 10px 10px 10px';
	textarea.appendChild(document.createTextNode(
		window.getSelection().toString()));

	// Post button
	var button = document.createElement('input');
	button.setAttribute('type', 'button');
	button.setAttribute('value', 'Post');
	button.style.fontWeight = 'bold';
	var post = function() {
		GM_xmlhttpRequest({
			method: 'POST',
			url: 'https://api.del.icio.us/v1/posts/add?url=' +
				encodeURIComponent(document.getElementById('link').value) +
				'&description=' +
				encodeURIComponent(document.getElementById('title').value) +
				'&extended=' +
				encodeURIComponent(document.getElementById('note').value) +
				'&tags=' +
				encodeURIComponent(document.getElementById('tags').value)
		});
		var node = document.getElementById('readelicious');
			node.parentNode.removeChild(node);
		var immersion = document.getElementById('immersion');
		if (immersion) {
			immersion.getElementsByTagName('iframe')[0].style.overflow = 'auto';
		} else {
			document.getElementById('sub-tree').style.overflowY = 'auto';
			document.getElementById('entries').style.overflowY = 'auto';
		}
	};
	button.addEventListener('click', post, true);
	unsafeWindow.addEventListener('keypress', function(e) {
		if (13 == e.which && 'note' != e.target.id) {
			post();
		}
	}, true);

	// Cancel link
	var a = document.createElement('a');
	a.appendChild(document.createTextNode('Cancel'));
	a.href = 'javascript:;';
	a.addEventListener('click', function() {
		var node = document.getElementById('readelicious');
		node.parentNode.removeChild(node);
		var immersion = document.getElementById('immersion');
		if (immersion) {
			immersion.getElementsByTagName('iframe')[0].style.overflow = 'auto';
		} else {
			document.getElementById('sub-tree').style.overflowY = 'auto';
			document.getElementById('entries').style.overflowY = 'auto';
		}
	}, true);

	// Button and link
	var p = document.createElement('p');
	p.style.margin = '0 10px';
	p.appendChild(button);
	p.appendChild(document.createTextNode(' or '));
	p.appendChild(a);

	// Hidden link field
	var hidden = document.createElement('input');
	hidden.setAttribute('type', 'hidden');
	hidden.setAttribute('id', 'link');
	hidden.setAttribute('name', 'link');
	hidden.setAttribute('value', link);

	// Put 'em in the form
	var form = document.createElement('form');
	form.style.width = '422px';
	form.style.margin = '200px auto 0 auto';
	form.style.padding = '10px';
	form.style.textAlign = 'left';
	form.style.background = '#eee';
	form.style.border = '1px solid #444';
	form.appendChild(labels[0]);
	form.appendChild(inputs[0]);
	form.appendChild(labels[1]);
	form.appendChild(textarea);
	form.appendChild(labels[2]);
	form.appendChild(inputs[1]);
	form.appendChild(p);
	form.appendChild(hidden);

	// Display centered and dimmed and pretty
	var div = document.createElement('div');
	div.id = 'readelicious';
	div.style.width = window.innerWidth + 'px';
	div.style.height = window.innerHeight + 'px';
	div.style.position = 'absolute';
	div.style.top = '0';
	div.style.left = '0';
	div.style.zIndex = '999999999';
	div.style.textAlign = 'center';
	div.style.backgroundImage = 'url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAQCAYAAADwMZRfAAAAG0lEQVQ4jWMICgraQClmGDVk1JBRQ0YNCdoAAHYawHDC5WlcAAAAAElFTkSuQmCC)';
	div.appendChild(form);
	document.getElementsByTagName('body')[0].appendChild(div);

	// Focus the tags field
	inputs[1].focus();

};

(function() {

	// The text link in each entry
	document.getElementById('entries').addEventListener(
		'DOMNodeInserted', function(e) {

		// We only care when the entry divs are inserted
		if (!(e.target && e.target.className &&
			e.target.className.match(/(^|\s)entry($|\s)/))) {
			return;
		}

		// Get the entry-actions div
		var actions = e.target.firstChild.firstChild.firstChild
			.nextSibling.nextSibling.firstChild.nextSibling.firstChild;

		// The link for saving directly to del.icio.us
		var a = document.createElement('a');
		a.style.paddingRight = '10px';
		a.style.fontWeight = 'bold';
		a.href = 'javascript:;';
		a.addEventListener('click', function() {
			readelicious(e.target);
		}, true);
		a.appendChild(document.createTextNode('Post to del.icio.us'));
		actions.appendChild(a);

	}, true);

	// A keyboard shortcut
	//   Based on a patch from Mike Malone
	//   http://immike.net/scripts/readelicious.user.js
	unsafeWindow.addEventListener('keypress', function(e) {
		var node = e.target;
		var name = node.nodeName.toLowerCase();
		if ('input' == name &&
			('text' == node.type || 'password' == node.type) ||
			'textarea' == name) {
			return true;
		} else if ('d' == String.fromCharCode(e.which) && !e.ctrlKey) {

			// First try for the marked current entry
			var entry = document.getElementById('current-entry');
			if (entry) {
				readelicious(entry);
				try {
					event.preventDefault();
				} catch (err) {}
				return false;
			}

			// If not just go for the first entry
			var entries = document.getElementById('entries');
			if (entries) {
				entry = entries.firstChild;
				if (entry) {
					readelicious(entry);
					try {
						event.preventDefault();
					} catch (err) {}
					return false;
				}
			}

		} else {
			return true;
		}
	}, true);

})();