<!--
  Usage Note:
  General syntax of instantiating spinbox is as follows.

  <sds:spinbox value="..." minvalue="..." maxvalue="..." size="..." />

  All attributes are optional. maxvalue and minvalue specifies upper and
  lower limits of values in the text when up and down arrows are pressed.
  size specifies width (in terms of number of characters) for text box.
   	   	 
  example:
  
  <html xmlns:sds>
  <head>
  .....
  <style>
  @media all
  {
    sds\:spinbox {behavior:url(spinbox.htc);}
  }
  </style>
  <script language="JavaScript" src="spinbox.js"></script>
  </head>
  
  <body>
  <script language="JavaScript" for="window" event="onload()">
  .....
  SetContinuousSpin("test_spin");	// optional, when continuous spin is needed
  .....
  </script>
  
  <sds:spinbox id="test_spin" value="10" minvalue="0" size="6" />
  </body>
-->

<PUBLIC:HTC URN="spinbox">

<PUBLIC:PROPERTY NAME="value" />
<PUBLIC:PROPERTY NAME="minvalue" />
<PUBLIC:PROPERTY NAME="maxvalue" />
<PUBLIC:PROPERTY NAME="size" />

<PUBLIC:METHOD NAME="SpinUp" />
<PUBLIC:METHOD NAME="SpinDown" />
<PUBLIC:METHOD NAME="SetValue" />
<PUBLIC:METHOD NAME="GetValue" />

<PUBLIC:EVENT ID="Increment" NAME="onincrement" />
<PUBLIC:EVENT ID="Decrement" NAME="ondecrement" />
<PUBLIC:EVENT ID="ValueChanged" NAME="onvaluechanged" />
<PUBLIC:EVENT ID="SpinCompleted" NAME="onspincompleted" />

<PUBLIC:ATTACH EVENT="ondocumentready" HANDLER="DoInit" />

<script language="JavaScript">
// global constants and variables
var DEFAULT_VALUE = 0;
var DEFAULT_MINVALUE = 0;
var DEFAULT_MAXVALUE = 65335;
var DEFAULT_SIZE = 6;
var initialized = false;

// initialize the entire spinbox control
function DoInit()
{
  SetDefaults();  
  BuildSpinBox();
  SetDisplay();
  
  initialized = true;
}

// set up defaults for properties when the user
// did not specify the value
function SetDefaults()
{
  if(value == null)
    value = DEFAULT_VALUE;
  if(minvalue == null)
    minvalue = DEFAULT_MINVALUE;
  if(maxvalue == null)
    maxvalue = DEFAULT_MAXVALUE;
  if(size == null)
    size = DEFAULT_SIZE;
}

// spins up only if spin text is smaller
// than upper limit
function SpinUp()
{
  // -0 will force numerical comparison
  if(text_area.value < (maxvalue - 0))
  {
    text_area.value++;
    return true;
  }
  else
    return false;
}

// image with up arrow pressed is displayed, and
// attempts to spins up the value, then only if value
// is actually spun up, fire the event.
function CountUp()
{
  image_area.src = "Images/updown_arrows_up.png"; 
  if(SpinUp())
    Increment.fire();
}

// image with down arrow pressed is displayed,
// and attempts to spins down the value, then only if
// value is actually spun up, fire the event.
function SpinDown()
{
  // -0 will force numerical comparison
  if(text_area.value > (minvalue - 0))
  {
    text_area.value--;
	return true;
  }
  else
    return false;
}

function CountDown()
{
  image_area.src = "Images/updown_arrows_down.png"; 
  if(SpinDown())
    Decrement.fire();
}

// check to see if key detected is number or not
// (only number key is accepted)
function CheckKeypressed()
{
  // if not number key, then do not change the text
  if(event.keyCode < 48 || (event.keyCode > 57 && event.keyCode < 128))
    event.returnValue = false;	
}

function CheckValue()
{
  if(text_area.value < (minvalue - 0))
    text_area.value = minvalue;
  if(text_area.value > (maxvalue - 0))
    text_area.value = maxvalue;
}

// value of spin box is just changes, so
// fire the event for it
function ValueChangeComplete()
{
  value = text_area.value;
  ValueChanged.fire();
}

// restores arrows image to the original one and
// fire the event for it, since spin is complete
function Restore()
{
  value = text_area.value;
  image_area.src = "Images/updown_arrows.png";  
  SpinCompleted.fire();
}

// retrieve value property
function SetValue(new_value)
{
  value = new_value;
  if(initialized)
	text_area.value = value;
}

// set value property
function GetValue()
{
  if(initialized)
    value = text_area.value;
  return value;
}

// construct the entire spin box control and attach necessary events
function BuildSpinBox()
{
  // Note: uniqueID is used to get unique string for each instance of spinbox
  // ('uniqueID' is element's property as extension to DHTML object model)
  var html_text =
    '<span id="spinbox_area_' + uniqueID + '">' +
	'  <input type="text_area" id="text_area_id" style="width:40px; height:18px">' +
    '  <img id="image_area_id" src="Images/updown_arrows.png" ' +
	'    style="position:relative; border="0" ' +
	'    usemap="#map_area_' + uniqueID + '">' +
	'  <map name="map_area_' + uniqueID + '">' +
	'    <area id="up_arrow_id" shape="rect">' +
	'    <area id="down_arrow_id" shape="rect">' +
	'  </map>' +
	'</span>';
	
  innerHTML = html_text;
  
  // create short-hand notation for reference to elements within spinbox.
  // all values (spinbox_area, up_arrow, & down_arrow) will become element's
  // attributes.
  spinbox_area = all["spinbox_area_" + uniqueID];
  text_area = spinbox_area.all["text_area_id"];
  image_area = spinbox_area.all["image_area_id"];
  up_arrow = spinbox_area.all["up_arrow_id"];
  down_arrow = spinbox_area.all["down_arrow_id"];
  
  // attach events to appropriate elements within spinbox
  text_area.attachEvent("onkeypress", CheckKeypressed);
  text_area.attachEvent("onkeyup", ValueChangeComplete);
  text_area.attachEvent("onblur", CheckValue);
  
  up_arrow.attachEvent("onmousedown", CountUp);
  up_arrow.attachEvent("onmouseup", Restore);
  up_arrow.attachEvent("onmouseout", Restore);
  
  down_arrow.attachEvent("onmousedown", CountDown);
  down_arrow.attachEvent("onmouseup", Restore);
  down_arrow.attachEvent("onmouseout", Restore);
}

// set display attributes for all elements
// (sizes, positions, etc.)
function SetDisplay()
{
  text_area.value = value;
  text_area.size = size;

  var top_offset = 3;
  var left_offset = -2;  
  var w = 15;
  var h = 16;
  var hw = w / 2;
  var hh = h / 2;
  
  image_area.style.top = top_offset;
  image_area.style.left = left_offset;
  image_area.style.width = w;
  image_area.style.height = h;
  
  up_arrow.coords = "0,0," + w + "," + hh;
  down_arrow.coords = "0," + hw + "," + w + "," + h;
}
</script>

</PUBLIC:HTC>