123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603 |
- unit htmlactions;
- {$mode ObjFPC}
- {$H+}
- interface
- uses
- {$ifdef pas2js}
- web,
- {$endif}
- htmleventnames, Classes, SysUtils;
- Type
- {$ifndef pas2js}
- TJSEvent = Class(TObject);
- TJSElement = class(TObject);
- TJSHTMLElement = class(TJSElement);
- TJSHTMLElementArray = array of TJSHTMLElement;
- {$endif}
- THTMLNotifyEvent = Procedure (Sender : TObject; Event : TJSEvent) of object;
- THTMLCustomElementActionList = Class;
- { THTMLElementAction }
- { THTMLCustomElementAction }
- TForeachHTMLElementDataEx = {$ifdef pas2js}reference to {$endif} procedure (aElement : TJSHTMLElement; aData : TObject);
- TForeachHTMLElementData = {$ifdef pas2js}reference to {$endif} procedure (aElement : TJSHTMLElement);
- THTMLCustomElementAction = class(TComponent)
- private
- FActionList: THTMLCustomElementActionList;
- FCSSSelector: String;
- FCustomEvents: String;
- FElementID: String;
- FElement : TJSHTMLElement;
- FElements: TJSHTMLElementArray;
- FEvents: THTMLEvents;
- FOnExecute: THTMLNotifyEvent;
- FPreventDefault: Boolean;
- FStopPropagation: Boolean;
- FBeforeBind : TNotifyEvent;
- FAfterBind : TNotifyEvent;
- function GetIndex: Integer;
- procedure SetActionList(AValue: THTMLCustomElementActionList);
- procedure SetCSSSelector(AValue: String);
- procedure SetCustomEvents(AValue: String);
- procedure SetElementID(AValue: String);
- procedure SetIndex(AValue: Integer);
- Protected
- function GetParentComponent: TComponent; override;
- procedure SetParentComponent(AParent: TComponent); override;
- procedure ReadState(Reader: TReader); override;
- function HasParent: Boolean; override;
- Procedure BindElementEvents; virtual;
- Procedure DoBeforeBind;
- Procedure DoAfterBind;
- Public
- Destructor Destroy; override;
- Procedure Bind; virtual;
- Procedure BindEvents(aEl : TJSElement); virtual;
- procedure HandleEvent(Event: TJSEvent); virtual;
- Procedure ForEach(aCallback : TForeachHTMLElementDataEx; aData : TObject); overload;
- Procedure ForEach(aCallback : TForeachHTMLElementData); overload;
- Procedure AddClass(const aClass : String);
- Procedure RemoveClass(const aClass : String);
- Procedure ToggleClass(const aClass : String);
- Property ActionList : THTMLCustomElementActionList Read FActionList Write SetActionList;
- Property Element : TJSHTMLElement Read FElement;
- Property Elements : TJSHTMLElementArray Read FElements;
- Property Index : Integer Read GetIndex Write SetIndex;
- Public
- // These can be published in descendents
- Property Events : THTMLEvents Read FEvents Write FEvents;
- Property CustomEvents : String Read FCustomEvents Write SetCustomEvents;
- Property ElementID : String Read FElementID Write SetElementID;
- Property CSSSelector : String Read FCSSSelector Write SetCSSSelector;
- Property OnExecute : THTMLNotifyEvent Read FOnExecute Write FOnExecute;
- Property PreventDefault : Boolean Read FPreventDefault Write FPreventDefault default false;
- Property StopPropagation : Boolean Read FStopPropagation Write FStopPropagation default false;
- property BeforeBind : TNotifyEvent Read FBeforeBind Write FAfterBind;
- Property AfterBind : TNotifyEvent Read FAfterBind Write FAfterBind;
- end;
- THTMLCustomElementActionClass = Class of THTMLCustomElementAction;
- THTMLCustomElementActionArray = Array of THTMLCustomElementAction;
- THTMLElementAction = Class(THTMLCustomElementAction)
- Published
- Property Events;
- Property CustomEvents;
- Property ElementID;
- Property CSSSelector;
- Property PreventDefault;
- Property StopPropagation;
- Property OnExecute;
- Property BeforeBind;
- Property AfterBind;
- end;
- THTMLElementActionClass = class of THTMLElementAction;
- THTMLGLobalNotifyEvent = Procedure (Sender : TObject; Event : TJSEvent; var Handled: Boolean) of object;
- { THTMLCustomElementActionList }
- THTMLCustomElementActionList = class(TComponent)
- private
- FList : TFPList;
- FOnExecute: THTMLGLobalNotifyEvent;
- function GetAction(aIndex: Integer): THTMLCustomElementAction;
- function GetActionsCount: Integer;
- Protected
- class function CreateAction(aOwner : TComponent) : THTMLCustomElementAction; virtual;
- function GetActionIndex(aAction : THTMLCustomElementAction) : Integer;
- Procedure SetActionIndex(aAction : THTMLCustomElementAction; aValue : Integer);
- procedure GetChildren(Proc: TGetChildProc; Root: TComponent); override;
- Procedure AddAction(aAction: THTMLCustomElementAction); virtual;
- Procedure RemoveAction(aAction: THTMLCustomElementAction); virtual;
- Function ExecuteAction(aAction: THTMLCustomElementAction; aEvent : TJSEvent) : Boolean; virtual;
- Public
- Constructor Create(aOwner : TComponent); override;
- Destructor Destroy; override;
- Procedure Clear;
- Function IndexOfElementID(aID : String; StartAt : Integer = 0) : Integer;
- Function FindActionByElementID(aID : String; StartAt : Integer = 0) : THTMLCustomElementAction;
- Function GetActionsForElementID(aID : String) : THTMLCustomElementActionArray;
- Function NewAction(aOwner: TComponent) : THTMLCustomElementAction;
- Function ActionByName(aName : String) : THTMLCustomElementAction;
- Property Actions[aIndex: Integer] : THTMLCustomElementAction Read GetAction;
- Property ActionCount : Integer Read GetActionsCount;
- Protected
- Property OnExecute : THTMLGLobalNotifyEvent Read FOnExecute Write FOnExecute;
- end;
- THTMLElementActionList = Class(THTMLCustomElementActionList)
- Published
- Property OnExecute;
- end;
- implementation
- uses strutils;
- { ----------------------------------------------------------------------
- THTMLCustomElementActionList
- ----------------------------------------------------------------------}
- function THTMLCustomElementActionList.GetAction(aIndex: Integer
- ): THTMLCustomElementAction;
- begin
- Result:=THTMLCustomElementAction(FList[aIndex])
- end;
- function THTMLCustomElementActionList.GetActionsCount: Integer;
- begin
- Result:=FList.Count;
- end;
- function THTMLCustomElementActionList.GetActionIndex(
- aAction: THTMLCustomElementAction): Integer;
- begin
- Result:=FList.IndexOf(aAction);
- end;
- procedure THTMLCustomElementActionList.SetActionIndex(
- aAction: THTMLCustomElementAction; aValue: Integer);
- Var
- Old : Integer;
- begin
- Old:=GetActionIndex(aAction);
- if Old<>aValue then
- FList.Move(Old,aValue);
- end;
- procedure THTMLCustomElementActionList.GetChildren(Proc: TGetChildProc;
- Root: TComponent);
- Var
- I : Integer;
- aAction : THTMLCustomElementAction;
- begin
- If Proc=Nil then
- exit;
- for I := 0 to ActionCount - 1 do
- begin
- aAction:=Actions[I];
- if (aAction.Owner=Root) then
- Proc(aAction);
- end;
- end;
- procedure THTMLCustomElementActionList.AddAction(
- aAction: THTMLCustomElementAction);
- begin
- FList.Add(aAction);
- end;
- procedure THTMLCustomElementActionList.RemoveAction(
- aAction: THTMLCustomElementAction);
- begin
- FList.Remove(aAction);
- end;
- function THTMLCustomElementActionList.ExecuteAction(
- aAction: THTMLCustomElementAction; aEvent: TJSEvent): Boolean;
- begin
- Result:=False;
- if Assigned(FOnExecute) then
- FOnExecute(aAction,aEvent,Result);
- end;
- constructor THTMLCustomElementActionList.Create(aOwner: TComponent);
- begin
- inherited Create(aOwner);
- FList:=TFPList.Create;
- end;
- destructor THTMLCustomElementActionList.Destroy;
- begin
- Clear;
- FreeAndNil(FList);
- inherited Destroy;
- end;
- procedure THTMLCustomElementActionList.Clear;
- Var
- A : THTMLCustomElementAction;
- begin
- While ActionCount>0 do
- begin
- A:=Actions[ActionCount-1];
- A.Free;
- end;
- end;
- function THTMLCustomElementActionList.IndexOfElementID(aID: String;
- StartAt: Integer): Integer;
- begin
- Result:=StartAt;
- if Result<0 then
- Result:=0;
- While (Result<ActionCount) and (GetAction(Result).ElementID<>aID) do
- Inc(Result);
- If Result>=ActionCount then
- Result:=-1;
- end;
- function THTMLCustomElementActionList.FindActionByElementID(aID: String;
- StartAt: Integer): THTMLCustomElementAction;
- Var
- Idx : Integer;
- begin
- Idx:=IndexOfElementID(aID,StartAt);
- if Idx=-1 then
- Result:=Nil
- else
- Result:=GetAction(Idx);
- end;
- function THTMLCustomElementActionList.GetActionsForElementID(aID: String): THTMLCustomElementActionArray;
- Var
- Idx,aCount : Integer;
- begin
- SetLength(Result,10);
- Idx:=IndexOfElementID(aID,0);
- aCount:=0;
- While (Idx<>-1) do
- begin
- if Length(Result)<=aCount then
- SetLength(Result,Length(Result)+10);
- Result[aCount]:=GetAction(Idx);
- Inc(aCount);
- Idx:=IndexOfElementID(aID,Idx+1);
- end;
- SetLength(Result,aCount);
- end;
- function THTMLCustomElementActionList.NewAction(aOwner: TComponent
- ): THTMLCustomElementAction;
- begin
- Result:=CreateAction(aOwner);
- Result.ActionList:=Self;
- end;
- class function THTMLCustomElementActionList.CreateAction(aOwner: TComponent
- ): THTMLCustomElementAction;
- begin
- Result:=THTMLElementAction.Create(aOwner);
- end;
- function THTMLCustomElementActionList.ActionByName(aName: String
- ): THTMLCustomElementAction;
- Var
- I : Integer;
- begin
- Result:=Nil;
- I:=ActionCount-1;
- While (Result=Nil) and (I>=0) do
- begin
- Result:=Actions[i];
- If Not SameText(Result.Name,aName) then
- Result:=Nil;
- Dec(I);
- end;
- end;
- { ----------------------------------------------------------------------
- THTMLCustomElementAction
- ----------------------------------------------------------------------}
- procedure THTMLCustomElementAction.SetActionList(AValue: THTMLCustomElementActionList);
- begin
- if (aValue=FActionList) then exit;
- if Assigned(FActionList) then
- FActionList.RemoveAction(Self);
- FActionList:=aValue;
- if Assigned(FActionList) then
- FActionList.AddAction(Self);
- end;
- function THTMLCustomElementAction.GetIndex: Integer;
- begin
- if Assigned(FActionList) then
- Result:=FActionList.GetActionIndex(Self)
- else
- Result:=-1;
- end;
- procedure THTMLCustomElementAction.SetIndex(AValue: Integer);
- begin
- FActionList.SetActionIndex(Self,aValue);
- end;
- function THTMLCustomElementAction.GetParentComponent: TComponent;
- begin
- if ActionList <> nil then
- Result := ActionList
- else
- Result := inherited GetParentComponent;
- end;
- destructor THTMLCustomElementAction.Destroy;
- begin
- if Assigned(ActionList) then
- ActionList.RemoveAction(Self);
- Inherited;
- end;
- procedure THTMLCustomElementAction.SetCSSSelector(AValue: String);
- begin
- if (FCSSSelector=aValue) then exit;
- FCSSSelector:=aValue;
- If Not (csDesigning in ComponentState) then
- Bind;
- end;
- procedure THTMLCustomElementAction.SetCustomEvents(AValue: String);
- begin
- if (FCustomEvents=aValue) then exit;
- FCustomEvents:=aValue;
- If Not (csDesigning in ComponentState) then
- BindElementEvents;
- end;
- procedure THTMLCustomElementAction.SetElementID(AValue: String);
- begin
- if (FElementID=aValue) then exit;
- FElementID:=aValue;
- If Not (csDesigning in ComponentState) then
- Bind;
- end;
- Procedure THTMLCustomElementAction.DoBeforeBind;
- begin
- If Assigned(FBeforeBind) then
- FBeforeBind(Self);
- end;
- Procedure THTMLCustomElementAction.DoAfterBind;
- begin
- If Assigned(FAfterBind) then
- FAfterBind(Self);
- end;
- procedure THTMLCustomElementAction.ForEach(
- aCallback: TForeachHTMLElementDataEx; aData: TObject);
- Var
- El : TJSHTMLElement;
- begin
- For el in FElements do
- if El<>Nil then
- aCallBack(El,aData);
- end;
- procedure THTMLCustomElementAction.ForEach(aCallback: TForeachHTMLElementData);
- Var
- El : TJSHTMLElement;
- begin
- For el in FElements do
- if El<>Nil then
- aCallBack(El);
- end;
- procedure THTMLCustomElementAction.SetParentComponent(AParent: TComponent);
- begin
- if not(csLoading in ComponentState) and (AParent is THTMLCustomElementActionList) then
- ActionList := THTMLCustomElementActionList(AParent);
- end;
- procedure THTMLCustomElementAction.ReadState(Reader: TReader);
- begin
- inherited ReadState(Reader);
- if Reader.Parent is THTMLCustomElementActionList then
- ActionList := THTMLCustomElementActionList(Reader.Parent);
- end;
- function THTMLCustomElementAction.HasParent: Boolean;
- begin
- if Assigned(ActionList) then
- Result:=True
- else
- Result:=inherited HasParent;
- end;
- { ----------------------------------------------------------------------
- The methods in this last part are either empty or implemented,
- depending on whether the unit is used in FPC (IDE) or pas2js
- ----------------------------------------------------------------------}
- {$ifdef pas2js}
- procedure THTMLCustomElementAction.BindElementEvents;
- Var
- El : TJSHTMLElement;
- begin
- For el in FElements do
- if Assigned(El) then
- BindEvents(El);
- end;
- procedure THTMLCustomElementAction.Bind;
- Var
- Nodes : TJSNodeList;
- I : Integer;
- begin
- DoBeforeBind;
- FElement:=Nil;
- FElements:=Nil;
- if ElementID<>'' then
- begin
- FElement:=TJSHTMLElement(document.getElementById(ElementID));
- FElements:=[FElement];
- end
- else if CSSSelector<>'' then
- begin
- Nodes:=document.querySelectorAll(CSSSelector);
- SetLength(FElements,Nodes.length);
- For I:=0 to Nodes.length-1 do
- Felements[I]:=TJSHTMLElement(Nodes.item(I));
- end;
- BindElementEvents;
- DoAfterBind;
- end;
- procedure THTMLCustomElementAction.HandleEvent(Event: TJSEvent);
- Var
- isHandled : Boolean;
- begin
- isHandled:=False;
- if Assigned(ActionList) then
- IsHandled:=ActionList.ExecuteAction(Self,Event);
- If (Not IsHandled) and Assigned(FOnExecute) then
- FonExecute(Self,Event);
- if StopPropagation then
- Event.stopPropagation;
- if PreventDefault then
- Event.preventDefault;
- end;
- procedure THTMLCustomElementAction.AddClass(const aClass: String);
- begin
- ForEach(procedure (aEl : TJSHTMLElement)
- begin
- aEl.classList.add(aClass);
- end
- );
- end;
- procedure THTMLCustomElementAction.RemoveClass(const aClass: String);
- begin
- ForEach(procedure (aEl : TJSHTMLElement)
- begin
- aEl.classList.Remove(aClass);
- end
- );
- end;
- procedure THTMLCustomElementAction.ToggleClass(const aClass: String);
- begin
- ForEach(procedure (aEl : TJSHTMLElement)
- begin
- aEl.classList.toggle(aClass);
- end
- );
- end;
- procedure THTMLCustomElementAction.BindEvents(aEl: TJSElement);
- Const
- Delims = [',',' '];
- var
- H : THTMLEvent;
- I,aCount : Integer;
- S : String;
- begin
- For h in THTMLEvent do
- if H in Events then
- aEl.addEventListener(HTMLEventNameArray[H],@HandleEvent)
- else
- aEl.removeEventListener(HTMLEventNameArray[H],@HandleEvent);
- aCount:=WordCount(CustomEvents,Delims);
- For I:=1 to aCount do
- begin
- S:=ExtractWord(I,CustomEvents,Delims);
- aEl.removeEventListener(HTMLEventNameArray[H],@HandleEvent);
- end;
- end;
- {$else}
- procedure THTMLCustomElementAction.BindElementEvents;
- begin
- end;
- procedure THTMLCustomElementAction.Bind;
- begin
- end;
- procedure THTMLCustomElementAction.HandleEvent(Event: TJSEvent);
- begin
- end;
- procedure THTMLCustomElementAction.AddClass(const aClass: String);
- begin
- end;
- procedure THTMLCustomElementAction.RemoveClass(const aClass: String);
- begin
- end;
- procedure THTMLCustomElementAction.ToggleClass(const aClass: String);
- begin
- end;
- procedure THTMLCustomElementAction.BindEvents(aEl: TJSElement);
- begin
- end;
- {$endif}
- end.
|