{***************************************************************************
{ TMS IntraWeb Component Pack Pro                                           }
{ for Delphi & C++Builder                                                   }
{                                                                           }
{ written by TMS Software                                                   }
{            copyright © 2012 - 2014                                        }
{            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 IWAdvMessageDialog;

interface

{$I TMSDEFS.INC}

uses
  Controls, Graphics, Forms, Windows, IWPicCntnr,
  {$IFDEF DELPHI6_LVL}
  Types,
  {$ENDIF}
  Classes,
  IWBaseControl, IWColor,
  IWControl, IWTypes, SysUtils, IWCompButton,
  IWCompEdit, IWCompLabel, IWCompCheckbox, IWHTMLTag, IWCompListbox,
  IWTMSBase,IWCompRectangle, IWRegion, IWFont, IWForm, IWRenderContext,
  IWBaseHTMLControl, IWScriptEvents, Dialogs, IWXMLTag
  {$IFDEF TMSIW121}
  ,IWCompExtCtrls
  {$ELSE}
  ,IWExtCtrls
  {$ENDIF}
  ;

type

 TIWInputType = (itNone, itCheck, itString, itInteger, itLogin, itPassword);
 TIWPosition = (pCentered, pTopLeft, pTopCenter, pTopRight, pMidLeft, pMidRight, pBottomLeft, pBottomCenter, pBottomRight);
 TIWPositionType = (ptDefault, ptAtControl, ptAbsolute);
 TIWCommonButton = (cbOK, cbYes, cbNo, cbCancel, cbRetry, cbClose);
 TIWCommonButtons = set of TIWCommonButton;

 TIWButtonClickEvent = procedure (Sender: TObject; ButtonIndex: Integer; InputString, InputPassword: string;
  InputCheck: boolean; var Allow: boolean) of object;
 TIWAsyncButtonClickEvent = procedure (Sender: TObject; EventParams: TStringList;
    ButtonIndex: Integer; InputString, InputPassword: string; InputCheck: boolean; var Allow: boolean) of object;

 TTIWAdvMessageDialog = class(TIWControl)
  private
    FBGColor: TIWColor;
    FBGColorTo: TIWColor;
    FBGGradientDirection: TTIWGradientDirection;
    FBorderColor: TIWColor;
    FBorderWidth: integer;
    FButtonBarBGColor: TIWColor;
    FButtonBarBGColorTo: TIWColor;
    FButtonBarBorderColor: TIWColor;
    FButtonBarFont: TIWFont;
    FButtonBarGradientDirection: TTIWGradientDirection;
    FButtonIndex: integer;
    FCaption: string;
    FCaptionBGColor: TIWColor;
    FCaptionBGColorTo: TIWColor;
    FCaptionBorderColor: TIWColor;
    FCaptionFont: TIWFont;
    FCaptionGradientDirection: TTIWGradientDirection;
    FCloseButtonColor: TIWColor;
    FCloseButtonHint: string;
    FCollapseControlHint: string;
    FCollapseControlText: string;
    FCommonButtons: TIWCommonButtons;
    FContentRegion: TIWCustomRegion;
    FCustomButtons: TStringList;
    FDefaultButton: integer;
    FEnableDragging: boolean;
    FEmptyText: string;
    FExpandControlHint: string;
    FExpandControlText: string;
    FExpandedText: string;
    FFont: TIWFont;
    FInputCheck: boolean;
    FInputString: string;
    FInputPassword: string;
    FInputType: TIWInputType;
    FNotes: string;
    FOverlayColor: TIWColor;
    FOverlayOpacity: integer;
    FPosition: TIWPosition;
    FPositionControl: TIWCustomControl;
    FPositionLeft: Integer;
    FPositionTop: integer;
    FPositionType: TIWPositionType;
    FRoundedBorderRadius: integer;
    FShowCloseButton: boolean;
    FShowDialog: boolean;
    FShowShadow: boolean;
    FShowVerificationCheckBox: boolean;
    FVerificationCheckBoxChecked: boolean;
    FVerificationText: string;
    FOnButtonClick: TIWButtonClickEvent;
    FOnAsyncButtonClick: TIWAsyncButtonClickEvent;
    FWantsEscape: boolean;
    FAsyncUpdateRequired: boolean;
    FFocusControl: string;
    procedure DoOnAsyncButtonClick(AParams: TStringList);
    procedure SetCaption(const Value: string);
    procedure SetCloseButtonHint(const Value: string);
    procedure SetCollapseControlHint(const Value: string);
    procedure SetCollapseControlText(const Value: string);
    procedure SetCommonButtons(const value: TIWCommonButtons);
    procedure SetContentRegion(const Value: TIWCustomRegion);
    procedure SetCustomButtons(const Value: TStringList);
    procedure SetDefaultButton(const Value: integer);
    procedure SetEmptyText(const Value: string);
    procedure SetExpandControlHint(const Value: string);
    procedure SetExpandControlText(const value: string);
    procedure SetExpandedText(const value: string);
    procedure SetInputCheck(const value: boolean);
    procedure SetInputString(const value: string);
    procedure SetInputType(const Value: TIWInputType);
    procedure SetNotes(const value: string);
    procedure SetPositionControl(const Value: TIWCustomControl);
    procedure SetShowVerificationCheckBox(const Value: boolean);
    procedure SetVerificationCheckBoxChecked(const Value: boolean);
    procedure SetVerificationText(const Value: string);
    procedure SetFont(const Value: TIWFont);
    procedure SetButtonBarFont(const Value: TIWFont);
    procedure SetCaptionFont(const Value: TIWFont);
    procedure SetOverlayOpacity(const Value: integer);
    procedure SetShowCloseButton(const Value: boolean);
    procedure SetEnableDragging(const Value: boolean);
    procedure SetShowDialog(const Value: boolean);
    procedure SetWantsEscape(const Value: boolean);
  protected
    procedure IWPaint; override;
    procedure SetValue(const AValue: string); override;
    procedure Submit(const AValue: string); override;
    function RenderAsync(AContext: TIWBaseHTMLComponentContext): TIWXMLTag; override;
    function RenderDialog(): string;

    //hide/disable default properties
    property Text;
    property Visible;
    procedure Loaded(); override;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    function RenderHTML(AContext: TIWBaseComponentContext): TIWHTMLTag; override;
    procedure Show();
    procedure ShowAsync();
    procedure Hide();
    procedure HideAsync();
    procedure ClearInputPassword();
    property ShowDialog: boolean read FShowDialog write SetShowDialog default false;
    property AsyncUpdateRequired: boolean read FAsyncUpdateRequired write FAsyncUpdateRequired;
  published
    property BGColor: TIWColor read FBGColor write FBGColor default clWhite;
    property BGColorTo: TIWColor read FBGColorTo write FBGColorTo default clNone;
    property BGGradientDirection: TTIWGradientDirection read FBGGradientDirection write FBGGradientDirection default gdVertical;
    property BorderColor: TIWColor read FBorderColor write FBorderColor default clBlack;
    property BorderWidth: integer read FBorderWidth write FBorderWidth default 2;
    property ButtonBarBGColor: TIWColor read FButtonBarBGColor write FButtonBarBGColor default $F0F0F0;
    property ButtonBarBGColorTo: TIWColor read FButtonBarBGColorTo write FButtonBarBGColorTo default clNone;
    property ButtonBarBorderColor: TIWColor read FButtonBarBorderColor write FButtonBarBorderColor default $DFDFDF;
    property ButtonBarFont: TIWFont read FButtonBarFont write SetButtonBarFont;
    property ButtonBarGradientDirection: TTIWGradientDirection read FButtonBarGradientDirection write FButtonBarGradientDirection default gdVertical;
    property Caption: string read FCaption write SetCaption;
    property CaptionBGColor: TIWColor read FCaptionBGColor write FCaptionBGColor default $FCFCFC;
    property CaptionBGColorTo: TIWColor read FCaptionBGColorTo write FCaptionBGColorTo default $EDEDED;
    property CaptionBorderColor: TIWColor read FCaptionBorderColor write FCaptionBorderColor default $7A7A7A;
    property CaptionFont: TIWFont read FCaptionFont write SetCaptionFont;
    property CaptionGradientDirection: TTIWGradientDirection read FCaptionGradientDirection write FCaptionGradientDirection default gdVertical;
    property CloseButtonColor: TIWColor read FCloseButtonColor write FCloseButtonColor default clWebBlack;
    property CloseButtonHint: string read FCloseButtonHint write SetCloseButtonHint;
    property CollapseControlHint: string read FCollapseControlHint write SetCollapseControlHint;
    property CollapseControlText: string read FCollapseControlText write SetCollapseControlText;
    property CommonButtons: TIWCommonButtons read FCommonButtons write SetCommonButtons;
    property ContentRegion: TIWCustomRegion read FContentRegion write SetContentRegion;
    property CustomButtons: TStringList read FCustomButtons write SetCustomButtons;
    property DefaultButton: integer read FDefaultButton write SetDefaultButton default 0;
    property EnableDragging: boolean read FEnableDragging write SetEnableDragging default true;
    property EmptyText: string read FEmptyText write SetEmptyText;
    property ExpandControlHint: string read FExpandControlHint write SetExpandControlHint;
    property ExpandControlText: string read FExpandControlText write SetExpandControlText;
    property ExpandedText: string read FExpandedText write SetExpandedText;
    property Font: TIWFont read FFont write SetFont;
    property FocusControl: string read FFocusControl write FFocusControl;
    property InputCheck: boolean read FInputCheck write SetInputCheck default false;
    property InputString: string read FInputString write SetInputString;
    property InputPassword: string read FInputPassword{ write FInputPassword};
    property InputType: TIWInputType read FInputType write SetInputType default itNone;
    property Notes: string read FNotes write SetNotes;
    property OverlayColor: TIWColor read FOverlayColor write FOverlayColor default clBlack;
    property OverlayOpacity: integer read FOverlayOpacity write SetOverlayOpacity default 2;
    property Position: TIWPosition read FPosition write FPosition default pCentered;
    property PositionControl: TIWCustomControl read FPositionControl write SetPositionControl;
    property PositionLeft: integer read FPositionLeft write FPositionLeft default 0;
    property PositionTop: integer read FPositionTop write FPositionTop default 0;
    property PositionType: TIWPositionType read FPositionType write FPositionType default ptDefault;
    property RoundedBorderRadius: integer read FRoundedBorderRadius write FRoundedBorderRadius default 8;
    property ShowCloseButton: boolean read FShowCloseButton write SetShowCloseButton default true;
    property ShowShadow: boolean read FShowShadow write FShowShadow default true;
    property ShowVerificationCheckBox: boolean read FShowVerificationCheckBox write SetShowVerificationCheckBox default false;
    property VerificationCheckBoxChecked: boolean read FVerificationCheckBoxChecked write SetVerificationCheckBoxChecked default false;
    property VerificationText: string read FVerificationText write SetVerificationText;
    property WantsEscape: boolean read FWantsEscape write SetWantsEscape default true;
    property OnButtonClick: TIWButtonClickEvent read FOnButtonClick write FOnButtonClick;
    property OnAsyncButtonClick: TIWAsyncButtonClickEvent read FOnAsyncButtonClick write FOnAsyncButtonClick;
  end;

var
  ButtonNames: array[TIWCommonButton] of shortstring = ('OK', 'Yes', 'No', 'Cancel', 'Retry', 'Close');
  ButtonCaptions: array[TIWCommonButton] of Pointer;

implementation

uses
  IWApplication;

{ TTIWAdvMessageBox }

procedure TTIWAdvMessageDialog.DoOnAsyncButtonClick(AParams: TStringList);
var
  Allow: boolean;
begin
  Allow := true;

  if Assigned(OnAsyncButtonClick) then
    OnAsyncButtonClick(Self, AParams, FButtonIndex, FInputString, FInputPassword, FInputCheck, Allow);

  if Allow then
  begin
    GGetWebApplicationThreadVar.CallBackResponse.AddJavaScriptToExecute(HTMLName + 'Hide();');
    ShowDialog := False;
  end
  else
  begin
    //GGetWebApplicationThreadVar.CallBackResponse.AddJavaScriptToExecute(HTMLName + 'Show();');
    ShowAsync;
    ShowDialog := True;
  end;
end;

function TTIWAdvMessageDialog.RenderAsync(
  AContext: TIWBaseHTMLComponentContext): TIWXMLTag;
var
  js, html: string;
begin
  Result := TIWXMLTag.CreateTag('control');
  try
    Result.AddStringParam('id', HTMLName);
    Result.AddStringParam('type', 'TTIWADVMESSAGEDIALOG');
    RenderAsyncCommonProperties( AContext, Result );

    html := StringReplace(RenderDialog, '"', '\"', [rfReplaceAll]);
    html := StringReplace(html, #$D, '', [rfReplaceAll]);
    html := StringReplace(html, #9, '', [rfReplaceAll]);

    js := '<![CDATA['

//    + ' if (' + HTMLName + 'ContentRegionEL)'#13
//    + ' alert("RA: " + ' + HTMLName + 'ContentRegionEL.innerHTML);'#13
      + HTMLName + 'DefaultValue = "' + EmptyText + '";'#13
      ;

  if PositionType = ptAbsolute then
    js := js
      + HTMLName + 'PositionTop = ' + IntToStr(PositionTop) + ';'#13
      + HTMLName + 'PositionLeft = ' + IntToStr(PositionLeft) + ';'#13
  else
    js := js
      + HTMLName + 'PositionTop = null;'#13
      + HTMLName + 'PositionLeft = null;'#13;

  if ContentRegion <> nil then
  begin
    //fix: the contentregion should be made visible server side
    //if the region is not visible the submit/setvalue will not work correctly

    ContentRegion.Top := 0;
    ContentRegion.Left := 0;

    if ShowDialog then
      ContentRegion.Visible := true
    else
      ContentRegion.Visible := false;

    js := js + HTMLName + 'ContentRegionID = "' + ContentRegion.HTMLName + '";'#13
  end
  else
    js := js + HTMLName + 'ContentRegionID = "";'#13;

  if (PositionType = ptAtControl) and (PositionControl <> nil) then
  begin
    js := js + HTMLName + 'PositionControlID = "' + PositionControl.HTMLName + '";'#13;
    js := js + HTMLName + 'atControl();'#13
  end
  else
    js := js + HTMLName + 'PositionControlID = "";'#13;

    js := js
      + 'var el = document.getElementById("' + HTMLName + 'Dialog");'#13
      + 'if (el){'#13
      + '  var tempEl = document.getElementById("' + HTMLName + 'Temp");'#13
      + '  if ((tempEl) && (' + HTMLName + 'ContentRegionEL))'#13
      + '    tempEl.appendChild(' + HTMLName + 'ContentRegionEL);'#13
      + '  el.innerHTML = "' + html + '";'
      + '  if ((tempEl) && (' + HTMLName + 'ContentRegionEL))'#13
      + '    ' + HTMLName + 'ContentRegionEL = tempEl.firstChild;'#13
      + '}'#13;

//    js := js
//    + ' if (' + HTMLName + 'ContentRegionEL)'#13
//    + ' alert("RA2: " + ' + HTMLName + 'ContentRegionEL.innerHTML);'#13;

    if ShowDialog then
    begin
      js := js + HTMLName + 'Show();'#13;
      js := js + HTMLName + 'RePosition();'#13;
      js := js + HTMLName + 'Focus();'#13;
    end
    else
      js := js + HTMLName + 'Hide();'#13;

    js := js + HTMLName + 'InitAsync();'#13;

    js := js
      +']]>';

    if AsyncUpdateRequired then
      GGetWebApplicationThreadVar.CallBackResponse.AddJavaScriptToExecute(js);

    AsyncUpdateRequired := true;

  except
    FreeAndNil(Result);
  end;
end;

procedure TTIWAdvMessageDialog.ClearInputPassword;
begin
  FInputPassword := EmptyStr;
  Invalidate;
end;

constructor TTIWAdvMessageDialog.Create(AOwner: TComponent);
var
  FDesignTime: boolean;
begin
  inherited;

  FBGColor := clWhite;
  FBGColorTo := clNone;
  FBGGradientDirection := gdVertical;
  FBorderColor := clBlack;
  FBorderWidth := 2;
  FButtonBarBGColor := $F0F0F0;
  FButtonBarBGColorTo := clNone;
  FButtonBarBorderColor := $DFDFDF;
  FButtonBarFont := TIWFont.Create;
  FButtonBarFont.FontName := 'Helvetica';
  FButtonBarGradientDirection := gdVertical;
  FButtonIndex := -1;
  FCaptionBGColor := $FCFCFC;
  FCaptionBGColorTo := $EDEDED;
  FCaptionBorderColor := $7A7A7A;
  FCaptionFont := TIWFont.Create;
  FCaptionFont.Style := [fsBold];
  FCaptionFont.FontName := 'Helvetica';
  FCaptionGradientDirection := gdVertical;
  FCloseButtonColor := clWebBlack;
  FCollapseControlHint := 'Show details';
  FCollapseControlText := 'Show details';
  FCommonButtons := [cbOk];
  FCustomButtons := TStringList.Create;
  FDefaultButton := 0;
  FEnableDragging := true;
  FEmptyText := EmptyStr;
  FExpandedText := EmptyStr;
  FFont := TIWFont.Create;
  FFont.Color := $993300;
  FFont.Size := 12;
  FFont.FontName := 'Helvetica';
  FFocusControl := '';
  FInputCheck := false;
  FInputString := EmptyStr;
  FInputPassword := EmptyStr;
  FInputType := itNone;
  FOverlayColor := clBlack;
  FOverlayOpacity := 2;
  FPosition := pCentered;
  FPositionLeft := 0;
  FPositionTop := 0;
  FPositionType := ptDefault;
  FRoundedBorderRadius := 8;
  FShowCloseButton := true;
  FShowDialog := false;
  FShowShadow := true;
  FShowVerificationCheckBox := false;
  FVerificationCheckBoxChecked := false;
  FVerificationText := EmptyStr;
  FWantsEscape := true;
  FAsyncUpdateRequired := true;

  FDesignTime := (csDesigning in ComponentState) and not
                 ((csReading in Owner.ComponentState) or (csLoading in Owner.ComponentState));

  if FDesignTime then
  begin
    FCaption := 'Caption';
    FCloseButtonHint := 'Close';
    FExpandControlHint := 'Hide details';
    FExpandControlText := 'Hide details';
    FNotes := 'Notes';
  end;

  Width := 140;
  Height := 25;
  Zindex := 1001;
end;

destructor TTIWAdvMessageDialog.Destroy;
begin
  FButtonBarFont.Free;
  FCaptionFont.Free;
  FCustomButtons.Free;
  FFont.Free;
  inherited;
end;


procedure TTIWAdvMessageDialog.Loaded;
var
  ParentForm: TIWForm;
begin
  inherited;

  //The AdvMessageDialog requires the form's RenderInvisibleControls to always be True
  //The AdvMessageDialog should always be placed directly on the form

  {$IFDEF TMSIW10}
  ParentForm := TIWForm(Self.Parent);
  ParentForm.RenderInvisibleControls := True;
  {$ENDIF}
end;

procedure TTIWAdvMessageDialog.IWPaint;
begin
  inherited;

  With Canvas do
  begin
    Brush.Color := clBtnFace;
    Pen.Color := clBtnFace;
    Rectangle(0,0,Width - 1,Height - 1);
    TextOut(Width div 2 - TextWidth(Name) div 2,Height div 2 - TextHeight(Name) div 2,Name);
  end;
end;

function TTIWAdvMessageDialog.RenderDialog(): string;
var
  html, inputvalue, inputclass: string;
  i: integer;
begin
  html := html
    + '<table cellpadding=0 cellspacing=0 border=0 id="' + HTMLName + 'Table">'#13
    + '<tr><td valign="top">'#13
    + '<div id="' + HTMLName + 'Caption"'#13;

  if EnableDragging then
    html := html + ' onmousedown="return ' + HTMLName + 'OnMouseDown(event);"'#13;

  html := html
    + '>'#13
    + '<table cellpadding=0 cellspacing=0><tr><td>'#13
    + Caption + #13
    + '</td><td>'#13;

  if ShowCloseButton then
    html := html
      + '<div id="' + HTMLName + 'Close" onclick="' + HTMLName + 'Hide();" title="' + CloseButtonHint + '">x</div>'#13;

  html := html
    + '</tr></table>'#13
    + '</div>'#13
    + '</td></tr>'#13
    + '<tr><td valign="top" height="100%" id="' + HTMLName + 'Content">'#13;

  if InputType = itCheck then
  begin
    html := html + '<br><input type="checkbox" id="' + HTMLName + 'InputC" style="height:auto;width:auto;"';
    if InputCheck then
      html := html + ' checked';
    html := html + '>';
  end;

  html := html
    + Notes + #13;

  if ContentRegion <> nil then
  begin
    html := html
      + '<table id="' + HTMLName + 'Region" cellpadding=0 cellspacing=0'
      + ' style="width:' + IntToStr(ContentRegion.Width) + 'px;height:' + IntToStr(ContentRegion.Height) + 'px;"><tr><td valign="top">'
      + '<div id="' + HTMLName + 'ContentRegion"></div>'
      + '</td></tr></table>'#13;
  end;

  if InputString = EmptyStr then
  begin
    inputvalue := EmptyText;
    inputclass := 'Input';
  end
  else
  begin
    inputvalue := InputString;
    inputclass := 'InputF';
  end;

  if InputType = itString then
  begin
    html := html + '<br><input type="text" id="' + HTMLName + 'Input1" class="' + HTMLName + inputclass + '"'
      + ' value="' + inputvalue + '" onFocus="' + HTMLName + 'EmptyText(this,1);" onBlur="' + HTMLName + 'EmptyText(this,0)">';
  end
  else if InputType = itInteger then
  begin
    html := html + '<br><input type="text" id="' + HTMLName + 'Input1" class="' + HTMLName + inputclass + '"'
      + ' value="' + inputvalue + '" onKeyPress="return ' + HTMLName + 'Integer(event);" onFocus="' + HTMLName + 'EmptyText(this,1);" onBlur="' + HTMLName + 'EmptyText(this,0)">';
  end
  else if InputType = itLogin then
  begin
    html := html + '<br>Login: <input type="text" id="' + HTMLName + 'Input1" class="' + HTMLName + inputclass + '"'
      + ' value="' + inputvalue + '" onFocus="' + HTMLName + 'EmptyText(this,1)" onBlur="' + HTMLName + 'EmptyText(this,0)">'
      + '<br>Password: <input type="password" id="' + HTMLName + 'Input2" class="' + HTMLName + 'InputF" value="' + InputPassword + '">';
  end
  else if InputType = itPassword then
  begin
    html := html + '<br>Password: <input type="password" id="' + HTMLName + 'Input2" class="' + HTMLName + 'InputF" value="' + InputPassword + '">';
  end;

  if ExpandedText <> EmptyStr then
    html := html
      + '<div id="' + HTMLName + 'ExpandedText" style="display:none;">' + ExpandedText + '</div>'#13;

  html := html
    + '</td></tr>'#13
    + '<tr><td id="' + HTMLName + 'Buttons">'#13
    + '<table cellspacing=0 cellpadding=0 border=0 width="100%"><tr><td>'
    ;

  if (ExpandedText <> EmptyStr) then
  begin
    html := html
      + '<div id="' + HTMLName + 'Details">'#13
      + '<div id="' + HTMLName + 'Collapsed" style="display:;">'#13
      + '<input type="button" title="' + CollapseControlHint + '" style="width:25px;" value="&#709" onclick="'
      + HTMLName + 'Details()">&nbsp;'#13
      + CollapseControlText + '</div>'#13
      + '<div id="' + HTMLName + 'Expanded" style="display:none;">'#13
      + '<input type="button" title="' + ExpandControlHint + '" style="width:25px;" value="&#708" onclick="'
      + HTMLName + 'Details()">&nbsp;'#13
      + ExpandControlText + '</div>'#13
      + '</div>'#13;
  end;

  html := html + '</td><td align="right">'#13;

  if visible then
  begin


    if cbOk in FCommonButtons then
      html := html + '<input type="submit" id="' + HTMLName + 'b0" value="'
      + string(ButtonNames[cbOk]) + '" onclick="' + HTMLName + 'Click(0);">'#13;

    if cbYes in FCommonButtons then
      html := html + '<input type="submit" id="' + HTMLName + 'b1" value="'
      + string(ButtonNames[cbYes]) + '" onclick="' + HTMLName + 'Click(1);">'#13;

    if cbNo in FCommonButtons then
      html := html + '<input type="submit" id="' + HTMLName + 'b2" value="'
      + string(ButtonNames[cbNo]) + '" onclick="' + HTMLName + 'Click(2);">'#13;

    if cbCancel in FCommonButtons then
      html := html + '<input type="submit" id="' + HTMLName + 'b3" value="'
      + string(ButtonNames[cbCancel]) + '" onclick="' + HTMLName + 'Click(3);">'#13;

    if cbClose in FCommonButtons then
      html := html + '<input type="submit" id="' + HTMLName + 'b4" value="'
      + string(ButtonNames[cbClose]) + '" onclick="' + HTMLName + 'Click(4);">'#13;

    if cbRetry in FCommonButtons then
      html := html + '<input type="submit" id="' + HTMLName + 'b5" value="'
      + string(ButtonNames[cbRetry]) + '" onclick="' + HTMLName + 'Click(5);">'#13;

    for I := 0 to CustomButtons.Count - 1 do
      html := html + '<input type="submit" value="' + CustomButtons[I] + '" onclick="'
      + HTMLName + 'Click(' + IntToStr(I+100) + ');">'#13;
  end;

  html := html + '</td></tr>'#13;

  if (ShowVerificationCheckBox) then
  begin
    html := html
      + '<tr><td colspan="2"><input style="height:auto;width:auto;" type="checkbox" id="' + HTMLName + 'cb" ';

    if VerificationCheckBoxChecked then
      html := html + ' checked';

    html := html
      + '>' + VerificationText + '</td></tr>'#13;
  end;

  html := html
    + '</table>'#13
    + '</td></tr></table>'#13
//    + '</div>'#13
    ;

  result := html;
end;

function TTIWAdvMessageDialog.RenderHTML(AContext: TIWBaseComponentContext): TIWHTMLTag;
var
  html, ajaxcall, submitclick, wrapperpos, dialogpos, opacity: string;
begin
  AsyncUpdateRequired := true;
  Width := 0;
  Height := 0;
  Top := 0;
  Left := 0;
  Align := alClient;

  if ShowDialog then
  begin
    TIWComponent40Context(AContext).AddToInitProc(HTMLName + 'Show();');
  end
  else
  begin
    TIWComponent40Context(AContext).AddToInitProc(HTMLName + 'InitHidden();');
  end;

  ajaxcall := EmptyStr;
  submitclick := EmptyStr;

  if Assigned(OnButtonClick) then
    submitclick := 'SubmitClick('#39 + HTMLName + #39','''',false);'#13;

  if Assigned(FOnAsyncButtonClick) then
  begin
    ajaxcall := 'processAjaxEvent(''onButtonClick'', '
      + HTMLControlImplementation.IWCLName
      + ',''' + HTMLName + '.' + 'DoOnAsyncButtonClick' + ''','
      + 'true' + ', null, '
      + 'true' + ');';

    submitclick := EmptyStr;
  end;

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

  html := html
    + '<script>'#13
    + 'var ' + HTMLName + 'IsVisible = false;'#13
    + 'var ' + HTMLName + 'DefaultValue = "' + EmptyText + '";'#13
    + 'var ' + HTMLName + 'InputControls = null;'#13
    + 'var ' + HTMLName + 'InputControlIDs = null;'#13
    ;

  if PositionType = ptAbsolute then
    html := html
      + 'var ' + HTMLName + 'PositionTop = ' + IntToStr(PositionTop) + ';'#13
      + 'var ' + HTMLName + 'PositionLeft = ' + IntToStr(PositionLeft) + ';'#13
  else
    html := html
      + 'var ' + HTMLName + 'PositionTop = null;'#13
      + 'var ' + HTMLName + 'PositionLeft = null;'#13;

  if ContentRegion <> nil then
  begin

    //move the contentregion outside of the visible area
    //to avoid flickering effect when repositioning
    ContentRegion.Top := -1000;
    ContentRegion.Left := -1000;

    //fix: the contentregion should be made visible server side
    //if the region is not visible the submit/setvalue will not work correctly
    if ShowDialog then
      ContentRegion.Visible := true
    else
      ContentRegion.Visible := false;

    html := html + 'var ' + HTMLName + 'ContentRegionID = "' + ContentRegion.HTMLName + '";'#13
  end
  else
    html := html + 'var ' + HTMLName + 'ContentRegionID = "";'#13;

  html := html + 'var ' + HTMLName + 'ContentRegionEL = null;'#13;

  if ((PositionType = ptAtControl) and (PositionControl <> nil)) then
    html := html + 'var ' + HTMLName + 'PositionControlID = "' + PositionControl.HTMLName + '";'#13
  else
    html := html + 'var ' + HTMLName + 'PositionControlID = "";'#13;

  html := html
    + 'function ' + HTMLName + 'Init(){'#13

    + 'var region = document.getElementById(' + HTMLName + 'ContentRegionID);'#13
    + 'if (region){'#13
    + '  el = document.getElementById("'+HTMLName+'ContentRegion");'#13
    + '  if (el){'#13

//    + '    ' + HTMLName + 'ContentRegionEL = region.innerHTML;'#13

    //enable changing the ContentRegion control using asynchronous events
    + '  if (' + HTMLName + 'ContentRegionEL != null) {'#13
    + '    ' + HTMLName + 'ContentRegionEL.style.visibility = "hidden";'#13
    + '    document.body.appendChild(' + HTMLName + 'ContentRegionEL);'#13
    + '  }'#13
    // * //

//    + '  if (' + HTMLName + 'ContentRegionEL == null)'#13
    + '    ' + HTMLName + 'ContentRegionEL = region;'#13

//    + '    el.innerHTML = region.innerHTML;'#13
//    + '    region.innerHTML = "";'#13
    + '    el.appendChild(' + HTMLName + 'ContentRegionEL);'#13
    + '    ' + HTMLName + 'ContentRegionEL.style.top = "0px";'#13
    + '    ' + HTMLName + 'ContentRegionEL.style.left = "0px";'#13

    + '    if (' + HTMLName + 'IsVisible) {'#13
    + '    ' + HTMLName + 'ContentRegionEL.style.visibility = "visible";'#13
    + '    setTimeout(' + HTMLName + 'FocusControl, 0);'#13
    + '    } else {'#13
    + '    ' + HTMLName + 'ContentRegionEL.style.visibility = "hidden";'#13
    + '    }'#13

    + '    }'#13
    + '  }'#13

    + '}'#13;

  html := html
    + 'function ' + HTMLName + 'InitAsync(){'#13

    + 'if (' + HTMLName + 'ContentRegionEL){'#13
    + '  el = document.getElementById("'+HTMLName+'ContentRegion");'#13
    + '  if (el){'#13
    + '    el.appendChild(' + HTMLName + 'ContentRegionEL);'#13
//    + '    el.innerHTML = ' + HTMLName + 'ContentRegionEL;'#13

    + '    if (' + HTMLName + 'IsVisible) {'#13
    + '    ' + HTMLName + 'ContentRegionEL.style.visibility = "visible";'#13
    + '    setTimeout(' + HTMLName + 'FocusControl, 0);'#13
    + '    } else {'#13
    + '    ' + HTMLName + 'ContentRegionEL.style.visibility = "hidden";'#13
    + '    }'#13

    + '    }'#13
    + '  }'#13
    + '}'#13

    + 'function ' + HTMLName + 'FocusControl(){'#13;

  if not (FocusControl = EmptyStr) then
  begin
    html := html
    + 'fc = document.getElementById("' + UpperCase(FocusControl) + '");'#13
    + 'if (fc){'#13
    + ' fc.focus();'#13
    + ' fc.value = fc.value;'#13
    + '}'#13
    ;
  end;

  html := html
    + '}'#13

    + 'function ' + HTMLName + 'Details(){'#13
    + '  var el = document.getElementById("' + HTMLName + 'ExpandedText");'#13
    + '  if (el){'#13
    + '    if (el.style.display == "")'#13
    + '      el.style.display = "none";'#13
    + '    else'#13
    + '      el.style.display = "";'#13
    + '  }'#13
    + '  ' + HTMLName + 'InitAsync();'#13
;

  if (PositionType = ptAtControl) then
    html := html + '  ' + HTMLName + 'atControl();'#13;

  html := html
    + '  var eel = document.getElementById("' + HTMLName + 'Expanded");'#13
    + '  var cel = document.getElementById("' + HTMLName + 'Collapsed");'#13
    + '  if ((eel) && (cel)){'#13
    + '    if (cel.style.display == ""){'#13
    + '      cel.style.display = "none";'#13
    + '      eel.style.display = "";'#13
    + '    }'#13
    + '    else {'#13
    + '      cel.style.display = "";'#13
    + '      eel.style.display = "none";'#13
    + '    }'#13
    + '  }'#13
    + '}'#13

    + 'function vpWidth() {'#13
    + 'return window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;'#13
    + '}'#13
    + 'function vpHeight() {'#13
    + 'return window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;'#13
    + '}'#13
    ;

    html := html
      + 'function ' + HTMLName + 'Resize(){'#13

      + '  if (document.getElementById("' + HTMLName + '").style.display == "") {'#13

      //HTML5 Fix: always do resizing to make sure the overlay fits the window
      + '    ol = document.getElementById("' + HTMLName + 'Overlay");'#13
      + '    ol.style.width = vpWidth() + "px";'#13
      + '    ol.style.height = vpHeight() + "px";'#13;

  if (PositionType = ptDefault) and (Position = pCentered) then
  begin
    html := html
      + '    ctrl = document.getElementById("' + HTMLName + 'Wrapper");'#13
      + '    var point = ' + HTMLName + 'center(ctrl.offsetWidth, ctrl.offsetHeight);'#13
      + '    ctrl.style.top = point.y + "px";'#13
      + '    ctrl.style.left = point.x + "px";'#13
      //ContentRegion handling
      + '    setTimeout(' + HTMLName + 'InitAsync, 250);'#13
  end;

    html := html
      + '  }'#13
      + '}'#13

////      + ' window.onresize = ' + HTMLName + 'Resize;'#13;

      + 'if (window.addEventListener)'#13 // W3C standard
      + '  window.addEventListener("resize", ' + HTMLName + 'Resize, false);'#13
      + 'else if (window.attachEvent)'#13 // Microsoft
      + '  window.attachEvent("onresize", ' + HTMLName + 'Resize);'#13;

  html := html
    + 'function ' + HTMLName + 'Focus(){'#13
    + '  input = document.getElementById("' + HTMLName + 'Input1");'#13
    + '  if ((input) && (' + HTMLName + 'DefaultValue == ""))'#13
    + '    input.focus();'#13
    + '  else {'#13
    + '    el = document.getElementById("' + HTMLName + 'b' + IntToStr(DefaultButton) + '");'#13
    + '    if (el){'#13
    + '      el.focus();'#13
    + '    }else{'#13
    + '      document.getElementById("' + HTMLName + 'Dialog").focus();'#13
    + '    }'#13
    + '  }'#13

    //ContentRegion handling
    + '    setTimeout(' + HTMLName + 'InitAsync, 250);'#13
    + '}'#13;

  html := html
    + 'function ' + HTMLName + 'IsParent(el){'#13
    + ' var result = true;'#13
    + ' var parent = el;'#13
    + ' while (parent){'#13
    + '   if (((parent.id == "' + HTMLName + '") || (parent.id == ' + HTMLName + 'ContentRegionID)) && (parent.id != ""))'#13
    + '     result = false;'#13
    + '   parent = parent.parentNode;'#13
    + ' }'
    + ' return result;'#13
    + '}'#13;

  html := html
    + 'function ' + HTMLName + 'DisableTab(){'
    + '  inputs = document.getElementsByTagName("INPUT");'#13
    + '  inputs2 = document.getElementsByTagName("DIV");'#13
    + '  inputs3 = document.getElementsByTagName("A");'#13
    + '  inputs4 = document.getElementsByTagName("TEXTAREA");'#13
    + '  inputs5 = document.getElementsByTagName("SELECT");'#13
    + '  inputs6 = document.getElementsByTagName("SPAN");'#13
    + '  totinput = inputs.length + inputs2.length + inputs3.length + inputs4.length + inputs5.length + inputs6.length;'#13

//    + '  alert(inputs.length + " * " + inputs2.length + " * " + inputs3.length + " * " + inputs4.length + " * " + inputs5.length + " * " + inputs6.length);'#13

    + '  ' + HTMLName + 'InputControls = new Array(totinput)'#13
    + '  ' + HTMLName + 'InputControlIDs = new Array(totinput)'#13

    + '  for (i = 0; i < inputs.length; i++){'#13
    + '    ' + HTMLName + 'InputControlIDs[i] = inputs[i];'#13
    + '    if (inputs[i].type == "radio"){'#13
    + '    ' + HTMLName + 'InputControls[i] = inputs[i].disabled;'#13
    + '      if (' + HTMLName + 'IsParent(inputs[i]))'#13
    + '        inputs[i].disabled = true;'#13
    + '    } else {'#13
    + '    ' + HTMLName + 'InputControls[i] = inputs[i].tabIndex;'#13
    + '    if (inputs[i].tagName == "INPUT")'#13
    + '      if (' + HTMLName + 'IsParent(inputs[i]))'#13
    + '        inputs[i].tabIndex = -1;'#13
    + '    }'#13
    + '  }'#13

    + '  var icount = inputs.length;'#13

    + '  for (i = 0; i < inputs2.length; i++){'#13
    + '    ' + HTMLName + 'InputControls[icount] = inputs2[i].tabIndex;'#13
    + '    ' + HTMLName + 'InputControlIDs[icount] = inputs2[i];'#13
    + '      if (' + HTMLName + 'IsParent(inputs2[i]))'#13
    + '        inputs2[i].tabIndex = -1;'#13
    + '  }'#13

    + '  icount = inputs.length + inputs2.length;'#13

    + '  for (i = 0; i < inputs3.length; i++){'#13
    + '    ' + HTMLName + 'InputControls[icount] = inputs3[i].tabIndex;'#13
    + '    ' + HTMLName + 'InputControlIDs[icount] = inputs3[i];'#13
    + '      if (' + HTMLName + 'IsParent(inputs3[i]))'#13
    + '        inputs3[i].tabIndex = -1;'#13
    + '  }'#13

    + '  icount = inputs.length + inputs2.length + inputs3.length;'#13

    + '  for (i = 0; i < inputs4.length; i++){'#13
    + '    ' + HTMLName + 'InputControls[icount] = inputs4[i].tabIndex;'#13
    + '    ' + HTMLName + 'InputControlIDs[icount] = inputs4[i];'#13
    + '      if (' + HTMLName + 'IsParent(inputs4[i]))'#13
    + '        inputs4[i].tabIndex = -1;'#13
    + '  }'#13

    + '  icount = inputs.length + inputs2.length + inputs3.length + inputs4.length;'#13

    + '  for (i = 0; i < inputs5.length; i++){'#13
    + '    ' + HTMLName + 'InputControls[icount] = inputs5[i].tabIndex;'#13
    + '    ' + HTMLName + 'InputControlIDs[icount] = inputs5[i];'#13
    + '      if (' + HTMLName + 'IsParent(inputs5[i]))'#13
    + '        inputs5[i].tabIndex = -1;'#13
    + '  }'#13

    + '  icount = inputs.length + inputs2.length + inputs3.length + inputs4.length + inputs5.length;'#13

    + '  for (i = 0; i < inputs6.length; i++){'#13
    + '    ' + HTMLName + 'InputControls[icount] = inputs6[i].tabIndex;'#13
    + '    ' + HTMLName + 'InputControlIDs[icount] = inputs6[i];'#13
    + '      if (' + HTMLName + 'IsParent(inputs6[i]))'#13
    + '        inputs6[i].tabIndex = -1;'#13
    + '  }'#13
    + '}';

  html := html
    + 'function ' + HTMLName + 'RePosition(){'#13

    + '  if (' + HTMLName + 'PositionTop && ' + HTMLName + 'PositionLeft){'#13
    + '    dialog = document.getElementById("' + HTMLName + 'Dialog");'#13
    + '    dialog.style.top = ' + HTMLName + 'PositionTop;'#13
    + '    dialog.style.left = ' + HTMLName + 'PositionLeft;'#13
    + '  }'#13
    ;

  if (PositionType = ptAtControl) then
    html := html + '  ' + HTMLName + 'atControl();'#13;
  //HTML5 Fix: always do resizing to make sure the overlay fits the window
  //else if (PositionType = ptDefault) and (Position = pCentered) then
    html := html + '  ' + HTMLName + 'Resize();'#13;

  html := html

    + '}'#13;

  html := html
    + 'function ' + HTMLName + 'InitHidden(){'#13

    + '  if (!containsName("'+HTMLName+'")) {'#13
    + ' 	 window.ChangedControls += "'+HTMLName+',";'#13
    + '}'#13

    + '    ' + HTMLName + 'Init();'#13

    + '}'#13;

  html := html
    + 'function ' + HTMLName + 'Show(){'#13

    //Init hidden input
    + '  FindElem("' + HTMLName + '").value = "";'#13

    + '  if (!containsName("'+HTMLName+'")) {'#13
    + ' 	 window.ChangedControls += "'+HTMLName+',";'#13
    + '}'#13

    + '  if (navigator.userAgent.indexOf("MSIE") > 0){'#13
    + '    setTimeout(' + HTMLName + 'Init, 150);'#13
    + '  } else {'#13
    + '    ' + HTMLName + 'Init();'#13
    + '}'#13

    //Without the setTimeout the Dialog was not correctly centered in non-IE browsers
//    + HTMLName + 'RePosition();'#13
    + '    setTimeout(' + HTMLName + 'RePosition, 0);'#13

    //make the dialog visible after repositioning to avoid flickering effect
    //when using synchronous event to show the dialog
//    + '  document.getElementById("' + HTMLName + '").style.visibility = "visible";'#13

    + '  document.getElementById("' + HTMLName + '").style.display = "";'#13

    + '  if (! ' + HTMLName + 'IsVisible){'#13
    + '    ' + HTMLName + 'IsVisible = true;'#13
    + '    ' + HTMLName + 'DisableTab();'#13
    + '  }'#13

    + HTMLName + 'Focus();'#13

    + '}'#13

    + 'function ' + HTMLName + 'Hide(){'#13

//    + '  alert(' + HTMLName + 'InputControls.length);'#13
    + '  if (' + HTMLName + 'InputControls) {'#13
    + '  for (i = 0; i < ' + HTMLName + 'InputControls.length; i++){'#13
    + '    if (' + HTMLName + 'InputControlIDs[i] != ""){'#13
    + '      el = ' + HTMLName + 'InputControlIDs[i];'#13
    + '      if (el){'#13
    + '        if (el.type == "radio"){'#13
    + '          el.disabled = ' + HTMLName + 'InputControls[i];'#13
    + '        } else {'#13
    + '          el.tabIndex = ' + HTMLName + 'InputControls[i];'#13
    + '        }'#13
    + '      }'#13
    + '    }'#13
    + '  }'#13
    + '  }'#13

    + HTMLName + 'IsVisible = false;'#13

    + '  document.getElementById("' + HTMLName + '").style.display = "none";'#13

    + '  newvalue = "^isvisible:" + ' + HTMLName + 'IsVisible;'#13
    + '  FindElem("' + HTMLName + '").value = newvalue;'#13

    + '}'#13

    + 'function ' + HTMLName + 'Click(index){'#13;

  if (ajaxcall = EmptyStr) and (submitclick = EmptyStr) then
    html := html
//      + '  document.getElementById("' + HTMLName + '").style.display = "none";'#13;
      + '  ' + HTMLName + 'Hide();'#13;

  html := html
    + '  newvalue = "^index:" + index;'#13
    + '  input = document.getElementById("' + HTMLName + 'Input1");'#13
    + '  newvalue += "^input1:";'#13
    + '  if (input){'#13
    + '    if (input.value != "' + EmptyText +'")'#13
    + '      newvalue += input.value;'#13
//    + '    input.value = input.defaultValue;'#13
//    + '    input.className = "' + HTMLName + 'Input";'#13
    + '  }'#13
    + '  input2 = document.getElementById("' + HTMLName + 'Input2");'#13
    + '  newvalue += "^input2:";'#13
    + '  if (input2)'#13
    + '    newvalue += input2.value;'#13
    + '  inputC = document.getElementById("' + HTMLName + 'InputC");'#13
    + '  newvalue += "^inputC:";'#13
    + '  if (inputC)'#13
    + '    newvalue += inputC.checked;'#13
    + '  newvalue += "^isvisible:" + ' + HTMLName + 'IsVisible;'#13
    + '  cb = document.getElementById("' + HTMLName + 'cb");'#13
    + '  newvalue += "^cb:";'#13
    + '  if (cb)'#13
    + '    newvalue += cb.checked;'#13
    + '  FindElem("' + HTMLName + '").value = newvalue;'#13
    + ajaxcall + #13
    + submitclick + #13
    + '}'#13;

  if WantsEscape then
  begin
    html := html
      + 'function ' + HTMLName + 'KeyPress(e){'#13
      + '  if (window.event) key = window.event.keyCode; else key = e.which;'#13
      + '  if (key == 27)'#13 //escape key
      + '    ' + HTMLName + 'Hide();'#13
      + '}'#13;
  end;

  html := html
    + 'function ' + HTMLName + 'Integer(e){'#13
    + '  if (window.event) key = window.event.keyCode; else key = e.which;'#13
    + '  if (key == 13){'#13
		+ '	   if (window.event)'#13
		+ '		   window.event.returnValue = true;'#13
		+ '	   else'#13
		+ '		   return true;'#13
    + '  }'#13
    + '  else if (key < 48 || key > 57)'#13
	  + '  {'#13
		+ '	   if (window.event)'#13
		+ '		   window.event.returnValue = false;'#13
		+ '	   else'#13
		+ '		   return false;'#13
		+ '  }'#13
    + '}'#13

    + 'function ' + HTMLName + 'EmptyText(fld,focussed)'#13
    + '{'#13
    + '  if (focussed)'#13
    + '  {'#13
//    + '    if (fld.value==fld.defaultValue)'#13
    + '    if (fld.value == ' + HTMLName + 'DefaultValue)'#13
    + '    {'#13
    + '      fld.className = "' + HTMLName + 'InputF";'#13
    + '      fld.value = "";'#13
    + '    }'#13
    + '  }'#13
    + '  else'#13
    + '  {'#13
    + '    if (fld.value == "")'#13
    + '    {'#13
    + '      fld.className = "' + HTMLName + 'Input";'#13
    + '      fld.value = ' + HTMLName + 'DefaultValue;'#13
    + '    }'#13
    + '  }'#13
    + '}'#13

    + 'window.size = function()'#13
    + '{'#13
    + '	var w = 0;'#13
    + '	var h = 0;'#13
      //IE
    + '	if(!window.innerWidth)'#13
    + '	{'#13
        //strict mode
    + '		if(!(document.documentElement.clientWidth == 0))'#13
    + '		{'#13
    + '			w = document.documentElement.clientWidth;'#13
    + '			h = document.documentElement.clientHeight;'#13
    + '		}'#13
        //quirks mode
    + '		else'#13
    + '		{'#13
    + '			w = document.body.clientWidth;'#13
    + '			h = document.body.clientHeight;'#13
    + '		}'#13
    + '	}'#13
      //w3c
    + '	else'#13
    + '	{'#13
    + '		w = window.innerWidth;'#13
    + '		h = window.innerHeight;'#13
    + '	}'#13
    + '	return {width:w,height:h};'#13
    + '}'#13

    + 'function ' + HTMLName + 'center(ctrlwidth, ctrlheight)'#13
    + '{'#13

    + '	var _x = 0;'#13
    + '	var _y = 0;'#13
    + '	var offsetX = 0;'#13
    + '	var offsetY = 0;'#13

      //IE
    + '	if(!window.pageYOffset)'#13
    + '	{'#13
        //strict mode
    + '		if(!(document.documentElement.scrollTop == 0))'#13
    + '		{'#13
    + '			offsetY = document.documentElement.scrollTop;'#13
    + '			offsetX = document.documentElement.scrollLeft;'#13
    + '		}'#13
        //quirks mode
    + '		else'#13
    + '		{'#13
    + '			offsetY = document.body.scrollTop;'#13
    + '			offsetX = document.body.scrollLeft;'#13
    + '		}'#13
    + '	}'#13
      //w3c
    + '	else'#13
    + '	{'#13
    + '		offsetX = window.pageXOffset;'#13
    + '		offsetY = window.pageYOffset;'#13
    + '	}'#13

    + '	_x = ((this.size().width-ctrlwidth)/2)+offsetX;'#13
    + '	_y = ((this.size().height-ctrlheight)/2)+offsetY;'#13

    + '	return{x:_x,y:_y};'#13
    + '}'#13;

  if (PositionType = ptAtControl) then
  begin
    html := html
      + 'function ' + HTMLName + 'atControl() {'#13
      + '  var scroll = ' + HTMLName + 'getScroll();'#13
      + '  var d = document.getElementById("' + HTMLName + 'Dialog");'#13
      + '  var ctrl = document.getElementById(' + HTMLName + 'PositionControlID);'#13

      + '       var parentLeft = 0;'#13
      + '       var parentTop = 0;'#13

      + '          var elParent = ctrl;'#13
      + '          do {'#13
      + '              parentLeft += elParent.offsetLeft;'#13
      + '              parentTop += elParent.offsetTop;'#13
      + '          }'#13
      + '          while (( elParent = elParent.offsetParent));'#13

      + '  if (ctrl){'#13
      + '    if ((parentLeft + ctrl.offsetWidth + d.offsetWidth) > scroll.width)'#13
      + '      d.style.left = (parentLeft - d.offsetWidth) + "px";'#13
      + '    else'#13
      + '      d.style.left = (parentLeft + ctrl.offsetWidth) + "px";'#13
      + '    if ((parentTop + d.offsetHeight) > scroll.height)'#13
      + '      d.style.top = ((parentTop + ctrl.offsetHeight) - d.offsetHeight) + "px";'#13
      + '    else'#13
      + '      d.style.top = parentTop + "px";'#13
      + '  }'#13
      + '}'#13;
  end;

  html := html
    // returns the scroll left and top for the browser viewport.
    + 'function ' + HTMLName + 'getScroll () {'#13
    + '	if (document.all && typeof document.body.scrollTop != "undefined") {	// IE model'#13
    + '		var ieBox = document.compatMode != "CSS1Compat";'#13
    + '		var cont = ieBox ? document.body : document.documentElement;'#13
    + '		return {'#13
    + '			left:	cont.scrollLeft,'#13
    + '			top:	cont.scrollTop,'#13
    + '			width:	cont.clientWidth,'#13
    + '			height:	cont.clientHeight'#13
    + '		};'#13
    + '	}'#13
    + '	else {'#13
    + '		return {'#13
    + '			left:	window.pageXOffset,'#13
    + '			top:	window.pageYOffset,'#13
    + '			width:	window.innerWidth,'#13
    + '			height:	window.innerHeight'#13
    + '		};'#13
    + '	}'#13
    + '}'#13

    + 'var _startX = 0;'#13            // mouse starting positions
    + 'var _startY = 0;'#13
    + 'var _offsetX = 0;'#13           // current element offset
    + 'var _offsetY = 0;'#13
    + 'var _dragElement;'#13           // needs to be passed from OnMouseDown to OnMouseMove
    + 'var _dragDialog;'#13
    + 'var _oldZIndex = 0;'#13         // we temporarily increase the z-index during drag

    + 'function ' + HTMLName + 'OnMouseDown(e)'#13
    + '{'#13
        // IE is retarded and doesn't pass the event object
    + '    if (e == null)'#13
    + '        e = window.event;'#13

        // IE uses srcElement, others use target
        //var target = e.target != null ? e.target : e.srcElement;
    + '    var closebutton = e.target != null ? e.target : e.srcElement;'#13
    + '    if (closebutton){'#13
    + '      if (closebutton.id == "' + HTMLName + 'Close")'#13
    + '        return false;'#13
    + '    }'#13

    + '    var target = document.getElementById("' + HTMLName + 'Wrapper");'#13
    + '    var dialog = document.getElementById("' + HTMLName + 'Dialog");'#13

        // for IE, left click == 1
        // for Firefox, left click == 0
    + '    if ((e.button == 1 && window.event != null ||'
    + '        e.button == 0) &&'
    + '        target.className == "drag")'#13
    + '    {'#13

            // grab the mouse position
    + '        _startX = e.clientX;'#13
    + '        _startY = e.clientY;'#13

            // grab the clicked element's position
//    + '        _offsetX = ExtractNumber(target.style.left);'#13
//    + '        _offsetY = ExtractNumber(target.style.top);'#13

    + '        _offsetX = ExtractNumber(target.offsetLeft);'#13
    + '        _offsetY = ExtractNumber(target.offsetTop);'#13

            // bring the clicked element to the front while it is being dragged
    + '        _oldZIndex = target.style.zIndex;'#13
    + '        target.style.zIndex = 10000;'#13

            // we need to access the element in OnMouseMove
    + '        _dragElement = target;'#13
    + '        _dragDialog = dialog;'#13

            // tell our code to start moving the element with the mouse
    + '        document.onmousemove = ' + HTMLName + 'OnMouseMove;'#13
    + '        document.onmouseup = ' + HTMLName + 'OnMouseUp;'#13

            // cancel out any text selections
    + '        document.body.focus();'#13

            // prevent text selection in IE
    + '        document.onselectstart = function () { return false; };'#13
            // prevent IE from trying to drag an image
    + '        target.ondragstart = function() { return false; };'#13

            // prevent text selection (except IE)
    + '        return false;'#13
    + '    }'#13
    + '}'#13

    + 'function ' + HTMLName + 'OnMouseMove(e)'#13
    + '{'#13
    + '    if (e == null)'#13
    + '        var e = window.event;'#13

        // this is the actual "drag code"
    + '    newleft = (_offsetX + e.clientX - _startX);'#13
    + '    if (newleft < 0) newleft = 0;'#13
    + '    newtop = (_offsetY + e.clientY - _startY);'#13
    + '    if (newtop < 0) newtop = 0;'#13
    + '    _dragElement.style.left = newleft + "px";'#13
    + '    _dragElement.style.top = newtop + "px";'#13

    + '    _dragDialog.style.top = "0px";'#13
    + '    _dragDialog.style.left = "0px";'#13
    + '    _dragElement.style.right = "auto";'#13
    + '    _dragElement.style.bottom = "auto";'#13

    + '  ' + HTMLName + 'InitAsync();'#13

    + '}'#13

    + 'function ' + HTMLName + 'OnMouseUp(e)'#13
    + '{'#13
    + '    if (_dragElement != null)'#13
    + '    {'#13
    + '        _dragElement.style.zIndex = _oldZIndex;'#13

            // we're done with these events until the next OnMouseDown
    + '        document.onmousemove = null;'#13
    + '        document.onselectstart = null;'#13
    + '        _dragElement.ondragstart = null;'#13

            // this is how we know we're not dragging
    + '        _dragElement = null;'#13
    + '        ' + HTMLName + 'Focus();'#13
    + '    }'#13
    + '}'#13

    + 'function ExtractNumber(value)'#13
    + '{'#13
    + '    var n = parseInt(value);'#13
    + '    return n == null || isNaN(n) ? 0 : n;'#13
    + '}'#13


    + '</script>'#13;

  if PositionType = ptAbsolute then
  begin
//    wrapperpos := '';
//    dialogpos := 'top:' + IntTostr(PositionTop) + 'px;'#13
//      + 'left:' + IntToStr(PositionLeft) + 'px;'#13;
  end
  else if (PositionType = ptAtControl) and (PositionControl <> nil) then
  begin
//    wrapperpos := '';
//    dialogpos := 'top:' + IntTostr(PositionControl.Top) + 'px;'#13
//      + 'left:' + IntToStr(PositionControl.Left + PositionControl.Width) + 'px;'#13;
  end
  else //if PositionType = ptDefault then
  begin
    if Position = pTopLeft then
    begin
      wrapperpos := '';
      dialogpos := 'top:5px;'#13
        + 'left:5px;'#13;
    end
    else if Position = pTopCenter then
    begin
      wrapperpos := 'right:50%;'#13;
      dialogpos := 'top:5px;'#13
        + 'left:50%;'#13;
    end
    else if Position = pTopRight then
    begin
      wrapperpos := 'right:10px;'#13;
      dialogpos := 'top:5px;'#13;
    end
    else if Position = pMidLeft then
    begin
      wrapperpos := 'bottom:50%;'#13;
      dialogpos := 'top:50%;'#13
        + 'left:5px;'#13;
    end
    else if Position = pMidRight then
    begin
      wrapperpos := 'bottom:50%;'#13
        + 'right:10px;'#13;
      dialogpos := 'top:50%;'#13;
    end
    else if Position = pBottomLeft then
    begin
      wrapperpos := 'bottom:10px;'#13;
      dialogpos := 'left:5px;'#13;
    end
    else if Position = pBottomCenter then
    begin
      wrapperpos := 'bottom:5px;'#13
        + 'right:50%;'#13;
      dialogpos := 'left:50%;'#13;
    end
    else if Position = pBottomRight then
    begin
      wrapperpos := 'bottom:10px;'#13
        + 'right:10px;'#13;
      dialogpos := '';
    end
    else if Position = pCentered then
    begin
//      wrapperpos := 'bottom:50%;'#13
//        + 'right:50%;'#13;
//      dialogpos := 'top:50%;'#13
//        + 'left:50%;'#13;
    end;
  end;

  html := html
    + '<style>'#13

    + '#' + HTMLName + ' {'#13
    //HMLT5 fix
    //+ 'width:auto;'#13
    //+ 'height:auto;'#13
    + '}'#13

    + '#' + HTMLName + ', #' + HTMLName + ' table {'#13
    //disable webkit focus border
    + 'outline:none;'#13
    //+ 'font-size:10pt;'#13
    + '}'#13

    + '#' + HTMLName + 'Overlay {'#13
    + 'position:absolute;'#13
    + 'top:0px;'#13
    + 'left:0px;'#13;
//HTML5 Fix set px size values in js
//    + 'width:100%;'#13
//    + 'height:100%;'#13;

  if OverlayOpacity < 10 then
    opacity := '0.' + IntToStr(OverlayOpacity)
  else
    opacity := '1.0';

  html := html
    + '-moz-opacity: ' + opacity + ';'#13
    + '-webkit-opacity: ' + opacity + ';'#13
    + '-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=' + IntToStr(OverlayOpacity*10) + ')";'#13
    + 'filter: alpha(opacity=' + IntToStr(OverlayOpacity*10) + ');'#13
    + 'opacity: ' + opacity + ';'#13
    + 'background-color:' + ColorToRGBString(OverlayColor) + ';'#13
    + '}'#13

    + '#' + HTMLName + 'Wrapper, #' + HTMLName + 'Dialog {'#13
    //+ 'width:' + IntToStr(Width) + 'px;'#13
    //+ 'height:' + IntToStr(Height) + 'px;'#13
    + '}'#13

    + '#' + HTMLName + 'Wrapper {'#13
    + wrapperpos
    + 'position:absolute;'#13
    + '}'#13

    + '#' + HTMLName + 'Dialog {'#13
    + 'position:relative;'#13
    + dialogpos
	  + '-webkit-border-radius: ' + IntToStr(RoundedBorderRadius) + 'px;'#13
	  + '-moz-border-radius: ' + IntToStr(RoundedBorderRadius) + 'px;'#13
    + 'border-radius: ' + IntToStr(RoundedBorderRadius) + 'px;'#13
    //+ 'background-color:' + ColorToRGBString(BorderColor) + ';'#13
    + 'outline:none;'#13
    + '}'#13

    + '#' + HTMLName + 'Table {'#13;

  if ShowShadow then
  begin
    html := html
      + 'box-shadow: 0 0 10px 1px #555;'#13
      + '-moz-box-shadow: 0 0 10px 1px #555;'#13
      + '-webkit-box-shadow: 0 0 10px 1px #555;'#13;
  end;

  html := html
    + 'border:' + IntToStr(BorderWidth) + 'px solid ' + ColorToRGBString(BorderColor) + ';'#13;

  if (not IsBrowserIE(AContext)) then
  begin
    html := html
      + '-webkit-border-radius: ' + IntToStr(RoundedBorderRadius) + 'px;'#13
      + '-moz-border-radius: ' + IntToStr(RoundedBorderRadius) + 'px;'#13
      + 'border-radius: ' + IntToStr(RoundedBorderRadius) + 'px;'#13;
  end;

  html := html
    + '}'#13

    + '#' + HTMLName + 'Caption {'#13;

  if (not IsBrowserIE(AContext)) then
  begin
    html := html
      + '-webkit-border-top-left-radius: ' + IntToStr(RoundedBorderRadius - 3) + 'px;'#13
      + '-webkit-border-top-right-radius: ' + IntToStr(RoundedBorderRadius - 3) + 'px;'#13
      + '-moz-border-radius-topleft: ' + IntToStr(RoundedBorderRadius - 3) + 'px;'#13
      + '-moz-border-radius-topright: ' + IntToStr(RoundedBorderRadius - 3) + 'px;'#13
      + 'border-top-left-radius: ' + IntToStr(RoundedBorderRadius - 3) + 'px;'#13
      + 'border-top-right-radius: ' + IntToStr(RoundedBorderRadius - 3) + 'px;'#13;
  end;

  html := html
    + 'padding:7px;'#13
    + 'height:20px;'#13
    + GradientStyle(CaptionBGColor,CaptionBGColor,CaptionBGColorTo,clNone,CaptionGradientDirection,AContext,true) + #13
    + 'border-bottom:1px solid ' + ColorToRGBString(CaptionBorderColor) + ';'#13
    + 'cursor:default;'#13
    + '}'#13

    + '#' + HTMLName + 'Content {'#13
    + 'padding:8px;'#13
    + GradientStyle(BGColor,BGColor,BGColorTo,clNone,BGGradientDirection,AContext,true) + #13
    + Font.FontToStringStyle(AContext.WebApplication.Browser) + #13
    + '}'#13

    + '#' + HTMLName + 'Buttons {'#13
    + GradientStyle(ButtonBarBGColor,ButtonBarBGColor,ButtonBarBGColorTo,clNone,ButtonBarGradientDirection,AContext,true) + #13
    + ButtonBarFont.FontToStringStyle(AContext.WebApplication.Browser) + #13
    + 'padding:10px;'#13
    + 'border-top:1px solid ' + ColorToRGBString(ButtonBarBorderColor) + ';'#13;

  if (not IsBrowserIE(AContext)) then
  begin
    html := html
      + '-webkit-border-bottom-left-radius: ' + IntToStr(RoundedBorderRadius) + 'px;'#13
      + '-webkit-border-bottom-right-radius: ' + IntToStr(RoundedBorderRadius) + 'px;'#13
      + '-moz-border-radius-bottomleft: ' + IntToStr(RoundedBorderRadius) + 'px;'#13
      + '-moz-border-radius-bottomright: ' + IntToStr(RoundedBorderRadius) + 'px;'#13
      + 'border-bottom-left-radius: ' + IntToStr(RoundedBorderRadius) + 'px;'#13
      + 'border-bottom-right-radius: ' + IntToStr(RoundedBorderRadius) + 'px;'#13;
  end;

  html := html
    + '}'#13

    + '#' + HTMLName + 'Buttons table {'#13
    + ButtonBarFont.FontToStringStyle(AContext.WebApplication.Browser) + #13
    + '}'#13

    + '#' + HTMLName + 'Buttons input{'#13;

    if (IsBrowserIE(AContext)) then
      html := html + 'width:85px;'#13
    else
      html := html + 'min-width:85px;'#13;

    html := html
    + 'height:24px;'#13
    //IE fix: autosize buttons with a long caption text
    + 'overflow:visible;'#13
    + '}'#13

    + '#' + HTMLName + 'Caption table{'#13
    + 'width:100%;'#13
    + CaptionFont.FontToStringStyle(AContext.WebApplication.Browser) + #13
    + '}'#13

    + '#' + HTMLName + 'Close {'#13
    + 'display:inline;'#13
    + 'top:0px;'#13
    + 'float:right;'#13
    + 'color:' + ColorToRGBString(CloseButtonColor) + ';'#13
    + 'font-size:12pt;'#13
    + 'font-family:"Helvetica";'#13
    + 'font-weight:bold;'#13
    + 'cursor:hand;'#13
    + '}'#13

    + '.' + HTMLName + 'Input{'#13
    + 'width:100%;'#13
    + 'color:#999;'#13
    + '}'#13

    + '.' + HTMLName + 'InputF{'#13
    + 'width:100%;'#13
    + 'color:black;'#13
    + '}'#13;

//  if ContentRegion <> nil then
//  begin
    html := html
//      + '#' + HTMLName + 'Region {'#13
//      + 'height:' + IntToStr(ContentRegion.Height) + 'px;'#13
//      + 'width:' + IntToStr(ContentRegion.Width) + 'px;'#13
//      + '}'#13
      + '#' + HTMLName + 'ContentRegion {'#13
      + 'position:relative;'#13
      + 'width:100%;'#13
      + 'height:100%;'#13
      + '}'#13;
//  end;

  html := html
    + '</style>'#13;

  html := html
    + '<div id="' + HTMLName + 'Overlay" onclick="' + HTMLName + 'Focus();"></div>'#13
    + '<div id="' + HTMLName+ 'Temp" style="display:none;"></div>'#13
    + '<div id="' + HTMLName + 'Wrapper" class="drag">'#13
    + '<div id="' + HTMLName + 'Dialog" tabindex="-1"';

  if WantsEscape then
  html := html + ' onkeydown="' + HTMLName + 'KeyPress(event)"';

  html := html
    + '>'#13
    + RenderDialog
    + '</div>'#13
    + '</div>'#13;

  Align := alClient;

  Result := TIWHTMLTag.CreateTag('DIV');
  if not ShowDialog then
    Result.AddStringParam('style', 'display:none;')
  else
    Result.AddStringParam('style', 'visibility:visible;');


  Result.Contents.AddText(html);

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

end;

procedure TTIWAdvMessageDialog.SetButtonBarFont(const Value: TIWFont);
begin
  FButtonBarFont.Assign(Value);
end;

procedure TTIWAdvMessageDialog.SetCaption(const Value: string);
begin
  FCaption := Value;
  Invalidate;
end;

procedure TTIWAdvMessageDialog.SetCaptionFont(const Value: TIWFont);
begin
  FCaptionFont.Assign(Value);
end;

procedure TTIWAdvMessageDialog.SetShowCloseButton(const Value: boolean);
begin
  FShowCloseButton := Value;
  Invalidate;
end;

procedure TTIWAdvMessageDialog.SetShowDialog(const Value: boolean);
begin
  FShowDialog := Value;
  Invalidate;
end;

procedure TTIWAdvMessageDialog.SetCloseButtonHint(const Value: string);
begin
  FCloseButtonHint := Value;
  Invalidate;
end;

procedure TTIWAdvMessageDialog.SetCollapseControlHint(const Value: string);
begin
  FCollapseControlHint := Value;
  Invalidate;
end;

procedure TTIWAdvMessageDialog.SetCollapseControlText(const Value: string);
begin
  FCollapseControlText := Value;
  Invalidate;
end;

procedure TTIWAdvMessageDialog.SetCommonButtons(const Value: TIWCommonButtons);
begin
  FCommonButtons := Value;
  Invalidate;
end;

procedure TTIWAdvMessageDialog.SetContentRegion(const Value: TIWCustomRegion);
begin
  FContentRegion := Value;
  Invalidate;
end;

procedure TTIWAdvMessageDialog.SetCustomButtons(const Value: TStringList);
begin
  FCustomButtons.Assign(Value);
  Invalidate;
end;

procedure TTIWAdvMessageDialog.SetDefaultButton(const Value: integer);
begin
  FDefaultButton := Value;
  Invalidate;
end;

procedure TTIWAdvMessageDialog.SetEmptyText(const Value: string);
begin
  FEmptyText := Value;
  Invalidate;
end;

procedure TTIWAdvMessageDialog.SetEnableDragging(const Value: boolean);
begin
  FEnableDragging := Value;
  Invalidate;
end;

procedure TTIWAdvMessageDialog.SetExpandControlHint(const Value: string);
begin
  FExpandControlHint := Value;
  Invalidate;
end;

procedure TTIWAdvMessageDialog.SetExpandControlText(const Value: string);
begin
  FExpandControlText := Value;
  Invalidate;
end;

procedure TTIWAdvMessageDialog.SetExpandedText(const Value: string);
begin
  FExpandedText := Value;
  Invalidate;
end;

procedure TTIWAdvMessageDialog.SetFont(const Value: TIWFont);
begin
  FFont.Assign(Value);
end;

procedure TTIWAdvMessageDialog.SetInputCheck(const Value: boolean);
begin
  FInputCheck := Value;
  Invalidate;
end;

procedure TTIWAdvMessageDialog.SetInputString(const Value: string);
begin
  FInputString := Value;
  Invalidate;
end;

procedure TTIWAdvMessageDialog.SetInputType(const Value: TIWInputType);
begin
  FInputType := Value;
  Invalidate;
end;

procedure TTIWAdvMessageDialog.SetNotes(const Value: string);
begin
  FNotes := Value;
  Invalidate;
end;

procedure TTIWAdvMessageDialog.SetOverlayOpacity(const Value: integer);
begin
  if (Value >= 0) and (Value <= 10) then
    FOverlayOpacity := Value;
  Invalidate;
end;

procedure TTIWAdvMessageDialog.SetPositionControl(const Value: TIWCustomControl);
begin
  FPositionControl := Value;
  Invalidate;
end;

procedure TTIWAdvMessageDialog.SetShowVerificationCheckBox(
  const Value: boolean);
begin
  FShowVerificationCheckBox := Value;
  Invalidate;
end;

procedure TTIWAdvMessageDialog.SetValue(const AValue: string);
var
  posval, val1: integer;
  buttonindex, checkbox: string;
begin
  inherited;
  if AValue <> EmptyStr then
  begin
    posval := pos('^index:', AValue);
    if posval > 0 then
    begin
      val1 := pos('^input1', AValue);
      posval := posval + 7;
      buttonindex := Copy(AValue, posval, val1 - posval);
      if Length(buttonindex) > 0 then
        FButtonIndex := StrToInt(buttonindex);
    end;

    posval := pos('^input1:', AValue);
    if posval > 0 then
    begin
      val1 := pos('^input2', AValue);
      posval := posval + 8;
      FInputString := Copy(AValue, posval, val1 - posval);
    end;

    posval := pos('^input2:', AValue);
    if posval > 0 then
    begin
      val1 := pos('^inputC', AValue);
      posval := posval + 8;
      FInputPassword := Copy(AValue, posval, val1 - posval);
    end;

    posval := pos('^inputC:', AValue);
    if posval > 0 then
    begin
      val1 := pos('^isvisible', AValue);
      posval := posval + 8;
      checkbox := Copy(AValue, posval, val1 - posval);
      if Length(checkbox) > 0 then
        InputCheck := StrToBool(checkbox);
    end;

    posval := pos('^isvisible:', AValue);
    if posval > 0 then
    begin
      val1 := pos('^cb', AValue);
      posval := posval + 11;
      if Copy(AValue, posval, val1 - posval) = 'true' then
        ShowDialog := true
      else
        ShowDialog := false;
    end;

    posval := pos('^cb:', AValue);
    if posval > 0 then
    begin
      val1 := Length(AValue) + 1;
      posval := posval + 4;
      checkbox := Copy(AValue, posval, val1 - posval);
      if Length(checkbox) > 0 then
        VerificationCheckBoxChecked := StrToBool(checkbox);
    end;
  end;
end;

procedure TTIWAdvMessageDialog.SetVerificationCheckBoxChecked(
  const Value: boolean);
begin
  FVerificationCheckBoxChecked := Value;
  Invalidate;
end;

procedure TTIWAdvMessageDialog.SetVerificationText(const Value: string);
begin
  FVerificationText := Value;
  Invalidate;
end;

procedure TTIWAdvMessageDialog.SetWantsEscape(const Value: boolean);
begin
  FWantsEscape := Value;
  Invalidate;
end;

procedure TTIWAdvMessageDialog.Show;
begin
  AsyncUpdateRequired := true;
  ShowDialog := true;
  Invalidate;
end;

procedure TTIWAdvMessageDialog.ShowAsync;
begin
  Show;
end;

procedure TTIWAdvMessageDialog.Hide;
begin
  AsyncUpdateRequired := true;
  ShowDialog := false;
  Invalidate;
end;

procedure TTIWAdvMessageDialog.HideAsync;
begin
  Hide;
end;

procedure TTIWAdvMessageDialog.Submit(const AValue: string);
var
  Allow: boolean;
begin
  inherited;
  Allow := true;

  if Assigned(OnButtonClick) then
  begin
    OnButtonClick(Self, FButtonIndex, FInputString, FInputPassword, FInputCheck, Allow);

    if Allow then
      ShowDialog := False
    else
      ShowDialog := True;

  end;
end;

end.

