/*
 * Rollover Engine: pre-loads and manages rollover images
 * $Id: rolloverengine.js,v 1.27 2001/12/05 17:10:54 scott Exp $
 * Copyright (C) 2001 Scott Martin (scott@coffeeblack.org)
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation; either version 2.1
 * of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this library; if not, it is available from the Free Software
 * Foundation, Inc. at http://www.gnu.org/copyleft/lesser.html or in writing at
 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

/*
 * Constructs a new rollover engine.
 *
 * The pat argument is a regular expression to specify that only images whose
 * names match that expression be loaded. If no pattern is specified or if the
 * specified pattern is null, the pattern "." is used (any character except
 * newline). If the pattern is ever set to null, no images are loaded.
 *
 * The loadMask argument is a number representing the mask to apply while
 * loading images, in order to avoid a request to the server for non-existant
 * images.
 * If the mask is >= RolloverEngine.MASK_OVER, the extension "over" is loaded.
 * If the mask is >= RolloverEngine.MASK_ON, the extension "on" is loaded.
 * If the mask is >= RolloverEngine.MASK_OVER + RolloverEngine.MASK_ON, both
 * extensions "over" and "on" area loaded.
 *
 * Upon creation, findImages() is called to find and load all applicable
 * rollover images in the document.
 *
 * dependency: Map
 */ 
var loaded = 0;
function RolloverEngine(pat, loadMask)
{	this.pattern = (pat && pat != null)
		? ((typeof pat == "string") ? new RegExp(pat) : pat)
			: new RegExp(".");	
	
	this.mask = (!isNaN(loadMask)
		&& loadMask > 0 && loadMask <= RolloverEngine.MASK_ON)
		? loadMask : RolloverEngine.MASK_OVER + RolloverEngine.MASK_ON;
		
	this.images = new Map();
	this.ready = false
	this.findImages()
	this.ready = true;
	loaded = 1;
}

/*
 * Mask for loading images with the "_over" extension.
 */
RolloverEngine.MASK_OVER = 1;

/*
 * Mask for loading images with the "_on" extension.
 */
RolloverEngine.MASK_ON = 2;

/*
 * Finds and loads rollover images by examining every image in the document and
 * calling loadImage() for any image that is named. only images whose names
 * match the engine's regular expression pattern are loaded. For Netscape 4.x
 * browsers, traverses the document.layers object tree to find all the
 * document's images.
 */
RolloverEngine.prototype.findImages = function(doc)
{	if(!doc) doc = window.document;
	
	if(doc.images.length > 0)
	{	var img;
		for(var a = 0; a < doc.images.length; a++)
		{	img = doc.images[a];
			if(img.name)
			{	with(this)	
				{	if(pattern != null && pattern.test(img.name))
						loadImage(img);
				}
			}
		}
	}
	if(doc.layers && doc.layers != null)
	{	if(doc.layers.length > 0)
		{	for(var b = 0; b < doc.layers.length; b++)
			{	this.findImages(doc.layers[b].document);
			}
		}
	}		
}

/*
 * Attempts to load <dir><name>_over.<ext> and <dir><name>_on.<ext> for
 * the image object specified as the 'img' argument.
 */
RolloverEngine.prototype.loadImage = function(img)
{	function doLoad(img, e)
	{	eval("img." + e + " = new Image();img." + e + ".src = \"" +
			imgLoc + baseName + "_" + e + ext + "\";");
	}
	
	if(img && img != null && img.src)
	{	var lastSlash = Math.max(img.src.lastIndexOf("/"), 0);
		
		var lastDot = img.src.lastIndexOf(".");
		if(lastDot == -1) lastDot = img.src.length;
		
		var imgLoc = (lastSlash > 0)
			? img.src.substring(0, lastSlash + 1) : new String(""), 
				baseName = img.src.substring(lastSlash + 1, lastDot), 
					ext = img.src.substring(lastDot, img.src.length);
		
		// fix for old _off naming
		var offIndex = baseName.lastIndexOf("_off");
		if(offIndex != -1) baseName = baseName.substring(0, offIndex);
		
		img.off = new Image();
		img.off.src = img.src;
		
		switch(this.mask)
		{	case 1:
				doLoad(img, "over");
				break;
			case 2:
				doLoad(img, "on");
				break;
			case 3:
				doLoad(img, "over");
				doLoad(img, "on");
				break;
			default: break;
		}
										
		this.images.put(img.name, img);
	}
}

/*
 * Gets the regular expression pattern used by this rollover engine while
 * loading its images.
 */
RolloverEngine.prototype.getPattern = function()
{	return this.pattern;
}

/*
 * Gets the load mask used by this rollover engine while
 * loading its images.
 */
RolloverEngine.prototype.getMask = function()
{	return this.mask;
}

/*
 * Tests whether this rollover engine has added the image named strName.
 */
RolloverEngine.prototype.containsImage = function(strName)
{	return this.images.containsKey(strName);
}

/*
 * Gets the image named strName as an image object, if it has been loaded by
 * this rollover engine.
 */
RolloverEngine.prototype.getImage = function(strName)
{	return this.images.get(strName);
}

/*
 * Sets the image named strName to its off state.
 */
RolloverEngine.prototype.setOff = function(strName)
{	with(this)
	{	if(ready)
		{	var img = getImage(strName);
			if(img && img != null && img.off && img.off != null && !img.locked
				&& img.src != img.off.src)
				img.src = img.off.src;
		}
	}
}

/*
 * Sets the image named strName to its over state.
 */
RolloverEngine.prototype.setOver = function(strName)
{	with(this)
	{	if(ready && mask >= RolloverEngine.MASK_OVER
			&& mask != RolloverEngine.MASK_ON)
		{	var img = getImage(strName);
			if(img && img != null && img.over && img.over != null && !img.locked
				&& img.src != img.over.src)
				img.src = img.over.src;
		}
	}
}

/*
 * Sets the image named strName to its on state.
 */
RolloverEngine.prototype.setOn = function(strName)
{	with(this)
	{	if(ready && mask >= RolloverEngine.MASK_ON)
		{	var img = getImage(strName);
			if(img && img != null && img.on && img.on != null && !img.locked
				&& img.src != img.on.src)
				img.src = img.on.src;
		}
	}
}

/*
 * Sets all images loaded by this rollover engine to their respective off states.
 */
RolloverEngine.prototype.setAllOff = function()
{	with(this)
	{	if(ready)
		{	with(images)
			{	var k = keys();
				for(var a = 0; a < k.length; a++)
					setOff(k[a]);
			}
		}
	}
}

/*
 * Tests whether the image named strName is in its off state.
 */
RolloverEngine.prototype.isOff = function(strName)
{	var img = this.getImage(strName);
	return (img && img != null && img.off && img.off != null
		&& img.src == img.off.src);
}

/*
 * Tests whether the image named strName is in its over state.
 */
RolloverEngine.prototype.isOver = function(strName)
{	var img = this.getImage(strName);
	return (img && img != null && img.over && img.over != null
		&& img.src == img.over.src);
}

/*
 * Tests whether the image named strName is in its on state.
 */
RolloverEngine.prototype.isOn = function(strName)
{	var img = this.getImage(strName);
	return (img && img != null && img.on && img.on != null
		&& img.src == img.on.src);
}

/*
 * Locks the image named strName. When an image is locked, its source
 * will not be altered by rollover engine until it is unlocked.
 */
RolloverEngine.prototype.lock = function(strName)
{	var img = this.getImage(strName);
	if(img && img != null) img.locked = true;
}

/*
 * Locks all images that have been loaded by this rollover engine.
 */
RolloverEngine.prototype.lockAll = function()
{	with(this)
	{	if(ready)
		{	with(images)	
			{	var vals = values(), img;
				for(var i = 0; i < vals.length; i++)
				{	img = vals[i];
					if(img && img != null)
						img.locked = true;
				}
			}
		}
	}
}

/*
 * Unlocks the image named strName.
 */
RolloverEngine.prototype.unlock = function(strName)
{	var img = this.getImage(strName);
	if(img && img != null) img.locked = false;
}

/*
 * Unlocks all images that have been loaded by this rollover engine.
 */
RolloverEngine.prototype.unlockAll = function()
{	with(this)
	{	if(ready)
		{	with(images)	
			{	var vals = values(), img;
				{	for(var j = 0; j < vals.length; j++)
					{	img = vals[j];	
						if(img && img != null)
							img.locked = false;
					}
				}
			}
		}
	}
}

/*
 * Tests whether the image named strName is locked.
 */
RolloverEngine.prototype.isLocked = function(strName)
{	var img = this.getImage(strName);
	return (img && img != null && img.locked && img.locked == true);
}

/*
 * Gets a string representation of this rollover engine.
 */
RolloverEngine.prototype.toString = function()
{	with(this)
	{	return "[object RolloverEngine {images:{" + images.toString() +
			"} pattern:{" + ((pattern != null) ? pattern.toString() : "null") +
				"} ready:" + ready + "}]";
	}
}