webpage.pp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676
  1. {
  2. This file is part of the Free Pascal fcl-web package
  3. Copyright (c) 1999-2022 by the Free Pascal development team
  4. Web page object
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. {$IFNDEF FPC_DOTTEDUNITS}
  12. unit WebPage;
  13. {$ENDIF FPC_DOTTEDUNITS}
  14. {$mode objfpc}{$H+}
  15. interface
  16. {$IFDEF FPC_DOTTEDUNITS}
  17. uses
  18. System.Classes, System.SysUtils, FpWeb.Html, Xml.HtmlElements, Html.Writer, FpWeb.Http.Defs, FpWeb.Base, System.Contnrs, Xml.Dom;
  19. {$ELSE FPC_DOTTEDUNITS}
  20. uses
  21. Classes, SysUtils, fphtml, htmlelements, htmlwriter, HTTPDefs, fpweb, contnrs, dom;
  22. {$ENDIF FPC_DOTTEDUNITS}
  23. type
  24. TRequestResponseEvent = procedure(Sender: TObject; ARequest: TRequest; AResponse: TResponse) of object;
  25. TRequestEvent = procedure(Sender: TObject; ARequest: TRequest) of object;
  26. THandleAjaxRequest = procedure(Sender: TObject; ARequest: TRequest; AnAjaxResponse: TAjaxResponse; var handled: boolean) of object;
  27. TAjaxRequestResponseEvent = procedure(Sender: TObject; ARequest: TRequest; AResponse: TAjaxResponse) of object;
  28. type
  29. { IWebPageDesigner }
  30. IWebPageDesigner = interface(IUnknown)
  31. ['{25629DEA-79D5-4165-A0A3-BE6E2BA74442}']
  32. procedure Invalidate;
  33. end;
  34. { IHTMLDesignable }
  35. IHTMLDesignable = interface(IUnknown)
  36. ['{C75546D6-9C93-49F0-809F-D29C52CD306D}']
  37. function GetDesigner: IWebPageDesigner;
  38. procedure SetDesigner(const AValue: IWebPageDesigner);
  39. property Designer: IWebPageDesigner read GetDesigner write SetDesigner;
  40. end;
  41. IHTMLIterationGroup = interface(IUnknown)
  42. ['{95575CB6-7D96-4F72-AF72-D2EAF0BECE71}']
  43. procedure SetIDSuffix(const AHTMLContentProducer: THTMLContentProducer);
  44. procedure SetAjaxIterationID(AValue: String);
  45. end;
  46. { TStandardWebController }
  47. TStandardWebController = class(TWebController)
  48. private
  49. FScriptFileReferences: TStringList;
  50. FScripts: TFPObjectList;
  51. FStyleSheetReferences: TContainerStylesheets;
  52. protected
  53. function GetScriptFileReferences: TStringList; override;
  54. function GetScripts: TFPObjectList; override;
  55. function GetStyleSheetReferences: TContainerStylesheets; override;
  56. public
  57. constructor Create(AOwner: TComponent); override;
  58. destructor Destroy; override;
  59. function CreateNewJavascriptStack(AJavaType: TJavaType): TJavaScriptStack; override;
  60. function GetUrl(ParamNames, ParamValues, KeepParams: array of string; const Action: string = ''): string; override;
  61. procedure BindJavascriptCallstackToElement(AComponent: TComponent; AnElement: THtmlCustomElement; const AnEvent: string); override;
  62. procedure AddScriptFileReference(const AScriptFile: String); override;
  63. procedure AddStylesheetReference(const Ahref, Amedia: String); override;
  64. function DefaultMessageBoxHandler(Sender: TObject; const AText: String; Buttons: TWebButtons; const ALoaded: string = ''): string; override;
  65. function CreateNewScript: TStringList; override;
  66. procedure ShowRegisteredScript(ScriptID: integer); override;
  67. procedure FreeScript(var AScript: TStringList); override;
  68. published
  69. property OnGetURL;
  70. end;
  71. { TWebPage }
  72. TWebPage = class(TDataModule, IHTMLContentProducerContainer, IHTMLDesignable)
  73. private
  74. FAfterAjaxRequest: TAjaxRequestResponseEvent;
  75. FBaseURL: string;
  76. FBeforeRequest: TRequestEvent;
  77. FBeforeShowPage: TRequestEvent;
  78. FDesigner: IWebPageDesigner;
  79. FOnAjaxRequest: THandleAjaxRequest;
  80. FRequest: TRequest;
  81. FWebController: TWebController;
  82. FWebModule: TFPWebModule;
  83. FContentProducers: TFPList; // list of THTMLContentProducer
  84. function GetContentProducer(Index: integer): THTMLContentProducer;
  85. function GetContentProducerList: TFPList;
  86. function GetContentProducers(Index: integer): THTMLContentProducer;
  87. function GetDesigner: IWebPageDesigner;
  88. function GetHasWebController: boolean;
  89. function GetWebController: TWebController;
  90. procedure SetDesigner(const AValue: IWebPageDesigner);
  91. protected
  92. procedure DoAfterAjaxRequest(ARequest: TRequest; AnAjaxResponse: TAjaxResponse); virtual;
  93. procedure DoHandleAjaxRequest(ARequest: TRequest; AnAjaxResponse: TAjaxResponse; var Handled: boolean); virtual;
  94. procedure DoBeforeRequest(ARequest: TRequest); virtual;
  95. procedure DoBeforeShowPage(ARequest: TRequest); virtual;
  96. procedure DoCleanupAfterRequest(const AContentProducer: THTMLContentProducer);
  97. procedure SetRequest(ARequest: TRequest); virtual;
  98. procedure GetChildren(Proc: TGetChildProc; Root: TComponent); override;
  99. property ContentProducerList: TFPList read GetContentProducerList;
  100. public
  101. destructor Destroy; override;
  102. function ContentProducerCount: integer;
  103. function ProduceContent : string;
  104. procedure AddContentProducer(AContentProducer: THTMLContentProducer);
  105. procedure RemoveContentProducer(AContentProducer: THTMLContentProducer);
  106. function ExchangeContentProducers(Child1, Child2: THTMLContentProducer) : boolean;
  107. function MoveContentProducer(MoveElement, MoveBeforeElement: THTMLContentProducer) : boolean;
  108. procedure ForeachContentProducer(AForeachChildsProc: TForeachContentProducerProc; Recursive: boolean);
  109. function IsAjaxCall: boolean; virtual;
  110. procedure HandlePage(ARequest: TRequest; AResponse: TResponse; AWriter: THTMLwriter; AWebModule: TFPWebModule = nil); virtual;
  111. procedure DoBeforeGenerateXML; virtual;
  112. procedure CleanupAfterRequest; virtual;
  113. property Designer: IWebPageDesigner read GetDesigner write SetDesigner;
  114. property Request: TRequest read FRequest;
  115. property ContentProducers[Index: integer]: THTMLContentProducer read GetContentProducer;
  116. property HasWebController: boolean read GetHasWebController;
  117. property WebController: TWebController read GetWebController write FWebController;
  118. property WebModule: TFPWebModule read FWebModule;
  119. published
  120. property BeforeRequest: TRequestEvent read FBeforeRequest write FBeforeRequest;
  121. property BeforeShowPage: TRequestEvent read FBeforeShowPage write FBeforeShowPage;
  122. property AfterAjaxRequest: TAjaxRequestResponseEvent read FAfterAjaxRequest write FAfterAjaxRequest;
  123. property OnAjaxRequest: THandleAjaxRequest read FOnAjaxRequest write FOnAjaxRequest;
  124. property BaseURL: string read FBaseURL write FBaseURL;
  125. end;
  126. function RegisterScript(const AScript: string) : integer;
  127. implementation
  128. {$IFDEF FPC_DOTTEDUNITS}
  129. uses System.TypInfo, System.StrUtils;
  130. {$ELSE FPC_DOTTEDUNITS}
  131. uses typinfo, strutils;
  132. {$ENDIF FPC_DOTTEDUNITS}
  133. var RegisteredScriptList : TStrings;
  134. function RegisterScript(const AScript: string) : integer;
  135. begin
  136. if not Assigned(RegisteredScriptList) then
  137. begin
  138. RegisteredScriptList := TStringList.Create;
  139. end;
  140. result := RegisteredScriptList.Add(AScript);
  141. end;
  142. { TWebPage }
  143. function TWebPage.ProduceContent: string;
  144. var i : integer;
  145. begin
  146. result := '';
  147. for i := 0 to ContentProducerCount-1 do
  148. result := result + THTMLContentProducer(ContentProducers[i]).ProduceContent;
  149. end;
  150. procedure TWebPage.AddContentProducer(AContentProducer: THTMLContentProducer);
  151. begin
  152. ContentProducerList.Add(AContentProducer);
  153. end;
  154. procedure TWebPage.RemoveContentProducer(AContentProducer: THTMLContentProducer);
  155. begin
  156. ContentProducerList.Remove(AContentProducer);
  157. end;
  158. function TWebPage.ExchangeContentProducers(Child1, Child2: THTMLContentProducer): boolean;
  159. var ChildIndex1, ChildIndex2: integer;
  160. begin
  161. result := false;
  162. ChildIndex1:=GetContentProducerList.IndexOf(Child1);
  163. if (ChildIndex1=-1) then
  164. Exit;
  165. ChildIndex2:=GetContentProducerList.IndexOf(Child2);
  166. if (ChildIndex2=-1) then
  167. Exit;
  168. GetContentProducerList.Exchange(ChildIndex1,ChildIndex2);
  169. result := true;
  170. end;
  171. function TWebPage.MoveContentProducer(MoveElement, MoveBeforeElement: THTMLContentProducer): boolean;
  172. var ChildIndex1, ChildIndex2: integer;
  173. begin
  174. result := false;
  175. ChildIndex1:=GetContentProducerList.IndexOf(MoveElement);
  176. if (ChildIndex1=-1) then
  177. Exit;
  178. ChildIndex2:=GetContentProducerList.IndexOf(MoveBeforeElement);
  179. if (ChildIndex2=-1) then
  180. Exit;
  181. GetContentProducerList.Move(ChildIndex1,ChildIndex2);
  182. result := true;
  183. end;
  184. procedure TWebPage.ForeachContentProducer(AForeachChildsProc: TForeachContentProducerProc; Recursive: boolean);
  185. var i : integer;
  186. tmpChild: THTMLContentProducer;
  187. begin
  188. for i := 0 to ContentProducerCount -1 do
  189. begin
  190. tmpChild := ContentProducers[i];
  191. AForeachChildsProc(tmpChild);
  192. if recursive then
  193. tmpChild.ForeachContentProducer(AForeachChildsProc,Recursive);
  194. end;
  195. end;
  196. procedure TWebPage.HandlePage(ARequest: TRequest; AResponse: TResponse; AWriter: THTMLwriter; AWebModule: TFPWebModule=nil);
  197. var Handled: boolean;
  198. CompName: string;
  199. AComponent: TComponent;
  200. AnAjaxResponse: TAjaxResponse;
  201. i: integer;
  202. ASuffixID: string;
  203. AIterationGroup: IHTMLIterationGroup;
  204. AIterComp: TComponent;
  205. wc: TWebController;
  206. Iterationlevel: integer;
  207. procedure SetIdSuffixes(AComp: THTMLContentProducer);
  208. var
  209. i: integer;
  210. s: string;
  211. begin
  212. if assigned(AComp.parent) and (acomp.parent is THTMLContentProducer) then
  213. SetIdSuffixes(THTMLContentProducer(AComp.parent));
  214. if supports(AComp,IHTMLIterationGroup,AIterationGroup) then
  215. begin
  216. if assigned(FWebController) then
  217. begin
  218. iterationlevel := FWebController.IncrementIterationLevel;
  219. assert(length(ASuffixID)>0);
  220. i := PosEx('_',ASuffixID,2);
  221. if i > 0 then
  222. s := copy(ASuffixID,2,i-2)
  223. else
  224. s := copy(ASuffixID,2,length(ASuffixID)-1);
  225. acomp.IDSuffix := s;
  226. AIterationGroup.SetAjaxIterationID(s);
  227. FWebController.SetIterationIDSuffix(iterationlevel,s);
  228. acomp.ForeachContentProducer(@AIterationGroup.SetIDSuffix,true);
  229. ASuffixID := copy(ASuffixID,i,length(ASuffixID)-i+1);
  230. end;
  231. end;
  232. end;
  233. begin
  234. SetRequest(ARequest);
  235. FWebModule := AWebModule;
  236. try
  237. try
  238. DoBeforeRequest(ARequest);
  239. if IsAjaxCall then
  240. begin
  241. AnAjaxResponse := TAjaxResponse.Create(GetWebController, AResponse);
  242. try
  243. try
  244. if HasWebController then
  245. WebController.InitializeAjaxRequest;
  246. Handled := false;
  247. DoHandleAjaxRequest(ARequest, AnAjaxResponse, Handled);
  248. if not Handled then
  249. begin
  250. CompName := Request.QueryFields.Values['AjaxID'];
  251. if CompName='' then CompName := Request.GetNextPathInfo;
  252. i := pos('$',CompName);
  253. AComponent:=self;
  254. while (i > 0) and (assigned(AComponent)) do
  255. begin
  256. AComponent := AComponent.FindComponent(copy(CompName,1,i-1));
  257. CompName := copy(compname,i+1,length(compname)-i);
  258. i := pos('$',CompName);
  259. end;
  260. if assigned(AComponent) then
  261. AComponent := AComponent.FindComponent(CompName);
  262. if assigned(AComponent) and (AComponent is THTMLContentProducer) then
  263. begin
  264. // Handle the SuffixID, search for iteration-groups and set their iteration-id-values
  265. ASuffixID := ARequest.QueryFields.Values['IterationID'];
  266. if ASuffixID<>'' then
  267. begin
  268. SetIdSuffixes(THTMLContentProducer(AComponent));
  269. webcontroller.ResetIterationLevel;
  270. end;
  271. THTMLContentProducer(AComponent).HandleAjaxRequest(ARequest, AnAjaxResponse);
  272. end;
  273. end;
  274. DoAfterAjaxRequest(ARequest, AnAjaxResponse);
  275. except on E: Exception do
  276. AnAjaxResponse.SetError(e.HelpContext, e.Message);
  277. end;
  278. AnAjaxResponse.BindToResponse;
  279. finally
  280. AnAjaxResponse.Free;
  281. end;
  282. end
  283. else
  284. begin
  285. if HasWebController then
  286. WebController.InitializeShowRequest;
  287. DoBeforeShowPage(ARequest);
  288. AResponse.Content := ProduceContent;
  289. if HasWebController then
  290. WebController.CleanupShowRequest;
  291. end;
  292. finally
  293. CleanupAfterRequest;
  294. end;
  295. finally
  296. SetRequest(nil);
  297. AWebModule := nil;
  298. end;
  299. end;
  300. procedure TWebPage.DoBeforeGenerateXML;
  301. begin
  302. // Do Nothing
  303. end;
  304. procedure TWebPage.CleanupAfterRequest;
  305. begin
  306. ForeachContentProducer(@DoCleanupAfterRequest, True);
  307. if HasWebController then
  308. WebController.CleanupAfterRequest;
  309. end;
  310. procedure TWebPage.DoCleanupAfterRequest(const AContentProducer: THTMLContentProducer);
  311. begin
  312. AContentProducer.CleanupAfterRequest;
  313. end;
  314. procedure TWebPage.SetRequest(ARequest: TRequest);
  315. begin
  316. FRequest := ARequest;
  317. end;
  318. procedure TWebPage.GetChildren(Proc: TGetChildProc; Root: TComponent);
  319. var i : integer;
  320. begin
  321. inherited GetChildren(Proc, Root);
  322. if (Root=Self) then
  323. for I:=0 to ContentProducerCount-1 do
  324. Proc(ContentProducers[i]);
  325. end;
  326. destructor TWebPage.Destroy;
  327. begin
  328. inherited Destroy;
  329. if assigned(FContentProducers) then
  330. FreeAndNil(FContentProducers);
  331. end;
  332. function TWebPage.ContentProducerCount: integer;
  333. begin
  334. if assigned(FContentProducers) then
  335. result := FContentProducers.Count
  336. else
  337. result := 0;
  338. end;
  339. function TWebPage.GetContentProducers(Index: integer): THTMLContentProducer;
  340. begin
  341. Result:=THTMLContentProducer(ContentProducerList[Index]);
  342. end;
  343. function TWebPage.GetDesigner: IWebPageDesigner;
  344. begin
  345. result := FDesigner;
  346. end;
  347. function TWebPage.GetHasWebController: boolean;
  348. begin
  349. result := assigned(FWebController);
  350. end;
  351. function TWebPage.GetWebController: TWebController;
  352. begin
  353. if not assigned(FWebController) then
  354. raise EHTTP.create('No webcontroller available');
  355. result := FWebController;
  356. end;
  357. procedure TWebPage.SetDesigner(const AValue: IWebPageDesigner);
  358. begin
  359. FDesigner := AValue;
  360. end;
  361. function TWebPage.GetContentProducerList: TFPList;
  362. begin
  363. if not assigned(FContentProducers) then
  364. FContentProducers := tfplist.Create;
  365. Result := FContentProducers;
  366. end;
  367. function TWebPage.GetContentProducer(Index: integer): THTMLContentProducer;
  368. begin
  369. Result := THTMLContentProducer(ContentProducerList[Index]);
  370. end;
  371. procedure TWebPage.DoAfterAjaxRequest(ARequest: TRequest; AnAjaxResponse: TAjaxResponse);
  372. begin
  373. if assigned(AfterAjaxRequest) then
  374. AfterAjaxRequest(Self,ARequest,AnAjaxResponse);
  375. end;
  376. procedure TWebPage.DoHandleAjaxRequest(ARequest: TRequest; AnAjaxResponse: TAjaxResponse; var Handled: boolean);
  377. begin
  378. if assigned(OnAjaxRequest) then
  379. OnAjaxRequest(Self,ARequest,AnAjaxResponse, Handled);
  380. end;
  381. procedure TWebPage.DoBeforeRequest(ARequest: TRequest);
  382. begin
  383. if assigned(BeforeRequest) then
  384. BeforeRequest(Self,ARequest);
  385. end;
  386. procedure TWebPage.DoBeforeShowPage(ARequest: TRequest);
  387. begin
  388. if assigned(BeforeShowPage) then
  389. BeforeShowPage(Self,ARequest);
  390. end;
  391. function TWebPage.IsAjaxCall: boolean;
  392. var s : string;
  393. begin
  394. if assigned(request) then
  395. begin
  396. s := Request.HTTPXRequestedWith;
  397. result := sametext(s,'XmlHttpRequest');
  398. end
  399. else
  400. result := false;
  401. end;
  402. { TStandardWebController }
  403. function TStandardWebController.GetScriptFileReferences: TStringList;
  404. begin
  405. Result:=FScriptFileReferences;
  406. end;
  407. function TStandardWebController.GetScripts: TFPObjectList;
  408. begin
  409. if not assigned(FScripts) then
  410. begin
  411. FScripts:=TFPObjectList.Create;
  412. FScripts.OwnsObjects:=true;
  413. end;
  414. Result:=FScripts;
  415. end;
  416. function TStandardWebController.GetStyleSheetReferences: TContainerStylesheets;
  417. begin
  418. Result:=FStyleSheetReferences;
  419. end;
  420. function TStandardWebController.CreateNewScript: TStringList;
  421. begin
  422. Result:=TStringList.Create;
  423. GetScripts.Add(result);
  424. end;
  425. procedure TStandardWebController.ShowRegisteredScript(ScriptID: integer);
  426. var
  427. i: Integer;
  428. s: string;
  429. begin
  430. s := '// ' + inttostr(ScriptID);
  431. for i := 0 to GetScripts.Count -1 do
  432. if tstrings(GetScripts.Items[i]).Strings[0]=s then
  433. Exit;
  434. with CreateNewScript do
  435. begin
  436. Append(s);
  437. Append(RegisteredScriptList.Strings[ScriptID]);
  438. end;
  439. end;
  440. procedure TStandardWebController.FreeScript(var AScript: TStringList);
  441. begin
  442. with GetScripts do
  443. GetScripts.Delete(IndexOf(AScript));
  444. AScript := nil;
  445. end;
  446. function TStandardWebController.DefaultMessageBoxHandler(Sender: TObject;
  447. const AText: String; Buttons: TWebButtons; const ALoaded: string = ''): string;
  448. var i : integer;
  449. HasCancel: boolean;
  450. OnOk: string;
  451. OnCancel: string;
  452. begin
  453. HasCancel:=false;
  454. OnOk:='';
  455. OnCancel:='';
  456. for i := low(Buttons) to High(Buttons) do
  457. begin
  458. if Buttons[i].ButtonType=btOk then
  459. OnOk := Buttons[i].OnClick;
  460. if Buttons[i].ButtonType=btCancel then
  461. begin
  462. HasCancel := True;
  463. OnCancel := Buttons[i].OnClick;
  464. end;
  465. end;
  466. if HasCancel then
  467. result := 'if (confirm('''+AText+''')==true) {'+OnOk+'} else {'+OnCancel+'}'
  468. else
  469. result := 'alert('''+AText+''');'+OnOk;
  470. end;
  471. constructor TStandardWebController.Create(AOwner: TComponent);
  472. begin
  473. inherited Create(AOwner);
  474. FStyleSheetReferences := TContainerStylesheets.Create(TContainerStylesheet);
  475. FScriptFileReferences := TStringList.Create;
  476. // For some reason the Duplicates property does not work when sorted is true,
  477. // But we don't want a sorted list so do a manual check in AddScriptFileReference
  478. //FScriptFileReferences.Sorted:=true;
  479. FScriptFileReferences.Duplicates:=dupIgnore;
  480. end;
  481. destructor TStandardWebController.Destroy;
  482. begin
  483. FScriptFileReferences.Free;
  484. FScripts.Free;
  485. FStyleSheetReferences.Free;
  486. inherited Destroy;
  487. end;
  488. function TStandardWebController.CreateNewJavascriptStack(AJavaType: TJavaType): TJavaScriptStack;
  489. begin
  490. Result:=TJavaScriptStack.Create(self, AJavaType);
  491. end;
  492. function TStandardWebController.GetUrl(ParamNames, ParamValues,
  493. KeepParams: array of string; const Action: string): string;
  494. var qs,p : String;
  495. i,j : integer;
  496. found: boolean;
  497. FancyTitle: boolean;
  498. ConnectChar: char;
  499. CGIScriptName: string;
  500. ActionVar: string;
  501. ARequest: TRequest;
  502. WebMod: TFPWebModule;
  503. begin
  504. FancyTitle:=false;
  505. qs := '';
  506. result := Action;
  507. ARequest := GetRequest;
  508. ActionVar := '';
  509. if assigned(owner) then
  510. begin
  511. if (owner is TWebPage) then
  512. WebMod := TWebPage(Owner).WebModule
  513. else if (owner is TFPWebModule) then
  514. WebMod := TFPWebModule(Owner);
  515. if assigned(WebMod) then
  516. begin
  517. ActionVar := WebMod.ActionVar;
  518. if (action = '') and assigned(WebMod.Actions) and assigned(WebMod.Actions.CurrentAction) then
  519. result := WebMod.Actions.CurrentAction.Name;
  520. end;
  521. end;
  522. if ActionVar='' then FancyTitle:=true;
  523. if Assigned(ARequest) then
  524. begin
  525. if (high(KeepParams)>=0) and (KeepParams[0]='*') then
  526. begin
  527. for i := 0 to ARequest.QueryFields.Count-1 do
  528. begin
  529. p := ARequest.QueryFields.Names[i];
  530. found := False;
  531. for j := 0 to high(ParamNames) do if sametext(ParamNames[j],p) then
  532. begin
  533. found := True;
  534. break;
  535. end;
  536. if not FancyTitle and SameText(ActionVar,p) then
  537. found := true;
  538. if not found then
  539. qs := qs + p + '=' + ARequest.QueryFields.ValueFromIndex[i] + '&';
  540. end;
  541. end
  542. else for i := 0 to high(KeepParams) do
  543. begin
  544. p := ARequest.QueryFields.Values[KeepParams[i]];
  545. if p <> '' then
  546. qs := qs + KeepParams[i] + '=' + p + '&';
  547. end;
  548. end;
  549. for i := 0 to high(ParamNames) do
  550. qs := qs + ParamNames[i] + '=' + ParamValues[i] + '&';
  551. ConnectChar:='?';
  552. if ScriptName='' then CGIScriptName:='.'
  553. else
  554. begin
  555. CGIScriptName:=ScriptName;
  556. if pos('?',ScriptName)>0 then ConnectChar := '&';
  557. end;
  558. if FancyTitle then // use ? or /
  559. result := CGIScriptName + '/' + Result
  560. else
  561. begin
  562. result := CGIScriptName + ConnectChar +ActionVar+'=' + Result;
  563. ConnectChar:='&';
  564. end;
  565. p := copy(qs,1,length(qs)-1);
  566. if p <> '' then
  567. result := result + ConnectChar + p;
  568. if assigned(OnGetURL) then
  569. OnGetURL(ParamNames, ParamValues, KeepParams, Action, Result);
  570. end;
  571. procedure TStandardWebController.BindJavascriptCallstackToElement(AComponent: TComponent; AnElement: THtmlCustomElement; const AnEvent: string);
  572. begin
  573. if AnEvent='onclick' then
  574. (AnElement as THTMLAttrsElement).onclick:=CurrentJavaScriptStack.GetScript
  575. else if AnEvent='onchange' then
  576. if AnElement is THTML_input then (AnElement as THTML_input).onchange:=CurrentJavaScriptStack.GetScript;
  577. end;
  578. procedure TStandardWebController.AddScriptFileReference(const AScriptFile: String);
  579. begin
  580. if FScriptFileReferences.IndexOf(AScriptFile)=-1 then
  581. FScriptFileReferences.Add(AScriptFile);
  582. end;
  583. procedure TStandardWebController.AddStylesheetReference(Const Ahref, Amedia: String);
  584. begin
  585. with FStyleSheetReferences.Add do
  586. begin
  587. href:=Ahref;
  588. media:=Amedia;
  589. end;
  590. end;
  591. initialization
  592. RegisteredScriptList := nil;
  593. finalization
  594. if assigned(RegisteredScriptList) then
  595. RegisteredScriptList.Free;
  596. end.