{***************************************************************************}
{ TMS IntraWeb Component Pack Pro                                           }
{ for Delphi & C++Builder                                                   }
{                                                                           }
{ written by TMS Software                                                   }
{            copyright © 2002 - 2009                                        }
{            Email : info@tmssoftware.com                                   }
{            Web : http://www.tmssoftware.com                               }
{                                                                           }
{ The source code is given as is. The author is not responsible             }
{ for any possible damage done due to the use of this code.                 }
{ The component can be freely used in any application. The complete         }
{ source code remains property of the author and may not be distributed,    }
{ published, given or sold in any form as such. No parts of the source      }
{ code can be included in any other component or application without        }
{ written authorization of the author.                                      }
{***************************************************************************}

unit IWTMSCal;

interface

{$I TMSDEFS.INC}

{$R tmsiwcal.res}

uses
  {$IFDEF LINUX}
  QControls, QGraphics, QIWPicCntnr,
  {$ELSE}
  Controls, Windows, Graphics, IWPicCntnr, IWTMSImg,
  {$ENDIF}
  {$IFDEF DELPHI6_LVL}
  Types,
  {$ENDIF}
  {$IFDEF TMSIW51}
  IWColor,
  {$ENDIF}
  Classes,
  IWControl, IWTypes, SysUtils, IWHTMLTag,
  IWCompEdit, IWCompLabel, IWCompCheckbox, IWExtCtrls, IWTMSBase, IWFont
  {$IFDEF TMSIW6}
  ,IWRenderContext
  {$ENDIF}
  {$IFDEF TMSIW9}
  , IWXMLTag
  {$ENDIF}
  ;

const
  Months: array[1..12] of string = ('January','February','March','April','May','June','July','August','September','October','November','December');

type
  TTIWCalendarClickEvent = procedure(Sender: TObject; ADate: TDateTime) of object;
  TTIWCustomDatePickerClickEvent = procedure(Sender: TObject; ADate: TDateTime) of object;

  {$IFDEF TMSIW9}
  TIWAsyncCalenDarClickEvent = procedure (Sender: TObject; EventParams: TStringList; ADate: TDateTime) of object;
  TIWAsyncDatePickerClickEvent = procedure (Sender: TObject; EventParams: TStringList; Month: integer; Year: integer) of object;
  {$ENDIF}

  TTIWGradientDirection = (gdHorizontal, gdVertical);

  TTIWDatePresentation = (dpYearMonthDay, dpDayMonthYear, dpMonthDayYear, dpYearDayMonth);

  TTIWCalendar = class;
  TTIWDatePicker = class;

  TIWDSClientEvents = class(TPersistent)
  private
    FDayChange: TStringList;
    FMonthChange: TStringList;
    FYearChange: TStringList;
    procedure SetDayChange(const Value: TStringList);
    procedure SetMonthChange(const Value: TStringList);
    procedure SetYearChange(const Value: TStringList);

  public
    function GetJSFunction(AValue: string): string;
    constructor Create;
    destructor Destroy; override;
  published
    property YearChange: TStringList read FYearChange write SetYearChange;
    property MonthChange: TStringList read FMonthChange write SetMonthChange;
    property DayChange: TStringList read FDayChange write SetDayChange;
  end;

  TTIWDateSelector = class(TIWControl)
  private
    FDay: Integer;
    FDesignMode: Boolean;
    FMonth: Integer;
    FPresentation : TTIWDatePresentation;
    FShowDay: boolean;
    FShowYear: boolean;
    FYear: Integer;
    FYearFrom: Integer;
    FYearTo: Integer;
    FBGColor: TIWColor;
    FClientEvents: TIWDSClientEvents;
    FNameOfMonths: TStringList;
    {$IFDEF TMSIW9}
    FOnAsyncYearChange: TIWAsyncEvent;
    FOnAsyncMonthChange: TIWAsyncEvent;
    FOnAsyncDayChange: TIWAsyncEvent;
    procedure DoOnAsyncYearChange(AParams: TStringList);
    procedure DoOnAsyncMonthChange(AParams: TStringList);
    procedure DoOnAsyncDayChange(AParams: TStringList);
    {$ENDIF}
    procedure SetDay(const Value: Integer);
    procedure SetMonth(const Value: Integer);
    procedure SetYear(const Value: Integer);
    procedure SetShowDay(const Value: boolean);
    procedure SetShowYear(const Value: boolean);
    function GetDate: TDateTime;
    procedure SetDate(const Value: TDateTime);
    {$IFNDEF TMSIW71}
    procedure SetDesignMode(const Value: Boolean);
    {$ENDIF}
    function JSDateToDate(AValue:string): TDateTime;
    procedure SetPresentation( const Value: TTIWDatePresentation);
    procedure SetBGColor(const Value: TIWColor);
    procedure SetNameOfMonths(const Value : TStringList);
    procedure InitMonths;
  protected
    {$IFDEF TMSIW6}
    procedure IWPaint; override;
    {$ELSE}
    procedure Paint; override;
    {$ENDIF}
    function HTMLClr(Color: TIWColor):string;
    {$IFDEF TMSIW72_NEW}
    function get_ShouldRenderTabOrder: Boolean; override;
    {$ENDIF}
  public
    {$IFDEF TMSIW72}
    function get_HasTabOrder: boolean; override;
    {$ENDIF}
    procedure Submit(const AValue: string); override;
    procedure SetValue(const AValue: string); override;
    {$IFDEF TMSIW6}
    function RenderHTML(AContext: TIWBaseComponentContext): TIWHTMLTag; override;
    {$ELSE}
    function RenderHTML: TIWHTMLTag; override;
    {$ENDIF}
    {$IFDEF TMSIW9}
    function RenderAsync(AContext: TIWBaseHTMLComponentContext): TIWXMLTag; override;
    {$ENDIF}
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    property Date: TDateTime read GetDate write SetDate;
  published
    property BGColor: TIWColor read FBGColor write SetBGColor;
    property ClientEvents: TIWDSClientEvents read FClientEvents write FClientEvents;
    property Day: Integer read FDay write SetDay;
    {$IFNDEF TMSIW71}
    property DesignMode: Boolean read FDesignMode write SetDesignMode default True;
    {$ENDIF}
    property Month: Integer read FMonth Write SetMonth;
    property NameOfMonths: TStringList read FNameOfMonths write SetNameOfMonths;    
    property ShowDay: boolean read FShowDay write SetShowDay;
    property ShowYear: boolean read FShowYear write SetShowYear;
    property Style: TTIWDatePresentation read FPresentation write SetPresentation;
    property TabOrder;
    property Year: Integer read FYear write SetYear;
    property YearFrom: Integer read FYearFrom write FYearFrom;
    property YearTo: Integer read FYearTo write FYearTo;
    {$IFDEF TMSIW9}
    property OnAsyncYearChange: TIWAsyncEvent read FOnAsyncYearChange write FOnAsyncYearChange;
    property OnAsyncMonthChange: TIWAsyncEvent read FOnAsyncMonthChange write FOnAsyncMonthChange;
    property OnAsyncDayChange: TIWAsyncEvent read FOnAsyncDayChange write FOnAsyncDayChange;
    {$ENDIF}
  end;

  TTIWCalGlyphs = class(TPersistent)
  private
    FOwner: TComponent;
    FNextYear: TBitmap;
    FNextYearURL: string;
    FPrevYear: TBitmap;
    FPrevYearURL: string;
    FNextMonth: TBitmap;
    FNextMonthURL: string;
    FPrevMonth: TBitmap;
    FPrevMonthURL: string;
    procedure SetNextYear(const Value: TBitmap);
    procedure SetPrevYear(const Value: TBitmap);
    procedure SetPrevMonth(const Value: TBitmap);
    procedure SetNextMonth(const Value: TBitmap);
  public
    constructor Create(AOwner: TComponent);
    destructor Destroy; override;
  published
    property NextMonth: TBitmap read FNextMonth write SetNextMonth;
    property NextMonthURL: string read FNextMonthURL write FNextMonthURL;
    property PrevMonth: TBitmap read FPrevMonth write SetPrevMonth;
    property PrevMonthURL: string read FPrevMonthURL write FPrevMonthURL;
    property NextYear: TBitmap read FNextYear write SetNextYear;
    property NextYearURL: string read FNextYearURL write FNextYearURL;
    property PrevYear: TBitmap read FPrevYear write SetPrevYear;
    property PrevYearURL: string read FPrevYearURL write FPrevYearURL;
  end;

  TIWCalendarClientEvents = class(TPersistent)
  private
    FNextYearClick: TStringList;
    FNextMonthClick: TStringList;
    FPrevYearClick: TStringList;
    FPrevMonthClick: TStringList;
    FDateClick: TStringList;
    procedure SetDateClick(const Value: TStringList);
    procedure SetNextMonthClick(const Value: TStringList);
    procedure SetNextYearClick(const Value: TStringList);
    procedure SetPrevMonthClick(const Value: TStringList);
    procedure SetPrevYearClick(const Value: TStringList);
  public
    function GetJSFunction(PropName: string): string; virtual;
    constructor Create;
    destructor Destroy; override;
    procedure Assign(Source: TPersistent); override;
  published
    property DateClick: TStringList read FDateClick write SetDateClick;
    property NextMonthClick: TStringList read FNextMonthClick write SetNextMonthClick;
    property NextYearClick: TStringList read FNextYearClick write SetNextYearClick;
    property PrevMonthClick: TStringList read FPrevMonthClick write SetPrevMonthClick;
    property PrevYearClick: TStringList read FPrevYearClick write SetPrevYearClick;
  end;

  TIWDatePickerClientEvents = class(TIWCalendarClientEvents)
  private
    FOnEnter: TStringList;
    FOnExit: TStringList;
    procedure SetOnEnter(const Value: TStringList);
    procedure SetOnExit(const Value: TStringList);
  public
    function GetJSFunction(PropName: string): string; override;
    constructor Create;
    destructor Destroy; override;
    procedure Assign(Source: TPersistent); override;
  published
    property OnExit: TStringList read FOnExit write SetOnExit;
    property OnEnter: TStringList read FOnEnter write SetOnEnter;
  end;

  TTIWCalendar = class(TIWControl)
  private
    FTodayColor: TIWColor;
    FTodayBorderColor: TIWColor;
    FTodayBorder: Boolean;
    FColor: TIWColor;
    FMonthColor: TIWColor;
    FMonthTextColor: TIWColor;
    FDay: Integer;
    FMonth: Integer;
    FYear: Integer;
    FNameOfMonths: TStringList;
    FNameOfDays: TStringList;
    FHoverColor: TIWColor;
    FBorderWidth: Integer;
    FBorderColor: TIWColor;
    FShowNextMonth: Boolean;
    FShowPrevMonth: Boolean;
    FShowNextYear: Boolean;
    FShowPrevYear: Boolean;
    FHintPrevYear: String;
    FHintPrevMonth: String;
    FHintNextMonth: String;
    FHintNextYear: String;
    FBorderCollapse: Boolean;
    FBackgroundImage: TIPicture;
    FBackgroundImageURL: string;
    FStartColor: TIWColor;
    FEndColor: TIWColor;
    FGradientDirection: TTIWGradientDirection;
    FMonthGradientStartColor: TIWColor;
    FMonthGradientEndColor: TIWColor;
    FMonthGradientDirection: TTIWGradientDirection;
    FGridLineWidth: Integer;
    FGridLineColor: TIWColor;
    FWeekendColor: TIWColor;
    FWeekendTextColor: TIWColor;
    FOnClick: TTIWCalendarClickEvent;
    FOnPrevMonth: TTIWCalendarClickEvent;
    FOnNextMonth: TTIWCalendarClickEvent;
    FOnPrevYear: TTIWCalendarClickEvent;
    FOnNextYear: TTIWCalendarClickEvent;
    FGlyphs: TTIWCalGlyphs;
    FClientEvents: TIWCalendarClientEvents;
    FStartDay : Integer;
    {$IFDEF TMSIW9}
    FOnAsyncNextMonth: TIWAsyncCalenDarClickEvent;
    FOnAsyncPrevMonth: TIWAsyncCalenDarClickEvent;
    FOnAsyncNextYear: TIWAsyncCalenDarClickEvent;
    FOnAsyncPrevYear: TIWAsyncCalenDarClickEvent;
    procedure DoOnAsyncNextMonth(AParams: TStringList);
    procedure DoOnAsyncPrevMonth(AParams: TStringList);
    procedure DoOnAsyncPrevYear(AParams: TStringList);
    procedure DoOnAsyncNextYear(AParams: TStringList);
    {$ENDIF}
    procedure SetColor(const Value: TIWColor);
    procedure SetTodayColor(const Value: TIWColor);
    procedure SetTodayBorderColor(const Value: TIWColor);
    procedure SetTodayBorder(const Value: Boolean);
    procedure SetMonthColor(const Value: TIWColor);
    procedure SetMonthTextColor(const Value: TIWColor);
    procedure SetDay(const Value: Integer);
    procedure SetMonth(const Value: Integer);
    procedure SetYear(const Value: Integer);
    procedure SetNameOfDays(const Value: TStringList);
    procedure SetNameOfMonths(const Value: TStringList);
    procedure SetHoverColor(const Value: TIWColor);
    procedure SetBorderWidth(const Value: Integer);
    procedure SetBorderColor(const Value: TIWColor);
    procedure SetBackgroundImage(const Value: TIPicture);
    procedure SetStartColor(const Value: TIWColor);
    procedure SetEndColor(const Value: TIWColor);
    procedure SetGradientDirection(const Value: TTIWGradientDirection);
    procedure setMonthGradientStartColor(const Value: TIWColor);
    procedure setMonthGradientEndColor(const Value: TIWColor);
    procedure SetMonthGradientDirection(const Value: TTIWGradientDirection);
    procedure SetWeekendColor(const Value: TIWColor);
    procedure SetWeekendTextColor(const Value: TIWColor);
    function GetDate: TDateTime;
    procedure SetDate(const Value: TDateTime);
    procedure InitMonths;
    procedure InitDays;
    procedure SetShowNextMonth(const Value: Boolean);
    procedure SetShowPrevMonth(const Value: Boolean);
    procedure SetShowNextYear(const Value: Boolean);
    procedure SetShowPrevYear(const Value: Boolean);
    procedure SetHintPrevYear(const Value: String);
    procedure SetHintPrevMonth(const Value: String);
    procedure SetHintNextMonth(const Value: String);
    procedure SetHintNextYear(const Value: String);
    procedure SetBorderCollapse(const Value: Boolean);
    function JSDateToDate(AValue:string): TDateTime;
    procedure SetGlyphs(const Value: TTIWCalGlyphs);
    procedure SetGridLineWidth(const Value: integer);
    procedure SetGridLineColor(const Value: TIWColor);
    procedure DrawGradient(Canvas: TCanvas; FromColor, ToColor: TIWColor; Steps: Integer; r:TRect; Direction: Boolean);
    procedure BackgroundChanged(Sender: TObject);
    procedure SetClientEvents(const Value: TIWCalendarClientEvents);
    procedure SetStartDay(const Value: Integer);
  protected
    {$IFDEF TMSIW6}
    procedure IWPaint; override;
    {$ELSE}
    procedure Paint; override;
    {$ENDIF}
    procedure Submit(const AValue: string); override;
    function HTMLClr(Color: TIWColor):string;

  public
    procedure SetValue(const AValue: String); override;
    {$IFDEF TMSIW6}
    function RenderHTML(AContext: TIWBaseComponentContext): TIWHTMLTag; override;
    {$ELSE}
    function RenderHTML: TIWHTMLTag; override;
    {$ENDIF}
    {$IFDEF TMSIW9}
    function RenderAsync(AContext: TIWBaseHTMLComponentContext): TIWXMLTag; override;
    {$ENDIF}
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    property Date: TDateTime read GetDate write SetDate;
  published
    property BackgroundImage: TIPicture read FBackgroundImage write SetBackgroundImage;
    property BackgroundImageURL: string read FBackgroundImageURL write FBackgroundImageURL;
    property BorderCollapse: Boolean read FBorderCollapse write SetBorderCollapse;
    property BorderColor: TIWColor read FBorderColor write SetBorderColor;
    property BorderWidth: Integer read FBorderWidth write SetBorderWidth;
    property ClientEvents: TIWCalendarClientEvents read FClientEvents write SetClientEvents;
    property Color: TIWColor read FColor write SetColor;
    property Day: Integer read FDay write SetDay;
    property Font;
    property HintNextMonth: String read FHintNextMonth write SetHintNextMonth;
    property HintNextYear: String read FHintNextYear write SetHintNextYear;
    property HintPrevMonth: String read FHintPrevMonth write SetHintPrevMonth;
    property HintPrevYear: String read FHintPrevYear write SetHintPrevYear;
    property HoverColor: TIWColor read FHoverColor write SetHoverColor;
    property Glyphs: TTIWCalGlyphs read FGlyphs write SetGlyphs;
    property GradientDirection: TTIWGradientDirection read FGradientDirection write SetGradientDirection;
    property GradientEndColor: TIWColor read FEndColor write SetEndColor;
    property GradientStartColor: TIWColor read FStartColor write SetStartColor;
    property GridLineColor: TIWColor read FGridLineColor write SetGridLineColor;
    property GridLineWidth: Integer read FGridLineWidth write SetGridLineWidth;
    property Month: Integer read FMonth write SetMonth;
    property MonthColor: TIWColor read FMonthColor write SetMonthColor;
    property MonthGradientDirection: TTIWGradientDirection read FMonthGradientDirection write SetMonthGradientDirection;
    property MonthGradientEndColor: TIWColor read FMonthGradientEndColor write SetMonthGradientEndColor;
    property MonthGradientStartColor: TIWColor read FMonthGradientStartColor write SetMonthGradientStartColor;
    property MonthTextColor: TIWColor read FMonthTextColor write SetMonthTextColor;
    property NameOfDays: TStringList read FNameOfDays write SetNameOfDays;
    property NameOfMonths: TStringList read FNameOfMonths write SetNameOfMonths;
    property OnClick: TTIWCalendarClickEvent read FOnClick write FOnClick;
    property OnNextMonth: TTIWCalendarClickEvent read FOnNextMonth write FOnNextMonth;
    {$IFDEF TMSIW9}
    property OnAsyncClick;
    property OnAsyncNextMonth: TIWAsyncCalenDarClickEvent read FOnAsyncNextMonth write FOnAsyncNextMonth;
    property OnAsyncPrevMonth: TIWAsyncCalenDarClickEvent read FOnAsyncPrevMonth write FOnAsyncPrevMonth;
    property OnAsyncNextYear: TIWAsyncCalenDarClickEvent read FOnAsyncNextYear write FOnAsyncNextYear;
    property OnAsyncPrevYear: TIWAsyncCalenDarClickEvent read FOnAsyncPrevYear write FOnAsyncPrevYear;
    {$ENDIF}
    property OnNextYear: TTIWCalendarClickEvent read FOnNextYear write FOnNextYear;
    property OnPrevMonth: TTIWCalendarClickEvent read FOnPrevMonth write FOnPrevMonth;
    property OnPrevYear: TTIWCalendarClickEvent read FOnPrevYear write FOnPrevYear;
    property ShowNextMonth: Boolean read FShowNextMonth write SetShowNextMonth default True;
    property ShowNextYear: Boolean read FShowNextYear write SetShowNextYear default True;
    property ShowPrevMonth: Boolean read FShowPrevMonth write SetShowPrevMonth default True;
    property ShowPrevYear: Boolean read FShowPrevYear write SetShowPrevYear default True;
    property StartDay : Integer read FStartDay write SetStartDay;
    property TodayBorder: Boolean read FTodayBorder write SetTodayBorder;
    property TodayBorderColor: TIWColor read FTodayBorderColor write SetTodayBorderColor;
    property TodayColor: TIWColor read FTodayColor write SetTodayColor;
    property WeekendColor: TIWColor read FWeekendColor write SetWeekendColor;
    property WeekendTextColor: TIWColor read FWeekendTextColor write SetWeekendTextColor;
    property Year: Integer read FYear write SetYear;
  end;

  TTIWDatePickerFormat = (dfEU,dfUS);

  TTIWDisabledAppearance = (daLabel, daGrayed);

  TTIWDateSeparator = (dsMinus, dsPoint, dsSlash);

  TTIWCustomDatePicker = class(TIWControl)
  private
    FTodayColor: TIWColor;
    FHintPrevYear: String;
    FHintPrevMonth: String;
    FHintNextMonth: String;
    FHintNextYear: String;
    FColor: TIWColor;
    FCalendarHeight : integer;
    FCalendarWidth : integer;
    FMonthColor: TIWColor;
    FMonthTextColor: TIWColor;
    FWeekendColor: TIWColor;
    FWeekendTextColor: TIWColor;
    FDay: Integer;
    FMonth: Integer;
    FYear: Integer;
    FFlat: Boolean;
    FFocusColor: TIWColor;
    FBorderColor: TIWColor;
    FBorderWidth: Integer;
    FNameOfMonths: TStringList;
    FNameOfDays: TStringList;
    FHoverColor: TIWColor;
    FDateFormat: TTIWDatePickerFormat;
    FNullIsToday: Boolean;
    FShowNextMonth: Boolean;
    FShowPrevMonth: Boolean;
    FShowNextYear: Boolean;
    FShowPrevYear: Boolean;
    FBorderCollapse: Boolean;
    FBackgroundImage: TIPicture;
    FDropDownImage: TIPicture;
    FDropDownImageURL: string;
    FGradientStartColor: TIWColor;
    FGradientEndColor: TIWColor;
    FGradientDirection: TTIWGradientDirection;
    FMonthGradientStartColor: TIWColor;
    FMonthGradientEndColor: TIWColor;
    FMonthGradientDirection: TTIWGradientDirection;
    FGlyphs: TTIWCalGlyphs;
    FGridLineWidth: integer;
    FGridLineColor: TIWColor;
    FCalendarFont: TIWFont;
    FEditText: string;
    FBGColor: TIWColor;
    FDateSep : TTIWDateSeparator;
    FEditorEnabled: Boolean;
    FEnabled: Boolean;
    FClientEvents: TIWDatePickerClientEvents;
    FOnClick: TTIWCalendarClickEvent;
    FOnPrevMonth: TTIWCustomDatePickerClickEvent;
    FOnNextMonth: TTIWCustomDatePickerClickEvent;
    FOnPrevYear: TTIWCustomDatePickerClickEvent;
    FOnNextYear: TTIWCustomDatePickerClickEvent;
    FStartDay: Integer;
    FTransparency: Integer;
    FDisabledAppearance: TTIWDisabledAppearance;
    {$IFDEF TMSIW9}
    FSelMonth: integer;
    FSelYear: integer;
    FOnAsyncClick: TIWAsyncEvent;
    FOnAsyncChange: TIWAsyncEvent;
    FOnAsyncEnter: TIWAsyncEvent;
    FOnAsyncExit: TIWAsyncEvent;    
    FOnAsyncNextMonth: TIWAsyncDatePickerClickEvent;
    FOnAsyncPrevMonth: TIWAsyncDatePickerClickEvent;
    FOnAsyncNextYear: TIWAsyncDatePickerClickEvent;
    FOnAsyncPrevYear: TIWAsyncDatePickerClickEvent;
    procedure DoOnAsyncClick(AParams: TStringList);
    procedure DoOnAsyncNextMonth(AParams: TStringList);
    procedure DoOnAsyncPrevMonth(AParams: TStringList);
    procedure DoOnAsyncPrevYear(AParams: TStringList);
    procedure DoOnAsyncNextYear(AParams: TStringList);
    procedure DoOnAsyncChange(AParams: TStringList);
    procedure DoOnAsyncEnter(AParams: TStringList);
    procedure DoOnAsyncExit(AParams: TStringList);    
    {$ENDIF}
    procedure SetCalendarHeight(const Value: integer);
    procedure SetDateSep(const Value : TTIWDateSeparator);
    procedure SetCalendarWidth(const Value :integer);
    procedure SetStartDay(const Value: integer);
    procedure SetTransparency(const Value : integer);
    procedure SetColor(const Value: TIWColor);
    procedure SetTodayColor(const Value: TIWColor);
    procedure SetMonthColor(const Value: TIWColor);
    procedure SetMonthTextColor(const Value: TIWColor);
    procedure SetDay(const Value: Integer);
    procedure SetMonth(const Value: Integer);
    procedure SetYear(const Value: Integer);
    procedure SetNameOfDays(const Value: TStringList);
    procedure SetNameOfMonths(const Value: TStringList);
    procedure SetHoverColor(const Value: TIWColor);
    procedure SetGlyphs(const Value: TTIWCalGlyphs);
    function GetDate: TDateTime;
    procedure SetDate(const Value: TDateTime);
    procedure InitMonths;
    procedure InitDays;
    function JSDateToDate(AValue:string): TDateTime;
    procedure SetDateFormat(const Value: TTIWDatePickerFormat);
    procedure SetFlat(const Value: Boolean);
    procedure SetBorderWidth(const Value: Integer);
    procedure SetBorderColor(const Value: TIWColor);
    procedure SetWeekendColor(const Value: TIWColor);
    procedure SetFocusColor(const Value: TIWColor);
    procedure SetShowNextMonth(const Value: Boolean);
    procedure SetShowPrevMonth(const Value: Boolean);
    procedure SetShowNextYear(const Value: Boolean);
    procedure SetShowPrevYear(const Value: Boolean);
    procedure SetHintPrevYear(const Value: String);
    procedure SetHintPrevMonth(const Value: String);
    procedure SetHintNextMonth(const Value: String);
    procedure SetHintNextYear(const Value: String);
    procedure SetBorderCollapse(const Value: Boolean);
    procedure SetBackgroundImage(const Value: TIPicture);
    procedure SetDropDownImage(const Value: TIPicture);
    procedure SetGradientStartColor(const Value: TIWColor);
    procedure SetGradientEndColor(const Value: TIWColor);
    procedure SetGradientDirection(const Value: TTIWGradientDirection);
    procedure setMonthGradientStartColor(const Value: TIWColor);
    procedure setMonthGradientEndColor(const Value: TIWColor);
    procedure SetMonthGradientDirection(const Value: TTIWGradientDirection);
    procedure SetWeekendTextColor(const Value: TIWColor);
    procedure SetGridLinewidth(const Value: Integer);
    procedure SetGridLineColor(const Value: TIWColor);
    procedure SetCalendarFont(const Value: TIWFont);
    procedure SetClientEvents(const Value: TIWDatePickerClientEvents);
    procedure SetEnabledEx(const Value: Boolean);
    procedure SetBGColor(const Value: TIWColor);
  protected
    {$IFDEF TMSIW6}
    procedure IWPaint; override;
    {$ELSE}
    procedure Paint; override;
    {$ENDIF}
    procedure Submit(const AValue: string); override;
    function HTMLClr(Color: TIWColor): string;
    {$IFDEF TMSIW72_NEW}
    function get_ShouldRenderTabOrder: Boolean; override;
    {$ENDIF}
  public
    {$IFDEF TMSIW72}
    function get_HasTabOrder: boolean; override;
    {$ENDIF}
    procedure SetValue(const AValue: String); override;
    {$IFDEF TMSIW6}
    function RenderHTML(AContext: TIWBaseComponentContext): TIWHTMLTag; override;
    {$ELSE}
    function RenderHTML: TIWHTMLTag; override;
    {$ENDIF}
    {$IFDEF TMSIW9}
    function RenderAsync(AContext: TIWBaseHTMLComponentContext): TIWXMLTag; override;
    {$ENDIF}
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override; 

    property BackgroundImage: TIPicture read FBackgroundImage write SetBackgroundImage;
    property BGColor: TIWColor read FBGColor write SetBGColor;
    property BorderCollapse: Boolean read FBorderCollapse write SetBorderCollapse;
    property BorderColor: TIWColor read FBorderColor write SetBorderColor;
    property BorderWidth: Integer read FBorderWidth write SetBorderWidth;
    property CalendarFont: TIWFont read FCalendarFont write SetCalendarFont;
    property CalendarHeight: integer read FCalendarHeight write SetCalendarHeight;
    property CalendarWidth: integer read FCalendarWidth write SetCalendarWidth;
    property ClientEvents: TIWDatePickerClientEvents read FClientEvents write SetClientEvents;
    property Color: TIWColor read FColor write SetColor;
    property Date: TDateTime read GetDate write SetDate;
    property DateFormat: TTIWDatePickerFormat read FDateFormat write SetDateFormat;
    property DateSep : TTIWDateSeparator read FDateSep write SetDateSep;
    property Day: Integer read FDay write SetDay;
    property DisabledAppearance: TTIWDisabledAppearance read FDisabledAppearance write FDisabledAppearance;
    property DropDownImage: TIPicture read FDropDownImage write SetDropDownImage;
    property DropDownImageURL: string read FDropDownImageURL write FDropDownImageURL;
    property EditorEnabled: Boolean read FEditorEnabled write FEditorEnabled;
    property EditText: string read FEditText write FEditText;
    property Enabled: Boolean read FEnabled write SetEnabledEx;
    property Flat: Boolean read FFlat write SetFlat;
    property FocusColor: TIWColor read FFocusColor write SetFocusColor;
    property GradientDirection: TTIWGradientDirection read FGradientDirection write SetGradientDirection;
    property GradientEndColor: TIWColor read FGradientEndColor write SetGradientEndColor;
    property GradientStartColor: TIWColor read FGradientStartColor write SetGradientStartColor;
    property GridLineColor: TIWColor read FGridLineColor write SetGridLineColor;
    property GridLineWidth: Integer read FGridLineWidth write SetGridLineWidth;
    property Glyphs: TTIWCalGlyphs read FGlyphs write SetGlyphs;
    property HintNextMonth: String read FHintNextMonth write SetHintNextMonth;
    property HintNextYear: String read FHintNextYear write SetHintNextYear;
    property HintPrevMonth: String read FHintPrevMonth write SetHintPrevMonth;
    property HintPrevYear: String read FHintPrevYear write SetHintPrevYear;
    property HoverColor: TIWColor read FHoverColor write SetHoverColor;
    property MonthGradientDirection: TTIWGradientDirection read FMonthGradientDirection write SetMonthGradientDirection;
    property MonthGradientEndColor: TIWColor read FMonthGradientEndColor write SetMonthGradientEndColor;
    property MonthGradientStartColor: TIWColor read FMonthGradientStartColor write SetMonthGradientStartColor;
    property Month: Integer read FMonth write SetMonth;
    property MonthColor: TIWColor read FMonthColor write SetMonthColor;
    property MonthTextColor: TIWColor read FMonthTextColor write SetMonthTextColor;
    property NameOfDays: TStringList read FNameOfDays write SetNameOfDays;
    property NameOfMonths: TStringList read FNameOfMonths write SetNameOfMonths;
    property NullIsToday: Boolean read FNullIsToday write FNullIsToday;
    property OnClick: TTIWCalendarClickEvent read FOnClick write FOnClick;
    property OnNextMonth: TTIWCustomDatePickerClickEvent read FOnNextMonth write FOnNextMonth;
    property OnNextYear: TTIWCustomDatePickerClickEvent read FOnNextYear write FOnNextYear;
    property OnPrevMonth: TTIWCustomDatePickerClickEvent read FOnPrevMonth write FOnPrevMonth;
    property OnPrevYear: TTIWCustomDatePickerClickEvent read FOnPrevYear write FOnPrevYear;
    property ShowNextMonth: Boolean read FShowNextMonth write SetShowNextMonth default True;
    property ShowNextYear: Boolean read FShowNextYear write SetShowNextYear default True;
    property ShowPrevMonth: Boolean read FShowPrevMonth write SetShowPrevMonth default True;
    property ShowPrevYear: Boolean read FShowPrevYear write SetShowPrevYear default True;
    property StartDay: Integer read FStartDay write SetStartDay;
    property Transparency: Integer read FTransparency write SetTransparency default 0;
    property TodayColor: TIWColor read FTodayColor write SetTodayColor;
    property WeekendColor: TIWColor read FWeekendColor write SetWeekendColor;
    property WeekendTextColor: TIWColor read FWeekendTextColor write SetWeekendTextColor;
    property Year: Integer read FYear write SetYear;

    {$IFDEF TMSIW9}
    property OnAsyncClick: TIWAsyncEvent read FOnAsyncClick write FOnAsyncClick;
    property OnAsyncChange: TIWAsyncEvent read FOnAsyncChange write FOnAsyncChange;
    property OnAsyncEnter: TIWAsyncEvent read FOnAsyncEnter write FOnAsyncEnter;
    property OnAsyncExit: TIWAsyncEvent read FOnAsyncExit write FOnAsyncExit;    
    property OnAsyncNextMonth: TIWAsyncDatePickerClickEvent read FOnAsyncNextMonth write FOnAsyncNextMonth;
    property OnAsyncPrevMonth: TIWAsyncDatePickerClickEvent read FOnAsyncPrevMonth write FOnAsyncPrevMonth;
    property OnAsyncNextYear: TIWAsyncDatePickerClickEvent read FOnAsyncNextYear write FOnAsyncNextYear;
    property OnAsyncPrevYear: TIWAsyncDatePickerClickEvent read FOnAsyncPrevYear write FOnAsyncPrevYear;
    {$ENDIF}
  end;

  TTIWDatePicker = class(TTIWCustomDatePicker)
  published
    property BackgroundImage;
    property BGColor;
    property BorderCollapse;
    property BorderColor;
    property BorderWidth;
    property CalendarFont;
    property CalendarHeight;
    property CalendarWidth;
    property ClientEvents;
    property Color;
    property DateFormat;
    property DateSep;
    property Day;
    property DisabledAppearance;
    property DropDownImage;
    property DropDownImageURL;
    property EditorEnabled;
    property Enabled;
    property Flat;
    property FocusColor;
    property Font;
    property Glyphs;
    property GradientDirection;
    property GradientEndColor;
    property GradientStartColor;
    property GridLineColor;
    property GridLineWidth;
    property HintNextMonth;
    property HintNextYear;
    property HintPrevMonth;
    property HintPrevYear;
    property HoverColor;
    property Month;
    property MonthColor;
    property MonthGradientDirection;
    property MonthGradientEndColor;
    property MonthGradientStartColor;
    property MonthTextColor;
    property NameOfDays;
    property NameOfMonths;
    property NullIsToday;
    property OnClick;
    property TabOrder;
    property TodayColor;
    property StartDay;
    property Transparency;
    property ShowNextMonth;
    property ShowNextYear;
    property ShowPrevMonth;
    property ShowPrevYear;
    property WeekendColor;
    property WeekendTextColor;
    property Year;
    {$IFDEF TMSIW9}
    property OnAsyncClick;
    property OnAsyncChange;
    property OnAsyncEnter;
    property OnAsyncExit;
    property OnAsyncNextMonth;
    property OnAsyncPrevMonth;
    property OnAsyncNextYear;
    property OnAsyncPrevYear;
    {$ENDIF}
  end;

implementation

uses
  {$IFDEF LINUX}
  QImgList,
  {$ELSE}
  ImgList, ShellAPI, CommCtrl,
  {$ENDIF}
  IWApplication, IWServerControllerBase,
  SWStrings, SWSystem, IWAppForm;


function IncMonth(D: TDateTime; Delta: Integer): TDateTime;
var
  daw,mow,yew: word;
  mo: Integer;

begin
  DecodeDate(d,yew,mow,daw);
  mo := mow;
  mo := mo + Delta;
  if mo < 1 then
  begin
    mow := 12;
    yew := yew - 1;
  end;

  if mo > 12 then
  begin
    mow := 1;
    yew := yew + 1;
  end;
  Result := EncodeDate(yew,mow,daw);
end;

function IncYear(D: TDateTime; Delta: Integer): TDateTime;
var
  daw, mow, yew: word;

begin
  DecodeDate(d,yew,mow,daw);
  yew := yew + Delta;
  Result := EncodeDate(yew,mow,daw);
end;

function DaysInMonth(mo,ye:word):word;
const
  adaysinmonth:array[1..13] of word = (31,28,31,30,31,30,31,31,30,31,30,31,29);
begin
  if (mo <> 2) then
    DaysInMonth := adaysinmonth[mo]
  else
  begin
   if (ye mod 4=0) then
     DaysInMonth := 29
   else
     DaysInMonth := 28;
   if (ye mod 100=0) then DaysInMonth := 28;
   if (ye mod 400=0) then DaysInmonth := 29;
  end;
end;


{ TTIWCalendar }
{$IFDEF TMSIW9}
procedure TTIWCalendar.DoOnAsyncNextMonth(AParams: TStringList);
begin
  if Assigned(OnAsyncNextMonth) then
    OnAsyncNextMonth(Self, AParams, Date);
end;

procedure TTIWCalendar.DoOnAsyncPrevMonth(AParams: TStringList);
begin
  if Assigned(OnAsyncNextMonth) then
    OnAsyncPrevMonth(Self, AParams, Date);
end;

procedure TTIWCalendar.DoOnAsyncNextYear(AParams: TStringList);
begin
  if Assigned(OnAsyncNextMonth) then
    OnAsyncNextYear(Self, AParams, Date);
end;

procedure TTIWCalendar.DoOnAsyncPrevYear(AParams: TStringList);
begin
  if Assigned(OnAsyncNextMonth) then
    OnAsyncPrevYear(Self, AParams, Date);
end;

function TTIWCalendar.RenderAsync(
  AContext: TIWBaseHTMLComponentContext): TIWXMLTag;
begin
  Result := TIWXMLTag.CreateTag('control');
  try
    Result.AddStringParam('id', HTMLName);
    Result.AddStringParam('type', 'TTIWCALENDAR');
    RenderAsyncCommonProperties( AContext, Result );
  except
    FreeAndNil(Result);
  end;

end;
{$ENDIF}

constructor TTIWCalendar.Create(AOwner: TComponent);
var
  da,mo,ye:word;
begin
  inherited;
  FColor := clWhite;
  FTodayColor := clRed;
  FMonthColor := clInfoBk;
  FMonthTextColor := clBlack;
  FHoverColor := clLime;
  FTodayBorder := False;
  FTodayBorderColor := clSilver;
  DecodeDate(Now,ye,mo,da);
  FYear := ye;
  FMonth := mo;
  FDay := da;
  FNameOfDays := TStringList.Create;
  FNameOfMonths := TStringList.Create;

  FGlyphs := TTIWCalGlyphs.Create(Self);

  Font.Color := clBlack;

  InitDays;
  InitMonths;

  StartDay := 1;
  {$IFDEF TMSIW6}
  SetRenderSize(True);
  {$ELSE}
  FRenderSize := True;
  {$ENDIF}
  {$IFDEF TMSIW6}
  {TODO}
  {$ELSE}
  FSupportsInput := True;
  FSupportsSubmit := True;
  FEditable := True;
  {$ENDIF}

  FShowNextMonth := True;
  FShowPrevMonth := True;
  FShowNextYear := True;
  FShowPrevYear := True;

  Width := 200;
  Height := 200;
  FBorderWidth := 1;
  FBorderColor := clSilver;
  if (csDesigning in ComponentState) then
  begin
    FHintPrevYear := 'Previous Year';
    FHintPrevMonth := 'Previous Month';
    FHintNextMonth := 'Next Month';
    FHintNextYear := 'Next Year';
  end;
  FBorderCollapse := true;
  FBackgroundImage := TIPicture.Create;
  FBackgroundImage.OnChange := BackgroundChanged;

  FStartColor := clNone;
  FEndColor := clNone;
  FGradientDirection := gdHorizontal;
  FMonthGradientStartColor := clNone;
  FMonthGradientEndColor := clNone;
  FMonthGradientDirection := gdHorizontal;
  FGridLineWidth := 0;
  FGridLineColor := clSilver;

  FWeekendColor := clWhite;
  FWeekendTextColor := clBlack;
  FClientEvents := TIWCalendarClientEvents.Create;
end;

{$IFDEF TMSIW6}
function TTIWCalendar.RenderHTML(AContext: TIWBaseComponentContext): TIWHTMLTag;
{$ELSE}
function TTIWCalendar.RenderHTML: TIWHTMLTag;
{$ENDIF}
var
  i: integer;
  html: string;
  ImgName: string;
  gradientType,monthGradientType :string;
  ajaxcall, ajaxnextmonth, ajaxprevmonth, ajaxnextyear, ajaxprevyear: string;

begin
  {$IFDEF TMSIW6}
  TIWComponent40Context(AContext).AddToInitProc('FindElem(''' + HTMLName + ''').value="'+
    IntToStr(day)+'/'+IntToStr(month-1)+'/'+IntToStr(year)+ '";' + EOL);
  {$ELSE}
  TIWAppForm(Form).AddToInitProc('FindElem(''' + HTMLName + ''').value="'+
    IntToStr(day)+'/'+IntToStr(month-1)+'/'+IntToStr(year)+ '";' + EOL);
  {$ENDIF}  

  ImgName := '';

  html := GetResourceText('TMSIWCAL');

  if Glyphs.NextMonthURL <> EmptyStr then
    html := StringReplace(html, '<#NEXTMONTH>','<IMG src="' + Glyphs.NextMonthURL + '">',[rfReplaceAll, rfIgnoreCase])
  else if not FGlyphs.NextMonth.Empty then
  begin
    {$IFDEF TMSIW71}
    ImgName := TIWServerControllerBase.NewCacheFile('bmp',true);
    {$ELSE}
    ImgName := TIWServerControllerBase.NewCacheFile('bmp');
    {$ENDIF}
    FGlyphs.NextMonth.SaveToFile(ImgName);

    html := StringReplace(html, '<#NEXTMONTH>','<IMG src="'+ GetCacheDir(Self) + ExtractFileName(ImgName) + '">',[rfReplaceAll, rfIgnoreCase]);
  end
  else
    html := StringReplace(html, '<#NEXTMONTH>','&gt;',[rfReplaceAll, rfIgnoreCase]);

  if Glyphs.NextYearURL <> EmptyStr then
    html := StringReplace(html, '<#NEXTYEAR>','<IMG src="' + Glyphs.NextYearURL + '">',[rfReplaceAll, rfIgnoreCase])
  else if not FGlyphs.NextYear.Empty then
  begin
    {$IFDEF TMSIW71}
    ImgName := TIWServerControllerBase.NewCacheFile('bmp',true);
    {$ELSE}
    ImgName := TIWServerControllerBase.NewCacheFile('bmp');
    {$ENDIF}
    FGlyphs.NextYear.SaveToFile(ImgName);
    html := StringReplace(html, '<#NEXTYEAR>','<IMG src="'+ GetCacheDir(Self) + ExtractFileName(ImgName) + '">',[rfReplaceAll, rfIgnoreCase]);
  end
  else
    html := StringReplace(html, '<#NEXTYEAR>','&gt;&gt;',[rfReplaceAll, rfIgnoreCase]);

  if Glyphs.PrevMonthURL <> EmptyStr then
    html := StringReplace(html, '<#PREVMONTH>','<IMG src="' + Glyphs.PrevMonthURL + '">',[rfReplaceAll, rfIgnoreCase])
  else if not FGlyphs.PrevMonth.Empty then
  begin
    {$IFDEF TMSIW71}
    ImgName := TIWServerControllerBase.NewCacheFile('bmp',true);
    {$ELSE}
    ImgName := TIWServerControllerBase.NewCacheFile('bmp');
    {$ENDIF}
    FGlyphs.PrevMonth.SaveToFile(ImgName);
    html := StringReplace(html, '<#PREVMONTH>','<IMG src="'+ GetCacheDir(Self) + ExtractFileName(ImgName) + '">',[rfReplaceAll, rfIgnoreCase]);
  end
  else
    html := StringReplace(html, '<#PREVMONTH>','&lt;',[rfReplaceAll, rfIgnoreCase]);

  if Glyphs.PrevYearURL <> EmptyStr then
    html := StringReplace(html, '<#PREVYEAR>','<IMG src="' + Glyphs.PrevYearURL + '">',[rfReplaceAll, rfIgnoreCase])
  else if not FGlyphs.PrevYear.Empty then
  begin
    {$IFDEF TMSIW71}
    ImgName := TIWServerControllerBase.NewCacheFile('bmp',true);
    {$ELSE}
    ImgName := TIWServerControllerBase.NewCacheFile('bmp');
    {$ENDIF}
    FGlyphs.PrevYear.SaveToFile(ImgName);
    html := StringReplace(html, '<#PREVYEAR>','<IMG src="'+ GetCacheDir(Self) + ExtractFileName(ImgName) + '">',[rfReplaceAll, rfIgnoreCase]);
  end
  else
    html := StringReplace(html, '<#PREVYEAR>','&lt;&lt;',[rfReplaceAll, rfIgnoreCase]);

  html := StringReplace(html,'<#MONTHTEXTCOLOR>',HTMLClr(FMonthTextColor), [rfReplaceAll,rfIgnoreCase]);

  if FBackgroundImage.Empty and (BackgroundImageURL = EmptyStr) then
  begin
    html := StringReplace(html,'<#BGIMAGE>','', [rfReplaceAll, rfIgnoreCase]);

    if (FStartColor = clNone) or (FEndColor = clNone) then
    begin
      html := StringReplace(html,'<#BKCOLOR>','background-color:'+HTMLClr(Color)+'; ', [rfReplaceAll, rfIgnoreCase]);
      html := StringReplace(html,'<#GRADIENT>','', [rfReplaceAll, rfIgnoreCase]);
    end
    else
    begin
      html := StringReplace(html,'<#BKCOLOR>','', [rfReplaceAll, rfIgnoreCase]);

      if FGradientDirection = gdVertical then
        gradientType := '0'
      else
        gradientType := '1';

      html := StringReplace(html,'<#GRADIENT>','STYLE="FILTER: progid:DXImageTransform.Microsoft.Gradient(GradientType='+GradientType + ', StartColorStr='+HTMLClr(GradientStartColor)+',EndColorStr='+HTMLClr(GradientEndColor)+')" ', [rfReplaceAll, rfIgnoreCase]);
      html := StringReplace(html,'<#WEEKENDCOLOR>','', [rfReplaceAll, rfIgnoreCase]);
    end;

    if FWeekendColor <> clNone then
      html := StringReplace(html,'<#WEEKENDCOLOR>','background-color:'+HTMLClr(FWeekendColor)+'; ', [rfReplaceAll, rfIgnoreCase])
    else
      html := StringReplace(html,'<#WEEKENDCOLOR>','', [rfReplaceAll, rfIgnoreCase]);

    if FWeekendTextColor <> clNone then
      html := StringReplace(html,'<#WEEKENDTEXTCOLOR>',HTMLClr(FWeekendTextColor), [rfReplaceAll, rfIgnoreCase])
    else
      html := StringReplace(html,'<#WEEKENDTEXTCOLOR>',HTMLClr(Font.Color), [rfReplaceAll, rfIgnoreCase])
  end
  else
  begin

    if BackgroundImageURL <> EmptyStr then
      html := StringReplace(html,'<#BGIMAGE>','BACKGROUND="' + BackgroundImageURL + '"', [rfReplaceAll, rfIgnoreCase])
    else
    begin
      if FBackgroundImage.IsGIF then
      {$IFDEF TMSIW71}
        ImgName := TIWServerControllerBase.NewCacheFile('gif',true)
      {$ELSE}
        ImgName := TIWServerControllerBase.NewCacheFile('gif')
      {$ENDIF}
      else
      {$IFDEF TMSIW71}
        ImgName := TIWServerControllerBase.NewCacheFile('jpg',true);
      {$ELSE}
        ImgName := TIWServerControllerBase.NewCacheFile('jpg');
      {$ENDIF}

      FBackgroundImage.SaveToFile(ImgName);
      html := StringReplace(html,'<#BGIMAGE>','BACKGROUND="' + GetCacheDir(Self) + ExtractFilename(ImgName)+'"', [rfReplaceAll, rfIgnoreCase]);
    end;

    html := StringReplace(html,'<#GRADIENT>','', [rfReplaceAll, rfIgnoreCase]);
    html := StringReplace(html,'<#BKCOLOR>','', [rfReplaceAll, rfIgnoreCase]);
    html := StringReplace(html,'<#GRADIENT>','',[rfReplaceAll, rfIgnoreCase]);
    html := StringReplace(html,'<#WEEKENDCOLOR>','', [rfReplaceAll, rfIgnoreCase]);

    if FWeekendTextColor <> clNone then
      html := StringReplace(html,'<#WEEKENDTEXTCOLOR>',HTMLClr(FWeekendTextColor), [rfReplaceAll, rfIgnoreCase])
    else
      html := StringReplace(html,'<#WEEKENDTEXTCOLOR>',HTMLClr(Font.Color), [rfReplaceAll, rfIgnoreCase]);
  end;

  if (FMonthGradientStartColor = clNone) or (FMonthGradientEndColor = clNone) then
  begin
    html := StringReplace(html,'<#HDRCOLOR>',HTMLClr(MonthColor), [rfReplaceAll, rfIgnoreCase]);
    html := StringReplace(html,'<#HEADER>','', [rfReplaceAll, rfIgnoreCase]);
  end
  else
  begin
    html := StringReplace(html,'background-color:"<#HDRCOLOR>";','', [rfReplaceAll, rfIgnoreCase]);
    if FMonthGradientDirection = gdVertical then
      monthGradientType := '0'
    else
      monthGradientType := '1';
    html := StringReplace(html, '<#HEADER>','STYLE="FILTER: progid:DXImageTransform.Microsoft.Gradient(GradientType='+monthGradientType + ', StartColorStr='+HTMLClr(MonthGradientStartColor)+',EndColorStr='+HTMLClr(MonthGradientEndColor)+')" ', [rfReplaceAll, rfIgnoreCase]);
  end;

  if FBorderCollapse then
  begin
    html := StringReplace(html,'<#BORDERCOLLAPSE>','collapse', [rfReplaceAll, rfIgnoreCase])
  end
  else
    html := StringReplace(html,'<#BORDERCOLLAPSE>','separate', [rfReplaceAll, rfIgnoreCase]);

  html := StringReplace(html, '<#GRIDLINES>', inttoStr(FGridLineWidth) , [rfReplaceAll, rfIgnoreCase]);

  if (FGridLineWidth > 0 ) then
    html := StringReplace(html, '<#GRIDBORDER>', '1' , [rfReplaceAll, rfIgnoreCase])
  else
    html := StringReplace(html, '<#GRIDBORDER>','0', [rfReplaceAll, rfIgnoreCase]);

  html := StringReplace(html, '<#GRIDLINECOLOR>', HTMLClr(FGridLineColor) , [rfReplaceAll, rfIgnoreCase]);
  html := StringReplace(html, '<#HINTPREVYEAR>', ' title="'+HintPrevYear+'" ' , [rfReplaceAll, rfIgnoreCase]);
  html := StringReplace(html, '<#HINTPREVMONTH>', ' title="'+FHintPrevMonth+'" ' , [rfReplaceAll, rfIgnoreCase]);
  html := StringReplace(html, '<#HINTNEXTMONTH>', ' title="'+FHintNextMonth+'" ' , [rfReplaceAll, rfIgnoreCase]);
  html := StringReplace(html, '<#HINTNEXTYEAR>', ' title="'+FHintNextYear+'" ' , [rfReplaceAll, rfIgnoreCase]);
  html := StringReplace(html,'<#BRDRCOLOR>',HTMLClr(FBorderColor), [rfReplaceAll, rfIgnoreCase]);
  html := StringReplace(html,'<#BRDRWIDTH>',IntToStr(FBorderWidth), [rfReplaceAll, rfIgnoreCase]);
  html := StringReplace(html,'<#WKCOLOR>',HTMLClr(Color), [rfReplaceAll, rfIgnoreCase]);

  html := StringReplace(html,'<#SELCOLOR>',HTMLClr(TodayColor), [rfReplaceAll, rfIgnoreCase]);
  html := StringReplace(html,'<#SELBORDERCOLOR>',HTMLClr(TodayBorderColor), [rfReplaceAll, rfIgnoreCase]);

  if TodayBorder then
    html := StringReplace(html,'<#SELBORDER>','1', [rfReplaceAll, rfIgnoreCase])
  else
    html := StringReplace(html,'<#SELBORDER>','0', [rfReplaceAll, rfIgnoreCase]);

  html := StringReplace(html,'<#HOVERCOLOR>',HTMLClr(HoverColor), [rfReplaceAll, rfIgnoreCase]);
  html := StringReplace(html,'<#FNTCOLOR>',HTMLClr(Font.Color), [rfReplaceAll, rfIgnoreCase]);
  html := StringReplace(html,'<#FONTNAME>',Font.FontName, [rfReplaceAll, rfIgnoreCase]);
  html := StringReplace(html,'<#FONTSIZE>',IntToStr(Font.Size), [rfReplaceAll, rfIgnoreCase]);
  html := StringReplace(html,'<#SELMONTH>',IntToStr(Month -1), [rfReplaceAll, rfIgnoreCase]);
  html := StringReplace(html,'<#CALWIDTH>',IntToStr(Width), [rfReplaceAll, rfIgnoreCase]);
  html := StringReplace(html,'<#SELYEAR>',IntToStr(Year), [rfReplaceAll, rfIgnoreCase]);
  html := StringReplace(html,'<#SELDAY>',IntToStr(Day), [rfReplaceAll, rfIgnoreCase]);

  {$IFDEF TMSIW9}
  html := StringReplace(html,'<#IW9>','true',[rfReplaceAll, rfIgnoreCase]);
  {$ELSE}
  html := StringReplace(html,'<#IW9>','false',[rfReplaceAll, rfIgnoreCase]);
  {$ENDIF}  

  html := StringReplace(html,'<#COMPNAME>',HTMLName,[rfReplaceAll, rfIgnoreCase]);

  html := StringReplace(html,'<#COLWIDTH>',IntToStr(((Width - 2 * BorderWidth) - 6) div 7)+'px',[rfReplaceAll, rfIgnoreCase]);
  html := StringReplace(html,'<#WIDTHDIV>',IntToStr((((Width - 2 * BorderWidth) - 6) div 7) - 3) + 'px',[rfReplaceAll, rfIgnoreCase]);
  html := StringReplace(html,'<#DIVMONTH>',IntToStr((((Width - 2 * BorderWidth) - 6) div 7) - 3),[rfReplaceAll, rfIgnoreCase]);

  html := StringReplace(html,'<#ROWHEIGHT>',IntToStr(Height div 7)+'px',[rfReplaceAll, rfIgnoreCase]);
  html := StringReplace(html,'<#ROW>',IntToStr(Height div 7),[rfReplaceAll, rfIgnoreCase]);

  if FShowPrevYear then
    html := StringReplace(html, '<#INSBEGINY>','BEGINYEAR',[rfReplaceAll,rfIgnoreCase])
  else
    html := StringReplace(html, '<#INSBEGINY>','''<TD id="'+HTMLName+'calh"></TD>''',[rfReplaceAll,rfIgnoreCase]);

  if FShowNextYear then
    html := StringReplace(html, '<#INSENDY>','ENDYEAR',[rfReplaceAll,rfIgnoreCase])
  else
    html := StringReplace(html, '<#INSENDY>','''<TD id="'+HTMLName+'calh"></TD>''',[rfReplaceAll,rfIgnoreCase]);

  if FShowPrevMonth then
    html := StringReplace(html,'<#INSBEGIN>','BEGINMONTH',[rfReplaceAll, rfIgnoreCase])
  else
    html := StringReplace(html,'<#INSBEGIN>','''<TD id="'+HTMLName+'calh"></TD>''',[rfReplaceAll, rfIgnoreCase]);

  if FShowNextMonth then
    html := StringReplace(html,'<#INSEND>','ENDMONTH',[rfReplaceAll, rfIgnoreCase])
  else
    html := StringReplace(html,'<#INSEND>','''<TD id="'+HTMLName+'calh"></TD>''',[rfReplaceAll, rfIgnoreCase]);

    {$IFDEF TMSIW9}
    if Assigned(FOnAsyncClick) then
      ajaxcall := 'processAjaxEvent(''onClick'', '
        + HTMLControlImplementation.IWCLName
        + ',''' + HTMLName + '.' + 'DoOnAsyncClick' + ''','
        + 'true' + ', null, '
        + 'true' + ');';
        
    if Assigned(FOnAsyncNextMonth) then
      ajaxnextmonth := 'processAjaxEvent(''onNextMonth'', '
        + HTMLControlImplementation.IWCLName
        + ',''' + HTMLName + '.' + 'DoOnAsyncNextMonth' + ''','
        + 'true' + ', null, '
        + 'true' + ');';

    Acontext.WebApplication.RegisterCallBack(HTMLName+'.DoOnAsyncNextMonth', DoOnAsyncNextMonth);

    if Assigned(FOnAsyncPrevMonth) then
      ajaxprevmonth := 'processAjaxEvent(''onPrevMonth'', '
        + HTMLControlImplementation.IWCLName
        + ',''' + HTMLName + '.' + 'DoOnAsyncPrevMonth' + ''','
        + 'true' + ', null, '
        + 'true' + ');';

    Acontext.WebApplication.RegisterCallBack(HTMLName+'.DoOnAsyncPrevMonth', DoOnAsyncPrevMonth);

    if Assigned(FOnAsyncNextYear) then
      ajaxnextyear := 'processAjaxEvent(''onNextYear'', '
        + HTMLControlImplementation.IWCLName
        + ',''' + HTMLName + '.' + 'DoOnAsyncNextYear' + ''','
        + 'true' + ', null, '
        + 'true' + ');';

    Acontext.WebApplication.RegisterCallBack(HTMLName+'.DoOnAsyncNextYear', DoOnAsyncNextYear);

    if Assigned(FOnAsyncPrevYear) then
      ajaxprevyear := 'processAjaxEvent(''onPrevYear'', '
        + HTMLControlImplementation.IWCLName
        + ',''' + HTMLName + '.' + 'DoOnAsyncPrevYear' + ''','
        + 'true' + ', null, '
        + 'true' + ');';

    Acontext.WebApplication.RegisterCallBack(HTMLName+'.DoOnAsyncPrevYear', DoOnAsyncPrevYear);
    {$ENDIF}

  if Assigned(FOnClick) then
    html := StringReplace(html,'<#SUBMITCALL>',ajaxcall + 'return SubmitClick('#39+HTMLName+#39', su, '#39'false'#39');',[rfReplaceAll, rfIgnoreCase])
  else
    html := StringReplace(html,'<#SUBMITCALL>',ajaxcall,[rfReplaceAll, rfIgnoreCase]);

  if Assigned(FOnPrevMonth) then
    html := StringReplace(html,'<#PREVMONTHCALL>',ajaxprevmonth + 'return SubmitClick('#39+HTMLName+#39', "Prev", '#39'false'#39');',[rfReplaceAll, rfIgnoreCase])
  else
    html := StringReplace(html,'<#PREVMONTHCALL>',ajaxprevmonth,[rfReplaceAll, rfIgnoreCase]);

  if Assigned(FOnNextMonth) then
    html := StringReplace(html,'<#NEXTMONTHCALL>',ajaxnextmonth + 'return SubmitClick('#39+HTMLName+#39', "Next", '#39'false'#39');',[rfReplaceAll, rfIgnoreCase])
  else
    html := StringReplace(html,'<#NEXTMONTHCALL>',ajaxnextmonth,[rfReplaceAll, rfIgnoreCase]);

  if Assigned(FOnPrevYear) then
    html := StringReplace(html,'<#PREVYEARCALL>',ajaxprevyear + 'return SubmitClick('#39+HTMLName+#39', "PrevY", '#39'false'#39');',[rfReplaceAll, rfIgnoreCase])
  else
    html := StringReplace(html,'<#PREVYEARCALL>',ajaxprevyear,[rfReplaceAll, rfIgnoreCase]);

  if Assigned(FOnNextYear) then
    html := StringReplace(html,'<#NEXTYEARCALL>',ajaxnextyear + 'return SubmitClick('#39+HTMLName+#39', "NextY", '#39'false'#39');',[rfReplaceAll, rfIgnoreCase])
  else
    html := StringReplace(html,'<#NEXTYEARCALL>',ajaxnextyear,[rfReplaceAll, rfIgnoreCase]);

  if FNameOfDays.Count > 6 then
    InitDays;

  html := StringReplace(html,'<#NEXTYEARCLIENT>',ClientEvents.NextYearClick.Text,[rfReplaceAll, rfIgnoreCase]);
  html := StringReplace(html,'<#NEXTMONTHCLIENT>',ClientEvents.NextMonthClick.Text,[rfReplaceAll, rfIgnoreCase]);

  html := StringReplace(html,'<#PREVYEARCLIENT>',ClientEvents.PrevYearClick.Text,[rfReplaceAll, rfIgnoreCase]);
  html := StringReplace(html,'<#PREVMONTHCLIENT>',ClientEvents.PrevMonthClick.Text,[rfReplaceAll, rfIgnoreCase]);

  html := StringReplace(html,'<#DATECLIENT>',ClientEvents.DateClick.Text,[rfReplaceAll, rfIgnoreCase]);
  html := StringReplace(html,'<#STARTDAY>',IntToStr(FStartDay),[rfReplaceAll, rfIgnoreCase]);

  for i := 0 to 6 do
  begin
    html := StringReplace(html,'<#DAY'+inttostr(i)+'>',FNameOfDays[i],[rfReplaceAll, rfIgnoreCase]);
  end;

  if FNameOfMonths.Count > 6 then
    InitMonths;

  for i := 0 to 11 do
  begin
    html := StringReplace(html,'<#MONTH'+inttostr(i)+'>',FNameOfMonths[i],[rfReplaceAll, rfIgnoreCase]);
  end;


  Result := TIWHTMLTag.CreateTag('DIV');
  Result.Contents.AddText(html);

  with Result.Contents.AddTag('INPUT') do
  begin
    AddStringParam('TYPE','hidden');
    AddStringParam('NAME',HTMLName);
    AddStringParam('ID',HTMLName+'_INPUT');
  end;

end;

procedure TTIWCalendar.SetClientEvents(const Value: TIWCalendarClientEvents);
begin
  FClientEvents.Assign(Value);
end;

procedure TTIWCalendar.SetColor(const Value: TIWColor);
begin
  FColor := Value;
  Invalidate;
end;

procedure TTIWCalendar.SetShowNextMonth(const Value: Boolean);
begin
  FShowNextMonth := Value;
  Invalidate;
end;

procedure TTIWCalendar.SetShowPrevMonth(const Value: Boolean);
begin
  FShowPrevMonth := Value;
  Invalidate;
end;

procedure TTIWCalendar.SetShowNextYear(const Value: Boolean);
begin
  FShowNextYear := Value;
  Invalidate;
end;

procedure TTIWCalendar.SetShowPrevYear(const Value: Boolean);
begin
  FShowPrevYear := Value;
  Invalidate;
end;

procedure TTIWCalendar.SetBackgroundImage(const Value: TIPicture);
begin
  FBackgroundImage.Assign(Value);
  Invalidate;
end;

procedure TTIWCalendar.BackgroundChanged(Sender: TObject);
begin
  Invalidate;
end;

procedure TTIWCalendar.SetDay(const Value: Integer);
begin
  if (Value >0) and (Value <= DaysInMonth(FMonth,FYear)) then
    FDay := Value;
  Invalidate;
end;

procedure TTIWCalendar.SetMonth(const Value: Integer);
begin
  if (Value > 0) and (Value < 13) then
    FMonth := Value;
  Invalidate;
end;

procedure TTIWCalendar.SetMonthColor(const Value: TIWColor);
begin
  FMonthColor := Value;
  Invalidate;
end;

procedure TTIWCalendar.SetMonthTextColor(const Value: TIWColor);
begin
  FMonthTextColor := Value;
  Invalidate;
end;

procedure TTIWCalendar.SetTodayColor(const Value: TIWColor);
begin
  FTodayColor := Value;
  Invalidate;
end;

procedure TTIWCalendar.SetTodayBorderColor(const Value: TIWColor);
begin
  FTodayBorderColor := Value;
  Invalidate;
end;

procedure TTIWCalendar.SetTodayBorder(const Value: Boolean);
begin
  FTodayBorder := Value;
  Invalidate;
end;

procedure TTIWCalendar.SetStartColor(const Value: TIWColor);
begin
  FStartColor := Value;
  Invalidate;
end;

procedure TTIWCalendar.SetEndColor(const Value: TIWColor);
begin
  FEndColor := Value;
  Invalidate;
end;

procedure TTIWCalendar.SetGradientDirection(const Value: TTIWGradientDirection);
begin
  FGradientDirection := Value;
  Invalidate;
end;

procedure TTIWCalendar.SetMonthGradientStartColor(const Value: TIWColor);
begin
  FMonthGradientStartColor := Value;
  Invalidate;
end;

procedure TTIWCalendar.SetMonthGradientEndColor(const Value: TIWColor);
begin
  FMonthGradientEndColor := Value;
  Invalidate;
end;

procedure TTIWCalendar.SetMonthGradientDirection(const Value: TTIWGradientDirection);
begin
  FMonthGradientDirection := Value;
  Invalidate;
end;

procedure TTIWCalendar.SetStartDay(const Value : integer);
begin
  if ((Value < 1) or (Value > 7)) then
  begin
    raise Exception.Create('StartDay must be between 1 and 7.');
    FStartDay := 1;
  end
  else
    FStartDay := Value;

  Invalidate;
end;

procedure TTIWCalendar.SetYear(const Value: Integer);
begin
  FYear := Value;
  Invalidate;
end;

{$IFDEF TMSIW6}
procedure TTIWCalendar.IWPaint;
{$ELSE}
procedure TTIWCalendar.Paint;
{$ENDIF}
var
  i,firstday: Word;
  d: TDateTime;
  r,brdr: TRect;
  dx,dy,top,left,k: Integer;
  ColorText : TIWColor;
begin
  if not Assigned(FNameofDays) then
    Exit;
  if not Assigned(FNameofMonths) then
    Exit;

  Canvas.Font.Name := Font.FontName;
  Canvas.Font.Size := Font.Size;
  ColorText := Font.Color;

  with Canvas do
  begin
    r := GetClientRect;
    Brush.Color := Monthcolor;
    Pen.Color := MonthColor;
    r.Bottom := r.Top + TextHeight('gh');
    Rectangle(r);

    Canvas.Font.Color := MonthTextColor;

    InflateRect(r,-1,-1);

    r.Left := r.Left + 2;

    if FShowPrevYear then
      TextOut(r.Left+1, r.Top,'<<');

    if FShowPrevMonth then
      TextOut(r.Left+25, r.Top,'<');

    if FShowNextMonth then
      TextOut(r.Right - TextWidth('>   >>'),r.Top,'>');

    if FShowNextYear then
     TextOut(r.Right - TextWidth('>>'), r.Top,'>>');


    if FNameOfMonths.Count > Month then
    begin
      dx := (Width - TextWidth(FNameOfMonths.Strings[Month-1])) shr 1;
      TextOut(r.Left + dx, r.Top,FNameOfMonths.Strings[Month - 1]);
    end;

    r := GetClientRect;


    r.Top := r.Top + TextHeight('gh') -1;

    {$IFNDEF LINUX}
    if not BackgroundImage.Empty then
      StretchDraw(r,BackgroundImage)
    else
    {$ENDIF}
    begin
      if not(FStartColor = clNone) and not (FEndColor = ClNone) then
      begin
        if (FGradientDirection = gdHorizontal) then
          DrawGradient(canvas,FStartColor, FEndColor,80,r,True)
        else
          DrawGradient(canvas,FStartColor, FEndColor,80,r,False);
      end
      else
      begin
        Brush.Color := Color;
        Brush.Style := bsSolid;
        Rectangle(r);
      end;
    end;

    r.Left := r.Left + 2;

    dx := Width div 7;
    dy := (Height - TextHeight('gh')) div 6;

    {$IFNDEF LINUX}
    SetBkMode(Handle,TRANSPARENT);
    {$ENDIF}

    Canvas.Font.Color := ColorText;
    k := 0;
    for i := FStartDay - 1 to 6 do
    begin
      if FNameOfDays.Count > i then
        TextOut(r.Left + dx * k,r.Top,FNameOfDays.Strings[i]);
      k := k + 1;
    end;

    if(FStartDay > 1) then
    begin
      for i := 0 to FStartDay do
      begin
        if FNameOfDays.Count > i then
          TextOut(r.Left + dx * k,r.Top,FNameOfDays.Strings[i]);
        k := k + 1;
      end;
    end;

    if FGridLineWidth > 0 then
    begin
      Canvas.Pen.Color := FGridLineColor;
      top := R.Top;
      left := R.Left;

      for i := 0 to 4 do
      begin
        Top := Top + dy;
        Moveto(r.Left,Top);
        LineTo(r.Right,Top);
      end;

      for i := 0 to 5 do
      begin
        Canvas.Pen.Color := FGridLineColor;
        left := left + dx;
        MoveTo(left,r.top);
        LineTo(left,r.Bottom);
      end;

    end;

    d := EncodeDate(FYear,FMonth,1);
    firstday := DayOfWeek(d);
    r.Top := r.Top + dy;

    Brush.Color := TodayColor;

    {$IFNDEF LINUX}
    SetBkMode(Handle,TRANSPARENT);
    {$ENDIF}

    for i := 1 to DaysInMonth(FMonth,FYear) do
    begin
      if Day = i then
      begin
        TextRect(Rect((firstday - 1) * dx,r.Top,firstday * dx,r.Top + dy),r.Left + (firstday - 1) * dx,r.Top,inttostr(i));

        if TodayBorder then
        begin
          Pen.Color := TodayBorderColor;
          brdr := Rect((firstday - 1) * dx,r.Top,firstday * dx,r.Top + dy);
          Brush.Style := bsClear;
          Rectangle(brdr);
        end;

      end
      else
        Textout(r.Left + (firstday - 1) * dx,r.Top, inttostr(i));

      inc(firstday);
      if firstday = 8 then
      begin
        firstday := 1;
        r.Top := r.Top + dy;
      end;
    end;

    r := GetCLientRect;
    Pen.Color := BorderColor;
    Pen.Width := BorderWidth;

    inflaterect(r,-1,-1);
    Moveto(r.Left,r.Top);
    LineTo(r.Right,r.Top);
    LineTo(r.Right,r.Bottom);
    LineTo(r.Left,r.Bottom);
    LineTo(r.Left,r.Top);
  end;
end;

procedure TTIWCalendar.SetNameOfDays(const Value: TStringList);
begin
  FNameOfDays.Assign(Value);
  Invalidate;
end;

procedure TTIWCalendar.SetNameOfMonths(const Value: TStringList);
begin
  FNameOfMonths.Assign(Value);
  Invalidate;
end;

procedure TTIWCalendar.SetGlyphs(const Value: TTIWCalGlyphs);
begin
  FGlyphs.Assign(Value);
end;

destructor TTIWCalendar.Destroy;
begin
  FBackgroundImage.Free;
  FNameOfDays.Free;
  FNameOfMonths.Free;
  FGlyphs.Free;
  FClientEvents.Free;
  inherited;
end;

procedure TTIWCalendar.SetGridLineWidth(const Value: Integer);
begin
  FGridLineWidth := Value;
  Invalidate;
end;

procedure TTIWCalendar.SetGridLineColor(const Value: TIWColor);
begin
  FGridLineColor := Value;
  Invalidate;
end;

procedure TTIWCalendar.SetBorderCollapse(const Value: Boolean);
begin
  FBorderCollapse := Value;
end;

procedure TTIWCalendar.SetHoverColor(const Value: TIWColor);
begin
  FHoverColor := Value;
end;

procedure TTIWCalendar.SetBorderWidth(const Value: Integer);
begin
  FBorderWidth := Value;
  Invalidate;
end;

procedure TTIWCalendar.SetBorderColor(const Value: TIWColor);
begin
  FBorderColor := Value;
  Invalidate;
end;

procedure TTIWCalendar.SetHintPrevMonth(const Value: String);
begin
  FHintPrevMonth := Value;
end;

procedure TTIWCalendar.SetHintNextMonth(const Value: String);
begin
  FHintNextMonth := Value;
end;

procedure TTIWCalendar.SetHintPrevYear(const Value: String);
begin
  FHintPrevYear := Value;
end;

procedure TTIWCalendar.SetHintNextYear(const Value: String);
begin
  FHintNextYear := Value;
end;

procedure TTIWCalendar.SetValue(const AValue: String);
begin
  Date := JSDateToDate(AValue);
end;

function TTIWCalendar.GetDate: TDateTime;
begin
  Result := EncodeDate(year,month,day);
end;

procedure TTIWCalendar.SetDate(const Value: TDateTime);
var
  da,mo,ye: word;
begin
   DecodeDate(value,ye,mo,da);
   Day := 1;
   Year := ye;
   Month := mo;
   Day := da
end;

procedure TTIWCalendar.DrawGradient(Canvas: TCanvas; FromColor, ToColor: TIWColor; Steps: Integer; r:TRect; Direction: Boolean);
var
  diffr,startr,endr: Integer;
  diffg,startg,endg: Integer;
  diffb,startb,endb: Integer;
  iend: Integer;
  rstepr,rstepg,rstepb,rstepw: Real;
  i,stepw: Word;

begin
  if Steps = 0 then
    Steps := 1;

  FromColor := ColorToRGB(FromColor);
  ToColor := ColorToRGB(ToColor);

  startr := (FromColor and $0000FF);
  startg := (FromColor and $00FF00) shr 8;
  startb := (FromColor and $FF0000) shr 16;
  endr := (ToColor and $0000FF);
  endg := (ToColor and $00FF00) shr 8;
  endb := (ToColor and $FF0000) shr 16;

  diffr := endr - startr;
  diffg := endg - startg;
  diffb := endb - startb;

  rstepr := diffr / steps;
  rstepg := diffg / steps;
  rstepb := diffb / steps;

  if Direction then
    rstepw := (R.Right - R.Left) / Steps
  else
    rstepw := (R.Bottom - R.Top) / Steps;

  with Canvas do
  begin
    for i := 0 to Steps - 1 do
    begin
      endr := startr + Round(rstepr*i);
      endg := startg + Round(rstepg*i);
      endb := startb + Round(rstepb*i);
      stepw := Round(i*rstepw);
      Pen.Color := endr + (endg shl 8) + (endb shl 16);
      Brush.Color := Pen.Color;
      if Direction then
      begin
        iend := R.Left + stepw + Trunc(rstepw) + 1;
        if iend > R.Right then
          iend := R.Right;
        Rectangle(R.Left + stepw,R.Top,iend,R.Bottom)
      end
      else
      begin
        iend := R.Top + stepw + Trunc(rstepw)+1;
        if iend > r.Bottom then
          iend := r.Bottom;
        Rectangle(R.Left, R.Top+stepw,R.Right,iend);
      end;
    end;
  end;
end;


procedure TTIWCalendar.InitMonths;
begin
  FNameOfMonths.Add('January');
  FNameOfMonths.Add('February');
  FNameOfMonths.Add('March');
  FNameOfMonths.Add('April');
  FNameOfMonths.Add('May');
  FNameOfMonths.Add('June');
  FNameOfMonths.Add('July');
  FNameOfMonths.Add('August');
  FNameOfMonths.Add('September');
  FNameOfMonths.Add('October');
  FNameOfMonths.Add('November');
  FNameOfMonths.Add('December');
end;

procedure TTIWCalendar.InitDays;
begin
  FNameOfDays.Add('Sun');
  FNameOfDays.Add('Mon');
  FNameOfDays.Add('Tue');
  FNameOfDays.Add('Wed');
  FNameOfDays.Add('Thu');
  FNameOfDays.Add('Fri');
  FNameOfDays.Add('Sat');
end;

procedure TTIWCalendar.Submit(const AValue: string);
begin
  inherited;

  if AValue = 'Prev' then
  begin
    if Assigned(FOnPrevMonth) then
      FOnPrevMonth(Self,IncMonth(Date,-1));
    Exit;
  end;

  if AValue = 'Next' then
  begin
    if Assigned(FOnNextMonth) then
      FOnNextMonth(Self,IncMonth(Date,1));
    Exit;
  end;

  if AValue = 'PrevY' then
  begin
    if Assigned(FOnPrevYear) then
      FOnPrevYear(Self, IncYear(Date,-1));
    Exit;
  end;

  if AValue = 'NextY' then
  begin
    if Assigned(FOnNextYear) then
      FOnNextYear(Self, IncYear(Date,1));
  end;

  if Assigned(FOnClick) then
    FOnClick(Self,JSDateToDate(AValue));
end;

function TTIWCalendar.JSDateToDate(AValue: string): TDateTime;
var
  s:string;
  da,mo,ye:word;
  err: Integer;
begin
  Result := Now;

  s := AValue;

  if pos('/',s) > 0 then
  begin
    val(copy(s,1,pos('/',s)-1),da,err);
    delete(s,1,pos('/',s));
    if pos('/',s) > 0 then
    begin
      val(copy(s,1,pos('/',s)-1),mo,err);
      delete(s,1,pos('/',s));
      val(s,ye,err);
      if err = 0 then
      begin
        if (mo < 12) then
        begin
          if (daysinmonth(mo + 1,ye) >= da) then
            Result := EncodeDate(ye,mo+1,da)
          else
            Result := 0;
        end
        else
          Result := 0;
        Day := da;
        Month := mo + 1;
        Year := ye;
      end;
    end;
  end;
end;

procedure TTIWCalendar.SetWeekendColor(const Value: TIWColor);
begin
  FWeekendColor := Value;
  Invalidate;
end;

procedure TTIWCalendar.SetWeekendTextColor(const Value: TIWColor);
begin
  FWeekendTextColor := Value;
  Invalidate;
end;

function TTIWCalendar.HTMLClr(Color: TIWColor): string;
begin
  Result := ColorToRGBString(Color);
end;

{ TTIWDatePicker }
{$IFDEF TMSIW9}
procedure TTIWCustomDatePicker.DoOnAsyncClick(AParams: TStringList);
begin
  if Assigned(OnAsyncClick) then
    OnAsyncClick(Self, AParams);
end;

procedure TTIWCustomDatePicker.DoOnAsyncChange(AParams: TStringList);
begin
  if Assigned(OnAsyncChange) then
    OnAsyncChange(Self, AParams);
end;

procedure TTIWCustomDatePicker.DoOnAsyncEnter(AParams: TStringList);
begin
  if Assigned(OnAsyncEnter) then
    OnAsyncEnter(Self, AParams);
end;

procedure TTIWCustomDatePicker.DoOnAsyncExit(AParams: TStringList);
begin
  if Assigned(OnAsyncExit) then
    OnAsyncExit(Self, AParams);
end;

procedure TTIWCustomDatePicker.DoOnAsyncNextMonth(AParams: TStringList);
begin
  FSelMonth := FSelMonth + 1;
  if (FSelMonth = 13) then
  begin
    FSelMonth := 1;
    FSelYear := FSelYear + 1;
  end;

  if Assigned(OnAsyncNextMonth) then
    OnAsyncNextMonth(Self, AParams, FSelMonth, FSelYear);
end;

procedure TTIWCustomDatePicker.DoOnAsyncPrevMonth(AParams: TStringList);
begin
  FSelMonth := FSelMonth - 1;
  if (FSelMonth = 0) then
  begin
    FSelMonth := 12;
    FSelYear := FSelYear - 1;
  end;

  if Assigned(OnAsyncNextMonth) then
    OnAsyncPrevMonth(Self, AParams, FSelMonth, FSelYear);
end;

procedure TTIWCustomDatePicker.DoOnAsyncNextYear(AParams: TStringList);
begin
  FSelYear := FSelYear + 1;

  if Assigned(OnAsyncNextMonth) then
    OnAsyncNextYear(Self, AParams, FSelMonth, FSelYear);
end;

procedure TTIWCustomDatePicker.DoOnAsyncPrevYear(AParams: TStringList);
begin
  FSelYear := FSelYear - 1;

  if Assigned(OnAsyncNextMonth) then
    OnAsyncPrevYear(Self, AParams, FSelMonth, FSelYear);
end;

function TTIWCustomDatePicker.RenderAsync(
  AContext: TIWBaseHTMLComponentContext): TIWXMLTag;
var
  strDate, strDateSep: string;
begin
  Result := TIWXMLTag.CreateTag('control');
  try
    Result.AddStringParam('id', HTMLName);
    Result.AddStringParam('type', 'TTIWDATEPICKER');
    RenderAsyncCommonProperties( AContext, Result );

    if (DateSep = dsMinus) then
      StrDateSep := '-'
    else
    begin
      if (DateSep = dsPoint) then
        StrDateSep := '.'
      else
        StrDateSep := '/';
    end;

    if DateFormat = dfEU then
      strDate := IntToStr(Day) + StrDateSep + IntToStr(Month) + StrDateSep + IntToStr(Year)
    else
      strDate := IntToStr(Month) + StrDateSep + IntToStr(Day) + StrDateSep + IntToStr(Year);

    GGetWebApplicationThreadVar.CallBackResponse.AddJavaScriptToExecute('<![CDATA['
      + 'document.getElementById("' + HTMLName + 'calvalue").value = "' + strDate + '";'#13
      + 'FindElem("' + HTMLName  + '").value = "' + strDate + '";'#13
      +']]>');

  except
    FreeAndNil(Result);
  end;

end;
{$ENDIF}

constructor TTIWCustomDatePicker.Create(AOwner: TComponent);
var
  da,mo,ye:word;
begin
  inherited;
  FColor := clWhite;
  FTodayColor := clRed;
  FMonthColor := clInfoBk;
  FMonthTextColor := clBlack;
  FHoverColor := clLime;
  DecodeDate(Now,ye,mo,da);
  FYear := ye;
  FMonth := mo;
  FDay := da;
  FNameOfDays := TStringList.Create;
  FNameOfMonths := TStringList.Create;
  FWeekendColor := clWhite;
  FWeekendTextColor := clBlack;
  FEnabled := True;
  FEditorEnabled := True;

  {$IFDEF TMSIW9}
  FSelMonth := Month;
  FSelYear := Year;
  {$ENDIF}

  FCalendarFont := TIWFont.Create;
  FCalendarHeight := 200;
  FCalendarWidth := 285;

  FBorderCollapse := true;
  Font.Color := clBlack;
  FBorderColor := clBlack;
  FFocusColor := clNone;
  FBorderWidth := 1;
  FBGColor := clNone;

  FDateSep := dsSlash;
  FTransparency := 0;

  FShowPrevMonth := true;
  FShowNextMonth := true;
  FShowPrevYear := true;
  FShowNextYear := true;

  InitDays;
  InitMonths;

  if (csDesigning in ComponentState) then
  begin
    FHintPrevYear := 'Previous Year';
    FHintPrevMonth := 'Previous Month';
    FHintNextMonth := 'Next Month';
    FHintNextYear := 'Next Year';
  end;

  FBackgroundImage := TIPicture.Create;

  FDropDownImage := TIPicture.Create;
//  FBackgroundImage.OnChange := BackgroundChanged;

  FGradientStartColor := clNone;
  FGradientEndColor := clNone;
  FGradientDirection := gdHorizontal;

  FGridLineWidth := 0;
  FGridLineColor := clSilver;

  FMonthGradientStartColor := clNone;
  FMonthGradientEndColor := clNone;
  FMonthGradientDirection := gdHorizontal;
  FGlyphs := TTIWCalGlyphs.Create(Self);

  {$IFDEF TMSIW6}
  {TODO}
  {$ELSE}
  FSupportsInput := True;
  FSupportsSubmit := True;
  FEditable := True;
  {$ENDIF}

  Width := 150;
  Height := 24;
  ZIndex := 1;
  StartDay := 1;

  FClientEvents := TIWDatePickerClientEvents.Create;
end;

function TTIWCustomDatePicker.HTMLClr(color: TIWColor):string;
begin
  Result := ColorToRGBString(color);
end;

procedure TTIWCustomDatePicker.SetCalendarFont(const Value: TIWFont);
begin
  FCalendarFont.Assign(Value);
end;

procedure TTIWCustomDatePicker.SetCalendarHeight(const Value : integer);
begin
  FCalendarHeight := Value;
end;

procedure TTIWCustomDatePicker.SetCalendarWidth(const Value : integer);
begin
  FCalendarWidth := Value;
end;

procedure TTIWCustomDatePicker.SetClientEvents(const Value: TIWDatePickerClientEvents);
begin
  FClientEvents.Assign(Value);
end;

procedure TTIWCustomDatePicker.SetBGColor(const Value: TIWColor);
begin
  FBGColor := Value;
  Invalidate;
end;

procedure TTIWCustomDatePicker.SetEnabledEx(const Value: Boolean);
begin
  FEnabled := Value;
  Invalidate;
end;

{$IFDEF TMSIW72}
function TTIWCustomDatePicker.get_HasTabOrder: boolean;
begin
  {$IFNDEF TMSIW72_NEW}
  Result := false;
  {$ELSE}
  Result := true;
  {$ENDIF}
end;
{$ENDIF}

{$IFDEF TMSIW72_NEW}
function TTIWCustomDatePicker.get_ShouldRenderTabOrder: Boolean;
begin
  Result := false;
end;
{$ENDIF}

{$IFDEF TMSIW6}
function TTIWCustomDatePicker.RenderHTML(AContext: TIWBaseComponentContext): TIWHTMLTag;
{$ELSE}
function TTIWCustomDatePicker.RenderHTML: TIWHTMLTag;
{$ENDIF}
var
  i: integer;
  datestr: string;
  html,bgcol: string;
  ImgName,GradientType, MonthGradientType: String;
  InputFieldWidth, InputFieldHeight : integer;
  ButtonWidth, ButtonHeight : integer;
  StrDateSep : string;
  CodeDateSeparator : integer;
  isOpera: boolean;
  ajaxcall, ajaxnextmonth, ajaxprevmonth, ajaxnextyear, ajaxprevyear: string;
  ajaxchange, ajaxenter, ajaxexit: string;
begin
  ImgName := '';

  //Modified
  {$IFDEF TMSIW6}
  if not (AContext.WebApplication.Browser = brIE) then
    TIWComponent40Context(AContext).AddToInitProc('document.captureEvents(Event.MOUSEOVER | Event.MOUSEOUT | Event.CLICK);');

  isOpera := (AContext.WebApplication.Browser = brOpera);
  {$ELSE}
  if not (WebApplication.Browser = brIE) then
    AddToInitProc('document.captureEvents(Event.MOUSEOVER | Event.MOUSEOUT | Event.CLICK);');
  isOpera := (WebApplication.Browser = brOpera);
  {$ENDIF}
  //End Modified

  if (DateSep = dsMinus) then
  begin
    StrDateSep := '-';
    CodeDateSeparator := 45;
  end
  else
  begin
    if (DateSep = dsPoint) then
    begin
      StrDateSep := '.';
      CodeDateSeparator := 46;
    end
    else
    begin
      StrDateSep := '/';
      CodeDateSeparator := 47;
    end;
  end;

    if DateFormat = dfEU then
    datestr := IntToStr(Day) + StrDateSep + IntToStr(Month) + StrDateSep + IntToStr(Year)
  else
    datestr := IntToStr(Month) + StrDateSep + IntToStr(Day) + StrDateSep + IntToStr(Year);

//  TIWAppForm(Form).AddToInitProc(HTMLName + 'changeZIndex();' + EOL);

  if Editable then
  begin
    {$IFDEF TMSIW6}
    TIWComponent40Context(AContext).AddToInitProc('FindElem(''' + HTMLName + ''').value="'+
      datestr + '";' + EOL);
    {$ELSE}
    TIWAppForm(Form).AddToInitProc('FindElem(''' + HTMLName + ''').value="'+
      datestr + '";' + EOL);
    {$ENDIF}
  end;

  if not Enabled and (DisabledAppearance = daLabel) then
  begin
    Result := TIWHTMLTag.CreateTag('DIV');
    if (Date = 0) and not NullIsToday then
      datestr := '';
    Result.Contents.AddText(datestr);
    with Result.Contents.AddTag('INPUT') do
    begin
      AddStringParam('TYPE','hidden');
      AddStringParam('NAME',HTMLName);
      AddStringParam('ID',HTMLName+'_INPUT');
    end;
    Exit;
  end;

  html := GetResourceText('TMSIWPOPCAL');
  html := StringReplace(html, '<#LEFTDATEPICKER>', IntToStr(Left) , [rfReplaceAll, rfIgnoreCase]);
  html := StringReplace(html, '<#TOPDATEPICKER>', IntToStr(Top), [rfReplaceAll, rfIgnoreCase]);

  html := StringReplace(html, '<#HINTPREVYEAR>', ' title="'+HintPrevYear+'" ' , [rfReplaceAll, rfIgnoreCase]);
  html := StringReplace(html, '<#HINTPREVMONTH>', ' title="'+FHintPrevMonth+'" ' , [rfReplaceAll, rfIgnoreCase]);
  html := StringReplace(html, '<#HINTNEXTMONTH>', ' title="'+FHintNextMonth+'" ' , [rfReplaceAll, rfIgnoreCase]);
  html := StringReplace(html, '<#HINTNEXTYEAR>', ' title="'+FHintNextYear+'" ' , [rfReplaceAll, rfIgnoreCase]);
  html := StringReplace(html, '<#STARTDAY>', IntToStr(FStartDay) , [rfReplaceAll, rfIgnoreCase]);

  //Modified Bug displaying calendarborder with BorderWidth property.
  html := StringReplace(html, '<#BW>', IntToStr(FBorderWidth) , [rfReplaceAll, rfIgnoreCase]);
  //End Modified

  if (DateFormat = dfUS) then
    html := StringReplace(html,'<#DATEFORMAT>','0',[rfReplaceAll,rfIgnoreCase])
  else
    html := StringReplace(html,'<#DATEFORMAT>','1',[rfReplaceAll,rfIgnoreCase]);

  html := StringReplace(html, '<#MONTHTEXTCOLOR>', HTMLClr(FMonthTextColor), [rfReplaceAll, rfIgnoreCase]);

  if Glyphs.NextMonthURL <> EmptyStr then
    html := StringReplace(html, '<#NEXTMONTH>','<IMG src="' + Glyphs.NextMonthURL + '">',[rfReplaceAll, rfIgnoreCase])
  else if FGlyphs.NextMonth.Empty then
  begin
    if isOpera then
      html := StringReplace(html, '<#NEXTMONTH>','&gt;',[rfReplaceAll, rfIgnoreCase])
    else
      html := StringReplace(html, '<#NEXTMONTH>','<FONT face=webdings>4</FONT>',[rfReplaceAll, rfIgnoreCase]);
  end
  else
  begin
    {$IFDEF TMSIW71}
    ImgName := TIWServerControllerBase.NewCacheFile('bmp',true);
    {$ELSE}
    ImgName := TIWServerControllerBase.NewCacheFile('bmp');
    {$ENDIF}
    FGlyphs.NextMonth.SaveToFile(ImgName);
    html := StringReplace(html, '<#NEXTMONTH>','<IMG src="' + GetCacheDir(Self) + ExtractFileName(ImgName) + '">',[rfReplaceAll, rfIgnoreCase]);
  end;

  if Glyphs.NextYearURL <> EmptyStr then
    html := StringReplace(html, '<#NEXTYEAR>','<IMG src="' + Glyphs.NextYearURL + '">',[rfReplaceAll, rfIgnoreCase])
  else if FGlyphs.NextYear.Empty then
  begin
    if isOpera then
      html := StringReplace(html, '<#NEXTYEAR>','&gt;&gt;',[rfReplaceAll, rfIgnoreCase])
    else
      html := StringReplace(html, '<#NEXTYEAR>','<FONT face=webdings>8</FONT>',[rfReplaceAll, rfIgnoreCase]);
  end
  else
  begin
    {$IFDEF TMSIW71}
    ImgName := TIWServerControllerBase.NewCacheFile('bmp',true);
    {$ELSE}
    ImgName := TIWServerControllerBase.NewCacheFile('bmp');
    {$ENDIF}
    FGlyphs.NextYear.SaveToFile(ImgName);
    html := StringReplace(html, '<#NEXTYEAR>','<IMG src="' + GetCacheDir(Self) + ExtractFileName(ImgName) + '">',[rfReplaceAll, rfIgnoreCase]);
  end;

  if Glyphs.PrevMonthURL <> EmptyStr then
    html := StringReplace(html, '<#PREVMONTH>','<IMG src="' + Glyphs.PrevMonthURL + '">',[rfReplaceAll, rfIgnoreCase])
  else if FGlyphs.PrevMonth.Empty then
  begin
    if isOpera then
      html := StringReplace(html, '<#PREVMONTH>','&lt;',[rfReplaceAll, rfIgnoreCase])
    else
      html := StringReplace(html, '<#PREVMONTH>','<FONT face=webdings>3</FONT>',[rfReplaceAll, rfIgnoreCase]);
  end
  else
  begin
    {$IFDEF TMSIW71}
    ImgName := TIWServerControllerBase.NewCacheFile('bmp',true);
    {$ELSE}
    ImgName := TIWServerControllerBase.NewCacheFile('bmp');
    {$ENDIF}
    FGlyphs.PrevMonth.SaveToFile(ImgName);
    html := StringReplace(html, '<#PREVMONTH>','<IMG src="' + GetCacheDir(Self) + ExtractFileName(ImgName) + '">',[rfReplaceAll, rfIgnoreCase]);
  end;

  if Glyphs.PrevYearURL <> EmptyStr then
    html := StringReplace(html, '<#PREVYEAR>','<IMG src="' + Glyphs.PrevYearURL + '">',[rfReplaceAll, rfIgnoreCase])  
  else if FGlyphs.PrevYear.Empty then
  begin
    if isOpera then
      html := StringReplace(html, '<#PREVYEAR>','&lt;&lt;',[rfReplaceAll, rfIgnoreCase])
    else
      html := StringReplace(html, '<#PREVYEAR>','<FONT face=webdings>7</FONT>',[rfReplaceAll, rfIgnoreCase]);
  end
  else
  begin
    {$IFDEF TMSIW71}
    ImgName := TIWServerControllerBase.NewCacheFile('bmp',true);
    {$ELSE}
    ImgName := TIWServerControllerBase.NewCacheFile('bmp');
    {$ENDIF}
    FGlyphs.PrevYear.SaveToFile(ImgName);
    html := StringReplace(html, '<#PREVYEAR>','<IMG src="' + GetCacheDir(Self) + ExtractFileName(ImgName) + '">',[rfReplaceAll, rfIgnoreCase]);
  end;

  if FBorderCollapse then
    html := StringReplace(html,'<#BORDERCOLLAPSE>','collapse', [rfReplaceAll, rfIgnoreCase])
  else
    html := StringReplace(html,'<#BORDERCOLLAPSE>','separate', [rfReplaceAll, rfIgnoreCase]);

  html := StringReplace(html, '<#GRIDLINEWIDTH>', inttoStr(FGridLineWidth) , [rfReplaceAll, rfIgnoreCase]);

  html := StringReplace(html, '<#GRIDLINECOLOR>', HTMLClr(FGridLineColor) , [rfReplaceAll, rfIgnoreCase]);

  if FShowPrevYear then
    html := StringReplace(html, '<#INSBEGINY>','BEGINYEAR',[rfReplaceAll,rfIgnoreCase])
  else
//    html := StringReplace(html, '<#INSBEGINY>','''<TD id="'+HTMLName+'calh"></TD>''',[rfReplaceAll,rfIgnoreCase]);
    html := StringReplace(html, '<#INSBEGINY>','''<TD width="<#WIDTHSPECIAL>" id="'+HTMLName+'calh"><div style="overflow:hidden;width:<#WIDTHSPECIAL>">&nbsp;</div></TD>''',[rfReplaceAll,rfIgnoreCase]);

  if FShowNextYear then
    html := StringReplace(html, '<#INSENDY>','ENDYEAR',[rfReplaceAll,rfIgnoreCase])
  else
//    html := StringReplace(html, '<#INSENDY>','''<TD id="'+HTMLName+'calh"></TD>''',[rfReplaceAll,rfIgnoreCase]);
    html := StringReplace(html, '<#INSENDY>','''<TD width="<#COLWIDTHE>" id="'+HTMLName+'calh"><div style="overflow:hidden;width:<#COLWIDTHE>">&nbsp;</div></TD>''',[rfReplaceAll,rfIgnoreCase]);

  if FShowPrevMonth then
    html := StringReplace(html,'<#INSBEGIN>','BEGINMONTH',[rfReplaceAll, rfIgnoreCase])
  else
//    html := StringReplace(html,'<#INSBEGIN>','''<TD id="'+HTMLName+'calh"></TD>''',[rfReplaceAll, rfIgnoreCase]);
    html := StringReplace(html,'<#INSBEGIN>','''<TD width="<#WIDTHSPECIAL>" id="'+HTMLName+'calh"><div style="overflow:hidden;width:<#WIDTHSPECIAL>">&nbsp;</div></TD>''',[rfReplaceAll, rfIgnoreCase]);

  if FShowNextMonth then
    html := StringReplace(html,'<#INSEND>','ENDMONTH',[rfReplaceAll, rfIgnoreCase])
  else
//    html := StringReplace(html,'<#INSEND>','''<TD id="'+HTMLName+'calh"></TD>''',[rfReplaceAll, rfIgnoreCase]);
    html := StringReplace(html,'<#INSEND>','''<TD width="<#WIDTHSPECIAL>" id="'+HTMLName+'calh"><div style="overflow:hidden;width:<#WIDTHSPECIAL>">&nbsp;</div></TD>''',[rfReplaceAll, rfIgnoreCase]);

    {$IFDEF TMSIW9}
    if Assigned(FOnAsyncClick) then
      ajaxcall := 'processAjaxEvent(''onClick'', '
        + HTMLControlImplementation.IWCLName
        + ',''' + HTMLName + '.' + 'DoOnAsyncClick' + ''','
        + 'true' + ', null, '
        + 'true' + ');';

    Acontext.WebApplication.RegisterCallBack(HTMLName+'.DoOnAsyncClick', DoOnAsyncClick);

    if Assigned(FOnAsyncNextMonth) then
      ajaxnextmonth := 'processAjaxEvent(''onNextMonth'', '
        + HTMLControlImplementation.IWCLName
        + ',''' + HTMLName + '.' + 'DoOnAsyncNextMonth' + ''','
        + 'true' + ', null, '
        + 'true' + ');';

    Acontext.WebApplication.RegisterCallBack(HTMLName+'.DoOnAsyncNextMonth', DoOnAsyncNextMonth);

    if Assigned(FOnAsyncPrevMonth) then
      ajaxprevmonth := 'processAjaxEvent(''onPrevMonth'', '
        + HTMLControlImplementation.IWCLName
        + ',''' + HTMLName + '.' + 'DoOnAsyncPrevMonth' + ''','
        + 'true' + ', null, '
        + 'true' + ');';

    Acontext.WebApplication.RegisterCallBack(HTMLName+'.DoOnAsyncPrevMonth', DoOnAsyncPrevMonth);

    if Assigned(FOnAsyncNextYear) then
      ajaxnextyear := 'processAjaxEvent(''onNextYear'', '
        + HTMLControlImplementation.IWCLName
        + ',''' + HTMLName + '.' + 'DoOnAsyncNextYear' + ''','
        + 'true' + ', null, '
        + 'true' + ');';

    Acontext.WebApplication.RegisterCallBack(HTMLName+'.DoOnAsyncNextYear', DoOnAsyncNextYear);

    if Assigned(FOnAsyncPrevYear) then
      ajaxprevyear := 'processAjaxEvent(''onPrevYear'', '
        + HTMLControlImplementation.IWCLName
        + ',''' + HTMLName + '.' + 'DoOnAsyncPrevYear' + ''','
        + 'true' + ', null, '
        + 'true' + ');';

    Acontext.WebApplication.RegisterCallBack(HTMLName+'.DoOnAsyncPrevYear', DoOnAsyncPrevYear);

    if Assigned(FOnAsyncChange) then
      ajaxchange := 'processAjaxEvent(''onChange'', '
        + HTMLControlImplementation.IWCLName
        + ',''' + HTMLName + '.' + 'DoOnAsyncChange' + ''','
        + 'true' + ', null, '
        + 'true' + ');';

    Acontext.WebApplication.RegisterCallBack(HTMLName+'.DoOnAsyncChange', DoOnAsyncChange);

    if Assigned(FOnAsyncEnter) then
      ajaxenter := 'processAjaxEvent(''onEnter'', '
        + HTMLControlImplementation.IWCLName
        + ',''' + HTMLName + '.' + 'DoOnAsyncEnter' + ''','
        + 'true' + ', null, '
        + 'true' + ');';

    Acontext.WebApplication.RegisterCallBack(HTMLName+'.DoOnAsyncEnter', DoOnAsyncEnter);

    if Assigned(FOnAsyncExit) then
      ajaxexit := 'processAjaxEvent(''onExit'', '
        + HTMLControlImplementation.IWCLName
        + ',''' + HTMLName + '.' + 'DoOnAsyncExit' + ''','
        + 'true' + ', null, '
        + 'true' + ');';

    Acontext.WebApplication.RegisterCallBack(HTMLName+'.DoOnAsyncExit', DoOnAsyncExit);
    {$ENDIF}

  html := StringReplace(html,'<#ASYNCCHANGECALL>',ajaxchange,[rfReplaceAll, rfIgnoreCase]);
  html := StringReplace(html,'<#ASYNCENTERCALL>',ajaxenter,[rfReplaceAll, rfIgnoreCase]);
  html := StringReplace(html,'<#ASYNCEXITCALL>',ajaxexit,[rfReplaceAll, rfIgnoreCase]);

  if Assigned(FOnPrevMonth) then
    html := StringReplace(html,'<#PREVMONTHCALL>',ajaxprevmonth + 'return SubmitClick('#39+HTMLName+#39', "Prev", '#39'false'#39');',[rfReplaceAll, rfIgnoreCase])
  else
    html := StringReplace(html,'<#PREVMONTHCALL>',ajaxprevmonth,[rfReplaceAll, rfIgnoreCase]);

  if Assigned(FOnNextMonth) then
    html := StringReplace(html,'<#NEXTMONTHCALL>',ajaxnextmonth + 'return SubmitClick('#39+HTMLName+#39', "Next", '#39'false'#39');',[rfReplaceAll, rfIgnoreCase])
  else
    html := StringReplace(html,'<#NEXTMONTHCALL>',ajaxnextmonth,[rfReplaceAll, rfIgnoreCase]);

  if Assigned(FOnPrevYear) then
    html := StringReplace(html,'<#PREVYEARCALL>',ajaxprevyear + 'return SubmitClick('#39+HTMLName+#39', "PrevY", '#39'false'#39');',[rfReplaceAll, rfIgnoreCase])
  else
    html := StringReplace(html,'<#PREVYEARCALL>',ajaxprevyear,[rfReplaceAll, rfIgnoreCase]);

  if Assigned(FOnNextYear) then
    html := StringReplace(html,'<#NEXTYEARCALL>',ajaxnextyear + 'return SubmitClick('#39 + HTMLName + #39',"NextY", '#39'false'#39');',[rfReplaceAll, rfIgnoreCase])
  else
    html := StringReplace(html,'<#NEXTYEARCALL>',ajaxnextyear,[rfReplaceAll, rfIgnoreCase]);

  html := StringReplace(html,'<#WEEKENDTEXTCOLOR>',HTMLClr(FWeekendTextColor), [rfReplaceAll, rfIgnoreCase]);

  if not Enabled and (DisabledAppearance = daGrayed) then
  begin
    html := StringReplace(html,'<#BUTTONENABLED>','disabled', [rfReplaceAll, rfIgnoreCase]);
    html := StringReplace(html,'<#IMAGEENABLED>','return;', [rfReplaceAll, rfIgnoreCase]);
  end
  else
  begin
    html := StringReplace(html,'<#BUTTONENABLED>','', [rfReplaceAll, rfIgnoreCase]);
    html := StringReplace(html,'<#IMAGEENABLED>','', [rfReplaceAll, rfIgnoreCase]);
  end;

  if DropDownImageURL <> EmptyStr then
  begin
    html := StringReplace(html,'<#BUTTONVISIBLE>','display:none;', [rfReplaceAll, rfIgnoreCase]);
    html := StringReplace(html,'<#IMAGEVISIBLE>','', [rfReplaceAll, rfIgnoreCase]);

    html := StringReplace(html,'<#BUTTONIMAGE>','src="' + DropDownImageURL + '"', [rfReplaceAll, rfIgnoreCase]);
  end
  else if FDropDownImage.Empty then
  begin
    html := StringReplace(html,'<#BUTTONVISIBLE>','', [rfReplaceAll, rfIgnoreCase]);
    html := StringReplace(html,'<#BUTTONIMAGE>','', [rfReplaceAll, rfIgnoreCase]);
    html := StringReplace(html,'<#IMAGEVISIBLE>','display:none;', [rfReplaceAll, rfIgnoreCase]);
  end
  else
  begin
    html := StringReplace(html,'<#BUTTONVISIBLE>','display:none;', [rfReplaceAll, rfIgnoreCase]);
    html := StringReplace(html,'<#IMAGEVISIBLE>','', [rfReplaceAll, rfIgnoreCase]);

    if FDropDownImage.IsGIF then
    {$IFDEF TMSIW71}
      ImgName := TIWServerControllerBase.NewCacheFile('gif', true)
    {$ELSE}                                                                      
      ImgName := TIWServerControllerBase.NewCacheFile('gif')
    {$ENDIF}
    else                                                                 
    {$IFDEF TMSIW71}
      ImgName := TIWServerControllerBase.NewCacheFile('jpg', true);
    {$ELSE}
      ImgName := TIWServerControllerBase.NewCacheFile('jpg');
    {$ENDIF}

    FDropDownImage.SaveToFile(ImgName);


    html := StringReplace(html,'<#BUTTONIMAGE>','src="'+ GetCacheDir(Self) + ExtractFilename(ImgName)+'"', [rfReplaceAll, rfIgnoreCase]);
  end;


  if FBackgroundImage.Empty then
  begin
//    html := StringReplace(html,'<#BGIMAGE>','', [rfReplaceAll, rfIgnoreCase]);

    {$IFDEF TMSIW6}
    if (FGradientStartColor = clNone) or (FGradientEndColor = clNone) or not (AContext.WebApplication.Browser = brIE) then
    {$ELSE}
    if (FGradientStartColor = clNone) or (FGradientEndColor = clNone) or not (WebApplication.Browser = brIE) then
    {$ENDIF}
    begin
      html := StringReplace(html,'<#BKCOLOR>','', [rfReplaceAll, rfIgnoreCase]);
      html := StringReplace(html,'<#GRADIENT>','', [rfReplaceAll, rfIgnoreCase]);
      html := StringReplace(html,'<#TRANSPARENCY>','', [rfReplaceAll, rfIgnoreCase]);

      if (FWeekendColor <> clNone) then
        html := StringReplace(html,'<#WEEKENDCOLOR>','background-color:'+HTMLClr(FWeekendColor)+';', [rfReplaceAll, rfIgnoreCase])
      else
        html := StringReplace(html,'<#WEEKENDCOLOR>','', [rfReplaceAll, rfIgnoreCase]);

      if (FTransparency = 0) then
        html := StringReplace(html, '<#BGIMAGE>',' Bgcolor="' + HTMLClr(Color) + '"', [rfReplaceAll, rfIgnoreCase])
      else
        html := StringReplace(html, '<#BGIMAGE>',' Bgcolor="' + HTMLClr(Color) + '" style="filter:alpha(opacity=' + IntToStr(100 - FTransparency) + ')"', [rfReplaceAll, rfIgnoreCase]);
    end
    else
    begin
      html := StringReplace(html,'<#TRANSPARENCY>','', [rfReplaceAll, rfIgnoreCase]);
      html := StringReplace(html,'<#BKCOLOR>','', [rfReplaceAll, rfIgnoreCase]);
      html := StringReplace(html,'<#WEEKENDCOLOR>','', [rfReplaceAll, rfIgnoreCase]);
      if FGradientDirection = gdVertical then
        GradientType := '0'
      else
        GradientType := '1';
      html := StringReplace(html, '<#GRADIENT>','STYLE="FILTER: progid:DXImageTransform.Microsoft.Gradient(GradientType='+GradientType + ', StartColorStr='+HTMLClr(GradientStartColor)+',EndColorStr='+HTMLClr(GradientEndColor)+')" ', [rfReplaceAll, rfIgnoreCase]);
      html := StringReplace(html, '<#BGIMAGE>','', [rfReplaceAll, rfIgnoreCase]);
    end;
    end

  else
  begin
    html := StringReplace(html,'<#BKCOLOR>','', [rfReplaceAll, rfIgnoreCase]);
    html := StringReplace(html,'<#GRADIENT>','', [rfReplaceAll, rfIgnoreCase]);
    html := StringReplace(html,'<#WEEKENDCOLOR>','', [rfReplaceAll, rfIgnoreCase]);

    if FBackgroundImage.IsGIF then
    {$IFDEF TMSIW71}
      ImgName := TIWServerControllerBase.NewCacheFile('gif',true)
    {$ELSE}
      ImgName := TIWServerControllerBase.NewCacheFile('gif')
    {$ENDIF}
    else
    {$IFDEF TMSIW71}
      ImgName := TIWServerControllerBase.NewCacheFile('jpg',true);
    {$ELSE}
      ImgName := TIWServerControllerBase.NewCacheFile('jpg');
    {$ENDIF}

    FBackgroundImage.SaveToFile(ImgName);

    if (FTransparency = 0) then
      html := StringReplace(html, '<#BGIMAGE>',' BACKGROUND="' + GetCacheDir(Self) + ExtractFilename(ImgName)+'" ', [rfReplaceAll, rfIgnoreCase])
    else
      html := StringReplace(html, '<#BGIMAGE>',' BACKGROUND="' + GetCacheDir(Self) + ExtractFilename(ImgName)
            + '" style="filter:alpha(opacity=' + IntToStr(100 - FTransparency) + ')"', [rfReplaceAll, rfIgnoreCase]);

    html := StringReplace(html, '<#TRANSPARENCY>', '', [rfReplaceAll, rfIgnoreCase]);
  end;

  if (FMonthGradientStartColor = clNone) or (FMonthGradientEndColor = clNone) then
  begin
    if (BackgroundImage.Empty) then
    begin
      html := StringReplace(html,'<#HDRCOLOR>', ColorToRGBString(MonthColor), [rfReplaceAll, rfIgnoreCase]);

      if (FTransparency = 0) then
        html := StringReplace(html,'<#TRANSPARENCYM>', '', [rfReplaceAll, rfIgnoreCase])
      else
        html := StringReplace(html,'<#TRANSPARENCYM>', 'style="filter:alpha(opacity=' + IntToStr(100 - Transparency) + ')"', [rfReplaceAll, rfIgnoreCase]);
    end
    else
    begin
      html := StringReplace(html,'<#HDRCOLOR>','', [rfReplaceAll, rfIgnoreCase]);
      html := StringReplace(html,'<#TRANSPARENCYM>','', [rfReplaceAll, rfIgnoreCase]);
    end;
    html := StringReplace(html,'<#HEADER>','', [rfReplaceAll, rfIgnoreCase]);
  end
  else
  begin
    html := StringReplace(html,'background-color:"<#HDRCOLOR>";','', [rfReplaceAll, rfIgnoreCase]);
    html := StringReplace(html, '<#TRANSPARENCYM>', '', [rfReplaceAll, rfIgnoreCase]);

    if FMonthGradientDirection = gdVertical then
      MonthGradientType := '0'
    else
      MonthGradientType := '1';

    if (BackgroundImage.Empty) then
      html := StringReplace(html,'<#HEADER>','STYLE="FILTER: progid:DXImageTransform.Microsoft.Gradient(GradientType='+MonthGradientType + ', StartColorStr='+HTMLClr(MonthGradientStartColor)+',EndColorStr='+HTMLClr(MonthGradientEndColor)+')" ', [rfReplaceAll, rfIgnoreCase])
    else
      html := StringReplace(html,'<#HEADER>','', [rfReplaceAll, rfIgnoreCase]);
  end;

  {$IFDEF TMSIW6}
  html := StringReplace(html,'<#INPUTFONT>', Font.FontToStringStyle(AContext.WebApplication.Browser),[rfReplaceAll, rfIgnoreCase]);
  {$ELSE}
  html := StringReplace(html,'<#INPUTFONT>', Font.FontToStringStyle(WebApplication.Browser),[rfReplaceAll, rfIgnoreCase]);
  {$ENDIF}

  if (BackgroundImage.Empty) then
    html := StringReplace(html,'<#WKCOLOR>',HTMLClr(Color), [rfReplaceAll, rfIgnoreCase])
  else
    html := StringReplace(html,'background-color:<#WKCOLOR>','', [rfReplaceAll, rfIgnoreCase]);

  html := StringReplace(html,'<#SELCOLOR>',HTMLClr(TodayColor), [rfReplaceAll, rfIgnoreCase]);
  html := StringReplace(html,'<#HOVERCOLOR>',HTMLClr(HoverColor), [rfReplaceAll, rfIgnoreCase]);
  html := StringReplace(html,'<#FNTCOLOR>',HTMLClr(CalendarFont.Color), [rfReplaceAll, rfIgnoreCase]);
  html := StringReplace(html,'<#BRDCOLOR>',HTMLClr(BorderColor), [rfReplaceAll, rfIgnoreCase]);
  html := StringReplace(html,'<#FONTNAME>',CalendarFont.FontName, [rfReplaceAll, rfIgnoreCase]);
  html := StringReplace(html,'<#FONTSIZE>',IntToStr(CalendarFont.Size), [rfReplaceAll, rfIgnoreCase]);
  html := StringReplace(html,'<#SELMONTH>',IntToStr(Month - 1), [rfReplaceAll, rfIgnoreCase]);
  html := StringReplace(html,'<#SELYEAR>',IntToStr(Year), [rfReplaceAll, rfIgnoreCase]);
  html := StringReplace(html,'<#SELDAY>',IntToStr(Day), [rfReplaceAll, rfIgnoreCase]);

  {$IFDEF TMSIW9}
  html := StringReplace(html,'<#IW9>','true',[rfReplaceAll, rfIgnoreCase]);
  {$ELSE}
  html := StringReplace(html,'<#IW9>','false',[rfReplaceAll, rfIgnoreCase]);
  {$ENDIF}

  html := StringReplace(html,'<#COMPNAME>',HTMLName,[rfReplaceAll, rfIgnoreCase]);

  html := StringReplace(html,'<#TOTALWIDTHCAL>',IntToStr(CalendarWidth),[rfReplaceAll, rfIgnoreCase]);
  html := StringReplace(html,'<#TOTALHEIGHTCAL>',IntToStr(CalendarHeight),[rfReplaceAll, rfIgnoreCase]);
{
  html := StringReplace(html,'<#COLWIDTH>',IntToStr(Round(CalendarWidth / 7) - FGridLineWidth) + 'px',[rfReplaceAll, rfIgnoreCase]);
  html := StringReplace(html,'<#WIDTHSPECIAL>',IntToStr(Round(CalendarWidth / 7)) + 'px',[rfReplaceAll, rfIgnoreCase]);
  html := StringReplace(html,'<#COLWIDTHE>',IntToStr(Round(CalendarWidth / 7) + FGridLineWidth) + 'px',[rfReplaceAll, rfIgnoreCase]);
}
  html := StringReplace(html,'<#COLWIDTH>',IntToStr(Round(CalendarWidth / 7)) + 'px',[rfReplaceAll, rfIgnoreCase]);

  if (FBorderCollapse) then
    html := StringReplace(html,'<#WIDTHSPECIAL>',IntToStr(Round(CalendarWidth / 7) + FGridLineWidth) + 'px',[rfReplaceAll, rfIgnoreCase])
  else
    html := StringReplace(html,'<#WIDTHSPECIAL>',IntToStr(Round(CalendarWidth / 7) + 2 * FGridLineWidth) + 'px',[rfReplaceAll, rfIgnoreCase]);

  if (FGridLineWidth > 0) then
  begin
    if (FBorderCollapse) then
      html := StringReplace(html,'<#COLWIDTHE>',IntToStr(Round(CalendarWidth / 7) + (2 * FGridLineWidth)) + 'px',[rfReplaceAll, rfIgnoreCase])
    else
      html := StringReplace(html,'<#COLWIDTHE>',IntToStr(Round(CalendarWidth / 7) + (4 * FGridLineWidth)) + 'px',[rfReplaceAll, rfIgnoreCase]);
  end
  else                                              
  begin
    if (FBorderCollapse) then
      html := StringReplace(html,'<#COLWIDTHE>',IntToStr(Round(CalendarWidth / 7) + 1) + 'px',[rfReplaceAll, rfIgnoreCase])
    else
      html := StringReplace(html,'<#COLWIDTHE>',IntToStr(Round(CalendarWidth / 7) + 2) + 'px',[rfReplaceAll, rfIgnoreCase]);
  end;

  html := StringReplace(html,'<#ROWHEIGHT>',IntToStr(CalendarHeight div 7) + 'px',[rfReplaceAll, rfIgnoreCase]);
  html := StringReplace(html,'<#ROW>',IntToStr((Font.Size + 6)),[rfReplaceAll, rfIgnoreCase]);

  html := StringReplace(html,'<#TOTALWIDTH>', IntToStr(CalendarWidth),[rfReplaceAll,rfIgnoreCase]);
  html := StringReplace(html,'<#TOTALHEIGHT>', IntToStr((Round(Font.Size * 1.6)) * 9 + Height),[rfReplaceAll,rfIgnoreCase]);

  html := StringReplace(html,'<#EDITWIDTH>',IntToStr((Width - 40) div 7),[rfReplaceAll, rfIgnoreCase]);

  if (FocusColor = clNone) then             
  begin
    html := StringReplace(html, '<#FOCUSCOLOR>', '', [rfReplaceAll, rfIgnoreCase]);
    html := StringReplace(html, '<#SETCOLORBACK>', 'N', [rfReplaceAll, rfIgnoreCase]);
  end
  else
  begin
    html := StringReplace(html, '<#FOCUSCOLOR>', 'ctrl.style.backgroundColor="' + ColorToRGBString(FocusColor) + '";', [rfReplaceAll,rfIgnoreCase]);
    html := StringReplace(html, '<#SETCOLORBACK>', 'Y', [rfReplaceAll, rfIgnoreCase]);
  end;

  InputFieldWidth := Round(Width * 0.85);
	InputFieldHeight := Height;
  ButtonWidth := Width - InputFieldWidth;
	ButtonHeight := Height;

  html := StringReplace(html,'<#INPUTFIELDWIDTH>',IntToStr(InputFieldWidth),[rfReplaceAll, rfIgnoreCase]);
  html := StringReplace(html,'<#INPUTFIELDHEIGHT>',IntToStr(InputFieldHeight),[rfReplaceAll, rfIgnoreCase]);
//  html := StringReplace(html,'<#INPUTFONT>',Font.FontName,[rfReplaceAll, rfIgnoreCase]);
  html := StringReplace(html,'<#BUTTONFIELDWIDTH>',IntToStr(ButtonWidth),[rfReplaceAll, rfIgnoreCase]);
  html := StringReplace(html,'<#BUTTONFIELDHEIGHT>',IntToStr(ButtonHeight),[rfReplaceAll, rfIgnoreCase]);

  html := StringReplace(html,'<#DATESEP>',#39+ StrDateSep + #39, [rfReplaceAll, rfIgnoreCase]);

  html := StringReplace(html,'<#DATESEPORD>',IntToStr(CodeDateSeparator), [rfReplaceAll, rfIgnoreCase]);

  if not EditorEnabled or ((Enabled = false) and (DisabledAppearance = daGrayed)) then
  begin
//    html :=  StringReplace(html,'<#EDITENABLE>','event.returnValue=false;'#13#10'return;', [rfReplaceAll, rfIgnoreCase]);
    html := StringReplace(html,'<#EDITABLE>','readonly', [rfReplaceAll, rfIgnoreCase]);
  end
  else
  begin
//    html := StringReplace(html,'<#EDITENABLE>','', [rfReplaceAll, rfIgnoreCase]);
    html := StringReplace(html,'<#EDITABLE>','', [rfReplaceAll, rfIgnoreCase]);
  end;

  {$IFDEF TMSIW72_NEW}
  if (TabOrder >= 0) then
    html := StringReplace(html,'<#INPUTTAB>','tabindex="'+IntToStr(TabOrder + 1)+'"', [rfReplaceAll, rfIgnoreCase])
  else
    html := StringReplace(html,'<#INPUTTAB>','', [rfReplaceAll, rfIgnoreCase]);
  {$ELSE}
  html := StringReplace(html,'<#INPUTTAB>','', [rfReplaceAll, rfIgnoreCase]);
  {$ENDIF}

  if (Date = 0) and FNullIsToday then
    Date := Now;

  if Date = 0 then
    html := StringReplace(html,'<#CALVALUE>','',[rfReplaceAll, rfIgnoreCase])
  else
  begin
    if DateFormat = dfEU then
      html := StringReplace(html,'<#CALVALUE>',IntToStr(Day) + StrDateSep + IntToStr(Month) + StrDateSep + IntToStr(Year),[rfReplaceAll, rfIgnoreCase])
    else
      html := StringReplace(html,'<#CALVALUE>',IntToStr(Month) + StrDateSep + IntToStr(Day) + StrDateSep + IntToStr(Year),[rfReplaceAll, rfIgnoreCase]);
  end;

  if DateFormat = dfEU then
    html := StringReplace(html,'<#FORMAT>','0',[rfReplaceAll, rfIgnoreCase])
  else
    html := StringReplace(html,'<#FORMAT>','1',[rfReplaceAll, rfIgnoreCase]);

  if FNameOfDays.Count > 6 then
    InitDays;

  if FFlat then
    html := StringReplace(html,'<#BUTTONSTYLES>',' style="border-style:solid;border-width:1;" ',[rfReplaceAll, rfIgnoreCase])
  else
    html := StringReplace(html,'<#BUTTONSTYLES>','',[rfReplaceAll, rfIgnoreCase]);


  if FBGColor <> clNone then
  begin
    bgcol := 'background:'+HTMLClr(FBGColor)+';';
    html := StringReplace(html,'<#INPBGCOLOR>','"'+HTMLClr(FBGColor)+'"',[rfReplaceAll, rfIgnoreCase]);
  end
  else
  begin
    bgcol := '';
    html := StringReplace(html,'<#INPBGCOLOR>','""',[rfReplaceAll, rfIgnoreCase]);
  end;

  if FFlat then
    html := StringReplace(html,'<#INPUTSTYLES>',' style="'+bgcol+'border-style:solid;border-width:'+IntToStr(FBorderWidth)+'px;border-color:'+HTMLClr(FBorderColor)+'";',[rfReplaceAll, rfIgnoreCase])
  else
  begin
    if bgcol <> '' then
      html := StringReplace(html,'<#INPUTSTYLES>',' style="'+bgcol+'"',[rfReplaceAll, rfIgnoreCase])
    else
      html := StringReplace(html,'<#INPUTSTYLES>','',[rfReplaceAll, rfIgnoreCase]);
  end;


  html := StringReplace(html,'<#FOCUSCOLOR>',HTMLClr(FFocusColor),[rfReplaceAll, rfIgnoreCase]);
  html := StringReplace(html,'<#NORMCOLOR>',HTMLClr(FColor),[rfReplaceAll, rfIgnoreCase]);

  html := StringReplace(html,'<#FOCUSCLIENT>',ClientEvents.OnEnter.Text,[rfReplaceAll, rfIgnoreCase]);
  html := StringReplace(html,'<#BLURCLIENT>',ClientEvents.OnExit.Text,[rfReplaceAll, rfIgnoreCase]);

  html := StringReplace(html,'<#NEXTYEARCLIENT>',ClientEvents.NextYearClick.Text,[rfReplaceAll, rfIgnoreCase]);
  html := StringReplace(html,'<#NEXTMONTHCLIENT>',ClientEvents.NextMonthClick.Text,[rfReplaceAll, rfIgnoreCase]);

  html := StringReplace(html,'<#PREVYEARCLIENT>',ClientEvents.PrevYearClick.Text,[rfReplaceAll, rfIgnoreCase]);
  html := StringReplace(html,'<#PREVMONTHCLIENT>',ClientEvents.PrevMonthClick.Text,[rfReplaceAll, rfIgnoreCase]);

  html := StringReplace(html,'<#DATECLIENT>',ClientEvents.DateClick.Text,[rfReplaceAll, rfIgnoreCase]);

  for i := 0 to 6 do                            
  begin
    html := StringReplace(html,'<#DAY'+inttostr(i)+'>',FNameOfDays[i],[rfReplaceAll, rfIgnoreCase]);
  end;

  if Assigned(FOnClick) then
    html := StringReplace(html,'<#SUBMITCALL>',ajaxcall + 'return SubmitClick('#39+HTMLName+#39', s, '#39'false'#39');',[rfReplaceAll, rfIgnoreCase])
  else
    html := StringReplace(html,'<#SUBMITCALL>',ajaxcall,[rfReplaceAll, rfIgnoreCase]);

  if FNameOfMonths.Count > 6 then
    InitMonths;

  for i := 0 to 11 do
  begin
    html := StringReplace(html,'<#MONTH'+inttostr(i)+'>',FNameOfMonths[i],[rfReplaceAll, rfIgnoreCase]);
  end;
  
  {$IFDEF TMSIW9}
   if (Css <> EmptyStr) then
     html := StringReplace(html,'<#CLASSNAME>','class="' + Css + '"',[rfReplaceAll, rfIgnoreCase])
   else
   {$ENDIF}
     html := StringReplace(html,'<#CLASSNAME>','',[rfReplaceAll, rfIgnoreCase]);

//  s := '<script>function ' + HTMLName + 'changeZIndex() {'#13
//      + ' el = document.getElementById(''' +  HTMLName + ''');'#13
//      + ' el.style.zIndex = ' + IntToStr(ZIndex) + ';'#13
//      + '}</script>'#13;

  Result := TIWHTMLTag.CreateTag('DIV');
  //if css class is defined remove it from the outer div.
  //the class should only be set on the input tag
  {$IFDEF TMSIW9}
  if Css <> EmptyStr then
    Result.AddStringParam('class', ' ');
  {$ENDIF}  

  Result.Contents.AddText(html);

  with Result.Contents.AddTag('INPUT') do
  begin
    AddStringParam('TYPE','hidden');
    AddStringParam('NAME',HTMLName);
    AddStringParam('ID',HTMLName+'_INPUT');
  end;
end;

procedure TTIWCustomDatePicker.SetColor(const Value: TIWColor);
begin
  FColor := Value;
  Invalidate;
end;

procedure TTIWCustomDatePicker.SetWeekendTextColor(const Value: TIWColor);
begin
  FWeekendTextColor := Value;
end;

procedure TTIWCustomDatePicker.SetFlat(const Value: Boolean);
begin
  FFlat := Value;
  Invalidate;
end;

procedure TTIWCustomDatePicker.SetDateSep(const Value : TTIWDateSeparator);
begin
  FDateSep := Value;
  Invalidate;
end;

procedure TTIWCustomDatePicker.SetMonthTextColor(const Value: TIWColor);
begin
  FMonthTextColor := Value;
  Invalidate;
end;

procedure TTIWCustomDatePicker.SetDay(const Value: Integer);
begin
  if (Value > -1 ) and (Value <= DaysInMonth(FMonth,FYear)) then
    FDay := Value;
  Invalidate;
end;

procedure TTIWCustomDatePicker.SetMonth(const Value: Integer);
begin
  if (Value > 0) and (Value < 13) then
    FMonth := Value;
  Invalidate;
end;

procedure TTIWCustomDatePicker.SetMonthColor(const Value: TIWColor);
begin
  FMonthColor := Value;
  Invalidate;
end;

procedure TTIWCustomDatePicker.SetTodayColor(const Value: TIWColor);
begin
  FTodayColor := Value;
  Invalidate;
end;

procedure TTIWCustomDatePicker.SetYear(const Value: Integer);
begin
  FYear := Value;
  Invalidate;
end;

procedure TTIWCustomDatePicker.SetGridLinewidth(const Value: Integer);
begin
  FGridLineWidth := Value;
end;

procedure TTIWCustomDatePicker.SetGridLineColor(const Value: TIWColor);
begin
  FGridLineColor := Value;
end;

procedure Draw3DCtrl(FCanvas: TCanvas; Left,Top,Right,Bottom: Integer);
begin
  with FCanvas do
  begin
    Pen.Color := clBlack;
    MoveTo(Left,Bottom);
    LineTo(Left,Top);
    LineTo(Right,Top);

    Pen.Color := clSilver;
    LineTo(Right,Bottom);
    LineTo(Left,Bottom);

    Pen.Color := clGray;
    LineTo(Left + 1,Bottom);
    LineTo(Left + 1,Top + 1);
    LineTo(Right - 1,Top + 1);

  end;
end;

{$IFDEF TMSIW6}
procedure TTIWCustomDatePicker.IWPaint;
{$ELSE}
procedure TTIWCustomDatePicker.Paint;
{$ENDIF}
var
  r: TRect;
  StrDateSep : string;
begin
  if not Assigned(FNameofDays) then
    Exit;
  if not Assigned(FNameofMonths) then
    Exit;

  if (DateSep = dsMinus) then
    StrDateSep := '-'
  else
  begin
    if (DateSep = dsPoint) then
      StrDateSep := '.'
    else
      StrDateSep := '/';
  end;

  Canvas.Font.Name := Font.FontName;
  Canvas.Font.Size := Font.Size;

  with Canvas do
  begin
    if Enabled or (DisabledAppearance = daGrayed) then
    begin
      if FFlat then
      begin
        Pen.Color := clBlack;
        Pen.Width := 1;
        if BGColor = clNone then
          Brush.Style := bsClear
        else
        begin
          Brush.Style := bsSolid;
          Brush.Color := BGColor;
        end;
        Rectangle(0,0,Width - 20,Height);
      end
      else
      begin
        Draw3DCtrl(Canvas,0,0,Width - 22,Height - 1);
      end;
    end;

    if BGColor = clNone then
      Brush.Color := clWhite
    else
      Brush.Color := BGColor;

    Brush.Style := bsSolid;
    Pen.Color := clBlack;
    Pen.Width := 1;

    R := ClientRect;
    R.Right := R.Right - 20;

    Inflaterect(r,-2,-2);

    if (Date <> 0) then
    begin
      if DateFormat = dfEU then
        TextRect(r,2,2,IntToStr(Day) + StrDateSep + IntToStr(Month) + StrDateSep + IntToStr(Year))
      else
        TextRect(r,2,2,IntToStr(Month) + StrDateSep + IntToStr(Day) + StrDateSep + IntToStr(Year));
    end;

    R := ClientRect;

    r.Left := r.Right - 20;
    r.Bottom := r.Top + 20;

    if Enabled or (DisabledAppearance = daGrayed) then
    begin
      {$IFNDEF LINUX}
      DrawFrameControl(Handle,r,DFC_BUTTON,DFCS_BUTTONPUSH);
      SetBKMode(Handle,TRANSPARENT);
      {$ENDIF}
      InflateRect(r,-2,-2);
      TextOut(r.Left,r.Top,'...');
    end;
  end;
end;

procedure TTIWCustomDatePicker.SetNameOfDays(const Value: TStringList);
begin
  FNameOfDays.Assign(Value);
  Invalidate;
end;

procedure TTIWCustomDatePicker.SetBackgroundImage(const Value: TIPicture);
begin
  FBackgroundImage.Assign(Value);
end;

procedure TTIWCustomDatePicker.SetDropDownImage(const Value: TIPicture);
begin
  FDropDownImage.Assign(Value);
end;

procedure TTIWCustomDatePicker.SetNameOfMonths(const Value: TStringList);
begin
  FNameOfMonths.Assign(Value);
  Invalidate;
end;

destructor TTIWCustomDatePicker.Destroy;
begin
  FNameOfDays.Free;
  FNameOfMonths.Free;
  FBackgroundImage.Free;
  FDropDownImage.Free;
  FGlyphs.Free;
  FCalendarFont.Free;
  FClientEvents.Free;
  inherited;
end;

procedure TTIWCustomDatePicker.SetHoverColor(const Value: TIWColor);
begin
  FHoverColor := Value;
end;

procedure TTIWCustomDatePicker.SetStartDay(const Value: Integer);
begin
  if ((Value < 1) or (Value > 7)) then
  begin
    raise Exception.Create('StartDay must be between 1 and 7.');
    FStartDay := 1;
  end
  else
    FStartDay := Value;
end;

procedure TTIWCustomDatePicker.SetTransparency(const Value : Integer);
begin
  if ((Value < 0) or (Value > 100)) then
  begin
    raise Exception.Create('Transparency must be between 0 and 100.');
    FTransparency := 0;
  end
  else
    FTransparency := Value;
end;

procedure TTIWCustomDatePicker.SetGradientStartColor(const Value: TIWColor);
begin
  FGradientStartColor := Value;
  Invalidate;
end;

procedure TTIWCustomDatePicker.SetGradientEndColor(const Value: TIWColor);
begin
  FGradientEndColor := Value;
  Invalidate;
end;

procedure TTIWCustomDatePicker.SetGradientDirection(const Value: TTIWGradientDirection);
begin
  FGradientDirection := Value;
  Invalidate;
end;

procedure TTIWCustomDatePicker.SetValue(const AValue: string);
var
  s: string;
  da,mo,ye: Word;
  err: Integer;
  StrDateSep : String;
begin
  s := AValue;
  FEditText := AValue;

  if FEditText = '' then
  begin
    Date := 0;
    Exit;
  end;

  if (DateSep = dsMinus) then
    StrDateSep := '-'
  else
  begin
    if (DateSep = dsPoint) then
      StrDateSep := '.'
    else
      StrDateSep := '/';
  end;

  if pos(StrDateSep,s) > 0 then
  begin
    val(copy(s,1,pos(StrDateSep,s)-1),da,err);
    delete(s,1,pos(StrDateSep,s));
    if pos(StrDateSep,s) > 0 then
    begin
      val(copy(s,1,pos(StrDateSep,s)-1),mo,err);
      delete(s,1,pos(StrDateSep,s));
      val(s,ye,err);
      if err = 0 then
      begin

        if (ye < 100) then
          ye := ye + 2000;

        if DateFormat = dfEU then
        begin
          if (mo > 0) and (mo < 13) then
          begin
            if (da <= daysinmonth(mo,ye)) then
              Date := EncodeDate(ye,mo,da)
            else
              Date := 0;

          end
          else
            Date := 0;
        end
        else
        begin
          if (da > 0) and (da < 13) then
          begin
            if (mo <= daysinmonth(da,ye)) then
              Date := EncodeDate(ye,da,mo)
            else
              Date := 0;
          end
          else
            Date := 0;
        end;
 {
        if (mo > 0) and (mo < 13) then
        begin
          if da <= daysinmonth(mo,ye) then
          begin
            if DateFormat = dfEU then
              Date := EncodeDate(ye,mo,da)
            else
              Date := EncodeDate(ye,da,mo)
          end
          else
            Date := 0;
        end
        else
          Date := 0;
        }
      end;
    end;
  end;
end;

function TTIWCustomDatePicker.GetDate: TDateTime;
begin
  if (Day = 0) then
  begin
    Result := 0;
  end
  else
    Result := EncodeDate(year,month,day);
end;

procedure TTIWCustomDatePicker.SetDate(const Value: TDateTime);
var
  da,mo,ye: word;
begin
   DecodeDate(value,ye,mo,da);
   Day := 1;
   Year := ye;
   Month := mo;
   Day := da
end;

procedure TTIWCustomDatePicker.InitMonths;
begin
  FNameOfMonths.Add('January');
  FNameOfMonths.Add('February');
  FNameOfMonths.Add('March');
  FNameOfMonths.Add('April');
  FNameOfMonths.Add('May');
  FNameOfMonths.Add('June');
  FNameOfMonths.Add('July');
  FNameOfMonths.Add('August');
  FNameOfMonths.Add('September');
  FNameOfMonths.Add('October');
  FNameOfMonths.Add('November');
  FNameOfMonths.Add('December');
end;

procedure TTIWCustomDatePicker.InitDays;
begin
  FNameOfDays.Add('Sun');
  FNameOfDays.Add('Mon');
  FNameOfDays.Add('Tue');
  FNameOfDays.Add('Wed');
  FNameOfDays.Add('Thu');
  FNameOfDays.Add('Fri');
  FNameOfDays.Add('Sat');
end;

procedure TTIWCustomDatePicker.SetShowNextMonth(const Value: Boolean);
begin
  FShowNextMonth := Value;
  Invalidate;
end;

procedure TTIWCustomDatePicker.SetShowPrevMonth(const Value: Boolean);
begin
  FShowPrevMonth := Value;
  Invalidate;
end;

procedure TTIWCustomDatePicker.SetShowNextYear(const Value: Boolean);
begin
  FShowNextYear := Value;
  Invalidate;
end;

procedure TTIWCustomDatePicker.SetShowPrevYear(const Value: Boolean);
begin
  FShowPrevYear := Value;
  Invalidate;
end;

procedure TTIWCustomDatePicker.SetHintPrevYear(const Value: String);
begin
  FHintPrevYear := Value;
end;

procedure TTIWCustomDatePicker.SetHintPrevMonth(const Value: String);
begin
  FHintPrevMonth := Value;
end;

procedure TTIWCustomDatePicker.SetHintNextMonth(const Value: String);
begin
  FHintNextMonth := Value;
end;

procedure TTIWCustomDatePicker.SetHintNextYear(const Value: String);
begin
  FHintNextYear := Value;
end;

procedure TTIWCustomDatePicker.SetGlyphs(const Value: TTIWCalGlyphs);
begin
  FGlyphs.Assign(Value);
end;

procedure TTIWCustomDatePicker.SetBorderCollapse(const Value: boolean);
begin
  FBorderCollapse := Value;
end;

function TTIWCustomDatePicker.JSDateToDate(AValue: string): TDateTime;
var
  s:string;
  da,mo,ye:word;
  err: Integer;
  StrDateSep : string;
begin
  Result := Now;

  if (DateSep = dsMinus) then
    StrDateSep := '-'
  else
  begin
    if (DateSep = dsPoint) then
      StrDateSep := '.'
    else
      StrDateSep := '/';
  end;

  s := AValue;

  if pos(StrDateSep,s) > 0 then
  begin
    val(copy(s,1,pos(StrDateSep,s)-1),da,err);
    delete(s,1,pos(StrDateSep,s));
    if pos(StrDateSep,s) > 0 then
    begin
      val(copy(s,1,pos(StrDateSep,s)-1),mo,err);
      delete(s,1,pos(StrDateSep,s));
      val(s,ye,err);
      if err = 0 then
      begin
        if DateFormat = dfEU then
        begin
          Result := EncodeDate(ye,mo ,da);
          Day := da;
          Month := mo;
          Year := ye;
        end
        else
        begin
          Result := EncodeDate(ye,da ,mo);
          Day := mo;
          Month := da;
          Year := ye;
        end;
      end;
    end;
  end;
end;

procedure TTIWCustomDatePicker.Submit(const AValue: string);
begin
  inherited;
  Date := JSDateToDate(AValue);

  if AValue = 'Prev' then
  begin
    if Assigned(FOnPrevMonth) then
      FOnPrevMonth(Self,IncMonth(Date,-1));
    Exit;
  end;

  if AValue = 'Next' then
  begin
    if Assigned(FOnNextMonth) then
      FOnNextMonth(Self,IncMonth(Date,1));
    Exit;
  end;

  if AValue = 'PrevY' then
  begin
    if Assigned(FOnPrevYear) then
      FOnPrevYear(Self, IncYear(Date,-1));
    Exit;
  end;

  if AValue = 'NextY' then
  begin
    if Assigned(FOnNextYear) then
      FOnNextYear(Self, IncYear(Date,1));
  end;

  if Assigned(FOnClick) then
    FOnClick(Self,JSDateToDate(AValue));
end;

procedure TTIWCustomDatePicker.SetDateFormat(const Value: TTIWDatePickerFormat);
begin
  FDateFormat := Value;
  Invalidate;
end;

procedure TTIWCustomDatePicker.SetBorderWidth(const Value: Integer);
begin
  FBorderWidth := Value;
  Invalidate;
end;

procedure TTIWCustomDatePicker.SetBorderColor(const Value: TIWColor);
begin
  FBorderColor := Value;
  Invalidate;
end;

procedure TTIWCustomDatePicker.SetFocusColor(const Value: TIWColor);
begin
  FFocusColor := Value;
  Invalidate;
end;

procedure TTIWCustomDatePicker.setMonthGradientStartColor(const Value: TIWColor);
begin
  FMonthGradientStartColor := Value;
end;

procedure TTIWCustomDatePicker.setMonthGradientEndColor(const Value: TIWColor);
begin
  FMonthGradientEndColor := Value;
end;

procedure TTIWCustomDatePicker.SetWeekendColor(const Value: TIWColor);
begin
  FWeekendColor := Value;
  Invalidate;
end;

procedure TTIWCustomDatePicker.SetMonthGradientDirection(const Value: TTIWGradientDirection);
begin
  FMonthGradientDirection := Value;
end;


{ TTIWDateSelector }
{$IFDEF TMSIW9}
procedure TTIWDateSelector.DoOnAsyncYearChange(AParams: TStringList);
begin
  if Assigned(OnAsyncYearChange) then
    OnAsyncYearChange(Self, AParams);
end;

procedure TTIWDateSelector.DoOnAsyncMonthChange(AParams: TStringList);
begin
  if Assigned(OnAsyncMonthChange) then
    OnAsyncMonthChange(Self, AParams);
end;

procedure TTIWDateSelector.DoOnAsyncDayChange(AParams: TStringList);
begin
  if Assigned(OnAsyncDayChange) then
    OnAsyncDayChange(Self, AParams);
end;

function TTIWDateSelector.RenderAsync(
  AContext: TIWBaseHTMLComponentContext): TIWXMLTag;
begin
  Result := TIWXMLTag.CreateTag('control');
  try
    Result.AddStringParam('id', HTMLName);
    Result.AddStringParam('type', 'TTIWDATESELECTOR');
    RenderAsyncCommonProperties( AContext, Result );
  except
    FreeAndNil(Result);
  end;

end;
{$ENDIF}

constructor TTIWDateSelector.Create(AOwner: TComponent);
var
  da,mo,ye: word;
begin
  inherited;
  DecodeDate(Now,ye,mo,da);
  FYearFrom := ye;
  FYearTo := ye + 5;
  FYear := ye;
  FMonth := 1;
  FDay := 1;
  Width := 208;
  Height := 24;
  {$IFDEF TMSIW6}
  {TODO}
  {$ELSE}
  FSupportsInput := True;
  FSupportsSubmit := True;
  FEditable := True;
  {$ENDIF}
  FDesignMode := True;
  FPresentation := dpYearMonthDay;
  FShowDay := true;
  FShowYear := true;
  FClientEvents := TIWDSClientEvents.Create;
  FBGColor := clNone;
  FNameOfMonths := TStringList.Create;

  InitMonths;
end;

destructor TTIWDateSelector.Destroy;
begin
  FClientEvents.Free;
  FNameOfMonths.Free;
  inherited;
end;

function TTIWDateSelector.GetDate: TDateTime;
begin
  Result := EncodeDate(year,month,day);
end;

function TTIWDateSelector.HTMLClr(Color: TIWColor):string;
begin
  Result := ColorToRGBString(Color);
end;

function TTIWDateSelector.JSDateToDate(AValue: string): TDateTime;
var
  s:string;
  da,mo,ye:word;
  err: Integer;
begin
  Result := Now;

  s := AValue;

  if pos('/',s) > 0 then
  begin
    val(copy(s,1,pos('/',s)-1),da,err);
    delete(s,1,pos('/',s));
    if pos('/',s) > 0 then
    begin
      val(copy(s,1,pos('/',s)-1),mo,err);
      delete(s,1,pos('/',s));
      val(s,ye,err);
      if err = 0 then
      begin
        Result := EncodeDate(ye,mo+1,da);
        Day := da;
        Month := mo + 1;
        Year := ye;
      end;
    end;
  end;
end;

procedure TTIWDateSelector.InitMonths;
begin
  FNameOfMonths.Add('January');
  FNameOfMonths.Add('February');
  FNameOfMonths.Add('March');
  FNameOfMonths.Add('April');
  FNameOfMonths.Add('May');
  FNameOfMonths.Add('June');
  FNameOfMonths.Add('July');
  FNameOfMonths.Add('August');
  FNameOfMonths.Add('September');
  FNameOfMonths.Add('October');
  FNameOfMonths.Add('November');
  FNameOfMonths.Add('December');
end;

procedure TTIWDateSelector.Submit(const AValue: string);
begin
  inherited;
  JSDateToDate(AValue);
end;

{$IFDEF TMSIW6}
procedure TTIWDateSelector.IWPaint;
{$ELSE}
procedure TTIWDateSelector.Paint;
{$ENDIF}
var
  r: TRect;
begin
  with Canvas do
  begin
    if BGColor = clNone then
      Brush.Color := clWhite
    else
      Brush.Color := BGColor;
        
    Pen.Color := clBlack;
    Pen.Width := 1;

    case Fpresentation of
    dpYearMonthDay:
      begin
        if (FShowYear) then
        begin
          Rectangle(4,4,50,20);
          TextRect(Rect(5,5,49,19),6,5,IntToStr(Year));
          r := Rect(33,4,49,20);
          {$IFNDEF LINUX}
          DrawFrameControl(Handle,r, DFC_SCROLL,DFCS_SCROLLCOMBOBOX );
          {$ENDIF}
        end;

        Rectangle(54,4,150,20);
        TextRect(Rect(55,5,149,19),56,5,FNameOfMonths[Month-1]);
        r := Rect(133,4,149,20);
        {$IFNDEF LINUX}
        DrawFrameControl(Handle,r, DFC_SCROLL,DFCS_SCROLLCOMBOBOX );
        {$ENDIF}

        if (FShowDay) then
        begin
          Rectangle(154,4,200,20);
          TextRect(Rect(155,5,199,19),156,5,IntToStr(Day));
          r := Rect(183,4,199,20);
          {$IFNDEF LINUX}
          DrawFrameControl(Handle,r, DFC_SCROLL,DFCS_SCROLLCOMBOBOX );
          {$ENDIF}
        end;
      end;

    dpDayMonthYear:
      begin
        if (FShowDay) then
        begin
          Rectangle(4,4,50,20);
          TextRect(Rect(5,5,49,19),6,5,IntToStr(Day));
          r := Rect(33,4,49,20);
          {$IFNDEF LINUX}
          DrawFrameControl(Handle,r, DFC_SCROLL,DFCS_SCROLLCOMBOBOX );
          {$ENDIF}
        end;

        Rectangle(54,4,150,20);
        TextRect(Rect(55,5,149,19),56,5,FNameOfMonths[Month-1]);
        r := Rect(133,4,149,20);
        {$IFNDEF LINUX}
        DrawFrameControl(Handle,r, DFC_SCROLL,DFCS_SCROLLCOMBOBOX );
        {$ENDIF}

        if (FShowYear) then
        begin
          Rectangle(154,4,200,20);
          TextRect(Rect(155,5,199,19),156,5,IntToStr(Year));
          r := Rect(183,4,199,20);
          {$IFNDEF LINUX}
          DrawFrameControl(Handle,r, DFC_SCROLL,DFCS_SCROLLCOMBOBOX );
          {$ENDIF}
        end;
      end;

    dpMonthDayYear:
      begin
        Rectangle(4,4,100,20);
        TextRect(Rect(5,5,99,19),6,5,FNameOfMonths[Month-1]);
        r := Rect(83,4,99,20);
        {$IFNDEF LINUX}
        DrawFrameControl(Handle,r, DFC_SCROLL,DFCS_SCROLLCOMBOBOX );
        {$ENDIF}

        if (FShowDay) then
        begin
          Rectangle(104,4,150,20);
          TextRect(Rect(105,5,149,19),106,5,IntToStr(Day));
          r := Rect(133,4,149,20);
          {$IFNDEF LINUX}
          DrawFrameControl(Handle,r, DFC_SCROLL,DFCS_SCROLLCOMBOBOX );
          {$ENDIF}
        end;

        if (FShowYear) then
        begin
          Rectangle(154,4,200,20);
          TextRect(Rect(155,5,199,19),156,5,IntToStr(Year));
          r := Rect(183,4,199,20);
          {$IFNDEF LINUX}
          DrawFrameControl(Handle,r, DFC_SCROLL,DFCS_SCROLLCOMBOBOX );
          {$ENDIF}
        end;
      end;

    dpYearDayMonth:
      begin
        if (FShowYear) then
        begin
          Rectangle(4,4,50,20);
          TextRect(Rect(5,5,49,19),6,5,IntToStr(Year));
          r := Rect(33,4,49,20);
          {$IFNDEF LINUX}
          DrawFrameControl(Handle,r, DFC_SCROLL,DFCS_SCROLLCOMBOBOX );
          {$ENDIF}
        end;

        if (FShowDay) then
        begin
          Rectangle(54,4,100,20);
          TextRect(Rect(55,5,99,19),56,5,IntToStr(Day));
          r := Rect(83,4,99,20);
          {$IFNDEF LINUX}
          DrawFrameControl(Handle,r, DFC_SCROLL,DFCS_SCROLLCOMBOBOX );
          {$ENDIF}
        end;

        Rectangle(104,4,200,20);
        TextRect(Rect(105,5,199,19),106,5,FNameOfMonths[Month-1]);
        r := Rect(183,4,199,20);
        {$IFNDEF LINUX}
        DrawFrameControl(Handle,r, DFC_SCROLL,DFCS_SCROLLCOMBOBOX );
        {$ENDIF}
      end;
    end;

    if FDesignMode then
    begin
      Brush.Style := bsClear;
      Pen.Style := psDot;
      Pen.Color := clBlack;
      Pen.Width := 1;
      Polygon([Point(0, 0), Point(Width - 1, 0), Point(Width - 1, Height - 1), Point(0, Height - 1)]);
      Pen.Style := psSolid;
    end;
  end;
end;

procedure TTIWDateSelector.SetNameOfMonths(const Value: TStringList);
begin
  FNameOfMonths.Assign(Value);
  Invalidate;
end;

{$IFDEF TMSIW72_NEW}
function TTIWDateSelector.get_ShouldRenderTabOrder: Boolean;
begin
  Result := False;
end;
{$ENDIF}

{$IFDEF TMSIW72}
function TTIWDateSelector.get_HasTabOrder: boolean;
begin
  {$IFNDEF TMSIW72_NEW}
  Result := false;
  {$ELSE}
  Result := true;
  {$ENDIF}
end;
{$ENDIF}

{$IFDEF TMSIW6}
function TTIWDateSelector.RenderHTML(AContext: TIWBaseComponentContext): TIWHTMLTag;
{$ELSE}
function TTIWDateSelector.RenderHTML: TIWHTMLTag;
{$ENDIF}
var
  i: Integer;
  ResY,ResM,ResD,html,strYear, strDay,bgclr: string;
  comboDisable, fontStyle : string;
  tabs: string;
  ajaxyearchange, ajaxmonthchange, ajaxdaychange: string;
begin
  {$IFDEF TMSIW6}
  TIWComponent40Context(AContext).AddToInitProc('FindElem(''' + HTMLName + ''').value="'+
    IntToStr(day)+'/'+IntToStr(month)+'/'+IntToStr(year)+ '";' + EOL);
  {$ELSE}
  TIWAppForm(Form).AddToInitProc('if (FindElem(''' + HTMLName + ''').value="'+
    IntToStr(day)+'/'+IntToStr(month)+'/'+IntToStr(year)+ '";' + EOL);
  {$ENDIF}

  {$IFDEF TMSIW9}
//  if Assigned(FOnAsyncYearChange) then
    ajaxyearchange := 'processAjaxEvent(''onYearChange'', '
      + HTMLControlImplementation.IWCLName
      + ',''' + HTMLName + '.' + 'DoOnAsyncYearChange' + ''','
      + 'true' + ', null, '
      + 'true' + ');';

    Acontext.WebApplication.RegisterCallBack(HTMLName+'.DoOnAsyncYearChange', DoOnAsyncYearChange);

//  if Assigned(FOnAsyncMonthChange) then
    ajaxmonthchange := 'processAjaxEvent(''onMonthChange'', '
      + HTMLControlImplementation.IWCLName
      + ',''' + HTMLName + '.' + 'DoOnAsyncMonthChange' + ''','
      + 'true' + ', null, '
      + 'true' + ');';

    Acontext.WebApplication.RegisterCallBack(HTMLName+'.DoOnAsyncMonthChange', DoOnAsyncMonthChange);

//  if Assigned(FOnAsyncDayChange) then
    ajaxdaychange := 'processAjaxEvent(''onDayChange'', '
      + HTMLControlImplementation.IWCLName
      + ',''' + HTMLName + '.' + 'DoOnAsyncDayChange' + ''','
      + 'true' + ', null, '
      + 'true' + ');';

    Acontext.WebApplication.RegisterCallBack(HTMLName+'.DoOnAsyncDayChange', DoOnAsyncDayChange);
  {$ENDIF}

  if FBGColor <> clNone then
    bgclr := ' style="background-Color:'+HTMLClr(FBGColor)+'"'
  else
    bgclr := '';

  if TabOrder <> -1 then
    tabs := ' tabindex="'+inttostr(taborder+1)+'" '
  else
    tabs := '';

  ResY := '';
  for i := FYearFrom to FYearTo do
  begin
    if i = FYear then
      ResY := ResY + '<option selected value='+IntToStr(i)+'>'+IntToStr(i)+'</option>'
    else
      ResY := ResY + '<option value='+IntToStr(i)+'>'+IntToStr(i)+'</option>'
  end;

  ResM := '';

  for i := 1 to 12 do
  begin
    if i = FMonth then
      ResM := ResM + '<option selected value='+inttostr(i)+'>'+FNameOfMonths[i-1]+'</option>'
    else
      ResM := ResM + '<option value='+inttostr(i)+'>'+FNameOfMonths[i-1]+'</option>';
  end;

  ResD := '';
  for i := 1 to DaysInMonth(FMonth,FYear) do
  begin
    if i = FDay then
      ResD := ResD + '<option selected value='+inttostr(i)+'>'+inttostr(i)+'</option>'
    else
      ResD := ResD + '<option value='+inttostr(i)+'>'+inttostr(i)+'</option>';
  end;

  html :=
    '<SCRIPT LANGUAGE="JavaScript">' +
    'function '+HTMLName+'populate() {'#13
    +'  ysel = document.getElementById("'+HTMLNAME+'YEAR");'#13
    +'  msel = document.getElementById("'+HTMLNAME+'MONTH");'#13
    +'  dsel = document.getElementById("'+HTMLNAME+'DAY");'#13

    +'  var selectedDay = dsel.options[dsel.selectedIndex].value;'#13
    +'  timeA = new Date(ysel.options[ysel.selectedIndex].value,msel.options[msel.selectedIndex].value,1);'#13
    +'  timeDifference = timeA - 86400000;'#13
    +'  timeB = new Date(timeDifference);'#13
    +'  var daysInMonth = timeB.getDate();'#13
    +'  var dim = dsel.length;'#13
    +'  for (var i = 0; i < dim; i++) {'#13
    +'    dsel.options[0] = null;'#13
    +'  }'#13
    +'  for (var i = 0; i < daysInMonth; i++) {'#13
    +'    dsel.options[i] = new Option(i+1);'#13
    +'    dsel.options[i].value = i + 1'#13
    +'  }'#13
    +' if (selectedDay > dsel.length) {'#13
    +'   selectedDay = dsel.length;'#13
    +' }'#13
    +'  dsel.selectedIndex = selectedDay - 1;'#13

    +'  yi = ysel.options[ysel.selectedIndex].value'#13
    +'  mi = msel.options[msel.selectedIndex].value'#13
    +' di = selectedDay;'#13
    +'  FindElem('#39+HTMLName+#39').value = di+"/"+mi+"/"+yi'#13
    +'}'#13

    +'function '+HTMLName+'UpdateDate(sel) {'#13
    +   FClientEvents.DayChange.Text + #13
    +'  ysel = document.getElementById("'+HTMLNAME+'YEAR");'#13
    +'  msel = document.getElementById("'+HTMLNAME+'MONTH");'#13
    +'  dsel = document.getElementById("'+HTMLNAME+'DAY");'#13
    +'  yi = ysel.options[ysel.selectedIndex].value;'#13
    +'  mi = msel.options[msel.selectedIndex].value;'#13
    +'  di = dsel.options[dsel.selectedIndex].value;'#13
    +'  FindElem('#39+HTMLName+#39').value = di+"/"+mi+"/"+yi'#13
    + ajaxdaychange
    +'}'#13

    +'function '+HTMLName+'YearChange(sel) {'#13
    + FClientEvents.YearChange.Text + #13
    + HTMLName +'populate();'#13
    + ajaxyearchange
    +'}'#13

    +'function '+HTMLName+'MonthChange(sel) {'#13
    + FClientEvents.MonthChange.Text + #13
    + HTMLName +'populate();'#13
    + ajaxmonthchange
    +'}'#13

    +'</SCRIPT>'#13
    ;

  html := html +
    '<table border=0>'
    +'<tr>'
    +'<td align=center>';

    //Changed - adding support for disable
    comboDisable := '';
    if (Self.Enabled = false) then
      comboDisable := ' DISABLED ';

    fontstyle := '';

    if ((font.FontName <> '') or (font.Style <> [])) then
    begin
      fontstyle := ' style="font:';

      if (fsBold in font.Style) then
        fontstyle := fontstyle + ' bold';

      if (fsItalic in font.Style) then
        fontstyle := fontstyle + ' italic';

      fontstyle := fontstyle + ' ' + inttostr(font.Size) + 'px ';

      if (font.FontName <> '') then
        fontstyle := fontstyle + '''' + font.FontName + '''';

      if (fsUnderline in font.Style) then
        fontstyle := fontstyle + ';text-decoration : underline';

      fontstyle := fontstyle + ' "';
    end;

    if (FShowYear) then
       strYear := '<select '+tabs + fontstyle + comboDisable +bgclr+' id="'+HTMLNAME+'YEAR" onChange="'+HTMLName+'YearChange(this);">'
    else
       strYear := '<select '+tabs + fontstyle + comboDisable + bgclr+' id="'+HTMLNAME+'YEAR" style="display:none" onChange="'+HTMLName+'YearChange(this);">';

    if (FShowDay) then
      strDay :=   '<select '+tabs + fontstyle + comboDisable + bgclr+' id="'+HTMLNAME+'DAY" onChange="'+HTMLName+'UpdateDate(this);">'
    else
      strDay :=   '<select '+tabs + fontstyle + comboDisable + bgclr+' id="'+HTMLNAME+'DAY" style="display:none" onChange="'+HTMLName+'UpdateDate(this);">';

    case FPresentation of
    dpYearMonthDay:
      begin
        html := html + strYear
                + ResY
                +'</select>'
                +'<select '+tabs+ fontstyle + comboDisable + bgclr + ' id="'+HTMLNAME+'MONTH" onChange="'+HTMLName+'MonthChange(this);">'
                + ResM
                +'</select>'
                + strDay
                + ResD
                +'</select>'
                +'</td>'
                +'</tr>'
                +'</table>';
      end;
    dpDayMonthYear:
      begin
        html := html
                + strDay
                + ResD
                +'</select>'
                +'<select '+tabs+ fontstyle + comboDisable + bgclr+' id="'+HTMLNAME+'MONTH" onChange="'+HTMLName+'MonthChange(this);">'
                + ResM
                +'</select>'
                + strYear
                + ResY
                +'</select>'
                +'</td>'
                +'</tr>'
                +'</table>';
      end;
    dpMonthDayYear:
      begin
        html := html
                +'<select ' +tabs+ fontstyle + comboDisable + bgclr+' id="'+HTMLNAME+'MONTH" onChange="'+HTMLName+'MonthChange(this);">'
                + ResM
                +'</select>'
                + strDay
                + ResD
                +'</select>'
                + strYear
                + ResY
                +'</select>'
                +'</td>'
                +'</tr>'
                +'</table>';
      end;
    dpYearDayMonth:
      begin
        html := html
                + strYear
                + ResY
                +'</select>'
                + strDay
                + ResD
                +'</select>'
                +'<select '+tabs+ fontstyle + comboDisable +bgclr+' id="'+HTMLNAME+'MONTH" onChange="'+HTMLName+'MonthChange(this);">'
                + ResM
                +'</select>'
                +'</td>'
                +'</tr>'
                +'</table>';
      end;
    end;

  if FNameOfMonths.Count > 6 then
    InitMonths;

  for i := 0 to 11 do
  begin
    html := StringReplace(html,'<#MONTH'+inttostr(i)+'>',FNameOfMonths[i],[rfReplaceAll, rfIgnoreCase]);
  end;

  Result := TIWHTMLTag.CreateTag('DIV');
  Result.Contents.AddText(html);
  with Result.Contents.AddTag('INPUT') do
  begin
    AddStringParam('TYPE','HIDDEN');
    AddStringParam('NAME',HTMLName);
    AddStringParam('ID',HTMLName+'_INPUT');
  end;

end;

procedure TTIWDateSelector.setPresentation(const Value: TTIWDatePresentation);
begin
  FPresentation := Value;
  Invalidate;
end;

procedure TTIWDateSelector.SetShowDay(const Value: Boolean);
begin
  FShowDay := Value;
  Invalidate;
end;

procedure TTIWDateSelector.SetShowYear(const Value: boolean);
begin
  FShowYear := Value;
  Invalidate;
end;

procedure TTIWDateSelector.SetDate(const Value: TDateTime);
var
  da,mo,ye: word;
begin
   DecodeDate(value,ye,mo,da);
   Day := 1;
   Year := ye;
   Month := mo;
   Day := da
end;

procedure TTIWDateSelector.SetDay(const Value: Integer);
begin
  if (Value >= 1) and (Value <= DaysInMonth(FMonth,FYear)) then
  FDay := Value;
  Invalidate;
end;

{$IFNDEF TMSIW71}
procedure TTIWDateSelector.SetDesignMode(const Value: Boolean);
begin
  FDesignMode := Value;
  Invalidate;
end;
{$ENDIF}

procedure TTIWDateSelector.SetMonth(const Value: Integer);
begin
  if (Value >= 1) and (Value < 13) then
    FMonth := Value;
  Invalidate;
end;

procedure TTIWDateSelector.SetBGColor(const Value: TIWColor);
begin
  FBGColor := Value;
  Invalidate;
end;

procedure TTIWDateSelector.SetValue(const AValue: string);
var
  s:string;
  da,mo,ye:word;
  err: Integer;
begin
  s := AValue;
  if pos('/',s) > 0 then
  begin
    val(copy(s,1,pos('/',s)-1),da,err);
    delete(s,1,pos('/',s));
    if pos('/',s) > 0 then
    begin
      val(copy(s,1,pos('/',s)-1),mo,err);
      delete(s,1,pos('/',s));
      val(s,ye,err);
      if err = 0 then
        Date := EncodeDate(ye,mo,da);
    end;
  end;

end;

procedure TTIWDateSelector.SetYear(const Value: Integer);
begin
  FYear := Value;
  Invalidate;
end;

{ TTIWCalGlyphs }

constructor TTIWCalGlyphs.Create(AOwner: TComponent);
begin
  inherited Create;
  FOwner := AOwner;
  FNextYear := TBitmap.Create;
  FPrevYear := TBitmap.Create;
  FNextMonth := TBitmap.Create;
  FPrevMonth := TBitmap.Create;
end;

destructor TTIWCalGlyphs.Destroy;
begin
  FNextYear.Free;
  FPrevYear.Free;
  FNextMonth.Free;
  FPrevMonth.Free;
  inherited;
end;

procedure TTIWCalGlyphs.SetNextMonth(const Value: TBitmap);
begin
  FNextMonth.Assign(Value);
end;

procedure TTIWCalGlyphs.SetNextYear(const Value: TBitmap);
begin
  FNextYear.Assign(Value);
end;

procedure TTIWCalGlyphs.SetPrevMonth(const Value: TBitmap);
begin
  FPrevMonth.Assign(Value);
end;

procedure TTIWCalGlyphs.SetPrevYear(const Value: TBitmap);
begin
  FPrevYear.Assign(Value);
end;

{ TIWCalendarClientEvents }

procedure TIWCalendarClientEvents.Assign(Source: TPersistent);
begin
  inherited;
  FNextYearClick.Assign((Source as TIWCalendarClientEvents).NextYearClick);
  FNextMonthClick.Assign((Source as TIWCalendarClientEvents).NextMonthClick);
  FPrevYearClick.Assign((Source as TIWCalendarClientEvents).PrevYearClick);
  FPrevMonthClick.Assign((Source as TIWCalendarClientEvents).PrevMonthClick);
  FDateClick.Assign((Source as TIWCalendarClientEvents).DateClick);
end;

constructor TIWCalendarClientEvents.Create;
begin
  inherited;
  FNextYearClick := TStringList.Create;
  FNextMonthClick := TStringList.Create;
  FPrevYearClick := TStringList.Create;
  FPrevMonthClick := TStringList.Create;
  FDateClick := TStringList.Create;
end;

destructor TIWCalendarClientEvents.Destroy;
begin
  FNextYearClick.Free;
  FNextMonthClick.Free;
  FPrevYearClick.Free;
  FPrevMonthClick.Free;
  FDateClick.Free;
  inherited;
end;

function TIWCalendarClientEvents.GetJSFunction(PropName: string): string;
begin
  if PropName = 'DateClick' then
    Result := 'DateClick(s); // s=New date';

  if PropName = 'NextMonthClick' then
    Result := 'NextMonthClick(s); // s=New date';

  if PropName = 'NextYearClick' then
    Result := 'NextYearClick(s); // s=New date';

  if PropName = 'PrevMonthClick' then
    Result := 'PrevMonthClick(s); // s=New date';

  if PropName = 'PrevYearClick' then
    Result := 'PrevYearClick(s); // s=New date';

end;

procedure TIWCalendarClientEvents.SetDateClick(const Value: TStringList);
begin
  FDateClick.Assign(Value);
end;

procedure TIWCalendarClientEvents.SetNextMonthClick(
  const Value: TStringList);
begin
  FNextMonthClick.Assign(Value);
end;

procedure TIWCalendarClientEvents.SetNextYearClick(
  const Value: TStringList);
begin
  FNextYearClick.Assign(Value);
end;

procedure TIWCalendarClientEvents.SetPrevMonthClick(
  const Value: TStringList);
begin
  FPrevMonthClick.Assign(Value);
end;

procedure TIWCalendarClientEvents.SetPrevYearClick(
  const Value: TStringList);
begin
  FPrevYearClick.Assign(Value);
end;

{ TIWDatePickerClientEvents }

procedure TIWDatePickerClientEvents.Assign(Source: TPersistent);
begin
  inherited;
  FOnExit.Assign((Source as TIWDatePickerClientEvents).FOnExit);
  FOnEnter.Assign((Source as TIWDatePickerClientEvents).FOnEnter);  
end;

constructor TIWDatePickerClientEvents.Create;
begin
  inherited;
  FOnExit := TStringList.Create;
  FOnEnter := TStringList.Create;
end;

destructor TIWDatePickerClientEvents.Destroy;
begin
  FOnExit.Free;
  FOnEnter.Free;
  inherited;
end;

function TIWDatePickerClientEvents.GetJSFunction(PropName: string): string;
begin
  Result := inherited GetJSFunction(PropName);

  if PropName = 'OnExit' then
    Result := 'OnExit(s); // s=Current date';

  if PropName = 'OnEnter' then
    Result := 'OnEnter(s); // s=Current date';
end;


procedure TIWDatePickerClientEvents.SetOnEnter(const Value: TStringList);
begin
  FOnEnter.Assign(Value);
end;

procedure TIWDatePickerClientEvents.SetOnExit(const Value: TStringList);
begin
  FOnExit.Assign(Value);
end;

{ TIWDSClientEvents }

constructor TIWDSClientEvents.Create;
begin
  inherited Create;
  FMonthChange := TStringList.Create;
  FYearChange := TStringList.Create;
  FDayChange := TStringList.Create;
end;

destructor TIWDSClientEvents.Destroy;
begin
  FMonthChange.Free;
  FDayChange.Free;
  FYearChange.Free;
  inherited;
end;

procedure TIWDSClientEvents.SetDayChange(const Value: TStringList);
begin
  FDayChange.Assign(Value);
end;

procedure TIWDSClientEvents.SetMonthChange(const Value: TStringList);
begin
  FMonthChange.Assign(Value);
end;

procedure TIWDSClientEvents.SetYearChange(const Value: TStringList);
begin
  FYearChange.Assign(Value);
end;

function TIWDSClientEvents.GetJSFunction(AValue: string): string;
begin
  Result := AValue + '(ctrl)';
end;

end.

