//
// MM_Util.js
//
// utility functions
//
// Copyright (C) 2001-2007 Mixtur Interactive, Inc. All rights reserved.
// http://www.mixtur.com, 1-866-268-3994. Unlicensed use is prohibited.
//
// Mark Eissler, mark@mixtur.com
//
// $Id: MM_Util.js,v 1.13 2008/06/26 00:22:23 mark Exp $
//

/*
 IMPORTANT:  This Mixtur software is supplied to you by Mixtur Interactive, Inc. ("Mixtur")
 in consideration of your agreement to the following terms, and your use, installation, 
 or modification of this Mixtur software constitutes acceptance of these terms.  If you do
 not agree with these terms, please do not use, install, or modify this Mixtur software.
 
 In consideration of your agreement to abide by the following terms, and subject to these 
 terms, Mixtur grants you a personal, non-exclusive license, under MixturÕs copyrights in 
 this original Mixtur software (the "Mixtur Software"), to use, reproduce and modify the
 Mixtur Software.
 
 IMPORTANT:  THIS AGREEMENT DOES NOT PROVIDE FOR NOR DOES IT ALLOW REDISTRIBUTION OF THIS
 MIXTUR SOFTWARE. YOU MAY NOT REDISTRIBUTE THIS SOFTWARE WITH OR WITHOUT MODIFICATIONS.

 Neither the name, trademarks, service marks or logos of Mixtur Interactive, Inc. may be 
 used to endorse or promote products derived from the Mixtur Software without specific 
 prior written permission from Mixtur. Except as expressly stated in this notice, no other
 rights or licenses, express or implied, are granted by Mixtur herein, including but not
 limited to any patent rights that may be infringed by your derivative works or by other
 works in which the Mixtur Software may be incorporated.
 
 The Mixtur Software is provided by Mixtur on an "AS IS" basis.  MIXTUR MAKES NO WARRANTIES, 
 EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, 
 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE MIXTUR SOFTWARE OR ITS 
 USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
 
 IN NO EVENT SHALL MIXTUR BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL 
 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 
 OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, 
 REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE MIXTUR SOFTWARE, HOWEVER CAUSED AND 
 WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR 
 OTHERWISE, EVEN IF MIXTUR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

// global variables
var gRootFolder = location.hostname;

// where all of the images are in respect to the root folder
var gImageFolder = "/resimages/";

// array of browser types
//var browser_array = new Array();	// an array of browser types

var gBrowser;	// the current browser


// associative array (hash) of breadCrumb exceptions
//
// If there is a folder in the breadcrumb for which there is no index page,
// there is an exception (since we can't determine where to go). A url
// exception must be created to help out. Likewise, if we want to create a
// temporary redirection in the breadcrumb trail, then this is the place to 
// put it. This array is searched for replacements as the bread crumb is
// constructed in makeBreadCrumb().
var gBCExceptionList = {

	'example': "index.php",
	'example2': "products/somedir/index.php"

};


// browser_type
//
// A user-defined type to hold browser information for ease of use.
//
function browser_type(long_name, short_name, browser_version) {

	this.lName = long_name;
	this.sName = short_name;
	this.bVers = browser_version;
	
	return this;
}


// browserAdd()
//
// Add a new item to the browser_array.
//
function browserAdd(long_name, short_name, browser_version) {

	var theArrayLength = browser_array.length;
	
	browser_array[theArrayLength] = new browser_type(long_name, short_name, browser_version);
	
	return;
}


// browserSet()
//
// Set the detected browser in gBrowser.
//
function browserSet(long_name, short_name, browser_version) {

	gBrowser = new browser_type(long_name, short_name, browser_version);

	return;
}


// browserName()
//
// Return the value of gBrowser.lName.
//
function browserName() {

	if(gBrowser != null)
		return gBrowser.lName;
	else
		return null;	
}


// browserCode()
//
// Return the value of gBrowser.sName.
//
function browserCode() {

	if(gBrowser != null)
		return gBrowser.sName;
	else
		return null;
}


// browserVers()
//
// Return the value of gBrowser.bvers.
//
function browserVers() {
	
	if(gBrowser != null)
		return (gBrowser.bVers);
	else
		return 0;
}


// browserDetect()
//
// Try to determine the client browser version. If debugging is on,
// an alert will display showing useful information about the 
// detected browser.
//
// Receive: -int turning debug on (1) or off (0).
//
function browserDetect(debugFlag) {

	var btype = navigator.appName;
	var bversLong = navigator.appVersion;
	var bvers = 0;
	
	// is this navigator?
	if(btype.indexOf("Netscape") != -1) {
		bvers = parseFloat(navigator.appVersion);

		if(bvers >= 4 && bvers < 5)
			browserSet("Netscape", "NS", 4);
		
		else if(bvers >= 5 && bvers < 6)	// Mozilla
			browserSet("Mozilla", "MOZ", 5);
						
		else if(bvers >= 6 && bvers < 7)
			browserSet("Netscape", "NS", 6);
			
		else
			browserSet("Unsupported", "US", 0);
			
		// but this could be Safari...
		if(bversLong.search(/safari/i) != -1)
			browserSet("Safari", "SAF", 1);
	
	}
	
	
	// is this explorer?
	if(btype.indexOf("Microsoft") != -1) {
	
		// Determine the MSIE version from the appVersion string,
		// which is kind of convoluted. The version number appears
		// after the string "MSIE". Search for it via RegExp.
	
		// create a RegExp object with the first search pattern
		var theRegEx = new RegExp("MSIE.\\d\.\\d", "g");
		
		// execute the pattern
		var theBVersStr = theRegEx.exec(bversLong);

		// now chop off the "MSIE" string by changing the RegExp object
		theRegEx.compile("\\d\.\\d", "g");

		// execute the pattern
		bvers = parseFloat(theRegEx.exec(theBVersStr));

		// all done!

		if(bvers >= 4 && bvers < 5)
			browserSet("Explorer", "MSIE", 4);
		
		else if(bvers >= 5 && bvers < 6)
			browserSet("Explorer", "MSIE", 5);
			
		else if(bvers >= 6 && bvers < 7)
			browserSet("Explorer", "MSIE", 6);

		else if(bvers >= 7)
			browserSet("Explorer", "MSIE", 7);
		
		else
			browserSet("Unsupported", "US", 0);
	}
	

	// show debug alert if debug flag is set to 1
	if(debugFlag == 1)
		alert("btype: " + btype + "\nbvers: " + bvers + "\nbversLong: " + bversLong +
			"\nbrowser_type: {" + browserName() + "; " + browserCode() + "; " + browserVers() + "}");
			
	return;

}


// insertCSSLink()
//
// Insert a link tag line for the correct stylesheet for the target
// browser specified by the bCode and bVers parameters (which identify
// the type of browser--e.g. MOZ=Mozilla--and the version number. Both
// values are set through browserDetect() and retrieved via browserCode()
// and browserVers() functions.
//
function insertCSSLink(bCode, bVers, cssDir) {

    if(cssDir) {
        if(cssDir.length == 0) cssDir = "css";
    } else {
        cssDir = "css";
    }
    
    // drop the last / if there is one
    if(cssDir.lastIndexOf('/') == cssDir.length-1) {
        cssDir = cssDir.substr(0,cssDir.length-1);
    }

	if(bCode == "NS" || bCode == "SAF") {
		document.write('<link href="'+cssDir+'/std.css" rel="stylesheet" media="screen">\n');
	} else if (bCode == "MSIE" && bVers == 6) {
		document.write('<link href="'+cssDir+'/ie6.css" rel="stylesheet" media="screen">\n');
	} else if (bCode == "MSIE" && bVers >= 7) {
		document.write('<link href="'+cssDir+'/ie7.css" rel="stylesheet" media="screen">\n');
	} else if (bCode == "MOZ") {
		document.write('<link href="'+cssDir+'/moz.css" rel="stylesheet" media="screen">\n');
	} else {
		if(debugFlag == 1)
		  alert("Browser not supported with a custom CSS!");
		
		// let's just guess its some Mozilla variant instead of sending an alert error
		document.write('<link href="'+cssDir+'/std.css" rel="stylesheet" media="screen">\n');
	}
	
	return;
}


// insertFavIconLink()
//
// Insert a link tag for the correct fav icon for the target browser.
//
function insertFavIconLink(bCode, bVers) {
	
	if(bCode == "NS" || bCode == "SAF") {
		// doesn't follow partial link properly, give it the whole url for now
		document.write('<link href="http://' + findRootUrl() + '/favicon.ico" rel="shortcut icon"  type="image/x-icon">\n');
	} else if (bCode == "MSIE" && bVers == 5) {
		// doesn't care about favicon
		document.write('<!-- favicon not supported -->\n');
	} else if (bCode == "MSIE" && bVers >= 6) {
		// supports it, but can't follow partial link proplery
		document.write('<link href="http://' + findRootUrl() + '/favicon.ico" rel="shortcut icon">\n');
	} else if (bCode == "MOZ") {
		// knows how to follow the partial link properly
		document.write('<link href="favicon.ico" rel="shortcut icon" type="image/x-icon">\n');
	} else {
		document.write('<!-- favicon support unknown -->\n');
	}

	return;
}


// makeBreadCrumb
//
function makeBreadCrumb() {

	var theUrl = document.location.toString();
	var theUrlComponents = new Array();
	var theBreadCrumbTrail = "";
	var theExceptionUrl = "";
	
	// split the Url and stuff the pieces in theUrlComponents
	theUrlComponents = theUrl.split("/");
	
	// parse the url components
	//
	// skip everything up to theRootFolder and skip the last entry also 
	// because it will be an actual page.
	//
	for (var i=1; i < theUrlComponents.length -1; i++) {
		
		// there are more items, add an arrow
		//
		// NOTE: If this is the first item ("home") then the arrow will be 
		// erased as the string will be reset.
		//
		theBreadCrumbTrail += " > ";

		// Create the trail item. This section could be written more tightly but it
		// wouldn't be as clear. I hate nesting if/else blocks deeply! 
		if(theUrlComponents[i] == gRootFolder) {
			// We're at the root folder, so replace the root folder with a reference 
			// to "home".
		
			theBreadCrumbTrail = "";
			
			// now make everything that cames before "home"
			theBreadCrumbTrail +="<A HREF=\""+theUrl.substring(0,theUrl.indexOf("/"+theUrlComponents[i])+theUrlComponents[i].length+1)+"/\">home</A> ";
						
		} else if((theExceptionUrl = getBreadCrumbException(theUrlComponents[i])) != "") {
			// We're somewhere after the root folder (not at the home page) but 
			// there's an exception.
		
			if (i < theUrlComponents.length -2) {
			
				// we're in the path, make these items links
				theBreadCrumbTrail +="<A HREF=\""+theExceptionUrl+"\">"+theUrlComponents[i]+"</A> ";

			} else {
				// we're on the last element in the path, don't make it a link!
				theBreadCrumbTrail +=theUrlComponents[i];
				
			}
		
		} else {
			// We're somewhere after the root folder (not at the home page) so make
			// the appropriate entry.
			
			if (i < theUrlComponents.length -2) {
			
				// we're in the path, make these items links
				theBreadCrumbTrail +="<A HREF=\""+theUrl.substring(0,theUrl.indexOf("/"+theUrlComponents[i])+theUrlComponents[i].length+1)+"/\">"+theUrlComponents[i]+"</A> ";
					

			} else {
				// we're on the last element in the path, don't make it a link!
				theBreadCrumbTrail +=theUrlComponents[i];
				
			}

		}
		
		

	}
	
	document.writeln(theBreadCrumbTrail);
	
}


// getBreadCrumbException()
//
// Check the gBCExceptionList hash to see if the key passed has an entry. 
// If it does, return the associated url othewise return null.
//
// Receive: -string containing the key (directory name) to search for.
//
function getBreadCrumbException(inDirectoryName) {

	var theValue = "";
	
	// check the exceptions list to see if it contains an entry for
	// inDirectoryName
	//
	// NOTE: To avoid an "undefined property warning" we first make sure
	// that there is an entry by using the typeof operator to check what we
	// get back if we ding the associative array with inDirectoryName. If
	// we get back an undefined type then we know there wasn't an entry; on
	// the other hand if we get back a valid type then we just go ahead and
	// ding the array again to retrieve the value.
	//
	if(typeof gBCExceptionList[inDirectoryName] != "undefined") {

        // see if there is an entry in the exceptions list, if so get it,
        // otherwise theValue will be set to undefined.
        theValue = gBCExceptionList[inDirectoryName];
	}
		
	return theValue;
}


// makeUrlFromDocroot
//
// Prepend the root url to the url that is passed to this function and return
// the new string.
//
function makeUrlFromDocroot(inUrl) {

	var theDocrootUrl = "";
	
	
	// add the docroot url
	theDocrootUrl += findRootUrl();
	
	// add the inUrl to finish
	theDocrootUrl += inUrl;
	
	
	return theDocrootUrl;

}


// findRootUrl()
//
// Determines where the root folder is based on the name of the root folder
// and the complete path to the page where this function was called.
//
function findRootUrl() {

	var theUrl = document.location.toString();	// location of calling page
	var theUrlComponents = new Array();
	var theRootUrl = "";
	
	
	// split the Url and stuff the pieces in theUrlComponents
	theUrlComponents = theUrl.split("/");
	
	// parse the url components and stop when we find the name of the root
	// folder (specified by gRootFolder).
	//
	for (var i=1; i < theUrlComponents.length -1; i++) {
	

		if(theUrlComponents[i] == gRootFolder) {
			
			// the url is everything up to this point
			theRootUrl += theUrl.substring(0,theUrl.indexOf("/"+theUrlComponents[i])+theUrlComponents[i].length+1);
									
		}		
		

	}
	
	return theRootUrl;
	
}


// findImagesUrl()
//
// Determines where the image folder is based on the name of the root folder,
// the name of the image folder, and the complete path to the page where this 
// function was called.
//
function findImagesUrl() {

	var theImagesUrl = "";
	

	// add the root url to our images url
	theImagesUrl += findRootUrl();
	
	// now add the images folder
	theImagesUrl += gImageFolder;
	
	
	return theImagesUrl;
	
}


// showRootUrl
//
// Just spit out the value returned by findRootUrl().
//
function showRootUrl() {

	document.write("DocRoot URL=\n");
	document.writeln(findRootUrl());
	
	return;
}


// findImagesUrl()
//
// Determines where the image folder is based on the name of the root folder,
// the name of the image folder, and the complete path to the page where this 
// function was called.
//
function findImagesUrl_old() {

	var theUrl = document.location.toString();
	var theUrlComponents = new Array();
	var theImagesUrl = "";
	
	
	// split the Url and stuff the pieces in theUrlComponents
	theUrlComponents = theUrl.split("/");
	
	// parse the url components
	//
	// skip everything up to theRootFolder and skip the last entry also 
	// because it will be an actual page.
	//
	for (i=1; i < theUrlComponents.length -1; i++) {
	

		if(theUrlComponents[i] == gRootFolder) {
			
			// now make everything that came before "home"
			theImagesUrl += theUrl.substring(0,theUrl.indexOf("/"+theUrlComponents[i])+theUrlComponents[i].length+1);
			
			// now add the images folder
			theImagesUrl += gImageFolder;
						
		}		
		

	}
	
	return theImagesUrl;
	
}


// showImagesUrl
//
// Just spit out the value returned by findImagesUrl().
//
function showImagesUrl() {

	document.write("Images URL=\n");
	document.writeln(findImagesUrl());
	
	return;
}


// getObject()
//
// NOTE: -Netscape 4,5 are not supported.
//
// Receive: -ID of object (this is the contents of the element's id tag)
//
// Returns: -reference to the object
//
function getObject(id) {

    var theObj;

    if (document.getElementById) {  // all modern browsers including
                                    // Netscape 6 and IE5
        // get the element
        theObj = document.getElementById(id);

    } else if (document.all) {      // IE 4

        // get the element
        theObj = document.all[id];
    }
                  
    return theObj;
  
} // end of getObject


// getObjectText()
//
// NOTE: -Netscape 4,5 are not supported.
//
function getObjectText(id) {

    var theObj;
    var theText = "";
    
    // get a reference to the object
    theObj = getObject(id);
    
    // get the text if we have an object
    if(theObj != null)
        theText = theObj.innerHTML;
                         
    return theText;            
}


// setObjectText()
//
// NOTE: -Netscape 4,5 are not supported.
//
// Receive: -ID of object (this is the contents of the element's id tag)
//          -text containing the new string value
//
// Returns: Nothing.
//
function setObjectText(id, text) {

    var theObj;
    
    // get a reference to the object
    theObj = getObject(id);
    
    // set the text if we have an object
    if(theObj != null && text != null) {
    
        // get around a bug found in Mac IE5.1 and higher, we need to clear
        // the object's innerHTML first
        theObj.innerHTML = '';
        
        // write new text
        theObj.innerHTML = text;
    }

              
    return;
} // end of setObjectText()



// getFormObject()
//
// Get a reference to a form.
//
// Receive: -name of form that contains the desired element
//
// Returns: -reference to the object
//
function getFormObject(inFormName) {

    var theFormObj;

    // get the form object
    theFormObj = eval('document.' + inFormName);
                  
    return theFormObj;
  
} // end of getFormObject()


// getFormElementCount()
//
// Return the number of elements in the form specified by name.
//
// Receive: -name of form
//
// Returns: -number of elements in the form
//
function getFormElementCount(inFormName) {

    var theFormObj;
    var theCount = 0;
    
    // make sure the form exists
    theFormObj = getFormObject(inFormName);
    
    if(theFormObj != null)
        theCount = theFormObj.elements.length;
    
    return theCount;

} // end of getFormElementCount()


// getFormElementByIndex()
//
// Get a reference to a form element.
//
// Receive: -name of form that contains the desired element
//          -index of element
//
// Returns: -reference to the object
//
function getFormElementByIndex(inFormName, inElementIndex) {

    var theFormObj;
    var theElementObj;
    
    // make sure the form exists
    theFormObj = getFormObject(inFormName);
    
    if(theFormObj != null)
        theElementObj = theFormObj.elements[inElementIndex];
                  
    return theElementObj;
  
} // end of getFormElementByIndex()



// getFormElementByName()
//
// Get a reference to a form element.
//
// Receive: -name of form that contains the desired element
//          -name of element
//
// Returns: -reference to the object
//
function getFormElementByName(inFormName, inElementName) {

    var theFormObj;
    var theElementObj;
    var theObjStr;

    // make sure the form exists
    theFormObj = getFormObject(inFormName);

    if(theFormObj != null)
        theElementObj = theFormObj[inElementName];
                  
    return theElementObj;
  
} // end of getFormElementByName()


// getMenuCurrentVal() {
//
// Get the current value of the pulldown menu specified by name.
// The "name" is whatever is specified as the "NAME" tag for the
// target menu.
//
//
function getMenuCurrentVal(inFormName, inMenuName) {

    var theMenuObj = getFormElementByName(inFormName, inMenuName);
    var theMenuIndexVal = 0;
    var theMenuStringVal = "";

    if(theMenuObj != null) {
    
        theMenuIndexVal = theMenuObj.selectedIndex;
        theMenuStringVal = theMenuObj.options[theMenuIndexVal].value;
    }
    
    return theMenuStringVal;
    
} // end of getMenuCurrentVal()


// dollarValue
//
// Format a number as a dollar value with two decimal places.
//
// Receive: -number or string containing a number
//
// Returns: -formatted string
//
function dollarValue(number) {

    var theNumber = parseFloat(number);
    var theDollarVal = "0.00";

    // only proceed if we have an actual number and not garbage
    if(!isNaN(theNumber) && theNumber > 0) {
    
        var theRoundedNumber;
        var theCentsVal;
    
        // convert to cents
        theRoundedNumber = (theNumber * 100);
        
        // round it
        theRoundedNumber = Math.round(theRoundedNumber);
        
        // convert back to dollars and cents
        theRoundedNumber = (theRoundedNumber / 100);
        
        // make sure we have two decimal places
        theDollarVal  = theRoundedNumber.toString();
        
        // add one or two zeroes as necessary after the decimal point
        theCentsVal = theDollarVal.substring(theDollarVal.indexOf(".")+1, theDollarVal.length);
        if(theCentsVal == "") {
        
            theDollarVal = theDollarVal + "00";
            
        } else if (theCentsVal < 10) {

            theDollarVal = theDollarVal + "0";
        }
    }
        
    return theDollarVal;
    
}  // end of dollarValue()


// arrayPuxh
//
// Push an object onto an array.
//
// This is a wrapper to provide consistency between browsers.
// Specifically, IE does not support Array.push() while Mozilla
// browsers do.
//
// NOTE: Make sure you call browserDetect() at some point before
// you call this function.
//
// Receive: -reference to an array to which to add an object
//          -reference to the object to add
//
// Returns: -Nothing
//
function arrayPush(inArray, inObj) {

    if(inArray == null) return;

    if(browserCode() != "MSIE") {
        // push the new object onto the array
        inArray.push(inObj);
        
    } else {
        // dynamically add the new object to the end of the array
        inArray[inArray.length] = inObj;
    }

    return;
} // end of arrayPush()


// arrayPuxh
//
// Push an object onto an array.
//
// This is a wrapper to provide consistency between browsers.
// Specifically, IE does not support Array.pop() while Mozilla
// browsers do.
//
// NOTE: Make sure you call browserDetect() at some point before
// you call this function.
//
// Receive: -reference to an array from which to remove the last
//          object.
//
// Returns: -reference to the popped object or null
//
function arrayPop(inArray) {

    var theObj = null;

    if(inArray == null) return null;

    if(browserCode() != "MSIE") {
        // pop the last element from the array
        theObj = inArray.pop(inObj);
        
    } else {
        // dynamically remove the last object from the array
        var theArrayLength = inArray.length;
        
        // get the last object
        theObj = inArray[theArrayLength - 1];
        
        // adjust the length of the array
        inArray.length = theArrayLength - 1;
    }

    return theObj;
} // end of arrayPop()


// insertExplorerAlphaFilter
//
// This is the IE6 hack to support PNG transparency for 24bit PNG images in
// MSIE 6 (Windows). This is not supposed to be necessary for IE7. Also, it is
// only backwards supported from IE5.5 but we'll just skip that detail and only
// apply it to IE6. Consequently, this function will return without having done
// anything if inImageUrl is empty or if the browser isn't a version of IE6.
//
// NOTE: You do need to wrap your target image in a div tag for this to work.
//
//  <div id="alpha_subscribe_gr">
//      <img id="alpha_subscribe_gr" src="images/subscribe_gr.png" />
//  </div>
//
// Notice how BOTH the div and the img have id tags with the same value. If you
// don't specify an id tag, then one will be assigned (automatically) with the
// following format:
//
//      alpha_FILENAME
//
// Where FILENAME is the filename WITHOUT the extension. And "alpha_" is a
// distinctive preamble with the goal that assigned tags won't collide with user
// assigned tags.
//
// If you only specify an inIdDivTag, then the same tag name will be used for
// BOTH the div and the img. If you specify BOTH the inIdDivTag and the inImgTag,
// then the supplied name will be applied for each.
//
// How it works
// ------------
// Inserts a CSS style that wraps the PNG image (targetted by inImageUrl) in a
// div, and then applies the MSIE 6 AlphaImageLoader filter.
//
// One more thing
// --------------
// You do not need to call this code in the HEAD portion of the page. Call it
// whenever you want in the body but call it BEFORE you place the target image.
//
function insertExplorerAlphaFilter(inImageUrl, inIdDivTag, inImgTag) {

    // this filter only applied for IE6
    if(!(browserCode() == "MSIE" && browserVers() >= 6 && browserVers() < 7)) return;

    // make sure we have an image url!
    if(inImageUrl == undefined || inImageUrl == "") return;
    
    // create a RegExp object to extract the file name
    var theRegEx = new RegExp("[a-zA-Z0-9_]+\.png$");
    
    // execute the pattern  and extract the file name
    var theFilename = theRegEx.exec(inImageUrl);

    // error? perhaps file other than .png was offered? bail out!
    if(theFilename == undefined || theFilename == "") return;
    
    // now remove the filename extension so we can use the name for a div tag
    theRegEx.compile("^[a-zA-Z0-9_]+");

    // create div tag
    var theDivTag = 'alpha_' + theRegEx.exec(theFilename);
    
    // override the assigned div id tag if the caller supplied one
    if(inIdDivTag != undefined && inIdDivTag != "") {
        theDivTag = inIdDivTag;
    }
    
    // create img tag
    var theImgTag = theDivTag;
    
    // override the assigned img id tag if the caller supplied one
    if(inImgTag != undefined && inImgTag != "") {
        theImgTag = inImgTag;
    }
    
    // insert alpha filter for 24bit png
    var doc = window.document;
    
    doc.writeln('<style type="text/css">');
    // first, apply alpha to the background image.
    doc.writeln('div#'+theDivTag+' {');    
    doc.writeln('display: inline-block;');
    doc.writeln('background: none;');
    doc.writeln('filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src="'+inImageUrl+'",sizingMethod="");');
    doc.writeln('cursor: pointer;');
    doc.writeln('}');
    // apply transparency to the target image so the Alpha image can show through
    doc.writeln('img#'+theImgTag+' {');
    doc.writeln('filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);');
    doc.writeln('}');
    doc.writeln('</style>');
    

    return;
}


// mmjs_truncateStr
//
// Truncate a string by replacing the middle part with a pattern (...).
//
function mmjs_truncateStr(inStr, inMaxLen) {
    
    var theStrLen = inStr.length;
    var theCutPattern = "..."; // replace middle with cut pattern
    var theNewStr = "";
    
    theTruncLen = theStrLen - (inMaxLen + theCutPattern.length);
    
    if(theTruncLen > 0) {
        // half of the truncation will appear on either side of the middle
        //
        // -start truncation at the middle of the string, minus half of truncLen
        // -end truncation at the middle of the string, plus half o the truncLen.
        //
        theNewStr += inStr.substr(0, (theStrLen/2)-(theTruncLen/2));
        theNewStr += "...";
        theNewStr += inStr.substr((theStrLen/2)+(theTruncLen/2));
    } else {
        // just return the original string, nothing to truncate
        theNewStr = inStr;
    }
    
    return theNewStr;
}

// mmjs_changeStyleSheet
//
// Enable the existing style sheet named inEnableCSSTitle, and disable the style
// sheet named inDisableCSSTitle.
//
// This function lets you apply styles dynamically by swapping stylesheets.
//
// NOTE: You must load both of the stylesheets whose titles you pass to this
// function. That is, they must both appear in link tags in the head section of
// your html page.
//
// NOTE: Make sure you disable the secondary (or replacement) stylesheet on or
// right after page load. In other words, you need to make a call to this function
// with the names of both sheets with the inEnableCSSTitle targetting the sheet
// you want enabled at the starting.
//
function mmjs_changeStyleSheet(inEnableCSSTitle, inDisableCSSTitle) {
    // get array of of all links tags
    var lnks=document.getElementsByTagName("link");
   
    if(!lnks) { return };
   
    // iterate through the links tags array
    //
    // Only pay attention to links that contain a rel tag that includes "stylesheet"
    // (so that we ignore non css link tags) and includes a title attribute. When
    // we pass that test, we then disable the sheet with a title matching inDisableCSSTitle
    // and enable the sheet with a title matching inEnableCSSTitle.
    //
    for(var i=0; i<lnks.length; i++) {
        if((lnks[i].getAttribute("rel").toLowerCase()).indexOf("style") != -1
           && lnks[i].getAttribute('title')) {
            if(lnks[i].getAttribute('title') == inDisableCSSTitle) {
                lnks[i].disabled=true;
            }
            
            if(lnks[i].getAttribute('title') == inEnableCSSTitle) {
                lnks[i].disabled=false; 
            }
        }
    }
    
    return;
}

// mmjs_addLoadEvent
//
// Add a window onload event to the current list of onload events.
//
function mmjs_addLoadEvent(inNewFunction) {
    
    // preserve old onload list
    var prevOnloadList = window.onload;
    
    if (typeof window.onload != 'function') {
        window.onload = inNewFunction;
    } else {
        window.onload = function() {
            if (prevOnloadList) {
                prevOnloadList();
            }
            inNewFunction();
        }
    }
    
    return;
}
