<!--
	MMC Templates 2.5
	Version:		1.0.0.0
	Created:		2002-11-08
	Author:		John McCormick {Audacity, Inc.}
	Summary:	Creates a volume specific slider control for use in UI
	History:		
-->
<public:component tagName="volume">
	<public:attach event="oncontentready" onevent="DoContentReady()" />
	<public:attach event="ondocumentready" onevent="DoInit()" />
	<public:event name="oncontentchanged" id="eventOnContentChanged" />
	<public:event name="onchange" id="eventOnChange" />
	<public:event name="onerror" id="eventOnError"  />
	<public:property name="min" value="0" id="pMin" />
	<public:property name="max" value="100" id="pMax" />
	<public:property name="tickInterval" value="2" id="pTickInterval" />
	<public:property name="tickNumber" value="50" id="pTickNumber" />
	<public:property name="value" value="66" id="pValue" />
	<public:property name="name" value="null" id="pName" />
	<public:property name="title" value="null" id="pTitle" />
	<public:property name="dynamic" value="null" id="pDynamic" />
	<public:property name="sDebug" value="" id="pDebug" />
	<public:defaults viewlinkcontent="true" viewinheritstyle="true" />
</public:component>
<script language="jscript">
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//  Global Variables
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
var fOnContentReady = false;
var StyleInfo;						// Variable representing the stylesheet
var StyleRules = new Array();	// Array to track the individual stylesheet
var bIsForm = false;				// Tracks whether the element is in a form
var Orient;							// Direction of the slider
var iTempValue;					// Tracks value changes in the slider before they are applied to the actual value
var iBoundFirst;					// Tracks the min position as a pixel
var iBoundLast;					// Tracks the max position as a pixel
var iTickSpace;					// Tracks the space between pixels 
var bMouseDown;				// Tracks the status of the mouse button
var SLTOP = 			"images/slTop.gif";
var SLBOTTOM = 	"images/slBottom.gif";
var SLLEFT = 		"images/slLeft.gif";
var SLRIGHT = 		"images/slRight.gif";
var SLIDERGIF = 	"images/vol_slider_stat.gif";
var SLIDERROLL = 	"images/vol_slider_roll.gif";

//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//	Events - see file sliderEvents.js
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//<function>
//	<summary>Handles initialization functions for HTC object.</summary>
//	<returns>None</returns>
function DoContentReady()
{
	fOnContentReady = true;
}
//</function>

//<function>
//	<summary>Calls functions, set variables, and attaches events to initialize behavior</summary>
//	<returns>None</returns>
function DoInit()
{
	IsForm();
	SetDefaults();
	CreateStyleSheet();
	Format();
	CalcTicks();
	attachEvent("onpropertychange", DoPropChange);
}
//</function>

//<function>
//	<summary>
//		<para>Called during the initialization of the behavior.  Sets the defaults for custom CSS properties (calls the</param>
//       <para>CustomDefault() function), regular CSS properties (the NormalDefault() function), and attribute/properties.</para>
//	</summary>
//	<returns>None</returns>
function SetDefaults()
{
	//  Custom CSS Property Defaults
	CustomDefault('sl-orientation', 'slOrientation', 'horizontal');
	CustomDefault('sl-snap', 'slSnap', true);
	CustomDefault('sl-tick-color', 'slTickColor', 'black');
	CustomDefault('sl-tick-style', 'slTickStyle', 'bottomRight');
	CustomDefault('sl-bar-color', 'slBarColor', 'menu');

	//  Set global variable to track orientation
	Orient = (style.slOrientation == "vertical" ? "Ver" : "Hor" );

	//  CSS Property Defaults   
	NormalDefault('position', 'static', 'relative');
	NormalDefault('backgroundColor', 'transparent', 'menu');

	NormalDefault('width', 'auto', (Orient == 'Ver' ? '50px' : '200px'));
	NormalDefault('height', 'auto', (Orient == 'Ver' ? '200px' : '50px'));

	//  Attribute | Property Defaults
	if (dynamic== null)	{ dynamic= false; }
}
//</function>

//<function>
//	<summary>Sets the defaults for custom CSS properties and establishes a scriptable name for the property.</summary>
//	<param name="sCSSName">the CSS name of the property</param>
//	<param name="sScriptName">the desired Scriptable name of the property</param>
//	<param name="sDefault">the desired default value</param>
//	<returns>None</returns>
function CustomDefault(sCSSName, sScriptName, sDefault)
{
	if (currentStyle[sCSSName] == null)
	{
	   style[sCSSName] = sDefault;
	}
	else
	{ style[sCSSName] = currentStyle[sCSSName]; }
	    
	style[sScriptName] = style[sCSSName];
}
//</function>

//<function>
//	<summary>Sets the defaults for CSS properties by checking the currentStyle and style of the object against the IE default.</summary>
//	<param name="sCSSName">the CSS name of the property</param>
//	<param name="sIEDefault">the IE standard default of the property</param>
//	<param name="sDefault">the desired default of the property</param>
//	<returns>None</returns>
function NormalDefault(sCSSName, sIEDefault, sDefault)
{
	if (currentStyle[sCSSName] == sIEDefault && (style[sCSSName] == "" || style[sCSSName] == null))
	{
	   style[sCSSName] = sDefault;
	}
}
//</function>

//<function>
//	<summary>Handles property changes on CSS and regular property attributes.</summary>
//	<returns>None</returns>
function DoPropChange()
{
	var propertyName = window.event.propertyName;

	//  Handle CSS property changes by calling necessary functions, setting variables, and/or setting styles
	if (propertyName.substring(0,5) == "style")
	{
	   switch (propertyName)
	   {
	   case "style.slOrientation":
	       ReturnError("Property is Read Only"); 
	       break;
	                    
	   case "style.slTickStyle":
	       ReturnError("Property is Read Only");
	       break;
	                    
	   case "style.slTickColor":
	       StyleRules[Orient + 'Tick'].color = style.slTickColor;
	       break;
	                
	   case "style.slBarColor":
	       StyleRules[Orient + 'Bar'].backgroundColor = style.slBarColor;
	       break;
	                    
	   case "style.width":
	       StyleRules[Orient + 'Area'].width = style.width;
	       CalcTicks();
	       break;
	                    
	   case "style.height":
	       StyleRules[Orient + 'Area'].height = style.height;
	       CalcTicks();
	       break;
	                    
	   case "style.padding":
	       StyleRules[Orient + 'Area'].padding = style.padding;
	       CalcTicks();
	       break;
	                    
	   case "style.backgroundColor":
	       StyleRules[Orient + 'Area'].backgroundColor = style.backgroundColor;
	       break;
	                
	   case "style.margin":
	       break;
	                
	   case "style.slSnap":
	       break;
	   }
	}
	else
	{
	   //  Detach the onpropertychange event to prevent it from firing while the changes are handled
	   detachEvent("onpropertychange", DoPropChange);
	        
	   switch(propertyName)
	   {
		case "name":
		    if (bIsForm) window.document.all['inp_' + uniqueID].name = name;
		    break;
			        
		case "value":
		    if (bMouseDown) break;
		    if (bIsForm) window.document.all['inp_' + uniqueID].value = value;
		    SetSlider();
		    break;
			            
		case "min":
		    CalcTicks(propertyName);
		    break;
			                
		case "max":
		    CalcTicks(propertyName);
		    break;

		case "tickInterval":
		    CalcTicks(propertyName);
		    break;

		case "tickNumber":
		    CalcTicks(propertyName);
		    break;
			                
		case "dynamic":
		    break;
			                
		case "title":
		    break;
			            
		default:
		    ReturnError(propertyName + " not a valid property");
		    break;
	   }
	        
	   //  Re-attach the onpropertychange event
	   element.attachEvent("onpropertychange", DoPropChange);
	}
}
//</function>

//<function>
//	<summary>If the mousedown occurs on the slider piece, initiate movement of the slider.</summary>
//	<returns>false if the srcElement is not the slider piece.</returns>
function DoMouseDown()
{
	bMouseDown = true;
	var oSliderToggle = objSliderHost.children['slider_' + uniqueID];
	var oBar = objSliderHost.children['bar_' + uniqueID];
	if (window.event.srcElement.id == oBar.id)
	{
		DoMouseMove();
		return false;
	}
	if (window.event.srcElement.id != oSliderToggle.id) return false;
	    
	//  Capture the mouse and start tracking the onmousemove event
	oSliderToggle.setCapture();
	oSliderToggle.attachEvent ("onmousemove", DoMouseMove);
}
//</function>

//<function>
//	<summary>Move the slider piece within the boundaries of the slider bar.</summary>
//	<returns>None</returns>
function DoMouseMove()
{
	//  Move the slider within the bounds of the bar
	if (Orient == "Hor") 
	{
		var iNewX = window.event.x - 4;
		if (!objSliderHost.contains(window.event.srcElement))	{ iNewX -= offsetLeft + window.document.body.scrollLeft; }
		if (iNewX > iBoundLast)	{ iNewX = iBoundLast; }
		if (iNewX < iBoundFirst) { iNewX = iBoundFirst; }
		objSliderHost.children['slider_' + uniqueID].style.left = iNewX;
		iTempValue = iNewX;
	}
	else if (Orient == "Ver")
	{
		var iNewY = window.event.y - 4;
		if (!objSliderHost.contains(window.event.srcElement))	{ iNewY -= offsetTop - window.document.body.scrollTop; }
		if (iNewY > iBoundLast)	{ iNewY = iBoundLast; }
		if (iNewY < iBoundFirst) { iNewY = iBoundFirst; }
		objSliderHost.children['slider_' + uniqueID].style.top = iNewY;
		iTempValue = iNewY;
	}

	// If the dynamic property is true, repeatedly call the DoChange() function
	if (dynamic == "true" || dynamic == true) { DoChange(); }
}
//</function>

//<function>
//	<summary>On the mouseup, release the slider piece.  If the slSnap property is true, place the slider at one of the tick marks.</summary>
//	<returns>None</returns>
function DoMouseUp()
{
	bMouseDown = false;
	var oSliderToggle = objSliderHost.children['slider_' + uniqueID];

	if (style.slSnap != false && style.slSnap != "false")
	{
		var iCurrPos = 0;
		var iDiff = 0;
		var iNewPos = 0;
		    
		if (Orient == "Ver")
			{ iCurrPos = oSliderToggle.style.posTop; }
		else 
			{ iCurrPos = oSliderToggle.style.posLeft; }

		//  Find the closest tick mark to snap to        
		iCurrPos = (iCurrPos - iBoundFirst)/iTickSpace;
		iDiff = (iCurrPos - Math.floor(iCurrPos)) * iTickSpace;
		iNewPos = (Math.floor(iCurrPos) * iTickSpace) + iBoundFirst;
		if (iDiff > iTickSpace/2) 	{ iNewPos += iTickSpace; }

		//  Set the tracking variable to the value of the tick mark 
		iTempValue = iNewPos;
		
		//  Set the position of the slider piece to the tick mark
		if (Orient == "Ver") 
			{ oSliderToggle.style.top = iNewPos; }
		else
			{ oSliderToggle.style.left = iNewPos; }
	}

	//  Stop tracking the onmousemove event and release the mouse
	oSliderToggle.detachEvent ("onmousemove", DoMouseMove);
	oSliderToggle.releaseCapture();

	//  Call the DoChange() function to set the value of the element
	DoChange();
}
//</function>

//<function>
//	<summary>Change the value of the slider, based on its position on the bar.</summary>
//	<returns>None</returns>
function DoChange()
{
	//  Iterate through the tick mark's to determine which tick the slider is on (in the case of snapable = true) or closest to (in the case
	//  of snapable = false).  Base the value of the slider on that tick mark
	for (i=0; i<tickNumber; i++)
	{
	   var oTick = objSliderHost.children["tick" + i + "_" + uniqueID];

	   if  (!bMouseDown && ((Orient == "Hor" && oTick.style.posLeft == iTempValue + 4)
	      || (Orient == "Ver" && oTick.style.posTop == iTempValue + 4)))
	   {
	      value = parseFloat(oTick.title);
	      break;
	   }

	   else if ((Orient == "Hor" && oTick.style.posLeft > iTempValue + 4) || (Orient == "Ver" && oTick.style.posTop > iTempValue + 4))
	   {
	      value = ((iTempValue/(iBoundLast-iBoundFirst))*(max-min)) + min;
	      break;
	   }
	}
	//	Set the value of the element    
	if (min > value) { value = min; }
	if (max < value) { value = max; }
	objSliderHost.children['slider_' + uniqueID].title = String(parseInt(value)) + "%";
	
	//	Fire the change event
	eventOnChange.fire();
}
//</function>

//<function>
//	<summary>Cancels the onselectstart event to prevent user from selecting text in the slider.</summary>
//	<returns>false (returnValue)</returns>
function DoSelectStart()
{
   window.event.returnValue = false;
   window.event.cancelBubble = true;
}
//</function>

//<function>
//	<summary>Fires the error event, along with a descriptive text message.</summary>
//	<param name="sMsg">descriptive text message</param>
//	<returns>None</returns>
function ReturnError(sMsg)
{
   var oEvent = createEventObject();
   oEvent.setAttribute("error", sMsg);
   eventOnError.fire(oEvent);
}
//</function>

//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//	Methods
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//<function>
//	<summary></summary>
//	<returns>None</returns>
//</function>

//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//	Properties
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//<function>
//	<summary></summary>
//	<returns>None</returns>
//</function>

//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//	Private - see file sliderPrivate.js
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//	<summary>Adds HTML and CSS formatting (via the BehaviorStyleSheet)</summary>
//	<returns>None</returns>
function Format()
{
	var strToggle="";
	if (Orient == "Hor")
	{
		className = "HorArea_" + uniqueID;
		if (style.slTickStyle == "topLeft") 
			{ sSliderSrc = SLIDERGIF; }
		else
			{ sSliderSrc = SLIDERGIF; }
		strToggle += "<div id=\"bar_" + uniqueID + "\" class=\"HorBar_" + uniqueID + "\" onmouseover=\"this.style.cursor='hand';\"></div>";
		strToggle += "<img id=\"slider_" + uniqueID + "\" src=\"" + sSliderSrc + "\" class=\"HorSlider_" + uniqueID + "\" vspace=\"3\"";
		strToggle += " onmouseover=\"this.style.cursor='hand';doToggleRollState(this);\" onmouseout=\"doToggleStatState(this);\">";
		objSliderHost.innerHTML = strToggle;
	}
	else
	{
		className = "VerArea_" + uniqueID;
		if (style.slTickStyle == "topLeft") 
			{ sSliderSrc = SLIDERGIF; }
		else 
			{ sSliderSrc = SLIDERGIF; }
		strToggle += "<div id=\"bar_" + uniqueID + "\" class=\"VerBar_" + uniqueID + "\" onmouseover=\"this.style.cursor='hand';\"></div>";
		strToggle += "<img id=\"slider_" + uniqueID + "\" src=\"" + sSliderSrc + "\" class=\"VerSlider_" + uniqueID + "\" hspace=\"3\"";
		strToggle += " onmouseover=\"this.style.cursor='hand';doToggleRollState(this);\" onmouseout=\"doToggleStatState(this);\">";
		objSliderHost.innerHTML = strToggle;
	}
}
function doToggleRollState(obj)
{
	obj.src = SLIDERROLL;
}
function doToggleStatState(obj)
{
	obj.src = SLIDERGIF;
}
//</function>

//<function>
//	<summary>
//		<para>Adds necessary styles for the slider piece, tick marks, bar, and slider area to the BehaviorStyleSheet (which is</para>
//        <para> added if it doesn't already exist.  Each style is assigned a position in the StyleRules array for easy access later.</para>
//	</summary>
//	<returns>None</returns>
function CreateStyleSheet()
{
	//  If it's not already created, create a style sheet.
	if (! document.body.BehaviorStyleSheet)
	{
		document.body.BehaviorStyleSheet = document.createStyleSheet();
	}
	StyleInfo = document.body.BehaviorStyleSheet;

	//  Horizontal Slider StyleSheet Rules
	StyleInfo.addRule('.HorArea_' + uniqueID, 'position: ' + style.position + '; '
	 + 'height: ' + style.height + '; '
	 + 'width: ' + style.width + '; '
	 + 'background-color: ' + style.backgroundColor + '; '
	 + 'border: 1px solid white; '
	);
	StyleRules['HorArea'] = StyleInfo.rules[StyleInfo.rules.length-1].style;

	//2002-12-03: Height changed from 3px to 11px
	StyleInfo.addRule('.HorBar_' + uniqueID, 'width: 100%; '
	   + 'position: relative; '
	   + 'height: 11px; '
	   + 'font: 0px; '
	   + 'left: 0px; '
	   + 'background-color: ' + style.slBarColor + '; '
	   + 'text-align:center; '
	   + 'border:0px; '
	);
	StyleRules['HorBar'] = StyleInfo.rules[StyleInfo.rules.length-1].style;
	//2002-12-03: Horizontal top changed
	StyleRules['HorBar'].setAttribute("top", (style.slTickStyle == 'topLeft' ? '62%' : '7px'));

	StyleInfo.addRule(   '.HorSlider_' + uniqueID, 'position:absolute; bottom:3px; ');
	StyleRules['HorSlider'] = StyleInfo.rules[StyleInfo.rules.length-1].style;

	StyleInfo.addRule(   '.HorTick_' + uniqueID, 'position: absolute; '
	 + 'width: 5px; '
	 + 'color: ' + style.slTickColor + '; '
	 + 'cursor: hand; '
	 + 'margin: 0px; '
	 + 'padding: 0px; '
	 + 'font: bold 4pt'
	);
	StyleRules['HorTick'] = StyleInfo.rules[StyleInfo.rules.length-1].style;
	StyleRules['HorTick'].setAttribute("visibility", (style.slTickStyle == 'none' ? 'hidden' : 'visible'));

	//  Vertical Slider StyleSheet Rules
	StyleInfo.addRule(   '.VerArea_' + uniqueID, 'position: ' + style.position + '; '
	 + 'height: ' + style.height + '; '
	 + 'width: ' + style.width + '; '
	 + 'background-color: ' + style.backgroundColor
	);
	StyleRules['VerArea'] = StyleInfo.rules[StyleInfo.rules.length-1].style;

	StyleInfo.addRule(   '.VerBar_' + uniqueID, 'position: relative; '
	 + 'height: 95%; '
	 + 'top: 2.5%; '
	 + 'width: 4px; '
	 + 'background-color: ' + style.slBarColor + '; '
	 + 'border: 1px inset white'
	);
	StyleRules['VerBar'] = StyleInfo.rules[StyleInfo.rules.length-1].style;
	StyleRules['VerBar'].setAttribute("left", (style.slTickStyle == 'topLeft' ? '60%' : '32%'));

	StyleInfo.addRule(   '.VerSlider_' + uniqueID, 'position: absolute');
	StyleRules['VerSlider'] = StyleInfo.rules[StyleInfo.rules.length-1].style;
	    
	StyleInfo.addRule(   '.VerTick_' + uniqueID, 'position: absolute; '
	 + 'height: 5px; '
	 + 'color: ' + style.slTickColor + '; '
	 + 'cursor: hand; '
	 + 'margin: 0px; '
	 + 'padding: 0px; '
	 + 'font: bold 16px'
	);
	StyleRules['VerTick'] = StyleInfo.rules[StyleInfo.rules.length-1].style;
	StyleRules['VerTick'].setAttribute("visibility", (style.slTickStyle == 'none' ? 'hidden' : 'visible'));
}
//
//</function>

//<function>
//	<summary>
//		<para>Walks up the parentElements of the element until it finds either a FORM object or the BODY object.  If it's inside</para>
//		<para>of a form, a hidden INPUT object is added.  Value changes in the slider are duplicated in the INPUT.  Thus, when</para>
//		<para>the form is submitted, effectively the slider name/VALUE pair is included as well.</para>
//</summary>
//	<returns>None</returns>
function IsForm()
{
	return;
	var oFormCheck = element;
	
	//  Climb from the element through its parentElement's until finding either the BODY tag or a FORM tag
	while (oFormCheck.tagName.toLowerCase() != "body")
	{
		if (oFormCheck.tagName.toLowerCase() == "form" && name != null)
		{
		   //  Set variable
		   bIsForm = true;
		     
		   //  Insert hidden INPUT into form
		   sInputHTML = '<input type="hidden" id="inp_' + uniqueID + '" ' + 'name="' + name + '" value="' + value + '">';
		   oFormCheck.insertAdjacentHTML ("BeforeEnd", sInputHTML);
		         
		   break;
		}
		else 
		{ oFormCheck = oFormCheck.parentElement; }
	}
}
//</function>

//<function>
//	<summary>Remove the existing tick marks by renaming them and making them invisible.</summary>
//	<returns>None</returns>
function DeleteTicks()
{
	for (i=0; i<objSliderHost.children.length; i++)
	{
		if (objSliderHost.children(i).id.substring(0,4) == "tick") 
		{
			objSliderHost.children(i).id = "deletedTick";
			objSliderHost.children(i).style.visibility = "hidden";
		}
	}
}
//</function>

//<function>
//	<summary>
//		<para>In conjuction with TickFormula(), determine the desired position of the tick marks, based on four properties:</para>
//		<para>min, max, tickInterval, and tickNumber.</para>
//	</summary>
//	<param name="sAttribute">the specific property that has changed - (null at design time)</param>
//	<returns>true once the formula is set / false if the max is set lower than the min / false if the tickInterval is set to negative</returns>
function CalcTicks(sAttribute)
{

	//  If tick marks already exist, delete them
	if (objSliderHost.children['tick0_' + uniqueID] != null) DeleteTicks();

	//  Get Properties and Parse Accordingly
	//** Audacity, Inc.
	if (min != null) { min = parseFloat(min); } else { min = 0; }
	if (max != null) { max = parseFloat(max); } else { max = 100; }
	if (tickInterval != null) { tickInterval = parseFloat(tickInterval); }
	if (tickNumber != null) { tickNumber = parseFloat(tickNumber); }

	//  Return if max is less than min or tickInterval is negative
	if ((max <= min && max != null && min != null) || (tickInterval <= 0 && tickInterval != null))
	{
		ReturnError("MAX cannot have a value less than MIN, and TICKINTERVAL cannot be greater than zero.");
		return false;
	}

	//  Check if the formula works without setting defaults
	if (TickFormula(sAttribute)) 
	{
		CreateTicks();
		return true;
	}

	//  Set the tickInterval, should work this time (with 3 defaults set)
	tickInterval = 1;
	if (TickFormula())
	{
		CreateTicks();
		return true;
	}

	//  If it doesn't work, fire an error    
	ReturnError("Can't determine Ticks");
}
//</function>

//<function>
//	<summary>
//		<para>In conjunction with the CalcTicks() function, determine the desired position of the tick marks, based on four properties:</para>
//		<para>min, max, tickInterval, and tickNumber.</para>
//	</summary>
//	<param name="sAttribute">the specific property that has changed - (null at design time)</param>
//	<returns>true once the formula is set / else false</returns>
function TickFormula(sAttribute)
{
	if ((min != null && max != null && tickInterval != null) && sAttribute != "tickNumber")
	{
	   tickNumber = (max - min)/tickInterval + 1;
	   return true;
	}
	else if ((min != null && max != null && tickNumber != null) && sAttribute != "tickInterval")
	{
	   tickInterval = (max - min)/(tickNumber - 1);
	   return true;
	}
	else if ((min != null && tickInterval != null && tickNumber != null) && sAttribute != "max")
	{
	   max = min + ((tickNumber - 1) * tickInterval);
	   return true;
	}
	else if ((max != null && tickInterval != null && tickNumber != null) && sAttribute != "min")
	{
	   min = max - ((tickNumber - 1) * tickInterval);
	   return true;
	}
}
//</function>

//<function>
//	<summary>Add the tick marks to the page.</summary>
//	<returns>None</returns>
function CreateTicks()
{
	var sTickHTML, sTickChar, sTickClass;
	
	//  Set class and character based on the style.slOrientation property    
	if (Orient == "Ver") 
	{
		sTickChar = "-";
		sTickClass = "Ver";
	}
	else 
	{
		sTickChar = "|";
		sTickClass = "Hor";
	}
	    
	for (i=0; i<tickNumber; i++)
	{
		//  Write tick to page
		sTickTitle = "title='" + ((i * tickInterval) + min) + "' ";
		sTickHTML = "<span id=\"tick" + i + "_" + uniqueID + "\" class=\"" + sTickClass + "Tick_" + uniqueID + "\" " + sTickTitle + " " + ">" + sTickChar + "</span>";
		objSliderHost.insertAdjacentHTML("BeforeEnd", sTickHTML);
	}
	    
	//  Call function to place ticks
	SetTicks();
}
//</function>

//<function>
//	<summary>Based on the settings of min, max, tickInterval, and tickNumber, place the tick marks on the slider.</summary>
//	<returns>None</returns>
function SetTicks()
{
	var iBarLength, iBarStart;
	var oTick, iTickStart, iTickPos;
	var iTickSize = 2;

	//  Based on the style.slOrientation property, determine the length of the bar and it's starting pixel position
	if (Orient == "Hor") 
	{
		iBarLength = objSliderHost.children['bar_' + uniqueID].offsetWidth;
		iBarStart = objSliderHost.children['bar_' + uniqueID].offsetLeft;
	}
	else 
	{
		iBarLength = objSliderHost.children['bar_' + uniqueID].offsetHeight;
		iBarStart = objSliderHost.children['bar_' + uniqueID].offsetTop;
	}

	//.98 *  Determine the amount of space that should be between each tick mark.    
	iTickSpace = (( iBarLength) - (iTickSize * tickNumber))/(tickNumber - 1);
	iTickSpace = (iTickSpace > 0 ? Math.floor(iTickSpace) : Math.ceil(iTickSpace));
	iTickSpace = (iTickSpace + iTickSize);

	//  Determine where the first tick should be placed    
	iTickPos = (iBarLength - (iTickSpace * (tickNumber - 1)))/2;
	iTickPos = (iTickPos > 0 ? Math.floor(iTickPos) : Math.ceil(iTickPos));
	iTickPos += iBarStart;
	iTickStart = iTickPos;

	//  Set the global iBoundFirst and iBoundLast variables
	iBoundFirst = iTickStart - 4;
	iBoundLast = iTickStart + ((tickNumber - 1) * iTickSpace) - 4;

	var oBar = objSliderHost.children['bar_' + uniqueID];
	//  Write ticks to page based on the orientation and tickStyle of the element.  
	for (i=0; i<tickNumber; i++)
	{
		oTick = objSliderHost.children["tick" + i + "_" + uniqueID];
		if (Orient == "Ver") 
		{
			oTick.style.top = iTickPos - 10;
			if (style.slTickStyle == "topLeft")
				{ oTick.style.left = oBar.offsetLeft - 14; }
			else
				{oTick.style.left = oBar.offsetLeft + 14; }
		}
		else
		{
			oTick.style.left = iTickPos;
			if (style.slTickStyle == "topLeft")
				{ oTick.style.top = oBar.offsetTop - 14; }
			else 
				{ oTick.style.top = oBar.offsetTop + 14; }
		}
		iTickPos += iTickSpace
	}
	
	//  Call function to position the slider    
	SetSlider();
}
//</function>

//<function>
//	<summary>Based on the positions of the tick marks and the value of the element, place the slider.</summary>
//	<returns>false if the max is set lower than the min / false if the tickInterval is set to negative</returns>
function SetSlider()
{
	if ((max <= min && max != null && min != null) || (tickInterval <= 0 && tickInterval != null))
	{
	   return false;
	}

	var oSliderToggle = objSliderHost.children['slider_' + uniqueID];
	var oBar = objSliderHost.children['bar_' + uniqueID];
	var oFirstTickVal = eval(objSliderHost.children['tick0_' + uniqueID].title);

	if (value == null || value < min)
	{
	   value = oFirstTickVal;
	}

	if (Orient == "Ver")
	{
	   oSliderToggle.style.top = iBoundFirst + (((value - oFirstTickVal)/tickInterval)* iTickSpace);

	   if (style.slTickStyle == "topLeft")
	   {        
	      oSliderToggle.style.left = oBar.offsetLeft - 9; 
	   }
	   else
	   	{ oSliderToggle.style.left = oBar.offsetLeft - 7; }
	}

	else 
	{
	   oSliderToggle.style.left = iBoundFirst + (((value - oFirstTickVal)/tickInterval)* iTickSpace);

	   if (style.slTickStyle == "topLeft")
	   {
	      oSliderToggle.style.top = oBar.offsetTop - 9; 
	   }
	   else
	   	{ oSliderToggle.style.top = oBar.offsetTop - 7; }
	}
	DoMouseUp();
}
//</function>
</script>
<body background="images/volume_ctrl_uplvl2.gif">
<div id="objSliderHost" style="position:relative; left:0px; top:0px; height:100%; z-index:11;" onmousedown="DoMouseDown()" onmouseup="DoMouseUp()" onselectstart="DoSelectStart()"></div>
</body>