bootstrapwidgets.pp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787
  1. {
  2. This file is part of the Pas2JS run time library.
  3. Copyright (C) 2019 Michael Van Canneyt
  4. extra Bootstrap widgets
  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. unit bootstrapwidgets;
  12. {$mode objfpc}
  13. interface
  14. uses
  15. Classes, SysUtils, js, libjquery, libbootstrap, web, webwidget, htmlwidgets;
  16. Type
  17. { TSimpleToastWidget }
  18. TContextual = (cNone,cPrimary,cSecondary,cSuccess,cDanger,cWarning,cInfo,cLight,cDark);
  19. TSimpleToastWidget = Class(TCustomTemplateWidget)
  20. private
  21. FAnimate: Boolean;
  22. FAutoHide: Boolean;
  23. FBody: String;
  24. FBoolean: Boolean;
  25. FContextual: TContextual;
  26. FHeader: String;
  27. FHeaderImage: String;
  28. FHideDelay: Integer;
  29. FMinWidth: Integer;
  30. FSmallHeader: String;
  31. procedure SetAnimate(AValue: Boolean);
  32. procedure SetAutoHide(AValue: Boolean);
  33. procedure SetBody(AValue: String);
  34. procedure SetBoolean(AValue: Boolean);
  35. procedure SetContextual(AValue: TContextual);
  36. procedure SetHeader(AValue: String);
  37. procedure SetHeaderImage(AValue: String);
  38. procedure SetHideDelay(AValue: Integer);
  39. procedure SetMinWidth(AValue: Integer);
  40. procedure SetSmallHeader(AValue: String);
  41. Protected
  42. function BodyHTML: String; virtual;
  43. function CloseButtonHTML: String; virtual;
  44. function HeaderHTML: String; virtual;
  45. Function GetTemplateHTML: String; override;
  46. Function DoRenderHTML(aParent, aElement: TJSHTMLElement): TJSHTMLElement; override;
  47. Public
  48. Constructor Create(aOwner : TComponent); override;
  49. Procedure Hide;
  50. Published
  51. Property Header : String Read FHeader Write SetHeader;
  52. Property SmallHeader : String Read FSmallHeader Write SetSmallHeader;
  53. Property Body : String Read FBody Write SetBody;
  54. Property HeaderImage : String Read FHeaderImage Write SetHeaderImage;
  55. Property CloseButton : Boolean Read FBoolean Write SetBoolean;
  56. Property Contextual : TContextual Read FContextual write SetContextual;
  57. Property HideDelay : Integer Read FHideDelay Write SetHideDelay default 2000;
  58. Property AutoHide : Boolean Read FAutoHide Write SetAutoHide default True;
  59. Property Animate : Boolean Read FAnimate Write SetAnimate default False;
  60. Property MinWidth : Integer Read FMinWidth Write SetMinWidth default 200;
  61. end;
  62. // Encapsulates the global tag where the toasts are shown.
  63. { TToastManager }
  64. TToastManager = Class(TWebWidget)
  65. Private
  66. FAnimate: Boolean;
  67. FAutoHide: Boolean;
  68. FHideDelay: Integer;
  69. FMinheight: Integer;
  70. FMinWidth: Integer;
  71. FMultiToast: Boolean;
  72. FContentElement : TJSHTMLElement;
  73. FToastIcon: String;
  74. class var
  75. _instance : TToastManager;
  76. procedure CheckInit;
  77. procedure SetMinHeight(AValue: Integer);
  78. procedure SetMultiToast(AValue: Boolean);
  79. Protected
  80. Class Function DefaultParentElement : TJSHTMLElement; override;
  81. Function DoRenderHTML(aParent, aElement: TJSHTMLElement): TJSHTMLElement; override;
  82. Function GetContentElement: TJSHTMLELement; override;
  83. Procedure InvalidateElement; override;
  84. Function HTMLTag: String; override;
  85. Public
  86. Constructor Create(aOwner : TComponent); override;
  87. class function Instance : TToastManager;
  88. function ShowToast(const aHeader, aBody: String; aContext: TContextual=cNone; Closable: Boolean=True): TSimpleToastWidget;
  89. Published
  90. Property MultiToast : Boolean Read FMultiToast Write SetMultiToast;
  91. Property MinHeight : Integer Read FMinheight Write SetMinHeight default 250;
  92. Property ToastHideDelay : Integer Read FHideDelay Write FHideDelay default 2000;
  93. Property ToastAutoHide : Boolean Read FAutoHide Write FAutoHide default True;
  94. Property ToastAnimate : Boolean Read FAnimate Write FAnimate default False;
  95. Property ToastMinWidth : Integer Read FMinWidth Write FMinWidth default 200;
  96. Property ToastIcon : String Read FToastIcon Write FToastIcon;
  97. end;
  98. { TBootstrapButton }
  99. TBootstrapButton = class (TButtonWidget)
  100. private
  101. FContextual: TContextual;
  102. FOutLine: Boolean;
  103. procedure SetContextual(AValue: TContextual);
  104. procedure SetOutLine(AValue: Boolean);
  105. Protected
  106. Function RecalcClasses(aOldContextual : TContextual; aOldOutline : Boolean) : String;
  107. Public
  108. Constructor Create(aOwner : TComponent); override;
  109. Published
  110. Property Contextual : TContextual Read FContextual Write SetContextual default cPrimary;
  111. Property Outline : Boolean Read FOutLine Write SetOutLine;
  112. end;
  113. { TRowWidget }
  114. TRowWidget = Class(TDIVWidget)
  115. Protected
  116. Function WidgetClasses: String; override;
  117. end;
  118. { TColWidget }
  119. TColMediaSize = (cmsDefault,cmsXL,cmsLG,cmsMD,cmsSM);
  120. TColWidget = Class(TDIVWidget)
  121. private
  122. FSpan : Array[TColMediaSize] of Integer;
  123. function GetSpan(AIndex: Integer): Integer;
  124. procedure SetSpan(AIndex: Integer; AValue: Integer);
  125. Protected
  126. Function RecalcClasses(aRemoveSize : TColmediaSize;aRemoveValue : Integer) : String;
  127. Function WidgetClasses: String; override;
  128. Public
  129. Constructor Create(aOwner : TComponent); override;
  130. Published
  131. Property DefaultColSpan : Integer Index 0 Read GetSpan Write SetSpan;
  132. Property ExtraLargeColSpan : Integer Index 1 Read GetSpan Write SetSpan;
  133. Property LargeColSpan : Integer Index 2 Read GetSpan Write SetSpan;
  134. Property MediumColSpan : Integer Index 3 Read GetSpan Write SetSpan;
  135. Property SmallColSpan : Integer Index 4 Read GetSpan Write SetSpan;
  136. end;
  137. { TBootstrapModal }
  138. TOnModalHideEvent = Procedure (Sender : TObject; El : TJSHTMLElement; Values : TStrings) of object;
  139. TModalItemKind = (mikValue,mikClose);
  140. { TModalReferenceItem }
  141. TModalReferenceItem = Class(TReferenceItem)
  142. private
  143. FInitialValue: String;
  144. FKind: TModalItemKind;
  145. Protected
  146. Function GetValue: String;
  147. Procedure SetValue(aValue: String);
  148. Public
  149. Procedure Assign(Source : TPersistent); override;
  150. Property Value : String Read GetValue Write SetValue;
  151. Published
  152. Property Kind : TModalItemKind Read FKind Write FKind;
  153. Property InitialValue : String Read FInitialValue Write FInitialValue;
  154. end;
  155. { TModalReferences }
  156. TModalReferences = Class(TWebWidgetReferences)
  157. private
  158. function GetMR(aIndex : Integer): TModalReferenceItem;
  159. procedure SetMR(aIndex : Integer; AValue: TModalReferenceItem);
  160. Public
  161. Function Add(Const aName : String; aSelector : String; aKind : TModalItemKind) : TModalReferenceItem; overload;
  162. Property ModalRefs[aIndex : Integer] : TModalReferenceItem Read GetMR Write SetMR; default;
  163. end;
  164. TBootstrapModal = Class(TCustomTemplateWidget)
  165. private
  166. FHideEl : TJSHTMLElement;
  167. FBackDrop: Boolean;
  168. FFocus: Boolean;
  169. FKeyBoard: Boolean;
  170. FOnHide: TOnModalHideEvent;
  171. FShowOnRender: Boolean;
  172. FTemplate: String;
  173. FShowing : Boolean;
  174. function GetModalReferences: TModalReferences;
  175. function HideClick(Event: TJSEvent): Boolean;
  176. procedure SetModalReferences(AValue: TModalReferences);
  177. procedure SetTemplate(AValue: String);
  178. protected
  179. Function BootstrapHide(Event : TJSEvent) : Boolean;
  180. Function DoRenderHTML(aParent, aElement: TJSHTMLElement): TJSHTMLElement; override;
  181. Function GetTemplateHTML: String; override;
  182. Procedure RefreshReferences; override;
  183. Function CreateReferences: TWebWidgetReferences; override;
  184. Public
  185. procedure GetValues(aList: TStrings);
  186. Procedure Show;
  187. Procedure Hide;
  188. Property Showing : Boolean Read FShowing;
  189. Published
  190. Property ShowOnRender: Boolean Read FShowOnRender Write FShowOnrender;
  191. Property BackDrop : Boolean Read FBackDrop Write FBackDrop;
  192. Property KeyBoard : Boolean Read FKeyBoard Write FKeyBoard;
  193. Property Focus : Boolean Read FFocus Write FFocus;
  194. Property Template : String Read FTemplate Write SetTemplate;
  195. Property OnHide : TOnModalHideEvent Read FOnHide Write FOnHide;
  196. Property References : TModalReferences Read GetModalReferences Write SetModalReferences;
  197. end;
  198. Const
  199. ContextualNames : Array[TContextual] of string = ('','primary','secondary','success','danger','warning','info','light','dark');
  200. Function Toasts : TToastManager;
  201. Implementation
  202. function Toasts: TToastManager;
  203. begin
  204. Result:=TToastManager.Instance;
  205. end;
  206. { TColWidget }
  207. function TColWidget.GetSpan(AIndex: Integer): Integer;
  208. begin
  209. Result:=FSpan[TColMediaSize(aIndex)];
  210. end;
  211. procedure TColWidget.SetSpan(AIndex: Integer; AValue: Integer);
  212. Var
  213. aOld : integer;
  214. begin
  215. if aValue=FSpan[TColMediaSize(aIndex)] then exit;
  216. aOld:=FSpan[TColMediaSize(aIndex)];
  217. FSpan[TColMediaSize(aIndex)]:=aValue;
  218. recalcClasses(TColMediaSize(aIndex),aOld);
  219. end;
  220. function TColWidget.RecalcClasses(aRemoveSize : TColmediaSize; aRemoveValue: Integer): String;
  221. Const
  222. IdxNames : Array[TColMediaSize] of string = ('-','-xl-','-lg-','-md-','-sm-');
  223. Var
  224. c : String;
  225. S : TColmediaSize;
  226. begin
  227. Result:='';
  228. C:=RemoveClasses(Classes,' col-'+IdxNames[aRemoveSize]+IntToStr(aRemoveValue));
  229. For S in TColmediaSize do
  230. begin
  231. if FSpan[S]<>0 then
  232. Result:=Result+' col-'+IdxNames[S]+IntToStr(FSpan[S]);
  233. Classes:=AddClasses(C,Result);
  234. end;
  235. end;
  236. function TColWidget.WidgetClasses: String;
  237. begin
  238. Result:='col '+inherited WidgetClasses;
  239. end;
  240. constructor TColWidget.Create(aOwner: TComponent);
  241. begin
  242. inherited Create(aOwner);
  243. DefaultColSpan:=12;
  244. end;
  245. { TRowWidget }
  246. function TRowWidget.WidgetClasses: String;
  247. begin
  248. Result:='row '+inherited WidgetClasses;
  249. end;
  250. { TBootstrapButton }
  251. procedure TBootstrapButton.SetContextual(AValue: TContextual);
  252. Var
  253. Old : TContextual;
  254. begin
  255. if FContextual=AValue then Exit;
  256. old:=FContextual;
  257. FContextual:=AValue;
  258. RecalcClasses(Old,FOutline);
  259. end;
  260. procedure TBootstrapButton.SetOutLine(AValue: Boolean);
  261. Var
  262. Old : Boolean;
  263. begin
  264. if FOutLine=AValue then Exit;
  265. old:=FoutLine;
  266. FOutLine:=AValue;
  267. RecalcClasses(FContextual,Old);
  268. end;
  269. function TBootstrapButton.RecalcClasses(aOldContextual: TContextual; aOldOutline: Boolean): String;
  270. Const
  271. OL : Array[Boolean] of string = ('','outline-');
  272. Var
  273. c : String;
  274. begin
  275. Result:='btn btn-'+OL[FOutLine]+ContextualNames[FContextual];
  276. C:=RemoveClasses(Classes,'btn-'+OL[aOldOutLine]+ContextualNames[aOldContextual]);
  277. Classes:=AddClasses(C,Result);
  278. end;
  279. constructor TBootstrapButton.Create(aOwner: TComponent);
  280. begin
  281. inherited Create(aOwner);
  282. Contextual:=cPrimary;
  283. end;
  284. { TToastManager }
  285. class function TToastManager.Instance: TToastManager;
  286. begin
  287. if _instance=Nil then
  288. _instance:=TToastManager.Create(Nil);
  289. Result:=_instance;
  290. end;
  291. procedure TToastManager.CheckInit;
  292. begin
  293. if not IsRendered then
  294. Refresh;
  295. end;
  296. procedure TToastManager.SetMinHeight(AValue: Integer);
  297. begin
  298. if FMinheight=AValue then Exit;
  299. FMinheight:=AValue;
  300. if IsRendered then
  301. Refresh;
  302. end;
  303. procedure TToastManager.SetMultiToast(AValue: Boolean);
  304. begin
  305. if FMultiToast=AValue then Exit;
  306. FMultiToast:=AValue;
  307. if IsRendered then refresh;
  308. end;
  309. class function TToastManager.DefaultParentElement: TJSHTMLElement;
  310. begin
  311. Result:=TJSHTMLElement(Document.body);
  312. end;
  313. function TToastManager.DoRenderHTML(aParent, aElement: TJSHTMLElement): TJSHTMLElement;
  314. Var
  315. El : TJSHTMLElement;
  316. begin
  317. Result:=AElement;
  318. Result['aria-live']:='polite';
  319. Result['aria-atomic']:='true';
  320. Result['style']:='position: relative; min-height: '+IntToStr(MinHeight)+'px;';
  321. if not MultiToast then
  322. FContentElement:=Result
  323. else
  324. begin
  325. El:=CreateElement('div',ElementID+'-multi');
  326. El['style']:='position: absolute; top: 0; right: 0;';
  327. FContentElement:=El;
  328. Result.AppendChild(El);
  329. end;
  330. end;
  331. function TToastManager.GetContentElement: TJSHTMLELement;
  332. begin
  333. Result:=FContentElement;
  334. if (Result=Nil) then
  335. Result:=Element;
  336. end;
  337. procedure TToastManager.InvalidateElement;
  338. begin
  339. inherited;
  340. FContentElement:=nil;
  341. end;
  342. function TToastManager.HTMLTag: String;
  343. begin
  344. Result:='div';
  345. end;
  346. constructor TToastManager.Create(aOwner: TComponent);
  347. begin
  348. inherited Create(aOwner);
  349. FMinHeight:=250;
  350. FMinWidth:=200;
  351. FMultiToast:=True;
  352. FHideDelay:=2000;
  353. FAutoHide:=True;
  354. FAnimate:=False;
  355. end;
  356. function TToastManager.ShowToast(const aHeader, aBody: String; aContext : TContextual = cNone; Closable: Boolean = True): TSimpleToastWidget;
  357. begin
  358. CheckInit;
  359. Result:=TSimpleToastWidget.Create(Self) ;
  360. With Result do
  361. begin
  362. Parent:=Self;
  363. Header:=aHeader;
  364. Body:=aBody;
  365. HeaderImage:=ToastIcon;
  366. CloseButton:=Closable;
  367. Contextual:=aContext;
  368. AutoHide:=ToastAutoHide;
  369. HideDelay:=ToastHideDelay;
  370. Animate:=ToastAnimate;
  371. MinWidth:=ToastMinWidth;
  372. Refresh;
  373. end;
  374. end;
  375. { TSimpleToastWidget }
  376. function TSimpleToastWidget.CloseButtonHTML: String;
  377. Var
  378. S : String;
  379. begin
  380. S:=ContextualNames[Contextual];
  381. if S<>'' then
  382. S:='text-'+S;
  383. Result:=Result+ '<button type="button" class="ml-2 mb-1 close '+S+'" data-dismiss="toast" aria-label="Close">';
  384. Result:=Result+ ' <span aria-hidden="true">&times;</span>';
  385. Result:=Result+ '</button>';
  386. end;
  387. function TSimpleToastWidget.HeaderHTML: String;
  388. Var
  389. S : String;
  390. begin
  391. S:=ContextualNames[Contextual];
  392. if S<>'' then
  393. S:='text-'+S;
  394. Result:='<div class="toast-header '+S+'">';
  395. if HeaderImage<>'' then
  396. Result:=Result+'<img src="'+HeaderImage+'" class="rounded mr-2">';
  397. Result:=Result+'<div class="mr-auto">'+Header+'</div>';
  398. if (SmallHeader<>'') then
  399. Result:=Result+'<small>'+SmallHeader+'</small>';
  400. if CloseButton then
  401. Result:=Result+CloseButtonHTML;
  402. Result:=Result+'</div>';
  403. end;
  404. procedure TSimpleToastWidget.SetBody(AValue: String);
  405. begin
  406. if FBody=AValue then Exit;
  407. FBody:=AValue;
  408. if isRendered then Refresh;
  409. end;
  410. procedure TSimpleToastWidget.SetAnimate(AValue: Boolean);
  411. begin
  412. if FAnimate=AValue then Exit;
  413. FAnimate:=AValue;
  414. if isRendered then Refresh;
  415. end;
  416. procedure TSimpleToastWidget.SetAutoHide(AValue: Boolean);
  417. begin
  418. if FAutoHide=AValue then Exit;
  419. FAutoHide:=AValue;
  420. if isRendered then Refresh;
  421. end;
  422. procedure TSimpleToastWidget.SetBoolean(AValue: Boolean);
  423. begin
  424. if FBoolean=AValue then Exit;
  425. FBoolean:=AValue;
  426. if isRendered then Refresh;
  427. end;
  428. procedure TSimpleToastWidget.SetContextual(AValue: TContextual);
  429. begin
  430. if FContextual=AValue then Exit;
  431. FContextual:=AValue;
  432. if isRendered then Refresh;
  433. end;
  434. procedure TSimpleToastWidget.SetHeader(AValue: String);
  435. begin
  436. if FHeader=AValue then Exit;
  437. FHeader:=AValue;
  438. if isRendered then Refresh;
  439. end;
  440. procedure TSimpleToastWidget.SetHeaderImage(AValue: String);
  441. begin
  442. if FHeaderImage=AValue then Exit;
  443. FHeaderImage:=AValue;
  444. if isRendered then Refresh;
  445. end;
  446. procedure TSimpleToastWidget.SetHideDelay(AValue: Integer);
  447. begin
  448. if FHideDelay=AValue then Exit;
  449. FHideDelay:=AValue;
  450. if isRendered then Refresh;
  451. end;
  452. procedure TSimpleToastWidget.SetMinWidth(AValue: Integer);
  453. begin
  454. if FMinWidth=AValue then Exit;
  455. FMinWidth:=AValue;
  456. if isRendered then Refresh;
  457. end;
  458. procedure TSimpleToastWidget.SetSmallHeader(AValue: String);
  459. begin
  460. if FSmallHeader=AValue then Exit;
  461. FSmallHeader:=AValue;
  462. if isRendered then Refresh;
  463. end;
  464. function TSimpleToastWidget.BodyHTML: String;
  465. Var
  466. S : String;
  467. begin
  468. S:=ContextualNames[Contextual];
  469. if S<>'' then
  470. S:='alert-'+S;
  471. Result:='<div class="toast-body '+S+'">';
  472. Result:=Result+Body;
  473. Result:=Result+'</div>';
  474. end;
  475. function TSimpleToastWidget.GetTemplateHTML: String;
  476. Var
  477. Head : String;
  478. begin
  479. Result:='<div class="toast" aria-live="assertive" aria atomic="true" style="min-width: '+IntToStr(MinWidth)+'px;">';
  480. Result:=Result+HeaderHTML;
  481. Result:=Result+BodyHTML;
  482. Result:=Result+'</div>';
  483. end;
  484. function TSimpleToastWidget.DoRenderHTML(aParent, aElement: TJSHTMLElement): TJSHTMLElement;
  485. begin
  486. Result:=inherited DoRenderHTML(aParent, aElement);
  487. JQuery(Result).toast(New(['animation',FAnimate,'autohide',autohide,'delay',FHideDelay]));
  488. JQuery(Result).ToastShow;
  489. end;
  490. constructor TSimpleToastWidget.Create(aOwner: TComponent);
  491. begin
  492. inherited Create(aOwner);
  493. FMinWidth:=200;
  494. FAutoHide:=True;
  495. FHideDelay:=2000;
  496. end;
  497. procedure TSimpleToastWidget.Hide;
  498. begin
  499. JQuery(Element).Toast('hide');
  500. end;
  501. { TModalReferenceItem }
  502. procedure TModalReferenceItem.Assign(Source: TPersistent);
  503. begin
  504. if Source is TModalReferenceItem then
  505. Self.Kind:=TModalReferenceItem(Source).Kind
  506. else
  507. inherited Assign(Source);
  508. end;
  509. function TModalReferenceItem.GetValue: String;
  510. begin
  511. if (Kind=mikValue) and (Element<>Nil) then
  512. Result:=TJSHTMLInputElement(Element).value;
  513. end;
  514. procedure TModalReferenceItem.SetValue(aValue: String);
  515. begin
  516. if (Kind=mikValue) and (Element<>Nil) then
  517. TJSHTMLInputElement(Element).value:=aValue;
  518. end;
  519. { TModalReferences }
  520. function TModalReferences.GetMR(aIndex : Integer): TModalReferenceItem;
  521. begin
  522. Result:=TModalReferenceItem(Items[aIndex])
  523. end;
  524. procedure TModalReferences.SetMR(aIndex : Integer; AValue: TModalReferenceItem);
  525. begin
  526. Items[aIndex]:=aValue;
  527. end;
  528. function TModalReferences.Add(const aName: String; aSelector: String; aKind: TModalItemKind): TModalReferenceItem;
  529. begin
  530. Result:=TModalReferenceItem(Inherited Add(aName,aselector));
  531. Result.Kind:=aKind;
  532. end;
  533. { TBootstrapModal }
  534. procedure TBootstrapModal.Hide;
  535. begin
  536. if Assigned(Element) then
  537. jQuery(Element).ModalHide;
  538. end;
  539. function TBootstrapModal.HideClick (Event : TJSEvent): Boolean;
  540. begin
  541. // Writeln('In hide click');
  542. FHideEl:=TJSHtmlElement(Event.targetElement);
  543. Hide;
  544. end;
  545. function TBootstrapModal.GetModalReferences: TModalReferences;
  546. begin
  547. Result:=TModalReferences(Inherited References);
  548. end;
  549. procedure TBootstrapModal.SetModalReferences(AValue: TModalReferences);
  550. begin
  551. References.Assign(aValue);
  552. end;
  553. procedure TBootstrapModal.SetTemplate(AValue: String);
  554. begin
  555. if FTemplate=AValue then Exit;
  556. if Showing Then
  557. Raise EWidgets.Create('Cannot set template while showing bootstrap modal');
  558. FTemplate:=AValue;
  559. If IsRendered then
  560. Refresh;
  561. end;
  562. procedure TBootstrapModal.GetValues(aList: TStrings);
  563. Var
  564. I : integer;
  565. Itm : TModalReferenceItem;
  566. begin
  567. For I:=0 to references.Count-1 do
  568. begin
  569. Itm:=references[i];
  570. if (itm.Kind=mikValue) and assigned(itm.Element) then
  571. aList.Values[Itm.Name]:=Itm.Value
  572. end;
  573. end;
  574. function TBootstrapModal.BootstrapHide(Event: TJSEvent): Boolean;
  575. Var
  576. L : Tstrings;
  577. I,C : integer;
  578. begin
  579. Result:=False;
  580. FShowing:=False;
  581. // Writeln('In bootstraphide callback ', assigned(onhide));
  582. If Assigned(OnHide) then
  583. begin
  584. C:=0;
  585. L:=Nil;
  586. For I:=0 to references.Count-1 do
  587. if references[i].Kind=mikValue then Inc(C);
  588. if C>0 then
  589. begin
  590. L:=TStringList.Create;
  591. GetValues(L);
  592. end;
  593. Try
  594. OnHide(Self,FHideEl,L);
  595. finally
  596. L.Free;
  597. end;
  598. end;
  599. end;
  600. function TBootstrapModal.DoRenderHTML(aParent, aElement: TJSHTMLElement): TJSHTMLElement;
  601. begin
  602. FHideEl:=Nil;
  603. Result:=inherited DoRenderHTML(aParent, aElement);
  604. JQuery(Result).modal(New([
  605. 'backdrop', BackDrop,
  606. 'keyboard', keyboard,
  607. 'focus',Focus,
  608. 'show',ShowOnRender
  609. ]));
  610. jQuery(Result).on_('hidden.bs.modal',@BootstrapHide);
  611. end;
  612. function TBootstrapModal.GetTemplateHTML: String;
  613. begin
  614. Result:=FTemplate;
  615. end;
  616. procedure TBootstrapModal.RefreshReferences;
  617. Var
  618. I : Integer;
  619. E : TJSHTMLElement;
  620. MR : TModalReferenceItem;
  621. begin
  622. inherited RefreshReferences;
  623. E:=References.FindElementByName('OK');
  624. if (E<>Nil) then
  625. jQuery(E).on_('click',@HideClick);
  626. for I:=0 to References.Count-1 do
  627. begin
  628. MR:=References[i];
  629. if (MR.Kind=mikClose) then
  630. begin
  631. if MR.Exists then
  632. if Not MR.IsArray then
  633. jQuery(MR.Element).on_('click',@HideClick)
  634. else
  635. For E in MR.Elements do
  636. jQuery(E).on_('click',@HideClick);
  637. end
  638. else if (MR.Kind=mikValue) then
  639. begin
  640. if (MR.element<>Nil) and (MR.InitialValue<>'') then
  641. MR.Value:=MR.InitialValue;
  642. end;
  643. end;
  644. end;
  645. function TBootstrapModal.CreateReferences: TWebWidgetReferences;
  646. begin
  647. Result:=TModalReferences.Create(Self,TModalReferenceItem);
  648. end;
  649. procedure TBootstrapModal.Show;
  650. begin
  651. FHideEl:=Nil;
  652. if not IsRendered then
  653. Refresh;
  654. JQuery(Element).ModalShow;
  655. FShowing:=True;
  656. end;
  657. end.