Added by Gary Glass, last edited by David Parry on Feb 08, 2008  (view change)

Labels:

Enter labels to add to this page:
Wait Image 
Looking for a label? Just start typing.

Discussion at:  http://www.dgrin.com/showthread.php?p=675298

// resize journals -- BEGIN HERE

/*
	PHOTOSIZERCLASS resizes images in a journal gallery.

	Version: 1.1
	Author:  Gary Glass, based on excellent work by rutt and dmc.
                 David Parry (2008-02-08), modified code to support SmugMug security changes

	HOW TO

	1. Copy the PhotoSizerClass into the javascript on your site page.
	2. Also copy the three methods: isJournalPage, hasClass, ResizeJournal.
	3. Within a script tag in your custom footer copy the statement that
		executes the code: ResizeJournal();

	The PhotoSizer will search for and apply sizing rules that you specify.
	The rule always has the same form: "Journal<width>x<height>Rule"
	<width> and <height> are the maximum width and height for an image.
	The sizer will select among the standard image sizes
	(see: http://friend.smugmug.com/help/display-quality )
	provided by SmugMug, and use the one that does not exceed in either
	dimension the maximum size specified by your rule.

	There are three ways to apply sizing rules.
	1. With a CSS selector.
	2. Inserting into the gallery description.
	3. Inserting into a photo caption.

	Individual photo rules take precedence over gallery rules.
	Gallery rules take precedence over CSS rules.

	If you specify more than one rule in CSS, the first one found is the one
	that will be used at the CSS level. Likewise for the other levels, the
	first one found is the one that is applied at that level.

	EXAMPLE

	Suppose you wanted to make a general rule that journal images should scale
	up to 800 pixels wide and 600 pixels high. This is the rule:

	Journal800x600Rule

	To apply it site-wide (to all journal galleries in your site) insert into
	your CSS like this:

		#Journal800x600Rule { }

	(It's just a selector. No body is required.)

	Now suppose in a particular gallery you want to override with a 600 x 600
	rule. To do that, insert this HTML into the description for that gallery:

		<span name="Journal600x600Rule"></span>

	Finally to override the rule for one particular image, insert the same
	sort of tag into the image caption.

	MORE INFO

	See discussion here:	http://www.dgrin.com/showthread.php?p=675298
*/
function PhotoSizerClass(standardSizes)
{
	/*
		properties
	*/
	this.ruleStatementRegex = /Journal(\d+)[xX](\d+)Rule/; // matches a journal sizing rule
	this.limits = new SizeClass();
	if (standardSizes == null)
	{
		this.standardSizes = new StandardSizesClass();
	}
	else
	{
		this.standardSizes = standardSizes;
	}
	this.standardScalings = new StandardScalingsClass(this.standardSizes);

	/*
		public methods
	*/
	this.apply = Apply;

	/*
		private methods
	*/
	this.getGalleryRule = GetGalleryRule;
	this.getCssRule = GetCssRule;
	this.init = Init;
	this.resizeJournalEntry = ResizeJournalEntry;
	this.resizeImage = ResizeImage;

	/*
		-------------------------------
		Method Definitions
		-------------------------------
	*/

	/*
		Resize the gallery.
	*/
	function Apply()
	{
		this.init();
		var divs = document.getElementsByTagName('DIV');
		for (var i = 0; i < divs.length; i++)
		{
			if (divs[i].className == 'journal_entry')
			{
				this.resizeJournalEntry(divs[i]);
			}
		}
	}

	/*
		Finds global rules (rules applied via gallery description or stylesheet).
	*/
	function Init()
	{
		if (this.getGalleryRule() == false)
		{
			this.getCssRule();
		}
	}

	/*
		Look for a sizing rule in album description.
		Returns: A boolean value indicating whether a rule was found.
	*/
	function GetGalleryRule()
	{
		var foundRule = false;
		var description = document.getElementById('albumDescription');
		if (description)
		{
			if (this.ruleStatementRegex.test(description.innerHTML))
			{
				this.limits.set(RegExp.lastMatch);
				foundRule = true;
			}
		}
		return foundRule;
	}

	/*
		Search stylesheets for a journal sizer rule.
		The first rule found is used.
		Returns: A boolean value indicating whether a rule was found.
	*/
	function GetCssRule()
	{
		var found = false;
		for (var i = 1; i < document.styleSheets.length; i++)
		{
			if (found)
			{
				break;
			}
			var stylesheet = document.styleSheets[i];
			var rules = stylesheet.cssRules ? stylesheet.cssRules : (stylesheet.rules ? stylesheet.rules : stylesheet.css);
			for (var j = 0; j < rules.length; j++)
			{
				var cssRule = rules[j].selectorText;
				if (this.ruleStatementRegex.test(cssRule))
				{
					this.limits.set(RegExp.lastMatch);
					found = true;
					break;
				}
			}
		}
		return found;
	}

	/*
		Finds the journal images in an entry and resizes them.
	*/
	function ResizeJournalEntry(div)
	{
		var imgs = div.getElementsByTagName('IMG');
		//var re = /(http:\/\/[^\/]*\/photos\/(\d+)-)S((-\d+)?.jpg)/
		var re = /(http:\/\/.*\/photos\/(\d+)_(\w+)-)S((-\d+)?.jpg)/
		for (var i = 0; i < imgs.length; i++)
		{
			if (re.test(imgs[i].src))
			{
				this.resizeImage(imgs[i], RegExp.$2);
			}
		}
	}

	/*
		Gets the final rule for an image and applies it.
	*/
	function ResizeImage(img, imageNumber, prefix, suffix)
	{
		var finalRule = new FinalRuleClass(imageNumber, this.limits);
		var imageSizes = new ImageSizesClass(img, this.standardScalings);
		var size = "S";
		if (finalRule.limits.width >= imageSizes.x3large.width
			&& finalRule.limits.height >= imageSizes.x3large.height)
		{
			size = "X3L"; // go extra extra extra large
		}
		else if (finalRule.limits.width >= imageSizes.x2large.width
			&& finalRule.limits.height >= imageSizes.x2large.height)
		{
			size = "X2L"; // go extra extra large
		}
		else if (finalRule.limits.width >= imageSizes.xlarge.width
			&& finalRule.limits.height >= imageSizes.xlarge.height)
		{
			size = "XL"; // go extra large
		}
		else if (finalRule.limits.width >= imageSizes.large.width
			&& finalRule.limits.height >= imageSizes.large.height)
		{
			size = "L"; // go large
		}
		else if(finalRule.limits.width >= imageSizes.medium.width
			&& finalRule.limits.height >= imageSizes.medium.height)
		{
			size = "M"; // go medium
		}
		if (size != "S")
		{
			// resize
			switch (size)
			{
				case "M":
					img.width = imageSizes.medium.width;
					img.height = imageSizes.medium.height;
					break;
				case "L":
					img.width = imageSizes.large.width;
					img.height = imageSizes.large.height;
					break;
				case "XL":
					img.width = imageSizes.xlarge.width;
					img.height = imageSizes.xlarge.height;
					break;
				case "X2L":
					img.width = imageSizes.x2large.width;
					img.height = imageSizes.x2large.height;
					break;
				case "X3L":
					img.width = imageSizes.x3large.width;
					img.height = imageSizes.x3large.height;
					break;
			}
			// set new image source to matching size
			var re = /(http:\/\/.*\/photos\/(\d+)_(\w+)-)S((-\d+)?.jpg)/;
			img.src = RegExp.$1 + size + RegExp.$4;
		}
	}

	/*
		-------------------------------
		Inner Classes
		-------------------------------
	*/

	/*
		Defines a height & width dimension.
		If scaleFactor is provided, the specified width & height will be multiplied by it.
	*/
	function SizeClass(width, height, scaleFactor)
	{

		if (width == null)
		{
			this.width = -1;
		}
		else
		{
			this.width = width;
		}
		if (height == null)
		{
			this.height = -1;
		}
		else
		{
			this.height = height;
		}
		this.ruleStatementRegex = /Journal(\d+)[xX](\d+)Rule/; // matches a journal sizing rule
		this.set = Set;
		this.scale = Scale;
		if (scaleFactor != null)
		{
			this.scale(scaleFactor);
		}

		/*
			Sets dimensions from a rule statement.
		*/
		function Set(ruleStatement)
		{
			if (this.ruleStatementRegex.test(ruleStatement))
			{
				this.width = RegExp.$1;
				this.height = RegExp.$2;
			}
		}

		/*
			Scales the size by the specified factor.
		*/
		function Scale(factor)
		{
			this.width = Math.round(this.width * factor);
			this.height = Math.round(this.height * factor);
		}

	} // SizeClass

	/*
		Defines dimensions of standard image sizes.
	*/
	function StandardSizesClass()
	{

		this.small = new SizeClass(400, 300);
		this.medium = new SizeClass(600, 450);
		this.large = new SizeClass(800, 600);
		this.xlarge = new SizeClass(1024, 768);
		this.x2large = new SizeClass(1280, 960);
		this.x3large = new SizeClass(1600, 1200);

	} // StandardSizesClass

	/*
		Defines scaling factors for the members of a StandardSizesClass.
		standardSizes: a StandardSizesClass instance
	*/
	function StandardScalingsClass(standardSizes)
	{

		this.small = 1;
		this.medium = standardSizes.medium.width / standardSizes.small.width;
		this.large = standardSizes.large.width / standardSizes.small.width;
		this.xlarge = standardSizes.xlarge.width / standardSizes.small.width;
		this.x2large = standardSizes.x2large.width / standardSizes.small.width;
		this.x3large = standardSizes.x3large.width / standardSizes.small.width;

	} // StandardScalingsClass

	/*
		Defines the standard sizes for a specified image.
		img: the image to get sizes for
		scalings: a StandardScalingsClass instance.
	*/
	function ImageSizesClass(img, scalings)
	{

		this.small = new SizeClass(img.width, img.height, scalings.small);
		this.medium = new SizeClass(img.width, img.height, scalings.medium);
		this.large = new SizeClass(img.width, img.height, scalings.large);
		this.xlarge = new SizeClass(img.width, img.height, scalings.xlarge);
		this.x2large = new SizeClass(img.width, img.height, scalings.x2large);
		this.x3large = new SizeClass(img.width, img.height, scalings.x3large);

	} // ImageSizesClass

	/*
		The FinalRuleClass class defines the final rule to apply to an image.
		The final rule is either the global rule or an individual image rule.
		Image rules override global rules.
		The constructor requires a reference to the image, its number,
		and the PhotoSizerClass instance containing the global settings.
		imageNumber: the index of the image on the page (used to get the image
			caption and extract its rule, if any).
		limits: a SizeClass instance specifying the global rules.
	*/
	function FinalRuleClass(imageNumber, limits)
	{

		this.limits = new SizeClass(limits.width, limits.height); // copy global limits from specified PhotoSizer class
		var caption = document.getElementById('caption' + imageNumber);
		if (caption)
		{
			var ruleStatementRegex = /Journal(\d+)[xX](\d+)Rule/; // matches a journal sizing rule
			if (ruleStatementRegex.test(caption.innerHTML)) // look for image-specific rule
			{
				this.limits.set(RegExp.lastMatch); // override global limits
			}
		}

	} // FinalRuleClass

} // PhotoSizerClass

/*
	Returns true if the current page is a journal gallery.
*/
function isJournalPage()
{
	return hasClass("journal");
}

/*
	Returns true if the body of the current page has the specified CSS class applied.
*/
function hasClass(cssClass)
{
	var className = document.body.className;
	var re = new RegExp(cssClass + "( |$)")
	if (!className)
	{
		return false;
	}
	return re.test(className);
}

/*
	Resizes a journal gallery.
*/
function ResizeJournal()
{
	if (isJournalPage())
	{
		var scaler = new PhotoSizerClass();
		scaler.apply();
	}
}

// resize journals -- END HERE