DateBoxDateFormat = {};
DateBoxDateFormat.Default = 0;
DateBoxDateFormat.MonthDayYear = 1;
DateBoxDateFormat.DayMonthYear = 2;
DateBoxDateFormat.YearMonthDay = 3;
DateBoxDateFormat.YearDayMonth = 4;
/************************************************************************************/
TimeBoxTimeFormat = {};
TimeBoxTimeFormat.Default = 0;
TimeBoxTimeFormat.TwelveHour = 1;
TimeBoxTimeFormat.TwentyFourHour = 2;
/************************************************************************************/
function DateTimeBoxButton(parent, elementId, instanceName, increaseValue)
{
	DateTimeBoxButton.baseConstructor.call(this, parent.ElementId + '_' + elementId, parent.Name + '.' + instanceName);
	this.Parent        = parent;
	this.IncreaseValue = increaseValue;
	this.Text          = '&nbsp;';
	this.Pressed       = false;
	this.BorderPressed = new RectangleBorder(2, BorderStyle.Inset, '#FFFFFF');
	return;
}
Extend(DateTimeBoxButton, SimpleControl);
DateTimeBoxButton.prototype.GetType = function()
{
    return 'DateTimeBoxButton';
}
DateTimeBoxButton.prototype.DefaultSize = function()
{
    return new Size(16, 5);
}
DateTimeBoxButton.prototype.DefaultBorder = function()
{
    return new RectangleBorder(2, BorderStyle.Outset, '#FFFFFF');
}
DateTimeBoxButton.prototype.DefaultBackground = function()
{
    return new Background('#D4D0C8');
}
DateTimeBoxButton.prototype.DefaultPadding = function()
{
    return new Padding(0, 0, 0, 0);
}
DateTimeBoxButton.prototype.OnMouseDown = function(e, element)
{
    if (!this.Parent.Enabled)
    {
        return;
    }
    this.BorderPressed.SetCssDomProperties($(this.ElementId));
	this.Pressed = true;
	this.Parent.IncDecNumber(this.IncreaseValue);
	this.Parent._ButtonClickTimer = setTimeout(this.Parent.Name + '.IncDecNumberRecursive(' + (this.IncreaseValue ? 'true' : 'false') + ')', 1000);
	DateTimeBoxButton.superClass.OnMouseDown.call(this, e, element);
	return;
}
DateTimeBoxButton.prototype.OnMouseUp = function(e, element)
{
    if (!this.Parent.Enabled)
    {
        return;
    }
    this.Border.SetCssDomProperties($(this.ElementId));
	this.Pressed = false;
	clearTimeout(this.Parent._ButtonClickTimer);
	this.Parent._ButtonClickTimer = null;
	DateTimeBoxButton.superClass.OnMouseUp.call(this, e, element);
	return;
}
DateTimeBoxButton.prototype.GetRenderHtml = function(html)
{
	html.Append('<div id="').Append(this.ElementId).Append('" title="').Append(this.ToolTipText).Append('" style="');
	this.GetStyleString(html);
	html.Append(' overflow: hidden; margin: 0px;"');
	this.GetEventAttributeString(html);
	html.Append('>').Append(this.Text).Append('<\/div>');
	return;
}
/************************************************************************************/
function DateTimeBoxBase(elementId, instanceName, inputName, value, buttonIconImageDirectory)
{
	DateTimeBoxBase.baseConstructor.call(this, elementId, instanceName);
	this.InputName         = inputName;
	this.Value             = TypeOf(value) != 'Date' ? null : value;
	this.NextButton        = new DateTimeBoxButton(this, 'next_button', 'NextButton', true);
	this.PreviousButton    = new DateTimeBoxButton(this, 'previous_button', 'PreviousButton', false);
	this.NoName            = false;
	this.MinValue          = null;
	this.MaxValue          = null;
	this.Enabled           = true;
	this.ShowButtons       = true;
	this.InputToolTipText  = 'Type in a new value or use the arrow buttons to increase/decrease this value.';
	this.InputHeight       = 18;
	this.IncludeDirtyCheck = true;
	this.ValueWhenEmpty    = Date.Now();
	this.ValueChanged      = null;
	this._SelectedPart     = 1;
	this._ArrowClickFlag   = false;
	this._InputWidths      = [20, 20, 20];
	this._Increments       = [1, 1, 1];
	this._ButtonClickTimer = null;
	this._DirtyFlag        = false;

	if (String.IsNullOrEmpty(buttonIconImageDirectory))
	{
	    buttonIconImageDirectory = "/images/icons";
	}

	this.NextButton.ToolTipText = 'Increase Value';
	this.PreviousButton.ToolTipText = 'Decrease Value';
	this.NextButton.Background.Set('#D4D0C8', 'url(\'' + buttonIconImageDirectory + '/arrow_small_up.gif\')', BackgroundRepeat.None, '5px 0px');
	this.PreviousButton.Background.Set('#D4D0C8', 'url(\'' + buttonIconImageDirectory + '/arrow_small_down.gif\')', BackgroundRepeat.None, '5px 0px');
	return;
}
Extend(DateTimeBoxBase, SimpleControl);
DateTimeBoxBase.prototype.GetType = function()
{
    return 'DateTimeBoxBase';
}
DateTimeBoxBase.prototype.ToString = function()
{
    return this.GetValue().Format(this.GetFormatString());
}
DateTimeBoxBase.prototype.DefaultSize = function() 
{
    return new Size(120, 18);
}
DateTimeBoxBase.prototype.DefaultPadding = function()
{
    return new Padding(0, 0, 0, 0);
}
DateTimeBoxBase.prototype.DefaultBorder = function()
{
    return new RectangleBorder(2, BorderStyle.Inset, '#FFFFFF');
}
DateTimeBoxBase.prototype.DefaultTextAlign = function()
{
    return ContentAlignment.MiddleLeft;
}
DateTimeBoxBase.prototype.OnValueChanged = function()
{
    if (this.IncludeDirtyCheck && !this._DirtyFlag && typeof (DirtyCheck) != 'undefined')
    {
        DirtyCheck.MakeDirty();
    }
    if (this.ValueChanged)
    {
        this.ValueChanged(this);
    }
    return;
}
DateTimeBoxBase.prototype.GetDateTimeAreaValue = function(area)
{
    return '';
}
DateTimeBoxBase.prototype.GetFormatString = function()
{
    return '';
}
DateTimeBoxBase.prototype.GetDateTimeAreaElement = function(area)
{
    return;
}
DateTimeBoxBase.prototype.RenderDateTimeAreas = function(html)
{
    return;
}
DateTimeBoxBase.prototype.IncDecNumber = function(increase)
{
    return;
}
DateTimeBoxBase.prototype.IncDecNumberRecursive = function(increase)
{
    return;
}
DateTimeBoxBase.prototype.UpdateValueAreas = function()
{
    return;
}
DateTimeBoxBase.prototype.UpdatePart = function(part, value)
{
    return;
}
DateTimeBoxBase.prototype.GetMainInputValue = function()
{
    return this.Value == null ? '' : this.Value.Format(this.GetFormatString());
}
DateTimeBoxBase.prototype.GetValue = function()
{
    if (this.Value == null)
    {
        return this.ValueWhenEmpty;
    }
    return this.Value;
}
DateTimeBoxBase.prototype.SetValue = function(value)
{
    if (value != null)
    {
        if (TypeOf(value) != 'Date')
        {
            throw new Error('value must be a Date or null.');
        }
        if (TypeOf(this.MinValue) == 'Date' && value.IsLessThan(this.MinValue))
        {
            value = this.MinValue.Clone();
        }
        if (TypeOf(this.MaxValue) == 'Date' && value.IsGreaterThan(this.MaxValue))
        {
            value = this.MaxValue.Clone();
        }
    }
    this.Value = value;
    this.UpdateValueAreas();
    if (this.Enabled)
    {
        try
        {
            // If the box hasn't been rendered yet then this could cause an error.
            this.GetDateTimeAreaElement(1).value = this.GetDateTimeAreaValue(1);
            this.GetDateTimeAreaElement(2).value = this.GetDateTimeAreaValue(2);
            this.GetDateTimeAreaElement(3).value = this.GetDateTimeAreaValue(3);
            $(this.InputName).value = this.GetMainInputValue();
        }
        catch (e) { }
    }
    this.OnValueChanged();
    return;
}
DateTimeBoxBase.prototype.SetMinValue = function(value)
{
    if (TypeOf(value) != 'Date')
    {
        throw new Error('value must be a Date.');
    }
    this.MinValue = value;
    if (this.Value != null && this.Value.IsLessThan(value))
    {
        this._DirtyFlag = true;
        this.SetValue(value.Clone());
        this._DirtyFlag = false;
    }
    return;
}
DateTimeBoxBase.prototype.SetMaxValue = function(value)
{
    if (TypeOf(value) != 'Date')
    {
        throw new Error('value must be a Date.');
    }
    this.MaxValue = value;
    if (this.Value != null && this.Value.IsGreaterThan(value))
    {
        this._DirtyFlag = true;
        this.SetValue(value.Clone());
        this._DirtyFlag = false;
    }
    return;
}
DateTimeBoxBase.prototype.SetEnabled = function(value)
{
    if (TypeOf(value) != 'Boolean')
    {
        value = false;
    }
    this.Enabled = value;
    try
    {
        // If the box hasn't been rendered yet then this could cause an error.
        var v_main_input = $(this.InputName);
        var v_input_1 = this.GetDateTimeAreaElement(1);
        var v_input_2 = this.GetDateTimeAreaElement(2);
        var v_input_3 = this.GetDateTimeAreaElement(3);
        v_input_1.disabled = !value;
        v_input_2.disabled = !value;
        v_input_3.disabled = !value;
        v_main_input.disabled = !value;
        if (value)
        {
            v_input_1.value = this.GetDateTimeAreaValue(1);
            v_input_2.value = this.GetDateTimeAreaValue(2);
            v_input_3.value = this.GetDateTimeAreaValue(3);
            v_main_input.value = this.GetMainInputValue();
        }
        else
        {
            v_input_1.value = '';
            v_input_2.value = '';
            v_input_3.value = '';
            v_main_input.value = '';
        }
    }
    catch (e) { }
    return;
}
DateTimeBoxBase.prototype.SetInputWidths = function(width1, width2, width3)
{
	this._InputWidths = [Utils.GetIntValue(width1), Utils.GetIntValue(width2), Utils.GetIntValue(width3)];
	return;
}
DateTimeBoxBase.prototype.SetIncrements = function(increment1, increment2, increment3)
{
    increment1 = Utils.GetIntValue(increment1);
    increment2 = Utils.GetIntValue(increment2);
    increment3 = Utils.GetIntValue(increment3);
	this._Increments = [increment1 <= 0 ? 1 : increment1, increment2 <= 0 ? 1 : increment2, increment3 <= 0 ? 1 : increment3];
	return;
}
DateTimeBoxBase.prototype.GetRenderHtml = function()
{
	var v_sb = new StringBuilder();
	if(this.ShowButtons)
	{
	    v_sb.Append('<div style="float: right;">');
	    this.NextButton.GetRenderHtml(v_sb);
	    this.PreviousButton.GetRenderHtml(v_sb);
	    v_sb.Append('<\/div>');
    }
	this.RenderDateTimeAreas(v_sb);
	v_sb.Append('<input type="hidden"');
	if(!this.NoName)
	{
	    v_sb.Append(' name="').Append(this.InputName).Append('"');
	}
	v_sb.Append(' id="').Append(this.InputName).Append('" value="').Append(this.GetMainInputValue()).Append('" \/>');
	return v_sb.ToString();
}
DateTimeBoxBase.prototype.Render = function()
{
	var v_element = $(this.ElementId);
	v_element.style.whiteSpace = 'nowrap';
	this.SetCssDomProperties(v_element);
	this.AttatchEventsToElement(v_element);
	v_element.innerHTML = this.GetRenderHtml();
	this.IsRendered = true;
	return;
}
DateTimeBoxBase.prototype.Refresh = function() 
{ 
    var v_element = $(this.ElementId);
    v_element.style.whiteSpace = 'nowrap';
    this.SetCssDomProperties(v_element);
    v_element.innerHTML = this.GetRenderHtml();
    return;
}
DateTimeBoxBase.prototype.SelectArea = function(area)
{
	this.GetDateTimeAreaElement(area).select();
	this._SelectedPart = area;
	return;
}
DateTimeBoxBase.prototype._OnKeyDown = function(part, input, event, allowNumeric, allowAmPmKey)
{
	var v_key_code = Utils.GetKeyCode(event);
	if (v_key_code == 37 || v_key_code == 39) // Right/Left arrows.
	{
	    return true;
	}
	if (v_key_code == 38) // Up arrow.
	{
	    this.SelectArea(part);
	    this.IncDecNumber(true);
	    return true;
	}
	if (v_key_code == 40) // Down arrow.
	{
	    this.SelectArea(part);
	    this.IncDecNumber(false);
	    return true;
	}
	if (v_key_code == 13) // Enter key.
	{
	    this.UpdatePart(part, input.value);
	    return true;
	}
	if (allowNumeric && !Utils.IsNumericKey(v_key_code))
	{
	    return false;
	}
	if (allowAmPmKey && !DateTimeBoxBase.IsAmPmKey(v_key_code))
	{
	    return false;
	}
	return true;
}
DateTimeBoxBase.IsAmPmKey = function(keyCode)
{
	return keyCode <= 31 || keyCode == 65 || keyCode == 97 || keyCode == 80 || keyCode == 112 || keyCode == 77 || keyCode == 109; //less then 31 = system key codes, 65 = A, 97 = a, 80 = P, 112 = p, 77 = M, 109 = m
}
/************************************************************************************/
function DateBox(elementId, instanceName, inputName, date, buttonIconImageDirectory)
{
	inputName = TypeOf(inputName) == 'String' ? inputName : elementId + '_datetime_value_input';
	DateBox.baseConstructor.call(this, elementId, instanceName, inputName, date, buttonIconImageDirectory);
	this.DateFormat    = DateBoxDateFormat.Default;
	this.DateSeporator = this.DefaultDateSeporator();
	this.SetInputWidths(20, 20, 40);
	return;
}
Extend(DateBox, DateTimeBoxBase);
DateBox.prototype.GetType = function()
{
    return 'DateBox';
}
DateBox.prototype.DefaultDateSeporator = function()
{
    return '\/';
}
DateBox.prototype.GetDateTimeAreaValue = function(area)
{
    if (this.Value == null)
    {
        return '';
    }
    switch (area)
    {
        case 1: return this.Value.Format('MM');
        case 2: return this.Value.Format('dd');
        default: return this.Value.Format('yyyy');
    }
}
DateBox.prototype.UpdateValueAreas = function()
{
    if (this.Value != null)
    {
        this.Value.setHours(0, 0, 0, 0);
    }
    return;
}
DateBox.prototype.RenderDateTimeAreas = function(html)
{
    if (this.DateFormat == DateBoxDateFormat.YearMonthDay || this.DateFormat == DateBoxDateFormat.YearDayMonth)
    {
        this._SelectedPart = 3;
	}
	else if (this.DateFormat == DateBoxDateFormat.DayMonthYear)
	{
	    this._SelectedPart = 2;
	}
	if (TypeOf(this.DateSeporator) != 'String' || this.DateSeporator.length <= 0)
	{
	    this.DateSeporator = this.DefaultDateSeporator();
	}
	var v_seporator = '<div style="float: left;">' + this.DateSeporator + '</div>';
	switch(this.DateFormat)
	{
		case DateBoxDateFormat.DayMonthYear: this._GetDateAreaSpan(2, html); html.Append(v_seporator); this._GetDateAreaSpan(1, html); html.Append(v_seporator); this._GetDateAreaSpan(3, html); break;
		case DateBoxDateFormat.YearMonthDay: this._GetDateAreaSpan(3, html); html.Append(v_seporator); this._GetDateAreaSpan(1, html); html.Append(v_seporator); this._GetDateAreaSpan(2, html); break;
		case DateBoxDateFormat.YearDayMonth: this._GetDateAreaSpan(3, html); html.Append(v_seporator); this._GetDateAreaSpan(2, html); html.Append(v_seporator); this._GetDateAreaSpan(1, html); break;
		default:                             this._GetDateAreaSpan(1, html); html.Append(v_seporator); this._GetDateAreaSpan(2, html); html.Append(v_seporator); this._GetDateAreaSpan(3, html); break;
	}
	return;
}
DateBox.prototype._GetDateAreaSpan = function(datePart, html)
{
	switch(datePart)
	{
		case 1:  html.Append('<input type="text" id="').Append(this.ElementId).Append('_month_part" name="" onkeydown="return ').Append(this.Name).Append('._OnKeyDown(1,this,event,true,false);" onchange="').Append(this.Name).Append('.UpdatePart(1,this.value);" onclick="').Append(this.Name).Append('.SelectArea(1);" value="').Append(this.Enabled ? this.GetDateTimeAreaValue(1) : '').Append('" size="1" maxlength="2" style="float: left; border: none; height: ').Append(this.InputHeight.ToCssString()).Append('; width: ').Append(this._InputWidths[0].ToCssString()).Append('; font: ').Append(this.Font.ToCssString()).Append('; background: ').Append(this.Background.ToCssString()).Append('; color: ').Append(this.ForeColor).Append(';" title="').Append(this.InputToolTipText).Append('"').Append(!this.Enabled ? ' disabled="disabled"' : '').Append(' \/>'); break;
		case 2:  html.Append('<input type="text" id="').Append(this.ElementId).Append('_day_part" name="" onkeydown="return ').Append(this.Name).Append('._OnKeyDown(2,this,event,true,false);" onchange="').Append(this.Name).Append('.UpdatePart(2,this.value);" onclick="').Append(this.Name).Append('.SelectArea(2);" value="').Append(this.Enabled ? this.GetDateTimeAreaValue(2) : '').Append('" size="1" maxlength="2" style="float: left; border: none; height: ').Append(this.InputHeight.ToCssString()).Append('; width: ').Append(this._InputWidths[1].ToCssString()).Append('; font: ').Append(this.Font.ToCssString()).Append('; background: ').Append(this.Background.ToCssString()).Append('; color: ').Append(this.ForeColor).Append(';" title="').Append(this.InputToolTipText).Append('"').Append(!this.Enabled ? ' disabled="disabled"' : '').Append(' \/>'); break;
		default: html.Append('<input type="text" id="').Append(this.ElementId).Append('_year_part" name="" onkeydown="return ').Append(this.Name).Append('._OnKeyDown(3,this,event,true,false);" onchange="').Append(this.Name).Append('.UpdatePart(3,this.value);" onclick="').Append(this.Name).Append('.SelectArea(3);" value="').Append(this.Enabled ? this.GetDateTimeAreaValue(3) : '').Append('" size="1" maxlength="4" style="float: left; border: none; height: ').Append(this.InputHeight.ToCssString()).Append('; width: ').Append(this._InputWidths[2].ToCssString()).Append('; font: ').Append(this.Font.ToCssString()).Append('; background: ').Append(this.Background.ToCssString()).Append('; color: ').Append(this.ForeColor).Append(';" title="').Append(this.InputToolTipText).Append('"').Append(!this.Enabled ? ' disabled="disabled"' : '').Append(' \/>'); break;
	}
	return;
}
DateBox.prototype.UpdatePart = function(part, value)
{
    if (this._ArrowClickFlag)
    {
        return;
    }
    value = parseInt(value);
    if (isNaN(value))
    {
        this.SetValue(null);
        return;
    }
    var v_date = new Date(2000, 0, 1, 0, 0, 0, 0);
    switch (part)
    {
        case 1:
            var v_remainder = value % this._Increments[0];
            if (v_remainder != 0)
            {
                value += (this._Increments[0] - v_remainder);
            }
            if (this.Value == null)
            {
                v_date.setFullYear(2000, value - 1, 1);
                break;
            }
            v_date.setFullYear(this.Value.getFullYear(), value - 1, this.Value.getDate());
            break;
        case 2:
            var v_remainder = value % this._Increments[1];
            if (v_remainder != 0)
            {
                value += (this._Increments[1] - v_remainder);
            }
            if (this.Value == null)
            {
                v_date.setFullYear(2000, 0, value);
                break;
            }
            v_date.setFullYear(this.Value.getFullYear(), this.Value.getMonth(), value);
            break;
        default:
            var v_remainder = value % this._Increments[2];
            if (v_remainder != 0)
            {
                value += (this._Increments[2] - v_remainder);
            }
            if (this.Value == null)
            {
                v_date.setFullYear(value, 0, 1);
                break;
            }
            v_date.setFullYear(value, this.Value.getMonth(), this.Value.getDate());
            break;
    }
    this.SetValue(v_date);
    return;
}
DateBox.prototype.IncDecNumber = function(increase)
{
    this._ArrowClickFlag = true;
    if (this.Value == null)
    {
        this.Value = TypeOf(this.ValueWhenEmpty) != 'Date' ? Date.Now() : this.ValueWhenEmpty.Clone();
    }
    this.SelectArea(this._SelectedPart);
    var v_add = increase ? 1 : -1;
    var v_month = this.Value.getMonth();
    var v_day = this.Value.getDate();
    var v_year = this.Value.getFullYear();
    switch (this._SelectedPart)
    {
        case 1: v_month += (v_add * this._Increments[0]); break;
        case 2: v_day += (v_add * this._Increments[1]); break;
        default: v_year += (v_add * this._Increments[2]); break;
    }
    this.Value.setFullYear(v_year, v_month, v_day);
    this.SetValue(this.Value);
    this.GetDateTimeAreaElement(this._SelectedPart).select();
    this._ArrowClickFlag = false;
    return;
}
DateBox.prototype.IncDecNumberRecursive = function(increase)
{
	this.IncDecNumber(increase);
	clearTimeout(this._ButtonClickTimer);
	this._ButtonClickTimer = setTimeout(this.Name + '.IncDecNumberRecursive(' + (increase ? 'true' : 'false') + ')', 50);
	return;
}
DateBox.prototype.GetDateTimeAreaElement = function(area)
{
	switch(area)
	{
		case 1:  return $(this.ElementId + '_month_part');
		case 2:  return $(this.ElementId + '_day_part');
		default: return $(this.ElementId + '_year_part');
	}
}
DateBox.prototype.GetFormatString = function()
{
    if (TypeOf(this.DateSeporator) != 'String' || this.DateSeporator.length <= 0)
    {
        this.DateSeporator = this.DefaultDateSeporator();
	}
	switch(this.DateFormat)
	{
		case DateBoxDateFormat.DayMonthYear: return 'dd' + this.DateSeporator + 'MM' + this.DateSeporator + 'yyyy'; break;
		case DateBoxDateFormat.YearMonthDay: return 'yyyy' + this.DateSeporator + 'MM' + this.DateSeporator + 'dd'; break;
		case DateBoxDateFormat.YearDayMonth: return 'yyyy' + this.DateSeporator + 'dd' + this.DateSeporator + 'MM'; break;
		default: return 'MM' + this.DateSeporator + 'dd' + this.DateSeporator + 'yyyy'; break;
	}
}
function FindDateBox(inputName)
{
    if (DateBox.Instances.length > 0)
    {
        for (var i = 0; i < DateBox.Instances.length; i++)
        {
            if (DateBox.Instances[i].InputName == inputName)
            {
                return DateBox.Instances[i];
            }
        }
    }
    return null;
}
DateBox.Instances = [];
DateBox.Create = function(inputId, optionsOrValueChangedCallback, minValue, maxValue, dateFormat, seporator, buttonIconImageDirectory)
{
    var v_input = $(inputId);
    var v_index = DateBox.Instances.length;
    var v_db = new DateBox(inputId + '_datebox', 'DateBox.Instances[' + v_index.toString() + ']', v_input.name, (Date.IsDate(v_input.value) ? new Date(Date.parse(v_input.value)) : null), buttonIconImageDirectory);
    if (optionsOrValueChangedCallback != undefined && optionsOrValueChangedCallback != null && typeof (optionsOrValueChangedCallback) != 'function')
    {
        v_db.LoadOptions(optionsOrValueChangedCallback);
    }
    else
    {
        v_db.ValueChanged = optionsOrValueChangedCallback;
        v_db.MinValue = minValue;
        v_db.MaxValue = maxValue;
        v_db.DateFormat = TypeOf(dateFormat) == 'Number' ? dateFormat : DateBoxDateFormat.Default;
        v_db.DateSeporator = TypeOf(seporator) == 'String' ? seporator : '\/';
    }
    DateBox.Instances.Add(v_db);
    var v_div = document.createElement('div');
    v_div.setAttribute('id', inputId + '_datebox');
    v_div.style.overflow = 'hidden';
    v_db.SetCssDomProperties(v_div);
    v_db.AttatchEventsToElement(v_div);
    v_div.innerHTML = v_db.GetRenderHtml();
    v_input.parentNode.insertBefore(v_div, v_input);
    v_input.parentNode.removeChild(v_input);
    return v_db;
}
/************************************************************************************/
function TimeBox(elementId, instanceName, inputName, time, buttonIconImageDirectory)
{
	inputName = TypeOf(inputName) == 'String' ? inputName : elementId + '_datetime_value_input';
	TimeBox.baseConstructor.call(this, elementId, instanceName, inputName, time, buttonIconImageDirectory);
	this.TimeFormat    = TimeBoxTimeFormat.Default;
	this.TimeSeporator = this.DefaultTimeSeporator();
	this.Enable1159PM  = false;
	this.SetInputWidths(20, 20, 24);
	return;
}
Extend(TimeBox, DateTimeBoxBase);
TimeBox.prototype.GetType = function()
{
    return 'TimeBox';
}
TimeBox.prototype.DefaultTimeSeporator = function()
{
    return ':';
}
TimeBox.prototype.GetDateTimeAreaValue = function(area)
{
    if (this.Value == null)
    {
        return '';
    }
    switch (area)
    {
        case 1: return this.Value.Format(this.TimeFormat == TimeBoxTimeFormat.TwentyFourHour ? 'HH' : 'hh');
        case 2: return this.Value.Format('mm');
        default: return this.Value.Format('TT');
    }
}
TimeBox.prototype.UpdateValueAreas = function()
{
    if (this.Value != null)
    {
        this.Value.setFullYear(2000, 0, 1);
    }
    return;
}
TimeBox.prototype.RenderDateTimeAreas = function(html)
{
    if (TypeOf(this.TimeSeporator) != 'String' || this.TimeSeporator.length <= 0)
    {
        this.TimeSeporator = this.DefaultTimeSeporator();
	}
	var v_display = this.TimeFormat == TimeBoxTimeFormat.TwentyFourHour ? ' display: none;' : '';
	var v_seporator = '<div style="float: left;">' + this.TimeSeporator + '</div>';
	html.Append('<input type="text" id="').Append(this.ElementId).Append('_hour_part" name="" onkeydown="return ').Append(this.Name).Append('._OnKeyDown(1,this,event,true,false);" onchange="').Append(this.Name).Append('.UpdatePart(1,this.value);" onclick="').Append(this.Name).Append('.SelectArea(1);" value="').Append(this.Enabled ? this.GetDateTimeAreaValue(1) : '').Append('" size="1" maxlength="2" style="float: left; border: none; height: ').Append(this.InputHeight.ToCssString()).Append('; width: ').Append(this._InputWidths[0].ToCssString()).Append('; font: ').Append(this.Font.ToCssString()).Append('; background: ').Append(this.Background.ToCssString()).Append('; color: ').Append(this.ForeColor).Append(';" title="').Append(this.InputToolTipText).Append('"').Append(!this.Enabled ? ' disabled="disabled"' : '').Append(' \/>').Append(v_seporator)
		.Append('<input type="text" id="').Append(this.ElementId).Append('_minute_part" name="" onkeydown="return ').Append(this.Name).Append('._OnKeyDown(2,this,event,true,false);" onchange="').Append(this.Name).Append('.UpdatePart(2,this.value);" onclick="').Append(this.Name).Append('.SelectArea(2);" value="').Append(this.Enabled ? this.GetDateTimeAreaValue(2) : '').Append('" size="1" maxlength="2" style="float: left; border: none; height: ').Append(this.InputHeight.ToCssString()).Append('; width: ').Append(this._InputWidths[1].ToCssString()).Append('; font: ').Append(this.Font.ToCssString()).Append('; background: ').Append(this.Background.ToCssString()).Append('; color: ').Append(this.ForeColor).Append(';" title="').Append(this.InputToolTipText).Append('"').Append(!this.Enabled ? ' disabled="disabled"' : '').Append(' \/><div style="float: left;">&nbsp;</div>')
		.Append('<input type="text" id="').Append(this.ElementId).Append('_ampm_part" name="" onkeydown="return ').Append(this.Name).Append('._OnKeyDown(3,this,event,false,true);" onchange="').Append(this.Name).Append('.UpdatePart(3,this.value);" onclick="').Append(this.Name).Append('.SelectArea(3);" value="').Append(this.Enabled ? this.GetDateTimeAreaValue(3) : '').Append('" size="1" maxlength="2" style="float: left; border: none; height: ').Append(this.InputHeight.ToCssString()).Append('; width: ').Append(this._InputWidths[2].ToCssString()).Append('; font: ').Append(this.Font.ToCssString()).Append('; background: ').Append(this.Background.ToCssString()).Append('; color: ').Append(this.ForeColor).Append(';').Append(v_display).Append('" title="').Append(this.InputToolTipText).Append('"').Append(!this.Enabled ? ' disabled="disabled"' : '').Append(' \/>');
	return;
}
TimeBox.prototype.UpdatePart = function(part, value)
{
    if (this._ArrowClickFlag)
    {
        return;
    }
    var v_date = new Date(2000, 0, 1, 0, 0, 0, 0);
    switch (part)
    {
        case 1:
            value = parseInt(value);
            if (isNaN(value))
            {
                this.SetValue(null);
                return;
            }
            var v_remainder = value % this._Increments[0];
            if (v_remainder != 0)
            {
                value += (this._Increments[0] - v_remainder);
            }
            if (this.Value == null)
            {
                v_date.setHours(value, 0, 0, 0);
                break;
            }
            v_date.setHours(value + (this.TimeFormat != TimeBoxTimeFormat.TwentyFourHour && value < 12 && this.Value.Format('TT') == 'PM' ? 12 : 0), this.Value.getMinutes(), 0, 0);
            break;
        case 2:
            value = parseInt(value);
            if (isNaN(value))
            {
                value = 0;
            }
            if (this.Value != null && this.Enable1159PM && (this.Value.getHours() == 11 || this.Value.getHours() == 23) && value == 59)
            {
                v_date.setHours(23, 59, 0, 0);
                break;
            }
            var v_remainder = value % this._Increments[1];
            if (v_remainder != 0)
            {
                value += (this._Increments[1] - v_remainder);
            }
            if (this.Value == null)
            {
                v_date.setHours(0, value, 0, 0);
                break;
            }
            v_date.setHours(this.Value.getHours(), value, 0, 0);
            break;
        default:
            value = value.toUpperCase();
            if (this.Value != null && this.Enable1159PM && (this.Value.getHours() == 23) && this.Value.getMinutes() == 59)
            {
                break;
            }

            var v_ampm = this.Value == null ? 'AM' : this.Value.Format('TT');
            var v_hours = this.Value == null ? 0 : this.Value.getHours();
            if (value == 'AM' && v_ampm == 'PM')
            {
                v_hours += 12;
            }
            else if (value == 'PM' && v_ampm == 'AM')
            {
                v_hours -= 12;
            }
            v_date.setHours(v_hours, this.Value == null ? 0 : this.Value.getMinutes(), 0, 0);
            break;
    }
    this.SetValue(v_date);
    return;
}
TimeBox.prototype.IncDecNumber = function(increase)
{
    this._ArrowClickFlag = true;
    if (this.Value == null)
    {
        this.Value = TypeOf(this.ValueWhenEmpty) != 'Date' ? Date.Now() : this.ValueWhenEmpty.Clone();
    }
    this.SelectArea(this._SelectedPart);
    var v_add = increase ? 1 : -1;
    var v_hour = this.Value.getHours();
    var v_minute = this.Value.getMinutes();
    switch (this._SelectedPart)
    {
        case 1: v_hour += (v_add * this._Increments[0]); break;
        case 2:
            if (v_add == 1 && v_minute % this._Increments[1] > 0)
            {
                v_minute += (this._Increments[1] - v_minute % this._Increments[1]);
            }
            else if (v_add == -1 && v_minute % this._Increments[1] > 0)
            {
                v_minute -= v_minute % this._Increments[1];
            }
            else
            {
                v_minute += (v_add * this._Increments[1]);
            }
            break;
        default:
            if (this.Enable1159PM && (this.Value.getHours() == 23) && this.Value.getMinutes() == 59)
            {
                break;
            }
            else
            {
                v_hour += (v_add * 12);
            }
            break;
    }
    this.Value.setHours(v_hour, v_minute, 0, 0);
    this.SetValue(this.Value);
    this.GetDateTimeAreaElement(this._SelectedPart).select();
    this._ArrowClickFlag = false;
    return;
}
TimeBox.prototype.IncDecNumberRecursive = function(increase)
{
	this.IncDecNumber(increase);
	clearTimeout(this._ButtonClickTimer);
	this._ButtonClickTimer = setTimeout(this.Name + '.IncDecNumberRecursive(' + (increase ? 'true' : 'false') + ')', 50);
	return;
}
TimeBox.prototype.GetDateTimeAreaElement = function(area)
{
	switch(area)
	{
		case 1:  return $(this.ElementId + '_hour_part');
		case 2:  return $(this.ElementId + '_minute_part');
		default: return $(this.ElementId + '_ampm_part');
	}
}
TimeBox.prototype.GetFormatString = function()
{
    if (TypeOf(this.TimeSeporator) != 'String' || this.TimeSeporator.length <= 0)
    {
        this.TimeSeporator = this.DefaultTimeSeporator();
	}
	switch(this.TimeFormat)
	{
		case TimeBoxTimeFormat.TwentyFourHour: return 'HH' + this.TimeSeporator + 'mm';
		default: return 'hh' + this.TimeSeporator + 'mm TT';
	}
}
function FindTimeBox(inputName)
{
    if (TimeBox.Instances.length > 0)
    {
        for (var i = 0; i < TimeBox.Instances.length; i++)
        {
            if (TimeBox.Instances[i].InputName == inputName)
            {
                return TimeBox.Instances[i];
            }
        }
    }
    return null;
}
TimeBox.Instances = [];
TimeBox.Create = function(inputId, optionsOrValueChangedCallback, minValue, maxValue, timeFormat, seporator)
{
    var v_input = $(inputId);
    var v_index = TimeBox.Instances.length;
    var v_tb = new TimeBox(inputId + '_timebox', 'TimeBox.Instances[' + v_index.toString() + ']', v_input.name, Date.IsDate(v_input.value) ? new Date(Date.parse(v_input.value)) : null);
    if (optionsOrValueChangedCallback != undefined && optionsOrValueChangedCallback != null && typeof (optionsOrValueChangedCallback) != 'function')
    {
        v_tb.LoadOptions(optionsOrValueChangedCallback);
    }
    else
    {
        v_tb.ValueChanged = optionsOrValueChangedCallback;
        v_tb.MinValue = minValue;
        v_tb.MaxValue = maxValue;
        v_tb.TimeFormat = TypeOf(timeFormat) == 'Number' ? timeFormat : TimeBoxTimeFormat.Default;
        v_tb.TimeSeporator = TypeOf(seporator) == 'String' ? seporator : ':';
    }
    TimeBox.Instances.Add(v_tb);
    var v_div = document.createElement('div');
    v_div.setAttribute('id', inputId + '_timebox');
    v_div.style.overflow = 'hidden';
    v_tb.SetCssDomProperties(v_div);
    v_tb.AttatchEventsToElement(v_div);
    v_div.innerHTML = v_tb.GetRenderHtml();
    v_input.parentNode.insertBefore(v_div, v_input);
    v_input.parentNode.removeChild(v_input);
    return v_tb;
}
