mirror of
https://gitlab.com/freepascal.org/fpc/pas2js.git
synced 2025-04-06 02:27:48 +02:00

------------------------------------------------------------------------ r941 | svenbarth | 2020-11-13 16:02:27 +0100 (Fri, 13 Nov 2020) | 1 line * TStack<>.TrimExcess should override TCustomList<>.TrimExcess ------------------------------------------------------------------------ r942 | svenbarth | 2020-11-15 12:26:08 +0100 (Sun, 15 Nov 2020) | 1 line * fix compilation of Tetris demo ------------------------------------------------------------------------ r950 | michael | 2020-11-24 15:59:49 +0100 (Tue, 24 Nov 2020) | 1 line * Added rendercolumn, so columns can be disabled ------------------------------------------------------------------------ r951 | michael | 2020-11-25 12:15:19 +0100 (Wed, 25 Nov 2020) | 1 line * Add Focus and ReplaceClasses/AddRemoveClasses ------------------------------------------------------------------------ r952 | michael | 2020-11-27 09:41:43 +0100 (Fri, 27 Nov 2020) | 1 line * Make creation of data-tags optional ------------------------------------------------------------------------ r953 | michael | 2020-11-27 17:12:43 +0100 (Fri, 27 Nov 2020) | 1 line * Correct options objects ------------------------------------------------------------------------
3187 lines
80 KiB
ObjectPascal
3187 lines
80 KiB
ObjectPascal
{
|
|
This file is part of the Free Pascal run time library.
|
|
Copyright (c) 2019-Now by Michael Van Canneyt, member of the
|
|
Free Pascal development team
|
|
|
|
WEB Widget Set : Basic bare HTML Widgets
|
|
|
|
See the file COPYING.FPC, included in this distribution,
|
|
for details about the copyright.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
**********************************************************************}
|
|
unit htmlwidgets;
|
|
|
|
{$mode objfpc}
|
|
|
|
interface
|
|
|
|
uses
|
|
Classes, SysUtils, webwidget, js, web;
|
|
|
|
Type
|
|
TTextMode = (tmText,tmHTML);
|
|
|
|
{ TButtonWidget }
|
|
|
|
TButtonWidget = Class(TWebWidget)
|
|
private
|
|
FText: String;
|
|
FTextMode: TTextMode;
|
|
procedure SetText(AValue: String);
|
|
procedure SetTextMode(AValue: TTextMode);
|
|
Protected
|
|
procedure ApplyText(aElement: TJSHTMLElement);
|
|
Procedure SetName(const NewName: TComponentName); override;
|
|
Procedure ApplyWidgetSettings(aElement: TJSHTMLElement); override;
|
|
Public
|
|
Procedure Click;
|
|
Function HTMLTag : String; override;
|
|
Published
|
|
Property Text : String Read FText Write SetText;
|
|
Property TextMode : TTextMode Read FTextMode Write SetTextMode;
|
|
end;
|
|
|
|
{ TViewPort }
|
|
|
|
TViewPort = Class(TCustomWebWidget)
|
|
Private
|
|
Class var FInstance : TViewPort;
|
|
Protected
|
|
Class Function FixedParent : TJSHTMLElement; override;
|
|
Class Function FixedElement : TJSHTMLElement; override;
|
|
Function DoRenderHTML(aParent,aElement : TJSHTMLElement) :TJSHTMLElement; override;
|
|
Public
|
|
Constructor Create (aOwner: TComponent); override;
|
|
Function HTMLTag : String; override;
|
|
Class Function Instance : TViewPort;
|
|
Property Element;
|
|
end;
|
|
|
|
{ TWebPage }
|
|
|
|
TWebPage = Class(TCustomWebWidget)
|
|
private
|
|
Protected
|
|
Class Function DefaultParentElement: TJSHTMLElement; override;
|
|
Class Function DefaultParent : TCustomWebWidget; override;
|
|
Procedure DoUnRender(aParent : TJSHTMLElement) ; override;
|
|
Public
|
|
Constructor Create(AOwner : TComponent); override;
|
|
Function HTMLTag : String; override;
|
|
// Later on, allow IFrame;
|
|
Published
|
|
Property ParentID;
|
|
Property ElementID;
|
|
Property Classes;
|
|
Property Styles;
|
|
Property StyleRefresh;
|
|
Property Visible;
|
|
// Events
|
|
Property BeforeRenderHTML;
|
|
Property AfterRenderHTML;
|
|
Property OnAbort;
|
|
Property OnAnimationCancel;
|
|
Property OnAnimationEnd;
|
|
Property OnAnimationIteration;
|
|
Property OnAnimationStart;
|
|
Property OnAuxClick;
|
|
Property OnBlur;
|
|
Property OnCancel;
|
|
Property OnCanPlay;
|
|
Property OnCanPlayThrough;
|
|
Property OnChange;
|
|
Property OnClick;
|
|
Property OnCompositionEnd;
|
|
Property OnCompositionStart;
|
|
Property OnCompositionUpdate;
|
|
Property OnContextMenu;
|
|
Property OnCopy;
|
|
Property OnCut;
|
|
Property OnCueChange;
|
|
Property OnDblClick;
|
|
Property OnDurationChange;
|
|
Property OnEnded ;
|
|
Property OnError ;
|
|
Property OnFocus;
|
|
Property OnFocusIn ;
|
|
Property OnFocusOut ;
|
|
Property OnGotPointerCapture;
|
|
Property OnInput;
|
|
Property OnInvalid;
|
|
Property OnKeyDown;
|
|
Property OnKeyPress;
|
|
Property OnKeyUp;
|
|
Property OnLoad;
|
|
Property OnLoadedData;
|
|
Property OnLoadedMetaData;
|
|
Property OnLoadend;
|
|
Property OnLoadStart;
|
|
Property OnLostPointerCapture;
|
|
Property OnMouseDown;
|
|
Property OnMouseEnter;
|
|
Property OnMouseLeave;
|
|
Property OnMouseMove;
|
|
Property OnMouseOut;
|
|
Property OnMouseUp;
|
|
Property OnOverFlow;
|
|
Property OnPaste;
|
|
Property OnPause;
|
|
Property OnPlay;
|
|
Property OnPointerCancel;
|
|
Property OnPointerDown;
|
|
Property OnPointerEnter;
|
|
Property OnPointerLeave;
|
|
Property OnPointerMove;
|
|
Property OnPointerOut;
|
|
Property OnPointerOver;
|
|
Property OnPointerUp;
|
|
Property OnReset;
|
|
Property OnResize;
|
|
Property OnScroll;
|
|
Property OnSelect;
|
|
Property OnSubmit;
|
|
Property OnTouchStart;
|
|
Property OnTransitionCancel;
|
|
Property OnTransitionEnd;
|
|
Property OnTransitionRun;
|
|
Property OnTransitionStart;
|
|
Property OnWheel;
|
|
end;
|
|
|
|
{ TCustomInputWidget }
|
|
|
|
TCustomInputWidget = Class(TWebWidget)
|
|
private
|
|
FValue : String;
|
|
FValueName : String;
|
|
FText : String;
|
|
FReadOnly : Boolean;
|
|
FRequired : Boolean;
|
|
function GetReadOnly: Boolean;
|
|
function GetRequired: Boolean;
|
|
function GetText: String;
|
|
function GetValue: String;
|
|
function GetValueName: String;
|
|
procedure SetReadonly(AValue: Boolean);
|
|
procedure SetRequired(AValue: Boolean);
|
|
procedure SetText(AValue: String);
|
|
procedure SetValue(AValue: String);
|
|
function GetInputElement: TJSHTMLInputElement;
|
|
procedure SetValueName(AValue: String);
|
|
Protected
|
|
Procedure SetName(const NewName: TComponentName); override;
|
|
Procedure ApplyWidgetSettings(aElement: TJSHTMLElement); override;
|
|
Property InputElement : TJSHTMLInputElement Read GetInputElement;
|
|
// Text to show (checkbox etc). Enable in descendents as needed
|
|
Property Text : String Read GetText Write SetText;
|
|
Public
|
|
function InputType : String; virtual; abstract;
|
|
Function HTMLTag : String; override;
|
|
// Value as string
|
|
Property Value : String Read GetValue Write SetValue;
|
|
// Value Name to use when submitting using form.
|
|
Property ValueName : String Read GetValueName Write SetValueName;
|
|
Property ReadOnly : Boolean Read GetReadOnly Write SetReadonly;
|
|
Property Required : Boolean Read GetRequired Write SetRequired;
|
|
end;
|
|
|
|
{ TTextInputWidget }
|
|
|
|
TInputTextType = (ittText,ittPassword,ittNumber,ittEmail,ittSearch,ittTelephone,ittURL,ittColor);
|
|
TTextInputWidget = class(TCustomInputWidget)
|
|
private
|
|
FMaxLength : Integer;
|
|
FMinLength : Integer;
|
|
FTextType : TInputTextType;
|
|
function GetAsNumber: NativeInt;
|
|
function GetMaxLength: NativeInt;
|
|
function GetMinLength: NativeInt;
|
|
function GetTextType: TInputTextType;
|
|
procedure SetAsNumber(AValue: NativeInt);
|
|
procedure SetMaxLength(AValue: NativeInt);
|
|
procedure SetMinLength(AValue: NativeInt);
|
|
procedure SetTextType(AValue: TInputTextType);
|
|
Protected
|
|
Procedure ApplyWidgetSettings(aElement: TJSHTMLElement); override;
|
|
Public
|
|
Class Function AllowChildren : Boolean; override;
|
|
function InputType : String; override;
|
|
Published
|
|
Property Value;
|
|
Property ValueName;
|
|
Property Required;
|
|
Property TextType : TInputTextType Read GetTextType Write SetTextType;
|
|
property AsNumber : NativeInt Read GetAsNumber Write SetAsNumber;
|
|
Property MaxLength : NativeInt Read GetMaxLength Write SetMaxLength;
|
|
Property MinLength : NativeInt Read GetMinLength Write SetMinLength;
|
|
// Todo: List support
|
|
end;
|
|
|
|
|
|
{ TButtonInputWidget }
|
|
TInputButtonType = (ibtSubmit,ibtReset,ibtImage);
|
|
TInputButtonTypes = set of TInputButtonType;
|
|
|
|
TButtonInputWidget = class(TCustomInputWidget)
|
|
private
|
|
FButtonType: TInputButtonType;
|
|
FSrc: String;
|
|
procedure SetButtonType(AValue: TInputButtonType);
|
|
procedure SetSrc(AValue: String);
|
|
Public
|
|
Procedure ApplyWidgetSettings(aElement: TJSHTMLElement); override;
|
|
function InputType : String; override;
|
|
Class Function AllowChildren : Boolean; override;
|
|
Published
|
|
Property ButtonType : TInputButtonType Read FButtonType Write SetButtonType;
|
|
Property Value;
|
|
Property ValueName;
|
|
Property Src : String Read FSrc Write SetSrc;
|
|
end;
|
|
|
|
{ TCheckableInputWidget }
|
|
|
|
TCheckableInputWidget = class(TCustomInputWidget)
|
|
private
|
|
FChecked: Boolean;
|
|
function GetChecked: Boolean;
|
|
procedure SetChecked(AValue: Boolean);
|
|
Protected
|
|
Procedure ApplyWidgetSettings(aElement: TJSHTMLElement); override;
|
|
Public
|
|
Property Value;
|
|
Property ValueName;
|
|
Property Checked : Boolean Read GetChecked Write SetChecked;
|
|
Property Text;
|
|
end;
|
|
|
|
{ TRadioInputWidget }
|
|
|
|
TRadioInputWidget = class(TCheckableInputWidget)
|
|
private
|
|
Public
|
|
function InputType : String; override;
|
|
Published
|
|
Property Value;
|
|
Property ValueName;
|
|
Property Checked;
|
|
Property Text;
|
|
end;
|
|
|
|
{ TCheckboxInputWidget }
|
|
|
|
TCheckboxInputWidget = class(TCheckableInputWidget)
|
|
private
|
|
Public
|
|
function InputType : String; override;
|
|
Published
|
|
Property Value;
|
|
Property ValueName;
|
|
Property Checked;
|
|
Property Text;
|
|
end;
|
|
|
|
|
|
{ TDateInputWidget }
|
|
|
|
TDateInputWidget = class(TCustomInputWidget)
|
|
private
|
|
FDate: TDateTime;
|
|
function GetDate: TDateTime;
|
|
procedure SetDate(AValue: TDateTime);
|
|
Public
|
|
function InputType : String; override;
|
|
Class Function AllowChildren : Boolean; override;
|
|
Published
|
|
Property Required;
|
|
Property ValueName;
|
|
Property Date : TDateTime Read GetDate Write SetDate;
|
|
end;
|
|
|
|
{ TFileInputWidget }
|
|
TFileInfo = record
|
|
Name : String;
|
|
TimeStamp : TDateTime;
|
|
FileType : String;
|
|
Size : NativeInt;
|
|
end;
|
|
|
|
TFileInputWidget = class(TCustomInputWidget)
|
|
private
|
|
FMultiple: Boolean;
|
|
function GetFileCount: Integer;
|
|
function GetFileDate(aIndex : Integer): TDateTime;
|
|
function GetFileInfo(aIndex : Integer): TFileInfo;
|
|
function GetFileName(aIndex : Integer): String;
|
|
function GetFileSize(aIndex : Integer): NativeInt;
|
|
function GetFileType(aIndex : Integer): String;
|
|
function GetMultiple: Boolean;
|
|
procedure SetMultiple(AValue: Boolean);
|
|
Protected
|
|
Procedure ApplyWidgetSettings(aElement: TJSHTMLElement); override;
|
|
Public
|
|
Class Function AllowChildren : Boolean; override;
|
|
function InputType : String; override;
|
|
Property FileCount : Integer read GetFileCount;
|
|
Property Files[aIndex : Integer] : String Read GetFileName;
|
|
Property FileSizes[aIndex : Integer] : NativeInt Read GetFileSize;
|
|
Property FileTypes[aIndex : Integer] : String Read GetFileType;
|
|
Property FileDates[aIndex : Integer] : TDateTime Read GetFileDate;
|
|
Property FileInfos[aIndex : Integer] : TFileInfo Read GetFileInfo;
|
|
Published
|
|
Property ValueName;
|
|
Property Required;
|
|
Property Multiple : Boolean Read GetMultiple Write SetMultiple;
|
|
end;
|
|
|
|
{ THiddenInputWidget }
|
|
|
|
THiddenInputWidget = class(TCustomInputWidget)
|
|
Public
|
|
Class Function AllowChildren : Boolean; override;
|
|
function InputType : String; override;
|
|
Published
|
|
Property ValueName;
|
|
Property Value;
|
|
Property Required;
|
|
end;
|
|
|
|
{ TTextAreaWidget }
|
|
|
|
TTextAreaWrap = (tawSoft,tawHard,tawOff);
|
|
TTextAreaWidget = Class(TWebWidget)
|
|
private
|
|
FLines: TStrings;
|
|
FIgnoreChanges : Boolean;
|
|
FMaxLength: Cardinal;
|
|
FValueName : String;
|
|
FRows,
|
|
FColumns : Cardinal;
|
|
FWrap: TTextAreaWrap;
|
|
FRequired,
|
|
FReadOnly : Boolean;
|
|
procedure ApplyWrap(aElement: TJSHTMLTextAreaElement);
|
|
procedure DoLineChanges(Sender: TObject);
|
|
function GetColumns: Cardinal;
|
|
function GetLines: TStrings;
|
|
function GetReadOnly: Boolean;
|
|
function GetRequired: Boolean;
|
|
function GetRows: Cardinal;
|
|
function GetText: String;
|
|
function GetValueName: string;
|
|
procedure SetColumns(AValue: Cardinal);
|
|
procedure SetLines(AValue: TStrings);
|
|
procedure SetMaxLength(AValue: Cardinal);
|
|
procedure SetReadonly(AValue: Boolean);
|
|
procedure SetRequired(AValue: Boolean);
|
|
procedure SetRows(AValue: Cardinal);
|
|
procedure SetText(AValue: String);
|
|
procedure SetValueName(AValue: string);
|
|
Function GetTextArea : TJSHTMLTextAreaElement;
|
|
procedure SetWrap(AValue: TTextAreaWrap);
|
|
Protected
|
|
procedure ApplyLines(aElement: TJSHTMLTextAreaElement);
|
|
procedure LinesFromHTML(aHTML : String);
|
|
Procedure SetName(const NewName: TComponentName); override;
|
|
Procedure ApplyWidgetSettings(aElement: TJSHTMLElement); override;
|
|
Property TextArea :TJSHTMLTextAreaElement Read GetTextArea;
|
|
Public
|
|
Constructor Create(aOwner : TComponent); override;
|
|
Destructor Destroy; override;
|
|
Class Function AllowChildren : Boolean; override;
|
|
Function HTMLTag : String; override;
|
|
Property InnerHTML : String Read GetText Write SetText;
|
|
Published
|
|
Property ValueName : string Read GetValueName Write SetValueName;
|
|
Property Rows : Cardinal Read GetRows Write SetRows;
|
|
Property Columns : Cardinal Read GetColumns Write SetColumns;
|
|
Property Lines : TStrings Read GetLines Write SetLines;
|
|
Property MaxLength : Cardinal Read FMaxLength Write SetMaxLength;
|
|
Property Wrap : TTextAreaWrap Read FWrap Write SetWrap;
|
|
Property ReadOnly : Boolean Read GetReadOnly Write SetReadonly;
|
|
Property Required : Boolean Read GetRequired Write SetRequired;
|
|
end;
|
|
|
|
{ TImageWidget }
|
|
|
|
TImageWidget = class(TWebWidget)
|
|
private
|
|
FHeight: Integer;
|
|
FWidth: Integer;
|
|
FSrc : String;
|
|
function GetHeight: Integer;
|
|
function GetImg: TJSHTMLImageElement;
|
|
function GetSrc: String;
|
|
function GetWidth: Integer;
|
|
procedure SetHeight(AValue: Integer);
|
|
procedure SetSrc(AValue: String);
|
|
procedure SetWidth(AValue: Integer);
|
|
Protected
|
|
Procedure ApplyWidgetSettings(aElement: TJSHTMLElement); override;
|
|
Property ImgElement : TJSHTMLImageElement Read GetImg;
|
|
Public
|
|
Function HTMLTag : String; override;
|
|
Published
|
|
Property Src : String Read GetSrc Write SetSrc;
|
|
Property Width : Integer Read GetWidth Write SetWidth;
|
|
Property Height : Integer Read GetHeight Write SetHeight;
|
|
end;
|
|
|
|
{ TSelectWidget }
|
|
|
|
TJSHTMLOptionElementArray = Array of TJSHTMLOptionElement;
|
|
TCustomSelectWidget = Class;
|
|
|
|
|
|
{ TCustomSelectWidget }
|
|
|
|
TCustomSelectWidget = class(TWebWidget)
|
|
Private
|
|
FSize,
|
|
FSelectedIndex : Integer;
|
|
FOptions : TJSHTMLOptionElementArray;
|
|
FMultiple : Boolean;
|
|
function GetMultiple: Boolean;
|
|
function GetSelected(Index : Integer): Boolean;
|
|
function GetSelectedIndex: Integer;
|
|
function GetSelect: TJSHTMLSelectElement;
|
|
function GetSelectionCount: Integer;
|
|
function GetSelectionItem(aIndex : Integer): String;
|
|
function GetSelectionValue(aIndex : Integer): String;
|
|
function GetSize: Integer;
|
|
procedure SetMultiple(AValue: Boolean);
|
|
procedure SetSelected(Index : Integer; AValue: Boolean);
|
|
procedure SetSelectedIndex(AValue: Integer);
|
|
procedure SetSize(AValue: Integer);
|
|
Protected
|
|
Type
|
|
{ TSelectOptionEnumerator }
|
|
TSelectOptionEnumerator = Class
|
|
private
|
|
FSelect: TCustomSelectWidget;
|
|
public
|
|
constructor Create(ASelect : TCustomSelectWidget); reintroduce; virtual;
|
|
Function OptionText : String; virtual; abstract;
|
|
Function HasValue : boolean; virtual;
|
|
Function Value : string; virtual;
|
|
function MoveNext: Boolean; virtual; abstract;
|
|
Property Select: TCustomSelectWidget Read FSelect;
|
|
end;
|
|
Protected
|
|
function GetItemCount: Integer; virtual;
|
|
Function CreateOptionEnumerator : TSelectOptionEnumerator; virtual; abstract;
|
|
Procedure ApplyWidgetSettings(aElement: TJSHTMLElement); override;
|
|
Procedure BuildOptions(aSelect : TJSHTMLSelectElement); virtual;
|
|
Property Options : TJSHTMLOptionElementArray Read Foptions;
|
|
Property SelectElement : TJSHTMLSelectElement Read GetSelect;
|
|
Protected
|
|
// Can be made public/published
|
|
// Items that are selected
|
|
Property ItemCount : Integer Read GetItemCount;
|
|
Property Selected[Index : Integer] : Boolean Read GetSelected Write SetSelected;
|
|
Property SelectionCount : Integer Read GetSelectionCount;
|
|
Property SelectionValue[aIndex : Integer] : String Read GetSelectionValue;
|
|
Property SelectionItem[aIndex : Integer] : String Read GetSelectionItem;
|
|
property SelectedIndex : Integer Read GetSelectedIndex Write SetSelectedindex;
|
|
Property Multiple : Boolean Read GetMultiple Write SetMultiple;
|
|
Property Size : Integer Read GetSize Write SetSize;
|
|
Public
|
|
Constructor Create(aOWner : TComponent); override;
|
|
Function HTMLTag : String; override;
|
|
end;
|
|
|
|
TSelectWidget = class(TCustomSelectWidget)
|
|
private
|
|
FItems : TStrings;
|
|
FValues : TStrings;
|
|
function GetItems: TStrings;
|
|
function GetValues: TStrings;
|
|
procedure OptionsChanged(Sender: TObject);
|
|
procedure setItems(AValue: TStrings);
|
|
procedure setValues(AValue: TStrings);
|
|
Protected
|
|
Type
|
|
{ TStringsSelectOptionEnumerator }
|
|
TStringsSelectOptionEnumerator = Class(TSelectOptionEnumerator)
|
|
FCurrent : Integer;
|
|
constructor Create(ASelect : TCustomSelectWidget); override;
|
|
Function OptionText : String; override;
|
|
Function HasValue : boolean; override;
|
|
Function Value : string; override;
|
|
function MoveNext: Boolean; override;
|
|
end;
|
|
Function CreateOptionEnumerator: TSelectOptionEnumerator; override;
|
|
Public
|
|
Constructor Create(aOWner : TComponent); override;
|
|
Destructor Destroy; override;
|
|
Property SelectionCount;
|
|
Property SelectionValue;
|
|
Property SelectionItem;
|
|
Property Selected;
|
|
Property Options;
|
|
Property SelectElement;
|
|
Property ItemCount;
|
|
Published
|
|
Property Items : TStrings Read GetItems Write setItems;
|
|
Property Values : TStrings Read GetValues Write setValues;
|
|
property SelectedIndex;
|
|
Property Multiple;
|
|
property size;
|
|
property Classes;
|
|
end;
|
|
|
|
{ TLabelWidget }
|
|
|
|
TLabelWidget = Class(TWebWidget)
|
|
private
|
|
FLabelFor: TWebWidget;
|
|
FText: String;
|
|
function GetLabelEl: TJSHTMLLabelElement;
|
|
function GetText: String;
|
|
procedure SetLabelFor(AValue: TWebWidget);
|
|
procedure SetText(AValue: String);
|
|
Protected
|
|
procedure ApplyLabelFor(aLabelElement: TJSHTMLLabelElement);
|
|
Procedure Notification(AComponent: TComponent; Operation: TOperation); override;
|
|
Procedure SetName(const NewName: TComponentName); override;
|
|
Procedure ApplyWidgetSettings(aElement: TJSHTMLElement); override;
|
|
Property LabelElement : TJSHTMLLabelElement Read GetLabelEl;
|
|
Public
|
|
Function HTMLTag : String; override;
|
|
Property Text : String Read GetText Write SetText;
|
|
Property LabelFor : TWebWidget Read FLabelFor Write SetLabelFor;
|
|
end;
|
|
|
|
TTextTag = (ttParagraph,ttBold,ttItalic,ttUnderline,ttStrikeThrough,ttSpan,ttQuote,ttBlockQuote,ttH1,ttH2,ttH3,ttH4,ttH5,ttH6,ttPre,ttRuby,ttArticle,ttAddress,ttAbbr,ttCustom);
|
|
|
|
{ TTextWidget }
|
|
|
|
{ TCustomTextWidget }
|
|
|
|
TCustomTextWidget = Class(TCustomWebWidget)
|
|
private
|
|
FCustomTag: String;
|
|
FEnvelopeTag: TTextTag;
|
|
FTextMode: TTextMode;
|
|
procedure SetCustomTag(AValue: String);
|
|
procedure SetEnvelopeTag(AValue: TTextTag);
|
|
procedure SetTextMode(AValue: TTextMode);
|
|
Protected
|
|
procedure ApplyWidgetSettings(aElement: TJSHTMLElement); override;
|
|
procedure ApplyText(aElement : TJSHTMLElement); virtual;
|
|
Function GetText : String; virtual; abstract;
|
|
Public
|
|
Function HTMLTag : String; override;
|
|
Published
|
|
Property CustomTag : String Read FCustomTag Write SetCustomTag;
|
|
Property EnvelopeTag : TTextTag Read FEnvelopeTag Write SetEnvelopeTag;
|
|
Property TextMode : TTextMode Read FTextMode Write SetTextMode;
|
|
end;
|
|
|
|
TTextWidget = Class(TCustomTextWidget)
|
|
private
|
|
FText : String;
|
|
procedure SetText(AValue: String);
|
|
Protected
|
|
Function GetText : String; override;
|
|
published
|
|
Property Text : String Read FText Write SetText;
|
|
end;
|
|
|
|
{ TTextLinesWidget }
|
|
|
|
TTextLinesWidget = Class(TCustomTextWidget)
|
|
private
|
|
FLines : TStrings;
|
|
FForceLineBreaks: Boolean;
|
|
procedure DoLinesChanged(Sender: TObject);
|
|
procedure SetLines(AValue: TStrings);
|
|
procedure SetForceLineBreaks(AValue: Boolean);
|
|
Protected
|
|
Function GetText : String; override;
|
|
procedure ApplyText(aElement : TJSHTMLElement); override;
|
|
Public
|
|
Constructor Create(aOwner : TComponent); override;
|
|
Destructor Destroy; override;
|
|
published
|
|
Property Lines : TStrings Read FLines Write SetLines;
|
|
// When forcelinebreaks is true a <br> will be appended to every line.
|
|
// Note that for TextMode=tmText this means the lines will be rendered as-is, but there will still be a <br> between the lines
|
|
Property ForceLineBreaks : Boolean Read FForceLineBreaks Write SetForceLineBreaks;
|
|
end;
|
|
|
|
{ TCustomTableColumn }
|
|
TColumnOption = (coHeader,coCaptionHeader);
|
|
TColumnOptions = set of TColumnOption;
|
|
|
|
TCustomTableColumn = Class(TCollectionItem)
|
|
private
|
|
FAlignment: TAlignment;
|
|
FCaption: String;
|
|
FClassNames: String;
|
|
procedure SetAlignment(AValue: TAlignment);
|
|
procedure SetCaption(AValue: String);
|
|
procedure SetClassNames(AValue: String);
|
|
Protected
|
|
Function RenderColumn : Boolean; virtual;
|
|
Function GetDisplayName: string; override;
|
|
function GetCaption: String; virtual;
|
|
Public
|
|
Procedure Assign(Source : TPersistent); override;
|
|
Property Alignment : TAlignment Read FAlignment Write SetAlignment;
|
|
Property Caption : String Read GetCaption Write SetCaption;
|
|
Property ClassNames : String Read FClassNames Write SetClassNames;
|
|
end;
|
|
|
|
{ TCustomTableColumns }
|
|
|
|
TCustomTableColumns = Class(TCollection)
|
|
private
|
|
function GetCustomColumn(Index : Integer): TCustomTableColumn;
|
|
procedure SetCustomColumn(Index : Integer; AValue: TCustomTableColumn);
|
|
Protected
|
|
Property CustomColumns [Index : Integer] : TCustomTableColumn Read GetCustomColumn Write SetCustomColumn; default;
|
|
Public
|
|
Function Add(aCaption : String): TCustomTableColumn; overload;
|
|
end;
|
|
|
|
{ TCustomTableWidget }
|
|
TTableOption = (toHeader, // use THead tag
|
|
toHeaderRow, // Create header row
|
|
toBody, // use TBody tag
|
|
toFooter, // use TFoot tag
|
|
toFooterRow, // create footer row
|
|
toRowID, // add ID to tr: -kind-row
|
|
toCellID, // add ID to cell td: -kind-row-col
|
|
toHeaderRowData, // Add rowno to <tr data-row> for header.
|
|
toHeaderCellDataRow, // Add rowno to <th data-row> for header. Automatic if onheadercellclick is set.
|
|
toHeaderCellDataCol, // Add colno to <th data-col> for header. Automatic if onheadercellclick is set.
|
|
toBodyRowData, // Add rowno to <tr data-row> for body.
|
|
toBodyCellDataRow, // Add rowno to <th data-row> for body. Automatic if oncellclick is set.
|
|
toBodyCellDataCol, // Add colno to <th data-col> for body. Automatic if oncellclick is set.
|
|
tofooterRowData, // Add rowno to <tr data-row> for footer
|
|
tofooterCellDataRow, // Add rowno to <th data-row> for footer. Automatic if onfootercellclick is set.
|
|
tofooterCellDataCol // Add colno to <th data-col> for footer. Automatic if onfootercellclick is set.
|
|
);
|
|
TTableOptions = Set of TTableOption;
|
|
|
|
TRowKind = (rkHeader,rkBody,rkFooter);
|
|
|
|
Type
|
|
TCustomTableWidget = Class;
|
|
|
|
// Constructed only once when rendering !
|
|
{ TTableWidgetCelldata }
|
|
TTableWidgetCellData = Class
|
|
private
|
|
FAsHTML: Boolean;
|
|
FClassNames: String;
|
|
FCol: Integer;
|
|
FColumn: TCustomTableColumn;
|
|
FContent: TJSHTMLElement;
|
|
FKind: TRowKind;
|
|
FRow: Integer;
|
|
FTable: TCustomTableWidget;
|
|
FTableID: String;
|
|
FTag: String;
|
|
FText: String;
|
|
FWidget: TWebWidget;
|
|
Protected
|
|
Procedure SetRowColKind(aRow,aCol : Integer; aKind : TRowKind); virtual;
|
|
Procedure Reset; // do not reset row,col, column
|
|
Public
|
|
Constructor Create(aTable : TCustomTableWidget;aTableID : String); virtual;
|
|
Property Table : TCustomTableWidget Read FTable;
|
|
Property Column : TCustomTableColumn Read FColumn;
|
|
Property Row : Integer Read FRow;
|
|
Property Col : Integer Read FCol;
|
|
Property Kind : TRowKind Read FKind;
|
|
Property Tag : String Read FTag Write FTag;
|
|
Property ClassNames : String Read FClassNames Write FClassNames;
|
|
Property Text : String Read FText Write FText;
|
|
Property AsHTML : Boolean Read FAsHTML Write FAsHTML;
|
|
Property Content : TJSHTMLElement Read FContent Write FContent;
|
|
Property Widget : TWebWidget Read FWidget Write FWidget;
|
|
Property TableID : String Read FTableID;
|
|
end;
|
|
|
|
|
|
TTableRowEnumerator = Class
|
|
private
|
|
FTable: TCustomTableWidget;
|
|
FCurrent : Integer;
|
|
public
|
|
constructor Create(ATable : TCustomTableWidget); reintroduce; virtual;
|
|
Procedure GetCellData(aCell : TTableWidgetCellData); virtual;
|
|
function MoveNext: Boolean; virtual;
|
|
property CurrentRow : Integer Read FCurrent;
|
|
Property Table : TCustomTableWidget Read FTable;
|
|
end;
|
|
|
|
TTableRowCountEnumerator = Class (TTableRowEnumerator)
|
|
private
|
|
FRowCount: Integer;
|
|
public
|
|
constructor Create(ATable : TCustomTableWidget;aCount : Integer); reintroduce;
|
|
function MoveNext: Boolean; override;
|
|
Property RowCount : Integer read FRowCount;
|
|
end;
|
|
|
|
TOnCellDataEvent = Procedure (Sender : TObject; Enum : TTableRowEnumerator; aCell : TTableWidgetCellData) of object;
|
|
|
|
TCustomTableWidget = Class(TCustomWebWidget)
|
|
private
|
|
FCaption: String;
|
|
FColumns: TCustomTableColumns;
|
|
FOnCellClick: THTMLNotifyEvent;
|
|
FOnFooterCellClick: THTMLNotifyEvent;
|
|
FOnFooterRowClick: THTMLNotifyEvent;
|
|
FOnHeaderCellClick: THTMLNotifyEvent;
|
|
FOnHeaderRowClick: THTMLNotifyEvent;
|
|
FOnRowClick: THTMLNotifyEvent;
|
|
FTableOptions: TTableOptions;
|
|
FOnGetCellData : TOnCellDataEvent;
|
|
FWidgets : Array of TWebWidget;
|
|
FUpdateCount : Integer;
|
|
procedure SetCaption(AValue: String);
|
|
procedure SetColumns(AValue: TCustomTableColumns);
|
|
procedure SetTableOptions(AValue: TTableOptions);
|
|
Protected
|
|
procedure AppendCaption(aCaptionElement: TJSHTMLElement); virtual;
|
|
procedure RenderData(aElement: TJSHTMLElement); virtual;
|
|
function DoCellClick(aEvent: TJSMouseEvent): boolean; virtual;
|
|
function DoHeaderCellClick(aEvent: TJSMouseEvent): boolean;virtual;
|
|
function DoFooterCellClick(aEvent: TJSMouseEvent): boolean;virtual;
|
|
function DoRowClick(aEvent: TJSMouseEvent): boolean; virtual;
|
|
function DoHeaderRowClick(aEvent: TJSMouseEvent): boolean;virtual;
|
|
function DoFooterRowClick(aEvent: TJSMouseEvent): boolean;virtual;
|
|
function CreateColumns: TCustomTableColumns; virtual;
|
|
Function DefaultTableOptions: TTableOptions; virtual;
|
|
Procedure CreateDefaultColumns; virtual;
|
|
Function GetRowEnumerator(aKind : TRowKind) : TTableRowEnumerator; virtual;
|
|
function RenderCell(aCell: TTableWidgetCellData): TJSHTMLElement; virtual;
|
|
procedure RenderRow(aEnum : TTableRowEnumerator; aParent: TJSHTMLElement; aKind: TRowKind; aCell: TTableWidgetCellData); virtual;
|
|
procedure RenderRows(aParent: TJSHTMLElement; aKind : TRowKind; aCell: TTableWidgetCellData); virtual;
|
|
Procedure ApplyWidgetSettings(aElement : TJSHTMLElement); override;
|
|
Function HTMLTag : String; override;
|
|
Function CreateCellData(const aTableID : String) : TTableWidgetCellData; virtual;
|
|
Function GetBodyRowEnumerator : TTableRowEnumerator; virtual; abstract;
|
|
Protected
|
|
// These can be made public/published
|
|
Property CustomColumns : TCustomTableColumns Read FColumns Write SetColumns;
|
|
Property TableOptions : TTableOptions read FTableOptions write SetTableOptions;
|
|
Property Caption : String Read FCaption Write SetCaption;
|
|
Property OnGetCellData : TOnCellDataEvent Read FOnGetCellData Write FOnGetCellData;
|
|
Property OnCellClick : THTMLNotifyEvent Read FOnCellClick Write FOnCellClick;
|
|
Property OnHeaderCellClick : THTMLNotifyEvent Read FOnHeaderCellClick Write FOnHeaderCellClick;
|
|
Property OnFooterCellClick : THTMLNotifyEvent Read FOnFooterCellClick Write FOnFooterCellClick;
|
|
Property OnRowClick : THTMLNotifyEvent Read FOnRowClick Write FOnRowClick;
|
|
Property OnHeaderRowClick : THTMLNotifyEvent Read FOnHeaderRowClick Write FOnHeaderRowClick;
|
|
Property OnFooterRowClick : THTMLNotifyEvent Read FOnFooterRowClick Write FOnFooterRowClick;
|
|
Public
|
|
Constructor Create(aOwner : TComponent); override;
|
|
Destructor Destroy; override;
|
|
Procedure BeginUpdate;
|
|
Procedure EndUpdate;
|
|
Procedure RefreshBody;
|
|
end;
|
|
|
|
{ TEventTableWidget }
|
|
|
|
TEventTableWidget = Class(TCustomTableWidget)
|
|
private
|
|
FRowCount: Integer;
|
|
procedure SetRowCount(AValue: Integer);
|
|
Protected
|
|
Function GetBodyRowEnumerator : TTableRowEnumerator; override;
|
|
Published
|
|
Property RowCount : Integer Read FRowCount Write SetRowCount;
|
|
Property CustomColumns;
|
|
Property TableOptions;
|
|
Property Caption;
|
|
Property OnGetCellData;
|
|
Property OnCellClick;
|
|
Property OnHeaderCellClick;
|
|
Property OnFooterCellClick;
|
|
Property OnRowClick;
|
|
Property OnHeaderRowClick;
|
|
Property OnFooterRowClick;
|
|
end;
|
|
|
|
{ TCustomStringsTableWidget }
|
|
|
|
TCustomStringsTableWidget = Class(TCustomTableWidget)
|
|
private
|
|
Type
|
|
TRow = Array of string;
|
|
private
|
|
FRows : Array of TRow;
|
|
function GetRowCount: Integer;
|
|
procedure SetRowCount(AValue: Integer);
|
|
Protected
|
|
Type
|
|
TStringRowsEnumerator = Class(TTableRowCountEnumerator)
|
|
Procedure GetCellData(aCell : TTableWidgetCellData); override;
|
|
end;
|
|
Protected
|
|
Procedure CheckIndex(aCol,aRow : Integer);
|
|
function GetCell(aCol, aRow : integer): String;
|
|
procedure SetCell(aCol, aRow : integer; AValue: String);
|
|
Function GetBodyRowEnumerator : TTableRowEnumerator; override;
|
|
Public
|
|
Property RowCount : Integer Read GetRowCount Write SetRowCount;
|
|
Property Cells[aCol,aRow : integer] : String Read GetCell Write SetCell;
|
|
Property CustomColumns;
|
|
Property TableOptions;
|
|
Property Caption;
|
|
Property OnGetCellData;
|
|
Property OnCellClick;
|
|
Property OnHeaderCellClick;
|
|
Property OnFooterCellClick;
|
|
Property OnRowClick;
|
|
Property OnHeaderRowClick;
|
|
Property OnFooterRowClick;
|
|
end;
|
|
|
|
TStringsTableWidget = Class(TCustomStringsTableWidget)
|
|
Published
|
|
Property RowCount;
|
|
Property CustomColumns;
|
|
Property TableOptions;
|
|
Property Caption;
|
|
Property OnGetCellData;
|
|
Property OnCellClick;
|
|
Property OnHeaderCellClick;
|
|
Property OnFooterCellClick;
|
|
Property OnRowClick;
|
|
Property OnHeaderRowClick;
|
|
Property OnFooterRowClick;
|
|
end;
|
|
|
|
{ TDivWidget }
|
|
THTMLElementTag = (
|
|
etUnknown, eta, etabbr, etacronym, etaddress, etapplet, etarea, etb, etbase,
|
|
etbasefont, etbdo, etbig, etblockquote, etbody, etbr, etbutton,
|
|
etcaption, etcenter, etcite, etcode, etcol, etcolgroup, etdd, etdel,
|
|
etdfn, etdir, etdiv, etdl, etdt, etem, etfieldset, etfont, etform,
|
|
etframe, etframeset, eth1, eth2, eth3, eth4, eth5, eth6, ethead, ethr,
|
|
ethtml, eti, etiframe, etimg, etinput, etins, etisindex, etkbd, etlabel,
|
|
etlegend, etli, etlink, etmap, etmenu, etmeta, etnoframes, etnoscript,
|
|
etobject, etol, etoptgroup, etoption, etp, etparam, etpre, etq, ets,
|
|
etsamp, etscript, etselect, etsmall, etspan, etstrike, etstrong,
|
|
etstyle, etsub, etsup, ettable, ettbody, ettd, ettextarea, ettfoot,
|
|
etth, etthead, ettitle, ettr, ettt, etu, etul, etvar,
|
|
etText,etAudio,etVideo,etSource
|
|
);
|
|
THTMLElementTagSet = set of THTMLElementTag;
|
|
|
|
{ TCustomTagWidget }
|
|
|
|
TCustomTagWidget = Class(TWebWidget)
|
|
private
|
|
FElementTag: THTMLElementTag;
|
|
FTextContent: String;
|
|
procedure SetElementTag(AValue: THTMLElementTag);
|
|
procedure SetTextContent(AValue: String);
|
|
Protected
|
|
Procedure ApplyWidgetSettings(aElement: TJSHTMLElement); override;
|
|
Function HTMLTag : String; override;
|
|
// Set tag you wish to use
|
|
Property elementTag : THTMLElementTag Read FElementTag Write SetElementTag;
|
|
// If set, the text will be set as InnerText of the tag
|
|
Property TextContent : String Read FTextContent Write SetTextContent;
|
|
end;
|
|
|
|
{ TTagWidget }
|
|
|
|
TTagWidget = Class(TCustomTagWidget)
|
|
Public
|
|
Constructor Create(aOwner : TComponent); override;
|
|
Published
|
|
Property elementTag;
|
|
Property TextContent;
|
|
end;
|
|
|
|
TDivWidget = Class(TCustomTagWidget)
|
|
Public
|
|
Constructor Create(aOwner : TComponent); override;
|
|
end;
|
|
|
|
{ TParagraphWidget }
|
|
|
|
TParagraphWidget = Class(TCustomTagWidget)
|
|
Public
|
|
Constructor Create(aOwner : TComponent); override;
|
|
end;
|
|
|
|
{ TMediaWidget }
|
|
|
|
TMediaWidget = Class(TCustomTagWidget)
|
|
private
|
|
Const
|
|
MaxAttrs = 20;
|
|
PropAttrs : Array[0..MaxAttrs] of string
|
|
= ('src','defaultPlaybackRate','duration','playbackRate','ended', // 0..4
|
|
'paused','seeking','sinkId','mediaGroup','currentSrc', // 5..9
|
|
'volume','controls','autoplay','crossOrigin', 'defaultMuted', // 10..14
|
|
'currentTime', 'disableRemotePlayback', 'preservesPitch','loop','muted', // 15..19
|
|
'preload' // 20
|
|
);
|
|
|
|
function GetAudioTrack: TJSHTMLAudioTrackList;
|
|
function getBool(AIndex: Integer): Boolean;
|
|
function GetError: TJSMEdiaError;
|
|
function getFloat(AIndex: Integer): Double;
|
|
function GetSrcObj: TJSHTMLMediaStream;
|
|
function getString(AIndex: Integer): String;
|
|
function GetTextTrack: TJSHTMLTextTrackList;
|
|
function GetVideoTrack: TJSHTMLVideoTrackList;
|
|
procedure SetBool(AIndex: Integer; AValue: Boolean);
|
|
procedure SetFloat(AIndex: Integer; AValue: Double);
|
|
procedure SetString(AIndex: Integer; AValue: String);
|
|
function getEl: TJSObject;
|
|
Public
|
|
Property DefaultPlayBackRate : Double Index 1 Read getFloat;
|
|
Property Duration : Double Index 2 Read getFloat;
|
|
Property PlayBackRate : Double Index 3 Read getFloat;
|
|
Property Ended : Boolean Index 4 Read getBool;
|
|
Property Paused : Boolean Index 5 Read getBool;
|
|
Property Seeking : Boolean Index 6 Read getBool;
|
|
Property SinkID : String Index 7 Read getString Write SetString;
|
|
Property MediaGroup : String Index 8 Read getString Write SetString;
|
|
Property SrcObject : TJSHTMLMediaStream Read GetSrcObj;
|
|
Property textTracks : TJSHTMLTextTrackList Read GetTextTrack;
|
|
Property videoTracks : TJSHTMLVideoTrackList Read GetVideoTrack;
|
|
Property audioTracks : TJSHTMLAudioTrackList Read GetAudioTrack;
|
|
Property Error : TJSMEdiaError Read GetError;
|
|
Property CurrentSrc : String Index 9 Read getString;
|
|
Published
|
|
Property Src : String Index 0 Read getString Write SetString;
|
|
Property Controls : Boolean Index 11 Read getBool Write SetBool;
|
|
Property AutoPlay : Boolean Index 12 Read getBool Write SetBool;
|
|
Property CrossOrigin : String index 13 Read getString Write SetString;
|
|
Property DefaultMuted : Boolean Index 14 Read getBool Write SetBool;
|
|
Property CurrentTime : Double Index 15 Read getFloat Write SetFloat;
|
|
Property DisableRemotePlayback : Boolean Index 16 Read getBool Write SetBool;
|
|
Property PreservesPitch : Boolean Index 17 Read getBool Write SetBool;
|
|
Property Loop : Boolean Index 18 Read getBool Write SetBool;
|
|
Property Muted : Boolean Index 19 Read getBool Write SetBool;
|
|
Property Preload : String Index 20 Read getString Write SetString;
|
|
Property Volume : Double Index 10 Read getFloat Write SetFloat;
|
|
end;
|
|
|
|
{ TVideoWidget }
|
|
|
|
TVideoWidget = Class(TMediaWidget)
|
|
Public
|
|
Constructor Create(aOwner : TComponent); override;
|
|
end;
|
|
|
|
{ TAudioWidget }
|
|
|
|
TAudioWidget = Class(TMediaWidget)
|
|
Public
|
|
Constructor Create(aOwner : TComponent); override;
|
|
end;
|
|
|
|
|
|
Function ViewPort : TViewPort;
|
|
|
|
Const
|
|
TextTagNames : Array[TTextTag] of string
|
|
= ('p','b','i','u','s','span','quote','blockquote','h1','h2','h3','h4','h5','h6','pre','ruby','article','address','abbr','');
|
|
RowKindNames : Array[TRowKind] of string = ('header','body','footer');
|
|
|
|
HTMLTagNames : Array[THTMLElementTag] of string = (
|
|
'?', 'a', 'abbr', 'acronym', 'address', 'applet', 'area', 'b', 'base',
|
|
'basefont', 'bdo', 'big', 'blockquote', 'body', 'br', 'button',
|
|
'caption', 'center', 'cite', 'code', 'col', 'colgroup', 'dd', 'del',
|
|
'dfn', 'dir', 'div', 'dl', 'dt', 'em', 'fieldset', 'font', 'form',
|
|
'frame', 'frameset', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'hr',
|
|
'html', 'i', 'iframe', 'img', 'input', 'ins', 'isindex', 'kbd', 'label',
|
|
'legend', 'li', 'link', 'map', 'menu', 'meta', 'noframes', 'noscript',
|
|
'object', 'ol', 'optgroup', 'option', 'p', 'param', 'pre', 'q', 's',
|
|
'samp', 'script', 'select', 'small', 'span', 'strike', 'strong',
|
|
'style', 'sub', 'sup', 'table', 'tbody', 'td', 'textarea', 'tfoot',
|
|
'th', 'thead', 'title', 'tr', 'tt', 'u', 'ul', 'var',
|
|
'Text','Audio','Video','Source'
|
|
);
|
|
|
|
|
|
implementation
|
|
|
|
uses DateUtils;
|
|
|
|
resourcestring
|
|
SErrInvalidIndex = 'Index %d not in valid range of [0..%d]';
|
|
SErrInvalidRowCount = 'Invalid row count: %d';
|
|
SRow = 'Row';
|
|
SCol = 'Column';
|
|
|
|
Function ViewPort : TViewPort;
|
|
|
|
begin
|
|
Result:=TViewPort.Instance;
|
|
end;
|
|
|
|
{ TTableRowCountEnumerator }
|
|
|
|
Const
|
|
CellTags : Array[TRowKind] of string = ('th','td','td');
|
|
|
|
{ TEventTableWidget }
|
|
|
|
procedure TEventTableWidget.SetRowCount(AValue: Integer);
|
|
begin
|
|
if FRowCount=AValue then Exit;
|
|
BeginUpdate;
|
|
FRowCount:=AValue;
|
|
EndUpdate;
|
|
end;
|
|
|
|
function TEventTableWidget.GetBodyRowEnumerator: TTableRowEnumerator;
|
|
begin
|
|
Result:=TTableRowCountEnumerator.Create(Self,RowCount);
|
|
end;
|
|
|
|
{ TCustomStringsTableWidget.TStringRowsEnumerator }
|
|
|
|
procedure TCustomStringsTableWidget.TStringRowsEnumerator.GetCellData(aCell: TTableWidgetCellData);
|
|
begin
|
|
aCell.Text:=TCustomStringsTableWidget(Table).Cells[aCell.Col,aCell.Row];
|
|
end;
|
|
|
|
{ TCustomStringsTableWidget }
|
|
|
|
function TCustomStringsTableWidget.GetCell(aCol, aRow : integer): String;
|
|
begin
|
|
CheckIndex(aCol,aRow);
|
|
Result:=FRows[aRow][aCol];
|
|
end;
|
|
|
|
function TCustomStringsTableWidget.GetRowCount: Integer;
|
|
begin
|
|
Result:=Length(FRows);
|
|
end;
|
|
|
|
procedure TCustomStringsTableWidget.SetCell(aCol, aRow : integer; AValue: String);
|
|
begin
|
|
CheckIndex(aCol,aRow);
|
|
BeginUpdate;
|
|
try
|
|
FRows[aRow][aCol]:=AValue;
|
|
Finally
|
|
EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
function TCustomStringsTableWidget.GetBodyRowEnumerator: TTableRowEnumerator;
|
|
begin
|
|
Result:=TStringRowsEnumerator.Create(Self,RowCount);
|
|
end;
|
|
|
|
procedure TCustomStringsTableWidget.SetRowCount(AValue: Integer);
|
|
begin
|
|
if AValue<0 then
|
|
raise EWidgets.CreateFmt(SerrInvalidRowCount, [aValue]);
|
|
BeginUpdate;
|
|
try
|
|
SetLength(FRows,aValue);
|
|
Finally
|
|
EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
procedure TCustomStringsTableWidget.CheckIndex(aCol, aRow: Integer);
|
|
begin
|
|
If (aCol<0) or (aCol>=CustomColumns.Count) then
|
|
Raise EWidgets.CreateFmt(SCol+' '+SErrInvalidIndex,[aCol,0,CustomColumns.Count-1]);
|
|
If (aRow<0) or (aRow>=RowCount) then
|
|
Raise EWidgets.CreateFmt(SRow+' '+SErrInvalidIndex,[aRow,0,RowCount-1]);
|
|
end;
|
|
|
|
{ TTagWidget }
|
|
|
|
constructor TTagWidget.Create(aOwner: TComponent);
|
|
begin
|
|
inherited Create(aOwner);
|
|
ElementTag:=etdiv;
|
|
end;
|
|
|
|
{ TMediaWidget }
|
|
|
|
function TMediaWidget.GetAudioTrack: TJSHTMLAudioTrackList;
|
|
|
|
begin
|
|
if Assigned(Element) then
|
|
Result:=TJSHTMLMediaElement(Element).AudioTracks
|
|
else
|
|
Result:=Nil;
|
|
end;
|
|
|
|
function TMediaWidget.getBool(AIndex: Integer): Boolean;
|
|
|
|
Var
|
|
El : TJSObject;
|
|
Att : String;
|
|
|
|
begin
|
|
El:=GetEl;
|
|
Att:=PropAttrs[aIndex];
|
|
Result:=Assigned(el) and isDefined(El[Att]) and (Boolean(El[Att]));
|
|
end;
|
|
|
|
function TMediaWidget.GetError: TJSMEdiaError;
|
|
begin
|
|
If Assigned(Element) then
|
|
Result:=TJSHTMLMediaElement(Element).Error
|
|
else
|
|
Result:=Nil;
|
|
end;
|
|
|
|
function TMediaWidget.getFloat(AIndex: Integer): Double;
|
|
|
|
Var
|
|
El : TJSObject;
|
|
Att : String;
|
|
|
|
begin
|
|
El:=GetEl;
|
|
Att:=PropAttrs[aIndex];
|
|
if Assigned(el) and isDefined(El[Att]) then
|
|
Result:=Double(El[Att])
|
|
else
|
|
Result:=0;
|
|
end;
|
|
|
|
function TMediaWidget.GetSrcObj: TJSHTMLMediaStream;
|
|
begin
|
|
If Assigned(Element) then
|
|
Result:=TJSHTMLMediaElement(Element).srcObject
|
|
else
|
|
Result:=Nil;
|
|
end;
|
|
|
|
function TMediaWidget.getString(AIndex: Integer): String;
|
|
|
|
Var
|
|
El : TJSObject;
|
|
Att : String;
|
|
|
|
begin
|
|
El:=GetEl;
|
|
Att:=PropAttrs[aIndex];
|
|
if Assigned(el) and isDefined(El[Att]) then
|
|
Result:=String(El[Att])
|
|
else
|
|
Result:='';
|
|
end;
|
|
|
|
|
|
function TMediaWidget.GetTextTrack: TJSHTMLTextTrackList;
|
|
begin
|
|
If Assigned(Element) then
|
|
Result:=TJSHTMLMediaElement(Element).TextTracks
|
|
else
|
|
Result:=Nil;
|
|
end;
|
|
|
|
function TMediaWidget.GetVideoTrack: TJSHTMLVideoTrackList;
|
|
begin
|
|
If Assigned(Element) then
|
|
Result:=TJSHTMLMediaElement(Element).VideoTracks
|
|
else
|
|
Result:=Nil;
|
|
end;
|
|
|
|
procedure TMediaWidget.SetBool(AIndex: Integer; AValue: Boolean);
|
|
Var
|
|
El : TJSObject;
|
|
Att : String;
|
|
begin
|
|
El:=GetEl;
|
|
Att:=PropAttrs[aIndex];
|
|
if Assigned(el) then
|
|
El[Att]:=aValue
|
|
else
|
|
Attrs[Att]:=IntToStr(Ord(AValue));
|
|
end;
|
|
|
|
procedure TMediaWidget.SetFloat(AIndex: Integer; AValue: Double);
|
|
Var
|
|
El : TJSObject;
|
|
Att,S : String;
|
|
begin
|
|
El:=GetEl;
|
|
Att:=PropAttrs[aIndex];
|
|
if Assigned(el) then
|
|
El[Att]:=aValue
|
|
else
|
|
begin
|
|
Str(aValue,S);
|
|
Attrs[Att]:=S;
|
|
end;
|
|
end;
|
|
|
|
procedure TMediaWidget.SetString(AIndex: Integer; AValue: String);
|
|
|
|
Var
|
|
El : TJSObject;
|
|
Att : String;
|
|
begin
|
|
El:=GetEl;
|
|
Att:=PropAttrs[aIndex];
|
|
if Assigned(el) then
|
|
El[Att]:=aValue
|
|
else
|
|
Attrs[Att]:=aValue;
|
|
end;
|
|
|
|
function TMediaWidget.getEl: TJSObject;
|
|
begin
|
|
Result:=Element;
|
|
if Not Assigned(Result) then
|
|
Result:=Self.StoredAttrs;
|
|
end;
|
|
|
|
{ TVideoWidget }
|
|
|
|
constructor TVideoWidget.Create(aOwner: TComponent);
|
|
begin
|
|
inherited Create(aOwner);
|
|
elementTag:=etVideo;
|
|
end;
|
|
|
|
{ TAudioWidget }
|
|
|
|
constructor TAudioWidget.Create(aOwner: TComponent);
|
|
begin
|
|
inherited Create(aOwner);
|
|
elementTag:=etAudio;
|
|
end;
|
|
|
|
|
|
{ TSelectWidget.TStringsSelectOptionEnumerator }
|
|
|
|
constructor TSelectWidget.TStringsSelectOptionEnumerator.Create(ASelect: TCustomSelectWidget);
|
|
begin
|
|
inherited Create(ASelect);
|
|
FCurrent:=-1;
|
|
end;
|
|
|
|
function TSelectWidget.TStringsSelectOptionEnumerator.OptionText: String;
|
|
begin
|
|
Result:=TSelectWidget(Select).Items[FCurrent];
|
|
end;
|
|
|
|
function TSelectWidget.TStringsSelectOptionEnumerator.HasValue: boolean;
|
|
begin
|
|
Result:=FCurrent<TSelectWidget(Select).Values.Count;
|
|
end;
|
|
|
|
function TSelectWidget.TStringsSelectOptionEnumerator.Value: string;
|
|
begin
|
|
Result:=TSelectWidget(Select).Values[FCurrent];
|
|
end;
|
|
|
|
function TSelectWidget.TStringsSelectOptionEnumerator.MoveNext: Boolean;
|
|
begin
|
|
Result:=FCurrent<TSelectWidget(Select).Items.Count-1;
|
|
if Result then
|
|
Inc(FCurrent);
|
|
end;
|
|
|
|
{ TCustomSelectWidget.TSelectOptionEnumerator }
|
|
|
|
constructor TCustomSelectWidget.TSelectOptionEnumerator.Create(ASelect: TCustomSelectWidget);
|
|
begin
|
|
FSelect:=ASelect;
|
|
end;
|
|
|
|
function TCustomSelectWidget.TSelectOptionEnumerator.HasValue: boolean;
|
|
begin
|
|
Result:=False;
|
|
end;
|
|
|
|
function TCustomSelectWidget.TSelectOptionEnumerator.Value: string;
|
|
begin
|
|
Result:='';
|
|
end;
|
|
|
|
constructor TTableRowCountEnumerator.Create(ATable: TCustomTableWidget; aCount: Integer);
|
|
begin
|
|
Inherited Create(aTable);
|
|
FRowCount:=aCount;
|
|
end;
|
|
|
|
function TTableRowCountEnumerator.MoveNext: Boolean;
|
|
begin
|
|
Result:=Inherited MoveNext and (CurrentRow<RowCount)
|
|
end;
|
|
|
|
{ TTableWidgetCellData }
|
|
|
|
procedure TTableWidgetCellData.SetRowColKind(aRow, aCol: Integer; aKind: TRowKind);
|
|
begin
|
|
if (aRow<>-1) then
|
|
FRow:=aRow;
|
|
if (aCol<>-1) then
|
|
FCol:=aCol;
|
|
FKind:=aKind;
|
|
end;
|
|
|
|
procedure TTableWidgetCellData.Reset;
|
|
begin
|
|
Ftag:='td';
|
|
FClassNames:='';
|
|
FText:='';
|
|
FContent:=Nil;
|
|
FAsHTML:=False;
|
|
FWidget:=Nil;
|
|
end;
|
|
|
|
constructor TTableWidgetCellData.Create(aTable: TCustomTableWidget; aTableID: String);
|
|
begin
|
|
FTable:=aTable;
|
|
FTableID:=aTableID;
|
|
SetRowColKind(0,0,rkBody);
|
|
end;
|
|
|
|
{ TCustomTableWidget }
|
|
|
|
procedure TCustomTableWidget.SetColumns(AValue: TCustomTableColumns);
|
|
begin
|
|
if FColumns=AValue then Exit;
|
|
FColumns.Assign(AValue);
|
|
end;
|
|
|
|
procedure TCustomTableWidget.SetCaption(AValue: String);
|
|
begin
|
|
if FCaption=AValue then Exit;
|
|
FCaption:=AValue;
|
|
if isRendered then Refresh;
|
|
end;
|
|
|
|
function TCustomTableWidget.DoCellClick(aEvent: TJSMouseEvent): boolean;
|
|
begin
|
|
If Assigned(FOnCellClick) then
|
|
FOnCellClick(Self,aEvent);
|
|
If Assigned(FOnRowClick) then
|
|
FOnRowClick(Self,aEvent);
|
|
Result:=False;
|
|
// Writeln('On click for cell',aEvent.targetElement.innerText);
|
|
end;
|
|
|
|
function TCustomTableWidget.DoHeaderCellClick(aEvent: TJSMouseEvent): boolean;
|
|
begin
|
|
If Assigned(FOnHeaderCellClick) then
|
|
FOnHeaderCellClick(Self,aEvent);
|
|
If Assigned(FOnHeaderRowClick) then
|
|
FOnHeaderRowClick(Self,aEvent);
|
|
Result:=False;
|
|
// Writeln('On click for header cell',aEvent.targetElement.innerText);
|
|
end;
|
|
|
|
function TCustomTableWidget.DoFooterCellClick(aEvent: TJSMouseEvent): boolean;
|
|
begin
|
|
If Assigned(FOnFooterCellClick) then
|
|
FOnFooterCellClick(Self,aEvent);
|
|
If Assigned(FOnFooterRowClick) then
|
|
FOnFooterRowClick(Self,aEvent);
|
|
Result:=False;
|
|
// Writeln('On click for Footer cell',aEvent.targetElement.innerText);
|
|
end;
|
|
|
|
function TCustomTableWidget.DoRowClick(aEvent: TJSMouseEvent): boolean;
|
|
begin
|
|
If Assigned(FOnRowClick) then
|
|
FOnRowClick(Self,aEvent);
|
|
Result:=False;
|
|
// Writeln('On click for Row',aEvent.targetElement.innerText);
|
|
end;
|
|
|
|
function TCustomTableWidget.DoHeaderRowClick(aEvent: TJSMouseEvent): boolean;
|
|
begin
|
|
If Assigned(FOnHeaderRowClick) then
|
|
FOnHeaderRowClick(Self,aEvent);
|
|
Result:=False;
|
|
// Writeln('On click for Header Row',aEvent.targetElement.innerText);
|
|
end;
|
|
|
|
function TCustomTableWidget.DoFooterRowClick(aEvent: TJSMouseEvent): boolean;
|
|
begin
|
|
If Assigned(FOnFooterRowClick) then
|
|
FOnFooterRowClick(Self,aEvent);
|
|
Result:=False;
|
|
// Writeln('On click for Footer Row',aEvent.targetElement.innerText);
|
|
end;
|
|
|
|
procedure TCustomTableWidget.SetTableOptions(AValue: TTableOptions);
|
|
begin
|
|
if FTableOptions=AValue then Exit;
|
|
FTableOptions:=AValue;
|
|
if IsRendered then
|
|
Refresh;
|
|
end;
|
|
|
|
procedure TCustomTableWidget.AppendCaption(aCaptionElement: TJSHTMLElement);
|
|
begin
|
|
aCaptionElement.InnerHTML:=Caption;
|
|
end;
|
|
|
|
function TCustomTableWidget.GetRowEnumerator(aKind: TRowKind): TTableRowEnumerator;
|
|
begin
|
|
Case aKind of
|
|
rkHeader : Result:=TTableRowCountEnumerator.Create(Self,1);
|
|
rkFooter : Result:=TTableRowCountEnumerator.Create(Self,1);
|
|
rkBody : Result:=GetBodyRowEnumerator;
|
|
end;
|
|
end;
|
|
|
|
procedure TTableRowEnumerator.GetCellData(aCell: TTableWidgetCellData);
|
|
|
|
Var
|
|
K : TRowKind;
|
|
|
|
begin
|
|
K:=aCell.Kind;
|
|
Case K of
|
|
rkHeader:
|
|
begin
|
|
aCell.Tag:='th';
|
|
aCell.Text:=ACell.Column.Caption;
|
|
end;
|
|
rkFooter,
|
|
rkBody :
|
|
begin
|
|
aCell.Tag:='td';
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TCustomTableWidget.HTMLTag: String;
|
|
begin
|
|
Result:='table';
|
|
end;
|
|
|
|
function TCustomTableWidget.RenderCell(aCell: TTableWidgetCellData): TJSHTMLElement;
|
|
|
|
Const
|
|
Aligns : Array[TAlignment] of string = ('left','right','center');
|
|
RowChecks : Array[TRowKind] of TTableOption = (toHeaderCellDataRow,toBodyCellDataRow,toFooterCellDataRow);
|
|
ColChecks : Array[TRowKind] of TTableOption = (toHeaderCellDataCol,toBodyCellDataCol,toFooterCellDataCol);
|
|
|
|
Var
|
|
C : TJSHtmlElement;
|
|
cl : THTMLNotifyEvent;
|
|
K : TRowKind;
|
|
M : THTMLClickEventHandler;
|
|
elID : string;
|
|
begin
|
|
K:=aCell.Kind;
|
|
if (toCellID in TableOptions) or Assigned(aCell.Widget) then
|
|
elID:=aCell.TableID+'-'+RowKindNames[K]+'-'+IntToStr(ACell.Row)+'-'+IntToStr(aCell.Col)
|
|
else
|
|
elID:='';
|
|
C:=CreateElement(aCell.Tag,elID);
|
|
if aCell.Widget<>Nil then
|
|
aCell.Widget.ParentID:=elID;
|
|
if aCell.Content<>Nil then
|
|
C.AppendChild(aCell.Content)
|
|
else if aCell.AsHTML then
|
|
C.innerHTML:=aCell.text
|
|
else
|
|
C.innerText:=aCell.text;
|
|
C.className:=AddClasses(aCell.Column.ClassNames,aCell.ClassNames);
|
|
if ACell.Column.Alignment<>taLeftJustify then
|
|
C.Style.setProperty('text-align',Aligns[ACell.Column.Alignment]);
|
|
Case K of
|
|
rkBody :
|
|
begin
|
|
CL:=FOnCellClick;
|
|
M:=@DoCellClick;
|
|
end;
|
|
rkHeader :
|
|
begin
|
|
CL:=FOnHeaderCellClick;
|
|
M:=@DoHeaderCellClick;
|
|
end;
|
|
rkFooter :
|
|
begin
|
|
CL:=FOnFooterCellClick;
|
|
M:=@DoFooterCellClick;
|
|
end;
|
|
else
|
|
CL:=Nil;
|
|
M:=nil;
|
|
end;
|
|
if Assigned(cl) or (RowChecks[K] in TableOptions) then
|
|
begin
|
|
C.dataset['row']:=ACell.Row;
|
|
C.Dataset['kind']:=RowKindNames[K];
|
|
end;
|
|
if Assigned(cl) or (ColChecks[K] in TableOptions) then
|
|
begin
|
|
C.dataset['col']:=ACell.Col;
|
|
C.Dataset['kind']:=RowKindNames[K];
|
|
end;
|
|
if Assigned(M) then
|
|
C.OnClick:=M;
|
|
if aCell.Widget<>Nil then
|
|
TJSArray(FWidgets).Push(aCell.Widget);
|
|
Result:=C;
|
|
end;
|
|
|
|
procedure TCustomTableWidget.RenderRow(aEnum: TTableRowEnumerator; aParent: TJSHTMLElement; aKind: TRowKind; aCell: TTableWidgetCellData);
|
|
|
|
|
|
Var
|
|
I: integer;
|
|
|
|
begin
|
|
For I:=0 to CustomColumns.Count-1 do
|
|
if CustomColumns[i].RenderColumn then
|
|
begin
|
|
aCell.Reset;
|
|
aCell.FColumn:=CustomColumns[i];
|
|
aCell.SetRowColKind(-1,I,aKind);
|
|
// Writeln(CellKinds[aKind],' cell before : ',aCell.Tag,' data : ',aCell.Text);
|
|
aEnum.GetCellData(aCell);
|
|
// Writeln(CellKinds[aKind],' cell after : ',aCell.Tag,' data : ',aCell.Text);
|
|
if aCell.Tag='' then
|
|
ACell.Tag:=CellTags[aKind];
|
|
if Assigned(FOnGetCellData) then
|
|
FOnGetCellData(Self,aEnum,aCell);
|
|
aParent.appendChild(RenderCell(aCell));
|
|
end;
|
|
end;
|
|
|
|
procedure TCustomTableWidget.RenderRows(aParent: TJSHTMLElement; aKind: TRowKind; aCell: TTableWidgetCellData);
|
|
|
|
Const
|
|
TableRowChecks : Array[TRowKind] of TTableOption = (toHeaderRowData,toBodyRowData,toFooterRowData);
|
|
|
|
Var
|
|
RowEl : TJSHTMLElement;
|
|
Enum : TTableRowEnumerator;
|
|
M : THTMLClickEventHandler;
|
|
cl : THTMLNotifyEvent;
|
|
elid : String;
|
|
|
|
begin
|
|
Enum:=GetRowEnumerator(aKind);
|
|
if Enum=Nil then
|
|
Exit;
|
|
try
|
|
While Enum.MoveNext do
|
|
begin
|
|
if toRowID in TableOptions then
|
|
elID:=aCell.TableID+'-'+RowKindNames[aKind]+'-'+IntToStr(Enum.CurrentRow)
|
|
else
|
|
elID:='';
|
|
RowEl:=CreateElement('tr',elID);
|
|
aCell.SetRowColKind(Enum.CurrentRow,-1,aKind);
|
|
Case aKind of
|
|
rkBody :
|
|
begin
|
|
CL:=FOnRowClick;
|
|
M:=@DoRowClick;
|
|
end;
|
|
rkHeader :
|
|
begin
|
|
CL:=FOnHeaderRowClick;
|
|
M:=@DoHeaderRowClick;
|
|
end;
|
|
rkFooter :
|
|
begin
|
|
CL:=FOnFooterRowClick;
|
|
M:=@DoFooterRowClick;
|
|
end;
|
|
end;
|
|
if Assigned(CL) or (TableRowChecks[Akind] in TableOptions) then
|
|
begin
|
|
RowEl.dataset['row']:=Enum.CurrentRow;
|
|
RowEl.dataset['kind']:=RowKindNames[aKind];
|
|
end;
|
|
if Assigned(M) then
|
|
RowEl.OnClick:=M;
|
|
RenderRow(Enum,RowEl,aKind,aCell);
|
|
aParent.AppendChild(RowEl);
|
|
end;
|
|
finally
|
|
Enum.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TCustomTableWidget.ApplyWidgetSettings(aElement: TJSHTMLElement);
|
|
begin
|
|
inherited ApplyWidgetSettings(aElement);
|
|
RenderData(aElement);
|
|
end;
|
|
|
|
procedure TCustomTableWidget.RenderData(aElement: TJSHTMLElement);
|
|
|
|
Var
|
|
El : TJSHTMLElement;
|
|
aCell : TTableWidgetCellData;
|
|
W : TWebWidget;
|
|
|
|
begin
|
|
FWidgets:=[];
|
|
if (Caption<>'') then
|
|
begin
|
|
El:=CreateElement('caption',aElement.ID+'-caption');
|
|
AppendCaption(EL);
|
|
aElement.AppendChild(EL);
|
|
end;
|
|
aCell:=CreateCellData(aElement.ID);
|
|
If (CustomColumns.Count=0) then
|
|
CreateDefaultColumns;
|
|
if toHeaderRow in TableOptions then
|
|
begin
|
|
if toHeader in TableOptions then
|
|
begin
|
|
El:=CreateElement('thead',aElement.ID+'-head');
|
|
aElement.AppendChild(el);
|
|
end
|
|
else
|
|
El:=aElement;
|
|
aCell.SetRowColKind(-1,-1,rkHeader);
|
|
RenderRows(El,rkHeader,aCell);
|
|
end;
|
|
if toBody in TableOptions then
|
|
begin
|
|
El:=CreateElement('tbody',aElement.ID+'-body');
|
|
aElement.AppendChild(el);
|
|
end
|
|
else
|
|
El:=aElement;
|
|
aCell.SetRowColKind(-1,-1,rkBody);
|
|
RenderRows(El,rkBody,aCell);
|
|
if toFooterRow in TableOptions then
|
|
begin
|
|
if toFooter in TableOptions then
|
|
begin
|
|
El:=CreateElement('tFoot',aElement.ID+'-foot');
|
|
aElement.AppendChild(el);
|
|
end
|
|
else
|
|
El:=aElement;
|
|
aCell.SetRowColKind(-1,-1,rkFooter);
|
|
RenderRows(El,rkFooter,aCell);
|
|
end;
|
|
for W in FWidgets do
|
|
W.Refresh;
|
|
FWidgets:=[];
|
|
end;
|
|
|
|
function TCustomTableWidget.CreateCellData(const aTableID : String): TTableWidgetCellData;
|
|
begin
|
|
Result:=TTableWidgetCellData.Create(Self,aTableID);
|
|
end;
|
|
|
|
|
|
function TCustomTableWidget.CreateColumns: TCustomTableColumns;
|
|
begin
|
|
Result:=TCustomTableColumns.Create(TCustomTableColumn);
|
|
end;
|
|
|
|
function TCustomTableWidget.DefaultTableOptions: TTableOptions;
|
|
begin
|
|
Result:=[toHeader,toBody,toFooter,toHeaderRow]
|
|
end;
|
|
|
|
procedure TCustomTableWidget.CreateDefaultColumns;
|
|
begin
|
|
// Do nothing
|
|
end;
|
|
|
|
constructor TCustomTableWidget.Create(aOwner: TComponent);
|
|
begin
|
|
inherited Create(aOwner);
|
|
FTableOptions:=DefaultTableOptions;
|
|
FColumns:=CreateColumns;
|
|
end;
|
|
|
|
destructor TCustomTableWidget.Destroy;
|
|
begin
|
|
FreeAndNil(FColumns);
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TCustomTableWidget.BeginUpdate;
|
|
begin
|
|
Inc(FUpDateCount);
|
|
end;
|
|
|
|
procedure TCustomTableWidget.EndUpdate;
|
|
begin
|
|
if (FUpdateCount>0) then
|
|
Dec(FUpDateCount);
|
|
if (FUpdateCount=0) and IsRendered then
|
|
Refresh;
|
|
end;
|
|
|
|
procedure TCustomTableWidget.RefreshBody;
|
|
begin
|
|
if Not Assigned(Element) then
|
|
Refresh
|
|
else
|
|
begin
|
|
Element.Innerhtml:='';
|
|
RenderData(Element);
|
|
end;
|
|
end;
|
|
|
|
{ TCustomTableColumn }
|
|
|
|
procedure TCustomTableColumn.SetAlignment(AValue: TAlignment);
|
|
begin
|
|
if FAlignment=AValue then Exit;
|
|
FAlignment:=AValue;
|
|
end;
|
|
|
|
function TCustomTableColumn.GetCaption: String;
|
|
begin
|
|
Result:=FCaption;
|
|
end;
|
|
|
|
procedure TCustomTableColumn.SetCaption(AValue: String);
|
|
begin
|
|
if FCaption=AValue then Exit;
|
|
FCaption:=AValue;
|
|
end;
|
|
|
|
procedure TCustomTableColumn.SetClassNames(AValue: String);
|
|
begin
|
|
if FClassNames=AValue then Exit;
|
|
FClassNames:=AValue;
|
|
end;
|
|
|
|
function TCustomTableColumn.RenderColumn: Boolean;
|
|
begin
|
|
Result:=True;
|
|
end;
|
|
|
|
function TCustomTableColumn.GetDisplayName: string;
|
|
begin
|
|
Result:=Caption;
|
|
end;
|
|
|
|
procedure TCustomTableColumn.Assign(Source: TPersistent);
|
|
|
|
Var
|
|
C : TCustomTableColumn;
|
|
|
|
begin
|
|
if Source is TCustomTableColumn then
|
|
begin
|
|
C:=Source as TCustomTableColumn;
|
|
FCaption:=C.FCaption;
|
|
FClassNames:=C.FClassNames;
|
|
FAlignment:=C.Alignment;
|
|
end
|
|
else
|
|
inherited Assign(Source);
|
|
end;
|
|
|
|
{ TCustomTableColumns }
|
|
|
|
function TCustomTableColumns.GetCustomColumn(Index : Integer): TCustomTableColumn;
|
|
begin
|
|
Result:=TCustomTableColumn(Items[Index]);
|
|
end;
|
|
|
|
procedure TCustomTableColumns.SetCustomColumn(Index : Integer; AValue: TCustomTableColumn);
|
|
begin
|
|
Items[Index]:=aValue;
|
|
end;
|
|
|
|
function TCustomTableColumns.Add(aCaption: String): TCustomTableColumn;
|
|
begin
|
|
Result:=add as TCustomTableColumn;
|
|
Result.Caption:=aCaption;
|
|
end;
|
|
|
|
{ TTableRowEnumerator }
|
|
|
|
constructor TTableRowEnumerator.Create(ATable: TCustomTableWidget);
|
|
|
|
begin
|
|
FTable:=aTable;
|
|
FCurrent:=-1;
|
|
end;
|
|
|
|
|
|
function TTableRowEnumerator.MoveNext: Boolean;
|
|
begin
|
|
Inc(FCurrent);
|
|
Result:=True;
|
|
end;
|
|
|
|
{ TCustomTextWidget }
|
|
|
|
procedure TCustomTextWidget.SetEnvelopeTag(AValue: TTextTag);
|
|
begin
|
|
// Writeln('Setting text tag : ',aValue);
|
|
if FEnvelopeTag=AValue then Exit;
|
|
FEnvelopeTag:=AValue;
|
|
if (FEnvelopeTag=ttCustom) and (FCustomTag='') then
|
|
FCustomTag:='div';
|
|
if IsRendered then
|
|
Refresh;
|
|
end;
|
|
|
|
procedure TCustomTextWidget.SetCustomTag(AValue: String);
|
|
begin
|
|
if FCustomTag=AValue then Exit;
|
|
FCustomTag:=AValue;
|
|
if (FCustomTag<>'') then
|
|
FEnvelopeTag:=ttCustom;
|
|
if IsRendered then
|
|
Refresh;
|
|
end;
|
|
|
|
|
|
procedure TCustomTextWidget.SetTextMode(AValue: TTextMode);
|
|
begin
|
|
if FTextMode=AValue then Exit;
|
|
FTextMode:=AValue;
|
|
if IsRendered then
|
|
ApplyText(Element);
|
|
end;
|
|
|
|
procedure TCustomTextWidget.ApplyWidgetSettings(aElement: TJSHTMLElement);
|
|
begin
|
|
// Writeln('ApplyWidgetSettings: ',aElement.tagName);
|
|
inherited ApplyWidgetSettings(aElement);
|
|
ApplyText(aElement);
|
|
end;
|
|
|
|
procedure TCustomTextWidget.ApplyText(aElement: TJSHTMLElement);
|
|
begin
|
|
if FTextMode=tmText then
|
|
aElement.innerText:=GetText
|
|
else
|
|
aElement.innerHTML:=GetText;
|
|
end;
|
|
|
|
function TCustomTextWidget.HTMLTag: String;
|
|
|
|
begin
|
|
Result:=TextTagNames[FEnvelopeTag];
|
|
if Result='' then
|
|
Result:='div';
|
|
// Writeln('Getting element tag: ',Result);
|
|
end;
|
|
|
|
{ TTextLinesWidget }
|
|
|
|
procedure TTextLinesWidget.SetLines(AValue: TStrings);
|
|
begin
|
|
if FLines=AValue then Exit;
|
|
FLines.Assign(AValue);
|
|
end;
|
|
|
|
procedure TTextLinesWidget.SetForceLineBreaks(AValue: Boolean);
|
|
begin
|
|
if FForceLineBreaks=AValue then Exit;
|
|
FForceLineBreaks:=AValue;
|
|
if IsRendered then
|
|
ApplyText(Element);
|
|
end;
|
|
|
|
procedure TTextLinesWidget.DoLinesChanged(Sender: TObject);
|
|
begin
|
|
if IsRendered then
|
|
ApplyText(Element);
|
|
end;
|
|
|
|
function TTextLinesWidget.GetText: String;
|
|
|
|
Var
|
|
I : integer;
|
|
|
|
begin
|
|
if (FTextMode=tmHTML) and ForceLineBreaks then
|
|
begin
|
|
Result:='';
|
|
For I:=0 to FLines.Count-1 do
|
|
Result:=Result+flines[i]+'<br/>';
|
|
end
|
|
else
|
|
Result:=FLines.Text;
|
|
end;
|
|
|
|
procedure TTextLinesWidget.ApplyText(aElement: TJSHTMLElement);
|
|
|
|
Var
|
|
I : integer;
|
|
|
|
begin
|
|
if (TextMode=tmHTML) or (Not ForceLineBreaks) then
|
|
inherited ApplyText(aElement)
|
|
else
|
|
begin
|
|
For I:=0 to FLines.Count-1 do
|
|
begin
|
|
aElement.AppendChild(Document.createTextNode(FLines[i]));
|
|
aElement.AppendChild(CreateElement('br',''));
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
constructor TTextLinesWidget.Create(aOwner: TComponent);
|
|
begin
|
|
inherited Create(aOwner);
|
|
FLines:=TstringList.Create;
|
|
TstringList(FLines).OnChange:=@DoLinesChanged;
|
|
end;
|
|
|
|
destructor TTextLinesWidget.Destroy;
|
|
begin
|
|
FLines:=TstringList.Create;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
{ TTextWidget }
|
|
|
|
procedure TTextWidget.SetText(AValue: String);
|
|
begin
|
|
if FText=AValue then Exit;
|
|
FText:=AValue;
|
|
if IsRendered then
|
|
ApplyText(Element);
|
|
end;
|
|
|
|
function TTextWidget.GetText: String;
|
|
begin
|
|
Result:=FText;
|
|
end;
|
|
|
|
|
|
|
|
{ TLabelWidget }
|
|
|
|
procedure TLabelWidget.ApplyLabelFor(aLabelElement : TJSHTMLLabelElement);
|
|
|
|
begin
|
|
if Assigned(FlabelFor) then
|
|
begin
|
|
FlabelFor.EnsureElement;
|
|
aLabelElement.for_:=FlabelFor.ElementID;
|
|
end
|
|
else
|
|
aLabelElement.for_:='';
|
|
end;
|
|
|
|
procedure TLabelWidget.SetLabelFor(AValue: TWebWidget);
|
|
begin
|
|
if (FLabelFor=AValue) then Exit;
|
|
if Assigned(FLabelFor) then
|
|
FLabelFor.RemoveFreeNotification(Self);
|
|
FLabelFor:=AValue;
|
|
if Assigned(FLabelFor) then
|
|
FLabelFor.FreeNotification(Self);
|
|
If IsRendered then
|
|
ApplyLabelFor(LabelElement);
|
|
end;
|
|
|
|
function TLabelWidget.GetText: String;
|
|
begin
|
|
if IsElementDirty then
|
|
FText:=Element.InnerText;
|
|
Result:=FText;
|
|
end;
|
|
|
|
function TLabelWidget.GetLabelEl: TJSHTMLLabelElement;
|
|
begin
|
|
Result:=TJSHTMLLabelElement(Element);
|
|
end;
|
|
|
|
procedure TLabelWidget.SetText(AValue: String);
|
|
begin
|
|
If Text=aValue then exit;
|
|
Ftext:=aValue;
|
|
If IsRendered then
|
|
Element.innerText:=aValue;
|
|
end;
|
|
|
|
procedure TLabelWidget.Notification(AComponent: TComponent; Operation: TOperation);
|
|
begin
|
|
inherited Notification(AComponent, Operation);
|
|
if (Operation=opRemove) and (aComponent=FLabelFor) then
|
|
FLabelFor:=Nil;
|
|
end;
|
|
|
|
procedure TLabelWidget.SetName(const NewName: TComponentName);
|
|
|
|
Var
|
|
Old : String;
|
|
|
|
begin
|
|
Old:=Name;
|
|
inherited SetName(NewName);
|
|
if (csDesigning in ComponentState) then
|
|
if Old=Text then
|
|
Text:=Old;
|
|
end;
|
|
|
|
procedure TLabelWidget.ApplyWidgetSettings(aElement: TJSHTMLElement);
|
|
|
|
var
|
|
lbl : TJSHTMLLabelElement absolute aElement;
|
|
|
|
begin
|
|
inherited ApplyWidgetSettings(aElement);
|
|
lbl.InnerText:=Text;
|
|
ApplyLabelFor(Lbl);
|
|
end;
|
|
|
|
|
|
function TLabelWidget.HTMLTag: String;
|
|
begin
|
|
Result:='label';
|
|
end;
|
|
|
|
{ TSelectWidget }
|
|
|
|
function TCustomSelectWidget.GetSelectedIndex: Integer;
|
|
begin
|
|
if IsRendered then
|
|
FSelectedIndex:=SelectElement.selectedIndex;
|
|
Result:=FSelectedIndex
|
|
end;
|
|
|
|
function TCustomSelectWidget.GetMultiple: Boolean;
|
|
|
|
begin
|
|
if IsElementDirty then
|
|
FMultiple:=SelectElement.multiple;
|
|
Result:=FMultiple;
|
|
end;
|
|
|
|
function TCustomSelectWidget.GetItemCount: Integer;
|
|
begin
|
|
Result:=Length(Options);
|
|
end;
|
|
|
|
function TCustomSelectWidget.GetSelected(Index : Integer): Boolean;
|
|
begin
|
|
if (Index<0) or (Index>=Length(Foptions)) then
|
|
Raise EWidgets.CreateFmt(SErrInvalidIndex,[Index,Length(Foptions)-1]);
|
|
Result:=FOptions[Index].Selected
|
|
end;
|
|
|
|
function TCustomSelectWidget.GetSelect: TJSHTMLSelectElement;
|
|
begin
|
|
Result:=TJSHTMLSelectElement(Element);
|
|
end;
|
|
|
|
function TCustomSelectWidget.GetSelectionCount: Integer;
|
|
begin
|
|
Result:=SelectElement.selectedOptions.length;
|
|
end;
|
|
|
|
function TCustomSelectWidget.GetSelectionItem(aIndex : Integer): String;
|
|
begin
|
|
if (aIndex<0) or (aindex>=GetSelectionCount) then
|
|
Raise EWidgets.CreateFmt(SErrInvalidIndex,[aIndex,GetSelectionCount-1]);
|
|
Result:=TJSHTMLOptionElement(SelectElement.selectedOptions.item(aIndex)).innerText;
|
|
end;
|
|
|
|
function TCustomSelectWidget.GetSelectionValue(aIndex : Integer): String;
|
|
begin
|
|
if (aIndex<0) or (aindex>=GetSelectionCount) then
|
|
Raise EWidgets.CreateFmt(SErrInvalidIndex,[aIndex,GetSelectionCount-1]);
|
|
Result:=TJSHTMLOptionElement(SelectElement.selectedOptions.item(aIndex)).value;
|
|
end;
|
|
|
|
function TCustomSelectWidget.GetSize: Integer;
|
|
begin
|
|
if IsElementDirty then
|
|
FSize:=SelectElement.Size;
|
|
Result:=FSize;
|
|
end;
|
|
|
|
procedure TCustomSelectWidget.SetMultiple(AValue: Boolean);
|
|
begin
|
|
If (AValue=Multiple) then exit;
|
|
FMultiple:=aValue;
|
|
If IsRendered then
|
|
SelectElement.multiple:=FMultiple;
|
|
end;
|
|
|
|
procedure TCustomSelectWidget.SetSelected(Index : Integer; AValue: Boolean);
|
|
begin
|
|
if (Index<0) or (Index>=Length(Foptions)) then
|
|
Raise EWidgets.CreateFmt(SErrInvalidIndex,[Index,Length(Foptions)-1]);
|
|
FOptions[Index].Selected:=aValue;
|
|
end;
|
|
|
|
procedure TCustomSelectWidget.SetSelectedIndex(AValue: Integer);
|
|
|
|
begin
|
|
if (SelectedIndex=aValue) then
|
|
Exit;
|
|
FSelectedIndex:=aValue;
|
|
if IsRendered then
|
|
SelectElement.SelectedIndex:=FSelectedIndex;
|
|
if Assigned(OnChange) then
|
|
OnChange(Self,Nil);
|
|
end;
|
|
|
|
procedure TCustomSelectWidget.SetSize(AValue: Integer);
|
|
begin
|
|
If (AValue=Size) then exit;
|
|
FSize:=aValue;
|
|
If IsRendered then
|
|
SelectElement.Size:=FSize;
|
|
end;
|
|
|
|
procedure TCustomSelectWidget.BuildOptions(aSelect: TJSHTMLSelectElement);
|
|
|
|
Var
|
|
O : TJSHTMLOptionElement;
|
|
Idx : Integer;
|
|
enum : TSelectOptionEnumerator;
|
|
|
|
begin
|
|
// Clear
|
|
SetLength(FOptions,0);
|
|
aSelect.InnerHTML:='';
|
|
// Rebuild
|
|
Idx:=0;
|
|
enum:=CreateOptionEnumerator;
|
|
While enum.MoveNext do
|
|
begin
|
|
O:=TJSHTMLOptionElement(CreateElement('option',''));
|
|
O.innerText:=enum.OptionText;
|
|
if enum.HasValue then
|
|
O.value:=enum.Value;
|
|
if Idx=FSelectedIndex then
|
|
O.selected:=True;
|
|
aSelect.AppendChild(O);
|
|
Inc(Idx);
|
|
end;
|
|
SetLength(Foptions,Idx);
|
|
Dec(idx);
|
|
While Idx>=0 do
|
|
begin
|
|
FOptions[Idx]:=TJSHTMLOptionElement(aSelect.Children[Idx]);
|
|
dec(Idx);
|
|
end;
|
|
end;
|
|
|
|
constructor TCustomSelectWidget.Create(aOWner: TComponent);
|
|
begin
|
|
inherited Create(aOWner);
|
|
FSelectedIndex:=-1;
|
|
end;
|
|
|
|
procedure TCustomSelectWidget.ApplyWidgetSettings(aElement: TJSHTMLElement);
|
|
|
|
Var
|
|
el : TJSHTmlSelectElement absolute aElement;
|
|
|
|
begin
|
|
inherited ApplyWidgetSettings(aElement);
|
|
el.multiple:=Self.Multiple;
|
|
el.Size:=Self.Size;
|
|
BuildOptions(el);
|
|
// We need to force this.
|
|
if SelectedIndex=-1 then
|
|
el.selectedIndex:=-1;
|
|
end;
|
|
|
|
|
|
function TCustomSelectWidget.HTMLTag: String;
|
|
begin
|
|
Result:='select';
|
|
end;
|
|
|
|
|
|
{ TSelectWidget }
|
|
|
|
function TSelectWidget.GetItems: TStrings;
|
|
begin
|
|
Result:=FItems;
|
|
end;
|
|
|
|
|
|
function TSelectWidget.GetValues: TStrings;
|
|
begin
|
|
Result:=FValues;
|
|
end;
|
|
|
|
procedure TSelectWidget.OptionsChanged(Sender: TObject);
|
|
begin
|
|
if IsRendered then
|
|
BuildOptions(SelectElement);
|
|
end;
|
|
|
|
|
|
procedure TSelectWidget.setItems(AValue: TStrings);
|
|
begin
|
|
If (AValue=FItems) then exit;
|
|
FItems.Assign(aValue);
|
|
end;
|
|
|
|
|
|
procedure TSelectWidget.setValues(AValue: TStrings);
|
|
begin
|
|
If (AValue=FValues) then exit;
|
|
FValues.Assign(aValue);
|
|
end;
|
|
|
|
function TSelectWidget.CreateOptionEnumerator: TSelectOptionEnumerator;
|
|
begin
|
|
Result:=TStringsSelectOptionEnumerator.Create(Self);
|
|
end;
|
|
|
|
|
|
constructor TSelectWidget.Create(aOWner: TComponent);
|
|
begin
|
|
inherited Create(aOWner);
|
|
FItems:=TStringList.Create;
|
|
TStringList(FItems).OnChange:=@OptionsChanged;
|
|
FValues:=TStringList.Create;
|
|
TStringList(FValues).OnChange:=@OptionsChanged;
|
|
end;
|
|
|
|
destructor TSelectWidget.Destroy;
|
|
begin
|
|
FreeAndNil(FItems);
|
|
FreeAndNil(FValues);
|
|
inherited Destroy;
|
|
end;
|
|
|
|
{ TImageWidget }
|
|
|
|
function TImageWidget.GetHeight: Integer;
|
|
begin
|
|
if IsElementDirty then
|
|
FHeight:=ImgElement.Height;
|
|
Result:=Fheight;
|
|
end;
|
|
|
|
function TImageWidget.GetImg: TJSHTMLImageElement;
|
|
begin
|
|
Result:=TJSHTMLImageElement(Element);
|
|
end;
|
|
|
|
function TImageWidget.GetSrc: String;
|
|
begin
|
|
if IsElementDirty then
|
|
FSrc:=ImgElement.Src;
|
|
Result:=FSrc;
|
|
end;
|
|
|
|
function TImageWidget.GetWidth: Integer;
|
|
begin
|
|
if IsElementDirty then
|
|
FWidth:=ImgElement.Width;
|
|
Result:=FWidth;
|
|
end;
|
|
|
|
procedure TImageWidget.SetHeight(AValue: Integer);
|
|
begin
|
|
if AValue=Height then exit;
|
|
FHeight:=AValue;
|
|
If isrendered then
|
|
ImgElement.Height:=aValue;
|
|
end;
|
|
|
|
procedure TImageWidget.SetSrc(AValue: String);
|
|
begin
|
|
if AValue=Src then exit;
|
|
FSrc:=AValue;
|
|
If isrendered then
|
|
ImgElement.Src:=FSrc;
|
|
end;
|
|
|
|
procedure TImageWidget.SetWidth(AValue: Integer);
|
|
begin
|
|
if AValue=Width then exit;
|
|
FWidth:=AValue;
|
|
If isrendered then
|
|
ImgElement.Width:=aValue;
|
|
end;
|
|
|
|
procedure TImageWidget.ApplyWidgetSettings(aElement: TJSHTMLElement);
|
|
|
|
var
|
|
img : TJSHTMLImageElement absolute aElement;
|
|
|
|
begin
|
|
inherited ApplyWidgetSettings(aElement);
|
|
Img.Src:=FSrc;
|
|
Img.Height:=FHeight;
|
|
Img.Width:=FWidth;
|
|
end;
|
|
|
|
function TImageWidget.HTMLTag: String;
|
|
begin
|
|
Result:='img';
|
|
end;
|
|
|
|
{ TTextAreaWidget }
|
|
|
|
procedure TTextAreaWidget.SetLines(AValue: TStrings);
|
|
begin
|
|
if FLines=AValue then Exit;
|
|
FLines.Assign(AValue);
|
|
end;
|
|
|
|
procedure TTextAreaWidget.SetMaxLength(AValue: Cardinal);
|
|
begin
|
|
if FMaxLength=AValue then Exit;
|
|
FMaxLength:=AValue;
|
|
if IsRendered then
|
|
TextArea.maxLength:=aValue;
|
|
end;
|
|
|
|
procedure TTextAreaWidget.SetReadonly(AValue: Boolean);
|
|
begin
|
|
If aValue=ReadOnly then exit;
|
|
FReadOnly:=aValue;
|
|
if IsRendered then
|
|
TextArea.Readonly:=FReadOnly;
|
|
end;
|
|
|
|
procedure TTextAreaWidget.SetRequired(AValue: Boolean);
|
|
begin
|
|
If aValue=Required then exit;
|
|
FRequired:=aValue;
|
|
if IsRendered then
|
|
TextArea.Required:=FRequired;
|
|
end;
|
|
|
|
function TTextAreaWidget.GetColumns: Cardinal;
|
|
begin
|
|
if IsElementDirty then
|
|
FColumns:=TextArea.Cols;
|
|
Result:=FColumns;
|
|
end;
|
|
|
|
procedure TTextAreaWidget.DoLineChanges(Sender: TObject);
|
|
begin
|
|
if isRendered and not FIgnoreChanges then
|
|
ApplyLines(TextArea);
|
|
end;
|
|
|
|
|
|
function TTextAreaWidget.GetLines: TStrings;
|
|
begin
|
|
// We may want to change this to something more efficient. Maybe handle onchange
|
|
// Note that if yo
|
|
if IsElementDirty then
|
|
begin
|
|
FIgnoreChanges:=True;
|
|
try
|
|
LinesFromHTML(Element.InnerHTml);
|
|
finally
|
|
FIgnoreChanges:=False;
|
|
end;
|
|
end;
|
|
Result:=FLines;
|
|
end;
|
|
|
|
function TTextAreaWidget.GetReadOnly: Boolean;
|
|
begin
|
|
if IsElementDirty then
|
|
FReadonly:=TextArea.readOnly;
|
|
Result:=FReadonly;
|
|
end;
|
|
|
|
function TTextAreaWidget.GetRequired: Boolean;
|
|
begin
|
|
if IsElementDirty then
|
|
FRequired:=TextArea.Required;
|
|
Result:=FRequired;
|
|
end;
|
|
|
|
function TTextAreaWidget.GetRows: Cardinal;
|
|
begin
|
|
if IsElementDirty then
|
|
FRows:=TextArea.Rows;
|
|
Result:=FRows;
|
|
end;
|
|
|
|
function TTextAreaWidget.GetText: String;
|
|
begin
|
|
if IsElementDirty then
|
|
Result:=Element.InnerHTML
|
|
else
|
|
Result:=FLines.Text;
|
|
end;
|
|
|
|
function TTextAreaWidget.GetValueName: string;
|
|
begin
|
|
if IsElementDirty then
|
|
FValueName:=Element.Name;
|
|
Result:=FValueName;
|
|
end;
|
|
|
|
procedure TTextAreaWidget.SetColumns(AValue: Cardinal);
|
|
begin
|
|
if AValue=FColumns then exit;
|
|
FColumns:=aValue;
|
|
if isRendered then
|
|
TextArea.cols:=aValue;
|
|
end;
|
|
|
|
procedure TTextAreaWidget.SetRows(AValue: Cardinal);
|
|
begin
|
|
if AValue=FRows then exit;
|
|
FRows:=aValue;
|
|
if isRendered then
|
|
TextArea.Rows:=aValue;
|
|
end;
|
|
|
|
procedure TTextAreaWidget.SetText(AValue: String);
|
|
begin
|
|
if isRendered then
|
|
element.InnerText:=aValue
|
|
else
|
|
LinesFromHTML(aValue);
|
|
end;
|
|
|
|
procedure TTextAreaWidget.SetValueName(AValue: string);
|
|
begin
|
|
if aValue=FValueName then exit;
|
|
FValueName:=aValue;
|
|
if IsRendered then
|
|
TextArea.Name:=aValue;
|
|
end;
|
|
|
|
procedure TTextAreaWidget.SetName(const NewName: TComponentName);
|
|
|
|
var
|
|
Old : String;
|
|
begin
|
|
Old:=Name;
|
|
inherited SetName(NewName);
|
|
if csDesigning in ComponentState then
|
|
begin
|
|
if (FLines.Count=0) then
|
|
FLines.Add(Name)
|
|
else if (FLines.Count=1) and (FLines[0]=Old) then
|
|
FLines[0]:=Name;
|
|
end;
|
|
end;
|
|
|
|
procedure TTextAreaWidget.ApplyWidgetSettings(aElement: TJSHTMLElement);
|
|
|
|
var
|
|
area : TJSHTMLTextAreaElement absolute aElement;
|
|
|
|
begin
|
|
inherited ApplyWidgetSettings(aElement);
|
|
if FMaxLength>0 then
|
|
area.maxlength:=FMaxLength;
|
|
if FColumns>0 then
|
|
area.cols:=FColumns;
|
|
if FRows>0 then
|
|
area.Rows:=FRows;
|
|
if FLines.Count>0 then
|
|
ApplyLines(area);
|
|
if FValueName<>'' then
|
|
area.Name:=FValueName;
|
|
area.Readonly:=FReadOnly;
|
|
area.Required:=FRequired;
|
|
ApplyWrap(area);
|
|
end;
|
|
|
|
|
|
constructor TTextAreaWidget.Create(aOwner: TComponent);
|
|
begin
|
|
inherited Create(aOwner);
|
|
FLines:=TStringList.Create;
|
|
TStringList(FLines).OnChange:=@DoLineChanges;
|
|
FColumns:=50;
|
|
FRows:=10;
|
|
end;
|
|
|
|
destructor TTextAreaWidget.Destroy;
|
|
begin
|
|
FreeAndNil(Flines);
|
|
inherited;
|
|
end;
|
|
|
|
class function TTextAreaWidget.AllowChildren: Boolean;
|
|
begin
|
|
Result:=False;
|
|
end;
|
|
|
|
function TTextAreaWidget.GetTextArea: TJSHTMLTextAreaElement;
|
|
begin
|
|
Result:=TJSHTMLTextAreaElement(Element);
|
|
end;
|
|
|
|
procedure TTextAreaWidget.ApplyWrap(aElement :TJSHTMLTextAreaElement);
|
|
|
|
Const
|
|
Wraps : Array[TTextAreaWrap] of string = ('soft','hard','off');
|
|
|
|
begin
|
|
aElement.wrap:=Wraps[FWrap];
|
|
end;
|
|
|
|
procedure TTextAreaWidget.ApplyLines(aElement: TJSHTMLTextAreaElement);
|
|
begin
|
|
aElement.innerHTML:=FLines.Text;
|
|
end;
|
|
|
|
procedure TTextAreaWidget.LinesFromHTML(aHTML: String);
|
|
begin
|
|
FLines.Text:= StringReplace(aHTML,'<br>',sLineBreak,[rfIgnoreCase,rfReplaceAll]);
|
|
end;
|
|
|
|
|
|
|
|
procedure TTextAreaWidget.SetWrap(AValue: TTextAreaWrap);
|
|
|
|
begin
|
|
if FWrap=AValue then Exit;
|
|
FWrap:=AValue;
|
|
if IsRendered then
|
|
ApplyWrap(TextArea)
|
|
end;
|
|
|
|
function TTextAreaWidget.HTMLTag: String;
|
|
begin
|
|
result:='textarea';
|
|
end;
|
|
|
|
{ TCheckboxInputWidget }
|
|
|
|
function TCheckboxInputWidget.InputType: String;
|
|
begin
|
|
Result:='checkbox';
|
|
end;
|
|
|
|
{ TRadioInputWidget }
|
|
|
|
function TRadioInputWidget.InputType: String;
|
|
begin
|
|
Result:='radio';
|
|
end;
|
|
|
|
{ THiddenInputWidget }
|
|
|
|
class function THiddenInputWidget.AllowChildren: Boolean;
|
|
begin
|
|
Result:=False;
|
|
end;
|
|
|
|
function THiddenInputWidget.InputType: String;
|
|
begin
|
|
Result:='hidden';
|
|
end;
|
|
|
|
{ TFileInputWidget }
|
|
|
|
procedure TFileInputWidget.SetMultiple(AValue: Boolean);
|
|
begin
|
|
if FMultiple=AValue then Exit;
|
|
FMultiple:=AValue;
|
|
if Isrendered then
|
|
InputElement.multiple:=FMultiple;
|
|
end;
|
|
|
|
function TFileInputWidget.GetMultiple: Boolean;
|
|
begin
|
|
if IsElementDirty then
|
|
FMultiple:=InputElement.multiple;
|
|
Result:=FMultiple;
|
|
end;
|
|
|
|
|
|
function TFileInputWidget.GetFileName(aIndex : Integer): String;
|
|
begin
|
|
Result:=InputElement.files.Files[aIndex].name;
|
|
end;
|
|
|
|
function TFileInputWidget.GetFileSize(aIndex : Integer): NativeInt;
|
|
begin
|
|
Result:=InputElement.files.Files[aIndex].Size;
|
|
end;
|
|
|
|
function TFileInputWidget.GetFileType(aIndex : Integer): String;
|
|
begin
|
|
Result:=InputElement.files.Files[aIndex]._Type;
|
|
end;
|
|
|
|
function TFileInputWidget.GetFileCount: Integer;
|
|
begin
|
|
Result:=InputElement.files.Length;
|
|
end;
|
|
|
|
function TFileInputWidget.GetFileDate(aIndex : Integer): TDateTime;
|
|
begin
|
|
Result:=JSDateToDateTime(InputElement.files.Files[aIndex].lastModifiedDate);
|
|
end;
|
|
|
|
function TFileInputWidget.GetFileInfo(aIndex : Integer): TFileInfo;
|
|
|
|
Var
|
|
f : TJSHTMLFile;
|
|
|
|
begin
|
|
F:=InputElement.files.Files[aIndex];
|
|
Result.Name:=F.name;
|
|
Result.Size:=F.size;
|
|
Result.FileType:=F._type;
|
|
Result.TimeStamp:= JSDateToDateTime(F.lastModifiedDate);
|
|
end;
|
|
|
|
|
|
procedure TFileInputWidget.ApplyWidgetSettings(aElement: TJSHTMLElement);
|
|
|
|
Var
|
|
Old : String;
|
|
|
|
begin
|
|
Old:=FValue;
|
|
FValue:='';
|
|
try
|
|
inherited ApplyWidgetSettings(aElement);
|
|
TJSHTMLInputElement(aElement).multiple:=FMultiple;
|
|
finally
|
|
FValue:=Old;
|
|
end;
|
|
end;
|
|
|
|
class function TFileInputWidget.AllowChildren: Boolean;
|
|
begin
|
|
Result:=False;
|
|
end;
|
|
|
|
function TFileInputWidget.InputType: String;
|
|
begin
|
|
Result:='file';
|
|
end;
|
|
|
|
|
|
{ TDateInputWidget }
|
|
|
|
function TDateInputWidget.GetDate: TDateTime;
|
|
|
|
var
|
|
aDate : TDateTime;
|
|
|
|
begin
|
|
if IsElementDirty then
|
|
begin
|
|
aDate:=ScanDateTime('yyyy-mm-dd',Value);
|
|
if aDate<>0 then
|
|
FDate:=aDate;
|
|
end;
|
|
Result:=FDate;
|
|
end;
|
|
|
|
|
|
procedure TDateInputWidget.SetDate(AValue: TDateTime);
|
|
begin
|
|
FDate:=aValue;
|
|
Value:=FormatDateTime('yyyy-mm-dd',FDate);
|
|
end;
|
|
|
|
function TDateInputWidget.InputType: String;
|
|
begin
|
|
Result:='date';
|
|
end;
|
|
|
|
class function TDateInputWidget.AllowChildren: Boolean;
|
|
begin
|
|
Result:=False;
|
|
end;
|
|
|
|
{ TCheckableInputWidget }
|
|
|
|
|
|
procedure TCheckableInputWidget.SetChecked(AValue: Boolean);
|
|
begin
|
|
// Get actual value
|
|
if Checked=AValue then Exit;
|
|
if isRendered then
|
|
InputElement.checked:=aValue;
|
|
FChecked:=AValue;
|
|
end;
|
|
|
|
procedure TCheckableInputWidget.ApplyWidgetSettings(aElement: TJSHTMLElement);
|
|
begin
|
|
inherited ApplyWidgetSettings(aElement);
|
|
TJSHTMLInputElement(aElement).Checked:=FChecked;
|
|
end;
|
|
|
|
|
|
function TCheckableInputWidget.GetChecked: Boolean;
|
|
begin
|
|
if IsElementDirty then
|
|
FChecked:=InputElement.Checked;
|
|
Result:=FChecked;
|
|
end;
|
|
|
|
|
|
{ TButtonInputWidget }
|
|
|
|
procedure TButtonInputWidget.SetButtonType(AValue: TInputButtonType);
|
|
begin
|
|
if FButtonType=AValue then Exit;
|
|
FButtonType:=AValue;
|
|
if IsRendered then
|
|
Refresh;
|
|
end;
|
|
|
|
procedure TButtonInputWidget.SetSrc(AValue: String);
|
|
begin
|
|
if FSrc=AValue then Exit;
|
|
FSrc:=AValue;
|
|
if IsRendered and (ButtonType=ibtImage) then
|
|
Element.setAttribute('src',FSrc);
|
|
end;
|
|
|
|
procedure TButtonInputWidget.ApplyWidgetSettings(aElement: TJSHTMLElement);
|
|
begin
|
|
inherited ApplyWidgetSettings(aElement);
|
|
if ButtonType=ibtImage then
|
|
aElement.setAttribute('src',FSrc);
|
|
end;
|
|
|
|
function TButtonInputWidget.InputType: String;
|
|
|
|
Const
|
|
Types : Array[TInputButtonType] of string = ('submit','reset','image');
|
|
|
|
begin
|
|
Result:=Types[FButtonType]
|
|
end;
|
|
|
|
class function TButtonInputWidget.AllowChildren: Boolean;
|
|
begin
|
|
Result:=False;
|
|
end;
|
|
|
|
{ TTextInputWidget }
|
|
|
|
function TTextInputWidget.GetAsNumber: NativeInt;
|
|
begin
|
|
Result:=StrToIntDef(Value,0);
|
|
end;
|
|
|
|
function TTextInputWidget.GetMaxLength: NativeInt;
|
|
begin
|
|
if IsElementDirty then
|
|
FMaxLength:=InputElement.maxLength;
|
|
Result:=FMaxLength;
|
|
end;
|
|
|
|
function TTextInputWidget.GetMinLength: NativeInt;
|
|
begin
|
|
if IsElementDirty then
|
|
FMinLength:=InputElement.minLength;
|
|
Result:=FMinLength;
|
|
end;
|
|
|
|
function TTextInputWidget.GetTextType: TInputTextType;
|
|
begin
|
|
Result:=FTextType;
|
|
end;
|
|
|
|
procedure TTextInputWidget.SetAsNumber(AValue: NativeInt);
|
|
begin
|
|
Value:=IntToStr(aValue);
|
|
end;
|
|
|
|
|
|
procedure TTextInputWidget.SetMaxLength(AValue: NativeInt);
|
|
begin
|
|
if (aValue=FMaxLength) then exit;
|
|
FMaxLength:=aValue;
|
|
if IsRendered then
|
|
InputElement.maxLength:=FMaxLength;
|
|
end;
|
|
|
|
procedure TTextInputWidget.SetMinLength(AValue: NativeInt);
|
|
begin
|
|
if (aValue=FMinLength) then exit;
|
|
FMinLength:=aValue;
|
|
if IsRendered then
|
|
InputElement.minLength:=FMinLength;
|
|
end;
|
|
|
|
procedure TTextInputWidget.SetTextType(AValue: TInputTextType);
|
|
begin
|
|
if aValue=FTextType then exit;
|
|
FTextType:=aValue;
|
|
if IsRendered then
|
|
Refresh;
|
|
end;
|
|
|
|
procedure TTextInputWidget.ApplyWidgetSettings(aElement: TJSHTMLElement);
|
|
|
|
var
|
|
inp : TJSHTMLInputElement absolute aElement;
|
|
|
|
begin
|
|
inherited ApplyWidgetSettings(aElement);
|
|
if FMaxLength<>0 then
|
|
inp.maxLength:=FMaxLength;
|
|
if FMinLength<>0 then
|
|
inp.minLength:=FMinLength;
|
|
end;
|
|
|
|
class function TTextInputWidget.AllowChildren: Boolean;
|
|
begin
|
|
Result:=False;
|
|
end;
|
|
|
|
function TTextInputWidget.InputType: String;
|
|
|
|
Const
|
|
Types : Array[TInputTextType] of string =
|
|
('text','password','number','email','search','tel','url','color');
|
|
|
|
begin
|
|
Result:=Types[FTextType];
|
|
end;
|
|
|
|
{ TWebPage }
|
|
|
|
constructor TWebPage.Create(AOwner: TComponent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
Classes:='WebPage';
|
|
end;
|
|
|
|
|
|
class function TWebPage.DefaultParentElement: TJSHTMLElement;
|
|
begin
|
|
Result:=TViewport.Instance.Element;
|
|
end;
|
|
|
|
class function TWebPage.DefaultParent: TCustomWebWidget;
|
|
begin
|
|
Result:=TViewport.Instance;
|
|
end;
|
|
|
|
procedure TWebPage.DoUnRender(aParent: TJSHTMLElement);
|
|
begin
|
|
inherited DoUnRender(aParent);
|
|
end;
|
|
|
|
function TWebPage.HTMLTag: String;
|
|
begin
|
|
Result:='div';
|
|
end;
|
|
|
|
|
|
{ TViewPort }
|
|
|
|
function TViewPort.HTMLTag: String;
|
|
begin
|
|
Result:='body';
|
|
end;
|
|
|
|
class function TViewPort.FixedParent: TJSHTMLElement;
|
|
begin
|
|
Result:=TJSHTMLElement(Document.documentElement);
|
|
end;
|
|
|
|
class function TViewPort.FixedElement: TJSHTMLElement;
|
|
begin
|
|
Result:=TJSHTMLElement(Document.Body);
|
|
end;
|
|
|
|
function TViewPort.DoRenderHTML(aParent, aElement: TJSHTMLElement): TJSHTMLElement;
|
|
begin
|
|
Result:=FixedElement;
|
|
end;
|
|
|
|
constructor TViewPort.Create(aOwner: TComponent);
|
|
begin
|
|
inherited Create(aOwner);
|
|
EnsureElement;
|
|
end;
|
|
|
|
class function TViewPort.Instance: TViewPort;
|
|
begin
|
|
if Finstance=Nil then
|
|
FInstance:=TViewPort.Create(Nil);
|
|
Result:=FInstance;
|
|
end;
|
|
|
|
{ TButtonWidget }
|
|
|
|
{ TButtonWidget }
|
|
|
|
procedure TButtonWidget.SetText(AValue: String);
|
|
|
|
begin
|
|
if FText=AValue then Exit;
|
|
FText:=AValue;
|
|
if IsRendered then
|
|
ApplyText(Element);
|
|
end;
|
|
|
|
procedure TButtonWidget.SetTextMode(AValue: TTextMode);
|
|
begin
|
|
if FTextMode=AValue then Exit;
|
|
FTextMode:=AValue;
|
|
if IsRendered then
|
|
ApplyText(Element)
|
|
end;
|
|
|
|
|
|
procedure TButtonWidget.SetName(const NewName: TComponentName);
|
|
|
|
Var
|
|
Old : String;
|
|
|
|
begin
|
|
Old:=Name;
|
|
inherited SetName(NewName);
|
|
if (FText=Old) and (csDesigning in ComponentState) then
|
|
FText:=NewName;
|
|
end;
|
|
|
|
function TButtonWidget.HTMLTag: String;
|
|
begin
|
|
Result:='button';
|
|
end;
|
|
|
|
procedure TButtonWidget.ApplyWidgetSettings(aElement: TJSHTMLElement);
|
|
begin
|
|
Inherited;
|
|
ApplyText(aElement);
|
|
end;
|
|
|
|
Procedure TButtonWidget.ApplyText(aElement : TJSHTMLElement);
|
|
|
|
begin
|
|
if FTextMode=tmText then
|
|
aElement.InnerText:=FText
|
|
else
|
|
aElement.InnerHTML:=FText;
|
|
end;
|
|
|
|
procedure TButtonWidget.Click;
|
|
|
|
begin
|
|
DispatchEvent('click');
|
|
end;
|
|
|
|
|
|
{ TCustomInputWidget }
|
|
|
|
function TCustomInputWidget.GetValue: String;
|
|
|
|
Var
|
|
Inp : TJSHTMLInputElement;
|
|
begin
|
|
Inp:=InputElement;
|
|
If Assigned(Inp) then
|
|
Result:=Inp.value
|
|
else
|
|
Result:=FValue
|
|
end;
|
|
|
|
function TCustomInputWidget.GetText: String;
|
|
Var
|
|
Inp : TJSHTMLElement;
|
|
|
|
begin
|
|
Inp:=Element;
|
|
If Assigned(Inp) then
|
|
Result:=Inp.InnerText
|
|
else
|
|
Result:=FText;
|
|
// Writeln('Getting text: ',Result,' inner : ',FText);
|
|
end;
|
|
|
|
function TCustomInputWidget.GetReadOnly: Boolean;
|
|
begin
|
|
if IsElementDirty then
|
|
FReadonly:=InputElement.readOnly;
|
|
Result:=FReadonly;
|
|
end;
|
|
|
|
function TCustomInputWidget.GetRequired: Boolean;
|
|
begin
|
|
if IsElementDirty then
|
|
FRequired:=InputElement.Required;
|
|
Result:=FRequired;
|
|
end;
|
|
|
|
function TCustomInputWidget.GetValueName: String;
|
|
|
|
Var
|
|
Inp : TJSHTMLInputElement;
|
|
|
|
begin
|
|
Inp:=InputElement;
|
|
If Assigned(Inp) then
|
|
Result:=Inp.Name
|
|
else
|
|
begin
|
|
Result:=FValueName;
|
|
if Result='' then
|
|
Result:=Name;
|
|
end;
|
|
end;
|
|
|
|
procedure TCustomInputWidget.SetReadonly(AValue: Boolean);
|
|
begin
|
|
If aValue=ReadOnly then exit;
|
|
FReadOnly:=aValue;
|
|
if IsRendered then
|
|
InputElement.Readonly:=FReadOnly;
|
|
end;
|
|
|
|
procedure TCustomInputWidget.SetRequired(AValue: Boolean);
|
|
begin
|
|
If aValue=Required then exit;
|
|
FRequired:=aValue;
|
|
if IsRendered then
|
|
InputElement.Required:=FRequired;
|
|
end;
|
|
|
|
procedure TCustomInputWidget.SetText(AValue: String);
|
|
Var
|
|
Inp : TJSHTMLElement;
|
|
|
|
begin
|
|
Writeln('Setting text: ',AValue,' previous : ',Text);
|
|
if aValue=Text then exit;
|
|
FText:=aValue;
|
|
Inp:=Element;
|
|
If Assigned(Inp) then
|
|
Inp.innerText:=aValue;
|
|
end;
|
|
|
|
procedure TCustomInputWidget.SetValue(AValue: String);
|
|
|
|
Var
|
|
Inp : TJSHTMLInputElement;
|
|
|
|
begin
|
|
if aValue=Value then exit;
|
|
FValue:=aValue;
|
|
Inp:=InputElement;
|
|
If Assigned(Inp) then
|
|
Inp.value:=aValue;
|
|
end;
|
|
|
|
procedure TCustomInputWidget.ApplyWidgetSettings(aElement: TJSHTMLElement);
|
|
|
|
var
|
|
Inp : TJSHTMLInputElement absolute aElement;
|
|
|
|
begin
|
|
Inherited;
|
|
if (ExternalElement) and (FValue='') then
|
|
FValue:=TJSHTMLInputElement(aElement).value
|
|
else
|
|
begin
|
|
Inp._type:=InputType;
|
|
Inp.name:=FValueName;
|
|
Inp.value:=FValue;
|
|
Inp.Required:=FRequired;
|
|
Inp.ReadOnly:=FReadOnly;
|
|
Writeln('Setting inner text to "',FText,'"');
|
|
Inp.innerHtml:=FText;
|
|
Writeln('Setting inner text is now "',Inp.innerText,'"');
|
|
end;
|
|
end;
|
|
|
|
function TCustomInputWidget.HTMLTag: String;
|
|
begin
|
|
Result:='input';
|
|
end;
|
|
|
|
function TCustomInputWidget.GetInputElement: TJSHTMLInputElement;
|
|
begin
|
|
Result:=TJSHTMLInputElement(Element);
|
|
end;
|
|
|
|
procedure TCustomInputWidget.SetValueName(AValue: String);
|
|
Var
|
|
Inp : TJSHTMLInputElement;
|
|
begin
|
|
if aValue=ValueName then exit;
|
|
FValueName:=aValue;
|
|
Inp:=InputElement;
|
|
If Assigned(Inp) then
|
|
Inp.name:=aValue;
|
|
end;
|
|
|
|
procedure TCustomInputWidget.SetName(const NewName: TComponentName);
|
|
|
|
Var
|
|
Old : String;
|
|
|
|
begin
|
|
Old:=Name;
|
|
inherited SetName(NewName);
|
|
if (Value=Old) then
|
|
Value:=NewName;
|
|
end;
|
|
|
|
|
|
{ TCustomTagWidget }
|
|
|
|
procedure TCustomTagWidget.SetElementTag(AValue: THTMLElementTag);
|
|
|
|
begin
|
|
if FElementTag=AValue then Exit;
|
|
FElementTag:=AValue;
|
|
if IsRendered then
|
|
Refresh;
|
|
end;
|
|
|
|
procedure TCustomTagWidget.SetTextContent(AValue: String);
|
|
begin
|
|
if FTextContent=AValue then Exit;
|
|
FTextContent:=AValue;
|
|
if IsRendered then
|
|
Refresh;
|
|
end;
|
|
|
|
procedure TCustomTagWidget.ApplyWidgetSettings(aElement: TJSHTMLElement);
|
|
begin
|
|
inherited ApplyWidgetSettings(aElement);
|
|
if FTextContent<>'' then
|
|
aElement.InnerText:=TextContent;
|
|
end;
|
|
|
|
function TCustomTagWidget.HTMLTag: String;
|
|
|
|
begin
|
|
Result:=HTMLTagNames[ElementTag];
|
|
end;
|
|
|
|
{ TDivWidget }
|
|
|
|
|
|
constructor TDivWidget.Create(aOwner: TComponent);
|
|
begin
|
|
inherited Create(aOwner);
|
|
ElementTag:=etDiv;
|
|
end;
|
|
|
|
constructor TParagraphWidget.Create(aOwner: TComponent);
|
|
begin
|
|
inherited Create(aOwner);
|
|
ElementTag:=etP;
|
|
end;
|
|
|
|
|
|
end.
|
|
|