// ==UserScript==
// @name          Flickr All Sizes+
// @description	  Enhanced Features for the 'All Sizes' Page
// @author        Premasagar Rose (http://premasagar.com/contact/)
// @namespace     http://premasagar.com
// @identifier    http://premasagar.com/dev/gm/flickrallsizesplus.user.js
// @include       http://www.flickr.com/photo_zoom.gne*
// @include       http://flickr.com/photo_zoom.gne*
// @include       http://www.flickr.com/photos/*/*
// @include       http://flickr.com/photos/*/*
// @exclude       http://www.flickr.com/photos/organize*
// @exclude       http://flickr.com/photos/organize*
// @version       1.01 (20-Oct-2006)
// ==/UserScript==


/*
  INFO
  ====
  Before installing this script, you'll need the Firefox browser (http://www.mozilla.org/firefox/) and the Greasemonkey extension (http://greasemonkey.mozdev.org)
  
  Discuss this script, report bugs:
  http://www.flickr.com/groups/flickrhacks/discuss/72157594303798688/
  
  Download the latest version:
  http://premasagar.com/dev/gm/flickrallsizesplus.user.js
  
  Released under the GPL license:
  http://www.gnu.org/copyleft/gpl.html
  

  SUMMARY
  =======
  A Greasemonkey script to enhance the 'All Sizes' page for a photo on Flickr.com

  When you want to post a photo to a group discussion thread or to a blog or other website, you click the "All Sizes" button on the photopage and then copy and paste the HTML code that appears on the 'All Sizes' page. This script improves the HTML code that appears on that page, as well as some other related improvements.

  The behaviour of the script can be easily modified: change the 'User Settings' below.
  

  WHAT THE SCRIPT DOES (default)
  ====================
  On a photo's Photopage:
  - Changes the 'All Sizes' button to redirect to the <em>small</em> size - because that is the size most commonly posted
  
  On a photo's All Sizes page:
  - Adds the HTML code for displaying the photo, if not already present
  - Changes the title attribute from "Photo Sharing" to the actual photo title
  - Appends '(by *Photographer*)' to the title and alt attributes
  - Gives 'Untitled' for untitled photos
  - Converts HTML special characters to their character entities (e.g. & to &amp;) - to comply with web standards


  RESPECTING COPYRIGHT
  ====================
  Please respect the copyright attributed to a photo. You may only re-post a photo if the license permits it or if the owner has given you specific permission.
  
  
  
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */
(function() {


/*
  USER SETTINGS
  =============
  Change the settings in this section if you wish...


// Size of image displayed on clicking "All Sizes" button ('sq', 't', 's', 'm', 'l' or 'o') */
var photoSizeOnAllSizes = 's';

// Whether to add the photographer's username to the HTML title attribute (true or false)
var addPhotographer = true;

// Whether to add your username to the HTML title attribute, if you took the photo (true or false)
var addPhotographerWhenYou = true;

// Format for the (by *Photographer*) text. Use '[photographer]' to represent the photographer's username.
var photograperFormat = ' (by [photographer])';

// A title to use when there is no title. Use '' to keep it blank.
var untitledTitle = 'Untitled';

// Whether to display the HTML code if it is not already present (true or false)
var insertHTMLWhenAbsent = true;



// Don't change anything below this line unless you know what you're doing.
// If you improve the script, please let me know...
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+



// Get location of the page we're on
var path = window.location.pathname;
var slash = path.slice(1).indexOf('/');
var current_page = (slash === -1) ? path.slice(1) : path.slice(1, slash + 1);


// Determine which page we're on & call functions
switch (current_page){
	case 'photos':
	changeAllSizesButton();
	break;
	
	case 'photo_zoom.gne':
	changePhotoHTML();
	break;
}



// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+



// Change the 'All Sizes' button to go to a specific photo size
function changeAllSizesButton(){
	// Find the "All Sizes" button
	var button = document.getElementById('photo_gne_button_zoom');
	if (button)
		{
			// Get photoId from document URL
			var urlRegExp = /\/photos\/[\w@_-]+\/(\d+)\/[\w@_\/-]*$/;
			var photoId = path.replace(urlRegExp, '$1');
			
			// Function to change page visited on clicking "All Sizes"
			var goToAllSizes = function(){
				var allSizesUrl = 'http://www.flickr.com/photo_zoom.gne';
				window.location.href = allSizesUrl + '?id=' + photoId + '&size=' + photoSizeOnAllSizes;
				return false;
			};
			
			// Associate function with button onclick event
			button.addEventListener("click", goToAllSizes, true);
		}
}



// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+



// Change the HTML displayed for re-posting a photo
function changePhotoHTML(){
	// Get textareas in the document
	var textareas = document.getElementsByTagName('textarea');
	
	// Cycle through each textarea
	// Other gm scripts may have added textareas, so we won't assume there's only one
	for (var i=0; i<textareas.length; i++)
		{
			var ta = textareas[i];
			
			// If there's no title attribute, then we're in the wrong textarea
			if (ta.innerHTML.indexOf('title="Photo Sharing"') === -1)
				{ continue; }
			
			// Change the HTML title attribute. Job done!
			ta.innerHTML = getPhotoHTML();
			break;
		}
		
	// If there's no textarea, then insert one!
	if (textareas.length == 0 && insertHTMLWhenAbsent)
		{ insertPhotoHTML(); }
}



// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+



// Get elements from the document with a specific cssClass
function getElementsByCssClass(tagName, cssClass){
	// Construct empty array to return
	var returnArray = [];
	
	// Get divs in the document
	var elements = document.getElementsByTagName(tagName);
	
	// Cycle through elements
	for (var i=0; i<elements.length; i++)
		{
			// Find the element with the css class
			if (elements[i].getAttribute('class') == cssClass)
				{ returnArray.push(elements[i]); }
		}
	
	// Return array
	return returnArray;
}



// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+



// Convert special characters to their HTML entities
function specialChars(str){
	return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
}


// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+



// Get photo title
function getTitle(){
	// Get the title from the Page Title
	var title = document.title.slice('Flickr Photo Download: '.length);
	
	// If the title is blank, then add default value
	if (title == '')
		{ title = untitledTitle; }
	
	// Add the username to the title
	if (addPhotographer)
		{
			var username = getUsername();
			if (username)
				{ title += photograperFormat.replace(/\[photographer\]/g, username); }
		}
	
	// Convert special characters to their HTML entities
	return specialChars(specialChars(title));
}



// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+



// Get the image src
function getSrc(){
	// Find images in the document
	var images = document.getElementsByTagName('img');
	
	// A regular expression for the image src
	var photoSrcRegExp = /^http:\/\/static\.flickr\.com\/(\d+)\/(\d+)_(\w+?)(_[mstbo])?\.(jpg|gif|png)$/;
	
	// Find the image src of the photo
	for (var i=0; i<images.length; i++)
		{
			var src = images[i].getAttribute('src');
			if (src.match(photoSrcRegExp))
				{ return src; }
		}
	
	// If not found, return null
	return null;
}



// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+



// Get the image dimensions
function getDimensions(){
	// Get the spans with css class 'Dimensions'
	var elements = getElementsByCssClass('span', 'Dimensions');
	
	// Cycle through each span found
	for (var i=0; i<elements.length; i++)
		{
			// Find a sibling of the span that is a <strong> element. This is the current image size.
			var el = elements[i];
			if (el.parentNode.getElementsByTagName('strong').length > 0)
				{
					// Return array of dimensions [width, height]
					return el.innerHTML.slice(1, -1).split(' x ');
				}
		}
	// If not found, return null
	return null;
}



// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+



// Get the photographer's username
function getUsername(){
	// Get the 'Owner' div
	var elements = getElementsByCssClass('div', 'Owner');
	if (elements.length == 0)
		{ return null; }
	var owner = elements[0];
	
	// Markers to find the username within an anchor
	var prefix = 'Link to';
	var suffix = "'s photos";
	
	// Cycle through anchors in the div
	var anchors = owner.getElementsByTagName('a');
	for (var j=0; j<anchors.length; j++)
		{
			// Find the anchor's title attribute
			var a = anchors[j];
			if (a.getAttribute('title'))
				{
					// If the title starts with the prefix, then we've found the username.					
					if (a.getAttribute('title').slice(0, prefix.length) == prefix)
						{
							// Check if it's your photo & return username
							if (a.firstChild.innerHTML != 'You' || addPhotographerWhenYou)
								{
									return a.getAttribute('title').slice(prefix.length+1, -suffix.length);
								}
							break;
						}
				}
		}
		
	// If the username was not found return null.
	return null;
}



// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+



// Get the url of the photopage
function getPhotoPageUrl(){
	// Get the p element with css class 'EndBar'
	var elements = getElementsByCssClass('p', 'EndBar');
	
	// If not found, return null
	if (elements.length == 0)
		{ return null; }
	
	// Get the url from the first anchor in the p element
	var url = elements[0].getElementsByTagName('a')[0].getAttribute('href');
	
	// Check if 'http://www.flickr.com' is included in the url
	if (url.indexOf('/photos/') == 0)
		{ url = 'http://www.flickr.com' + url; }
	return url;
}



// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+



// Generate HTML for the textarea boxes
function getPhotoHTML(){
	// Get image dimensions and title
	var dims = getDimensions();
	var title = getTitle();
	
	// Generate HTML for the image
	var imgHTML = '<img src="'+ getSrc() +'" alt="'+ title +'" width="'+ dims[0] +'" height="'+ dims[1] +'" />';
	
	// Generate HTML for the link to the photopage & return
	return '<a href="'+ getPhotoPageUrl() +'" title="'+ title +'">' + imgHTML + '</a>';
}



// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+



// Add a textarea box with the photo HTML, if not already displayed
function insertPhotoHTML(){
	// Get the p element with css class 'EndBar'
	var elements = getElementsByCssClass('p', 'EndBar');
	
	// If not found, return null
	if (elements.length == 0)
		{ return null; }	
	
	// Prepare the HTML to be inserted
	var html = '<h3>To link to this photo on other websites you can either:</h3>';
	html += '<p><strong>1.</strong> Copy and paste this HTML into your webpage:</p>';
	html += '<p><textarea onFocus="this.select();" rows="4" style="width: 520px;">';
	html += getPhotoHTML() + '</textarea></p>';
	html += '<p><strong>2.</strong> Grab the photo\'s URL:</p>';
	html += '<p><input onFocus="this.select();" type="text" value="'+ getSrc() +'" style="width: 520px;"></p>';
	html += '<p><span style="background-color: #ffffcc"><strong>Remember!</strong></span> Flickr Terms of Service specify that if you post a Flickr photo on an external website, the photo must link back to its photo page. (So, use Option 1.)</p>';	
	
	// Create new node
	var newNode = document.createElement('div');
	newNode.innerHTML = html;
	
	// Insert into document
	elements[0].parentNode.insertBefore(newNode, elements[0]);
}



// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+



})();
