| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676 |
- {
- This file is part of the Free Pascal fcl-web package
- Copyright (c) 1999-2022 by the Free Pascal development team
- Web page object
- 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.
- **********************************************************************}
- {$IFNDEF FPC_DOTTEDUNITS}
- unit WebPage;
- {$ENDIF FPC_DOTTEDUNITS}
- {$mode objfpc}{$H+}
- interface
- {$IFDEF FPC_DOTTEDUNITS}
- uses
- System.Classes, System.SysUtils, FpWeb.Html, Xml.HtmlElements, Html.Writer, FpWeb.Http.Defs, FpWeb.Base, System.Contnrs, Xml.Dom;
- {$ELSE FPC_DOTTEDUNITS}
- uses
- Classes, SysUtils, fphtml, htmlelements, htmlwriter, HTTPDefs, fpweb, contnrs, dom;
- {$ENDIF FPC_DOTTEDUNITS}
- type
- TRequestResponseEvent = procedure(Sender: TObject; ARequest: TRequest; AResponse: TResponse) of object;
- TRequestEvent = procedure(Sender: TObject; ARequest: TRequest) of object;
- THandleAjaxRequest = procedure(Sender: TObject; ARequest: TRequest; AnAjaxResponse: TAjaxResponse; var handled: boolean) of object;
- TAjaxRequestResponseEvent = procedure(Sender: TObject; ARequest: TRequest; AResponse: TAjaxResponse) of object;
- type
- { IWebPageDesigner }
- IWebPageDesigner = interface(IUnknown)
- ['{25629DEA-79D5-4165-A0A3-BE6E2BA74442}']
- procedure Invalidate;
- end;
- { IHTMLDesignable }
- IHTMLDesignable = interface(IUnknown)
- ['{C75546D6-9C93-49F0-809F-D29C52CD306D}']
- function GetDesigner: IWebPageDesigner;
- procedure SetDesigner(const AValue: IWebPageDesigner);
- property Designer: IWebPageDesigner read GetDesigner write SetDesigner;
- end;
- IHTMLIterationGroup = interface(IUnknown)
- ['{95575CB6-7D96-4F72-AF72-D2EAF0BECE71}']
- procedure SetIDSuffix(const AHTMLContentProducer: THTMLContentProducer);
- procedure SetAjaxIterationID(AValue: String);
- end;
- { TStandardWebController }
- TStandardWebController = class(TWebController)
- private
- FScriptFileReferences: TStringList;
- FScripts: TFPObjectList;
- FStyleSheetReferences: TContainerStylesheets;
- protected
- function GetScriptFileReferences: TStringList; override;
- function GetScripts: TFPObjectList; override;
- function GetStyleSheetReferences: TContainerStylesheets; override;
- public
- constructor Create(AOwner: TComponent); override;
- destructor Destroy; override;
- function CreateNewJavascriptStack(AJavaType: TJavaType): TJavaScriptStack; override;
- function GetUrl(ParamNames, ParamValues, KeepParams: array of string; const Action: string = ''): string; override;
- procedure BindJavascriptCallstackToElement(AComponent: TComponent; AnElement: THtmlCustomElement; const AnEvent: string); override;
- procedure AddScriptFileReference(const AScriptFile: String); override;
- procedure AddStylesheetReference(const Ahref, Amedia: String); override;
- function DefaultMessageBoxHandler(Sender: TObject; const AText: String; Buttons: TWebButtons; const ALoaded: string = ''): string; override;
- function CreateNewScript: TStringList; override;
- procedure ShowRegisteredScript(ScriptID: integer); override;
- procedure FreeScript(var AScript: TStringList); override;
- published
- property OnGetURL;
- end;
- { TWebPage }
- TWebPage = class(TDataModule, IHTMLContentProducerContainer, IHTMLDesignable)
- private
- FAfterAjaxRequest: TAjaxRequestResponseEvent;
- FBaseURL: string;
- FBeforeRequest: TRequestEvent;
- FBeforeShowPage: TRequestEvent;
- FDesigner: IWebPageDesigner;
- FOnAjaxRequest: THandleAjaxRequest;
- FRequest: TRequest;
- FWebController: TWebController;
- FWebModule: TFPWebModule;
- FContentProducers: TFPList; // list of THTMLContentProducer
- function GetContentProducer(Index: integer): THTMLContentProducer;
- function GetContentProducerList: TFPList;
- function GetContentProducers(Index: integer): THTMLContentProducer;
- function GetDesigner: IWebPageDesigner;
- function GetHasWebController: boolean;
- function GetWebController: TWebController;
- procedure SetDesigner(const AValue: IWebPageDesigner);
- protected
- procedure DoAfterAjaxRequest(ARequest: TRequest; AnAjaxResponse: TAjaxResponse); virtual;
- procedure DoHandleAjaxRequest(ARequest: TRequest; AnAjaxResponse: TAjaxResponse; var Handled: boolean); virtual;
- procedure DoBeforeRequest(ARequest: TRequest); virtual;
- procedure DoBeforeShowPage(ARequest: TRequest); virtual;
- procedure DoCleanupAfterRequest(const AContentProducer: THTMLContentProducer);
- procedure SetRequest(ARequest: TRequest); virtual;
- procedure GetChildren(Proc: TGetChildProc; Root: TComponent); override;
- property ContentProducerList: TFPList read GetContentProducerList;
- public
- destructor Destroy; override;
- function ContentProducerCount: integer;
- function ProduceContent : string;
- procedure AddContentProducer(AContentProducer: THTMLContentProducer);
- procedure RemoveContentProducer(AContentProducer: THTMLContentProducer);
- function ExchangeContentProducers(Child1, Child2: THTMLContentProducer) : boolean;
- function MoveContentProducer(MoveElement, MoveBeforeElement: THTMLContentProducer) : boolean;
- procedure ForeachContentProducer(AForeachChildsProc: TForeachContentProducerProc; Recursive: boolean);
- function IsAjaxCall: boolean; virtual;
- procedure HandlePage(ARequest: TRequest; AResponse: TResponse; AWriter: THTMLwriter; AWebModule: TFPWebModule = nil); virtual;
- procedure DoBeforeGenerateXML; virtual;
- procedure CleanupAfterRequest; virtual;
- property Designer: IWebPageDesigner read GetDesigner write SetDesigner;
- property Request: TRequest read FRequest;
- property ContentProducers[Index: integer]: THTMLContentProducer read GetContentProducer;
- property HasWebController: boolean read GetHasWebController;
- property WebController: TWebController read GetWebController write FWebController;
- property WebModule: TFPWebModule read FWebModule;
- published
- property BeforeRequest: TRequestEvent read FBeforeRequest write FBeforeRequest;
- property BeforeShowPage: TRequestEvent read FBeforeShowPage write FBeforeShowPage;
- property AfterAjaxRequest: TAjaxRequestResponseEvent read FAfterAjaxRequest write FAfterAjaxRequest;
- property OnAjaxRequest: THandleAjaxRequest read FOnAjaxRequest write FOnAjaxRequest;
- property BaseURL: string read FBaseURL write FBaseURL;
- end;
- function RegisterScript(const AScript: string) : integer;
- implementation
- {$IFDEF FPC_DOTTEDUNITS}
- uses System.TypInfo, System.StrUtils;
- {$ELSE FPC_DOTTEDUNITS}
- uses typinfo, strutils;
- {$ENDIF FPC_DOTTEDUNITS}
- var RegisteredScriptList : TStrings;
- function RegisterScript(const AScript: string) : integer;
- begin
- if not Assigned(RegisteredScriptList) then
- begin
- RegisteredScriptList := TStringList.Create;
- end;
- result := RegisteredScriptList.Add(AScript);
- end;
- { TWebPage }
- function TWebPage.ProduceContent: string;
- var i : integer;
- begin
- result := '';
- for i := 0 to ContentProducerCount-1 do
- result := result + THTMLContentProducer(ContentProducers[i]).ProduceContent;
- end;
- procedure TWebPage.AddContentProducer(AContentProducer: THTMLContentProducer);
- begin
- ContentProducerList.Add(AContentProducer);
- end;
- procedure TWebPage.RemoveContentProducer(AContentProducer: THTMLContentProducer);
- begin
- ContentProducerList.Remove(AContentProducer);
- end;
- function TWebPage.ExchangeContentProducers(Child1, Child2: THTMLContentProducer): boolean;
- var ChildIndex1, ChildIndex2: integer;
- begin
- result := false;
- ChildIndex1:=GetContentProducerList.IndexOf(Child1);
- if (ChildIndex1=-1) then
- Exit;
- ChildIndex2:=GetContentProducerList.IndexOf(Child2);
- if (ChildIndex2=-1) then
- Exit;
- GetContentProducerList.Exchange(ChildIndex1,ChildIndex2);
- result := true;
- end;
- function TWebPage.MoveContentProducer(MoveElement, MoveBeforeElement: THTMLContentProducer): boolean;
- var ChildIndex1, ChildIndex2: integer;
- begin
- result := false;
- ChildIndex1:=GetContentProducerList.IndexOf(MoveElement);
- if (ChildIndex1=-1) then
- Exit;
- ChildIndex2:=GetContentProducerList.IndexOf(MoveBeforeElement);
- if (ChildIndex2=-1) then
- Exit;
- GetContentProducerList.Move(ChildIndex1,ChildIndex2);
- result := true;
- end;
- procedure TWebPage.ForeachContentProducer(AForeachChildsProc: TForeachContentProducerProc; Recursive: boolean);
- var i : integer;
- tmpChild: THTMLContentProducer;
- begin
- for i := 0 to ContentProducerCount -1 do
- begin
- tmpChild := ContentProducers[i];
- AForeachChildsProc(tmpChild);
- if recursive then
- tmpChild.ForeachContentProducer(AForeachChildsProc,Recursive);
- end;
- end;
- procedure TWebPage.HandlePage(ARequest: TRequest; AResponse: TResponse; AWriter: THTMLwriter; AWebModule: TFPWebModule=nil);
- var Handled: boolean;
- CompName: string;
- AComponent: TComponent;
- AnAjaxResponse: TAjaxResponse;
- i: integer;
- ASuffixID: string;
- AIterationGroup: IHTMLIterationGroup;
- AIterComp: TComponent;
- wc: TWebController;
- Iterationlevel: integer;
- procedure SetIdSuffixes(AComp: THTMLContentProducer);
- var
- i: integer;
- s: string;
- begin
- if assigned(AComp.parent) and (acomp.parent is THTMLContentProducer) then
- SetIdSuffixes(THTMLContentProducer(AComp.parent));
- if supports(AComp,IHTMLIterationGroup,AIterationGroup) then
- begin
- if assigned(FWebController) then
- begin
- iterationlevel := FWebController.IncrementIterationLevel;
- assert(length(ASuffixID)>0);
- i := PosEx('_',ASuffixID,2);
- if i > 0 then
- s := copy(ASuffixID,2,i-2)
- else
- s := copy(ASuffixID,2,length(ASuffixID)-1);
- acomp.IDSuffix := s;
- AIterationGroup.SetAjaxIterationID(s);
- FWebController.SetIterationIDSuffix(iterationlevel,s);
- acomp.ForeachContentProducer(@AIterationGroup.SetIDSuffix,true);
- ASuffixID := copy(ASuffixID,i,length(ASuffixID)-i+1);
- end;
- end;
- end;
- begin
- SetRequest(ARequest);
- FWebModule := AWebModule;
- try
- try
- DoBeforeRequest(ARequest);
- if IsAjaxCall then
- begin
- AnAjaxResponse := TAjaxResponse.Create(GetWebController, AResponse);
- try
- try
- if HasWebController then
- WebController.InitializeAjaxRequest;
- Handled := false;
- DoHandleAjaxRequest(ARequest, AnAjaxResponse, Handled);
- if not Handled then
- begin
- CompName := Request.QueryFields.Values['AjaxID'];
- if CompName='' then CompName := Request.GetNextPathInfo;
- i := pos('$',CompName);
- AComponent:=self;
- while (i > 0) and (assigned(AComponent)) do
- begin
- AComponent := AComponent.FindComponent(copy(CompName,1,i-1));
- CompName := copy(compname,i+1,length(compname)-i);
- i := pos('$',CompName);
- end;
- if assigned(AComponent) then
- AComponent := AComponent.FindComponent(CompName);
- if assigned(AComponent) and (AComponent is THTMLContentProducer) then
- begin
- // Handle the SuffixID, search for iteration-groups and set their iteration-id-values
- ASuffixID := ARequest.QueryFields.Values['IterationID'];
- if ASuffixID<>'' then
- begin
- SetIdSuffixes(THTMLContentProducer(AComponent));
- webcontroller.ResetIterationLevel;
- end;
- THTMLContentProducer(AComponent).HandleAjaxRequest(ARequest, AnAjaxResponse);
- end;
- end;
- DoAfterAjaxRequest(ARequest, AnAjaxResponse);
- except on E: Exception do
- AnAjaxResponse.SetError(e.HelpContext, e.Message);
- end;
- AnAjaxResponse.BindToResponse;
- finally
- AnAjaxResponse.Free;
- end;
- end
- else
- begin
- if HasWebController then
- WebController.InitializeShowRequest;
- DoBeforeShowPage(ARequest);
- AResponse.Content := ProduceContent;
- if HasWebController then
- WebController.CleanupShowRequest;
- end;
- finally
- CleanupAfterRequest;
- end;
- finally
- SetRequest(nil);
- AWebModule := nil;
- end;
- end;
- procedure TWebPage.DoBeforeGenerateXML;
- begin
- // Do Nothing
- end;
- procedure TWebPage.CleanupAfterRequest;
- begin
- ForeachContentProducer(@DoCleanupAfterRequest, True);
- if HasWebController then
- WebController.CleanupAfterRequest;
- end;
- procedure TWebPage.DoCleanupAfterRequest(const AContentProducer: THTMLContentProducer);
- begin
- AContentProducer.CleanupAfterRequest;
- end;
- procedure TWebPage.SetRequest(ARequest: TRequest);
- begin
- FRequest := ARequest;
- end;
- procedure TWebPage.GetChildren(Proc: TGetChildProc; Root: TComponent);
- var i : integer;
- begin
- inherited GetChildren(Proc, Root);
- if (Root=Self) then
- for I:=0 to ContentProducerCount-1 do
- Proc(ContentProducers[i]);
- end;
- destructor TWebPage.Destroy;
- begin
- inherited Destroy;
- if assigned(FContentProducers) then
- FreeAndNil(FContentProducers);
- end;
- function TWebPage.ContentProducerCount: integer;
- begin
- if assigned(FContentProducers) then
- result := FContentProducers.Count
- else
- result := 0;
- end;
- function TWebPage.GetContentProducers(Index: integer): THTMLContentProducer;
- begin
- Result:=THTMLContentProducer(ContentProducerList[Index]);
- end;
- function TWebPage.GetDesigner: IWebPageDesigner;
- begin
- result := FDesigner;
- end;
- function TWebPage.GetHasWebController: boolean;
- begin
- result := assigned(FWebController);
- end;
- function TWebPage.GetWebController: TWebController;
- begin
- if not assigned(FWebController) then
- raise EHTTP.create('No webcontroller available');
- result := FWebController;
- end;
- procedure TWebPage.SetDesigner(const AValue: IWebPageDesigner);
- begin
- FDesigner := AValue;
- end;
- function TWebPage.GetContentProducerList: TFPList;
- begin
- if not assigned(FContentProducers) then
- FContentProducers := tfplist.Create;
- Result := FContentProducers;
- end;
- function TWebPage.GetContentProducer(Index: integer): THTMLContentProducer;
- begin
- Result := THTMLContentProducer(ContentProducerList[Index]);
- end;
- procedure TWebPage.DoAfterAjaxRequest(ARequest: TRequest; AnAjaxResponse: TAjaxResponse);
- begin
- if assigned(AfterAjaxRequest) then
- AfterAjaxRequest(Self,ARequest,AnAjaxResponse);
- end;
- procedure TWebPage.DoHandleAjaxRequest(ARequest: TRequest; AnAjaxResponse: TAjaxResponse; var Handled: boolean);
- begin
- if assigned(OnAjaxRequest) then
- OnAjaxRequest(Self,ARequest,AnAjaxResponse, Handled);
- end;
- procedure TWebPage.DoBeforeRequest(ARequest: TRequest);
- begin
- if assigned(BeforeRequest) then
- BeforeRequest(Self,ARequest);
- end;
- procedure TWebPage.DoBeforeShowPage(ARequest: TRequest);
- begin
- if assigned(BeforeShowPage) then
- BeforeShowPage(Self,ARequest);
- end;
- function TWebPage.IsAjaxCall: boolean;
- var s : string;
- begin
- if assigned(request) then
- begin
- s := Request.HTTPXRequestedWith;
- result := sametext(s,'XmlHttpRequest');
- end
- else
- result := false;
- end;
- { TStandardWebController }
- function TStandardWebController.GetScriptFileReferences: TStringList;
- begin
- Result:=FScriptFileReferences;
- end;
- function TStandardWebController.GetScripts: TFPObjectList;
- begin
- if not assigned(FScripts) then
- begin
- FScripts:=TFPObjectList.Create;
- FScripts.OwnsObjects:=true;
- end;
- Result:=FScripts;
- end;
- function TStandardWebController.GetStyleSheetReferences: TContainerStylesheets;
- begin
- Result:=FStyleSheetReferences;
- end;
- function TStandardWebController.CreateNewScript: TStringList;
- begin
- Result:=TStringList.Create;
- GetScripts.Add(result);
- end;
- procedure TStandardWebController.ShowRegisteredScript(ScriptID: integer);
- var
- i: Integer;
- s: string;
- begin
- s := '// ' + inttostr(ScriptID);
- for i := 0 to GetScripts.Count -1 do
- if tstrings(GetScripts.Items[i]).Strings[0]=s then
- Exit;
- with CreateNewScript do
- begin
- Append(s);
- Append(RegisteredScriptList.Strings[ScriptID]);
- end;
- end;
- procedure TStandardWebController.FreeScript(var AScript: TStringList);
- begin
- with GetScripts do
- GetScripts.Delete(IndexOf(AScript));
- AScript := nil;
- end;
- function TStandardWebController.DefaultMessageBoxHandler(Sender: TObject;
- const AText: String; Buttons: TWebButtons; const ALoaded: string = ''): string;
- var i : integer;
- HasCancel: boolean;
- OnOk: string;
- OnCancel: string;
- begin
- HasCancel:=false;
- OnOk:='';
- OnCancel:='';
- for i := low(Buttons) to High(Buttons) do
- begin
- if Buttons[i].ButtonType=btOk then
- OnOk := Buttons[i].OnClick;
- if Buttons[i].ButtonType=btCancel then
- begin
- HasCancel := True;
- OnCancel := Buttons[i].OnClick;
- end;
- end;
- if HasCancel then
- result := 'if (confirm('''+AText+''')==true) {'+OnOk+'} else {'+OnCancel+'}'
- else
- result := 'alert('''+AText+''');'+OnOk;
- end;
- constructor TStandardWebController.Create(AOwner: TComponent);
- begin
- inherited Create(AOwner);
- FStyleSheetReferences := TContainerStylesheets.Create(TContainerStylesheet);
- FScriptFileReferences := TStringList.Create;
- // For some reason the Duplicates property does not work when sorted is true,
- // But we don't want a sorted list so do a manual check in AddScriptFileReference
- //FScriptFileReferences.Sorted:=true;
- FScriptFileReferences.Duplicates:=dupIgnore;
- end;
- destructor TStandardWebController.Destroy;
- begin
- FScriptFileReferences.Free;
- FScripts.Free;
- FStyleSheetReferences.Free;
- inherited Destroy;
- end;
- function TStandardWebController.CreateNewJavascriptStack(AJavaType: TJavaType): TJavaScriptStack;
- begin
- Result:=TJavaScriptStack.Create(self, AJavaType);
- end;
- function TStandardWebController.GetUrl(ParamNames, ParamValues,
- KeepParams: array of string; const Action: string): string;
- var qs,p : String;
- i,j : integer;
- found: boolean;
- FancyTitle: boolean;
- ConnectChar: char;
- CGIScriptName: string;
- ActionVar: string;
- ARequest: TRequest;
- WebMod: TFPWebModule;
- begin
- FancyTitle:=false;
- qs := '';
- result := Action;
- ARequest := GetRequest;
- ActionVar := '';
- if assigned(owner) then
- begin
- if (owner is TWebPage) then
- WebMod := TWebPage(Owner).WebModule
- else if (owner is TFPWebModule) then
- WebMod := TFPWebModule(Owner);
- if assigned(WebMod) then
- begin
- ActionVar := WebMod.ActionVar;
- if (action = '') and assigned(WebMod.Actions) and assigned(WebMod.Actions.CurrentAction) then
- result := WebMod.Actions.CurrentAction.Name;
- end;
- end;
- if ActionVar='' then FancyTitle:=true;
- if Assigned(ARequest) then
- begin
- if (high(KeepParams)>=0) and (KeepParams[0]='*') then
- begin
- for i := 0 to ARequest.QueryFields.Count-1 do
- begin
- p := ARequest.QueryFields.Names[i];
- found := False;
- for j := 0 to high(ParamNames) do if sametext(ParamNames[j],p) then
- begin
- found := True;
- break;
- end;
- if not FancyTitle and SameText(ActionVar,p) then
- found := true;
- if not found then
- qs := qs + p + '=' + ARequest.QueryFields.ValueFromIndex[i] + '&';
- end;
- end
- else for i := 0 to high(KeepParams) do
- begin
- p := ARequest.QueryFields.Values[KeepParams[i]];
- if p <> '' then
- qs := qs + KeepParams[i] + '=' + p + '&';
- end;
- end;
- for i := 0 to high(ParamNames) do
- qs := qs + ParamNames[i] + '=' + ParamValues[i] + '&';
- ConnectChar:='?';
- if ScriptName='' then CGIScriptName:='.'
- else
- begin
- CGIScriptName:=ScriptName;
- if pos('?',ScriptName)>0 then ConnectChar := '&';
- end;
- if FancyTitle then // use ? or /
- result := CGIScriptName + '/' + Result
- else
- begin
- result := CGIScriptName + ConnectChar +ActionVar+'=' + Result;
- ConnectChar:='&';
- end;
- p := copy(qs,1,length(qs)-1);
- if p <> '' then
- result := result + ConnectChar + p;
- if assigned(OnGetURL) then
- OnGetURL(ParamNames, ParamValues, KeepParams, Action, Result);
- end;
- procedure TStandardWebController.BindJavascriptCallstackToElement(AComponent: TComponent; AnElement: THtmlCustomElement; const AnEvent: string);
- begin
- if AnEvent='onclick' then
- (AnElement as THTMLAttrsElement).onclick:=CurrentJavaScriptStack.GetScript
- else if AnEvent='onchange' then
- if AnElement is THTML_input then (AnElement as THTML_input).onchange:=CurrentJavaScriptStack.GetScript;
- end;
- procedure TStandardWebController.AddScriptFileReference(const AScriptFile: String);
- begin
- if FScriptFileReferences.IndexOf(AScriptFile)=-1 then
- FScriptFileReferences.Add(AScriptFile);
- end;
- procedure TStandardWebController.AddStylesheetReference(Const Ahref, Amedia: String);
- begin
- with FStyleSheetReferences.Add do
- begin
- href:=Ahref;
- media:=Amedia;
- end;
- end;
- initialization
- RegisteredScriptList := nil;
- finalization
- if assigned(RegisteredScriptList) then
- RegisteredScriptList.Free;
- end.
|