Browse Source

* Bootstrap modal and demo

michael 5 years ago
parent
commit
7a9f1cddba
2 changed files with 395 additions and 1 deletions
  1. 138 1
      demo/webwidget/widgets/demobootstrap.pp
  2. 257 0
      packages/bootstrap/bootstrapwidgets.pp

+ 138 - 1
demo/webwidget/widgets/demobootstrap.pp

@@ -5,7 +5,7 @@ unit demobootstrap;
 interface
 
 uses
-  sysutils, web, js, webwidget, htmlwidgets, bootstrapwidgets,  widgetdemo;
+  sysutils, classes, web, js, webwidget, htmlwidgets, bootstrapwidgets,  widgetdemo;
 
 Type
 
@@ -50,8 +50,144 @@ Type
     Procedure ShowDemo; override;
   end;
 
+
+  { TBootstrapModalDemo }
+
+  TBootstrapModalDemo = class(TDemoContainer)
+  Private
+    FShow : TBootstrapButton;
+    FHide : TBootstrapButton;
+    FMemo : TTextAreaWidget;
+    procedure DoHideDialog(Sender: TObject; Event: TJSEvent);
+    procedure DoModalHide(Sender: TObject; El: TJSHTMLElement; Values: TStrings);
+    procedure DoShowDialog(Sender: TObject; Event: TJSEvent);
+    Function Modal : TBootstrapModal;
+  public
+    Class Function Demohelp : String; override;
+    Class Function Description : String; override;
+    class function WebWidgetClass: TCustomWebWidgetClass; override;
+    Function GetInspectorInstance: TObject; override;
+    Procedure ShowDemo; override;
+  end;
+
+
 implementation
 
+{ TBootstrapModalDemo }
+
+procedure TBootstrapModalDemo.DoHideDialog(Sender: TObject; Event: TJSEvent);
+begin
+  Modal.Hide;
+end;
+
+procedure TBootstrapModalDemo.DoModalHide(Sender: TObject; El: TJSHTMLElement; Values: TStrings);
+begin
+  Fmemo.Lines.Add('Modal closed and returned '+IntToStr(Values.Count)+' values.');
+  FMemo.Lines.AddStrings(Values);
+end;
+
+procedure TBootstrapModalDemo.DoShowDialog(Sender: TObject; Event: TJSEvent);
+begin
+  Modal.Show;
+end;
+
+function TBootstrapModalDemo.Modal: TBootstrapModal;
+begin
+  Result:=WidgetInstance as TBootstrapModal;
+end;
+
+class function TBootstrapModalDemo.Demohelp: String;
+begin
+  Result:='Bootstrap modal showas a modal template and returns list of form values on close (hide)';
+end;
+
+class function TBootstrapModalDemo.Description: String;
+begin
+  Result:='Bootstrap modal demo';
+end;
+
+class function TBootstrapModalDemo.WebWidgetClass: TCustomWebWidgetClass;
+begin
+  Result:=TBootStrapModal;
+end;
+
+function TBootstrapModalDemo.GetInspectorInstance: TObject;
+begin
+  Result:=inherited GetInspectorInstance;
+end;
+
+
+Const
+  SampleModal =
+    '<div class="modal fade" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true"> '+
+    '  <div class="modal-dialog" role="document">'+
+    '    <div class="modal-content">'+
+    '      <div class="modal-header">'+
+    '        <h5 class="modal-title" id="exampleModalLabel">Modal title</h5>'+
+    '        <button type="button" class="close" data-dismiss="modal" aria-label="Close">'+
+    '          <span aria-hidden="true">&times;</span>'+
+    '        </button>'+
+    '      </div>'+
+    '      <div class="modal-body">'+
+    '        <p>Modal body text goes here.</p>'+
+    '      </div>'+
+    '      <div class="modal-footer">'+
+    '        <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>'+
+    '        <button type="button" class="btn btn-primary">Save changes</button>'+
+    '      </div>'+
+    '    </div>'+
+    '  </div>'+
+    '</div>';
+
+procedure TBootstrapModalDemo.ShowDemo;
+
+Var
+  T : TContextual;
+  R : TRowWidget;
+  C : TColWidget;
+
+  Procedure AddRow;
+  begin
+    R:=TRowWidget.Create(Self);
+    R.Parent:=Self;
+    C:=TColWidget.Create(Self);
+    C.DefaultColSpan:=6;
+    C.Parent:=R;
+  end;
+
+begin
+  inherited ShowDemo;
+  Modal.Template:=SampleModal;
+  AddRow;
+  C.DefaultColSpan:=6;
+  FShow:=TBootstrapButton.Create(Self);
+  FShow.OnClick:=@DoShowDialog;
+  FShow.Contextual:=cPrimary;
+  FShow.Parent:=C;
+  FShow.Text:='Show dialog';
+  C:=TColWidget.Create(Self);
+  C.Parent:=R;
+  C.DefaultColSpan:=6;
+  FHide:=TBootstrapButton.Create(Self);
+  FHide.OnClick:=@DoHideDialog;
+  FHide.Contextual:=cSecondary;
+  FHide.Parent:=C;
+  FHide.Text:='Hide dialog';
+  AddRow;
+  With TLabelWidget.Create(Self) do
+    begin
+    Text:='Log:';
+    Parent:=C;
+    end;
+  AddRow;
+  FMemo:=TTextAreaWidget.Create(Self);
+  FMemo.Parent:=C;
+  FMemo.Columns:=80;
+  FMemo.Rows:=25;
+  Modal.OnHide:=@DoModalHide;
+  Refresh;
+end;
+
 { TToastManagerDemo }
 
 procedure TToastManagerDemo.DoShowToast(Sender: TObject; Event: TJSEvent);
@@ -183,5 +319,6 @@ initialization
   TBootstrapButtonDemo.RegisterDemo;
   TSimpleToastWidgetDemo.RegisterDemo;
   TToastManagerDemo.RegisterDemo;
+  TBootstrapModalDemo.Registerdemo;
 end.
 

+ 257 - 0
packages/bootstrap/bootstrapwidgets.pp

@@ -154,6 +154,75 @@ Type
     Property SmallColSpan : Integer Index 4 Read GetSpan Write SetSpan;
   end;
 
+  { TBootstrapModal }
+  TOnModalHideEvent = Procedure (Sender : TObject; El : TJSHTMLElement; Values : TStrings) of object;
+
+  TModalItemKind = (mikValue,mikClose);
+
+  { TModalReferenceItem }
+
+  TModalReferenceItem = Class(TReferenceItem)
+  private
+    FInitialValue: String;
+    FKind: TModalItemKind;
+  Protected
+    Function GetValue: String;
+    Procedure SetValue(aValue: String);
+  Public
+    Procedure Assign(Source : TPersistent); override;
+    Property Value : String Read GetValue Write SetValue;
+  Published
+    Property Kind : TModalItemKind Read FKind Write FKind;
+    Property InitialValue : String Read FInitialValue Write FInitialValue;
+  end;
+
+  { TModalReferences }
+
+  TModalReferences = Class(TWebWidgetReferences)
+  private
+    function GetMR(aIndex : Integer): TModalReferenceItem;
+    procedure SetMR(aIndex : Integer; AValue: TModalReferenceItem);
+  Public
+    Function Add(Const aName : String; aSelector : String; aKind : TModalItemKind) : TModalReferenceItem; overload;
+    Property ModalRefs[aIndex : Integer] : TModalReferenceItem Read GetMR Write SetMR; default;
+  end;
+
+  TBootstrapModal = Class(TCustomTemplateWidget)
+  private
+    FHideEl : TJSHTMLElement;
+    FBackDrop: Boolean;
+    FFocus: Boolean;
+    FKeyBoard: Boolean;
+    FOnHide: TOnModalHideEvent;
+    FShowOnRender: Boolean;
+    FTemplate: String;
+    FShowing : Boolean;
+    function GetModalReferences: TModalReferences;
+    function HideClick(Event: TJSEvent): Boolean;
+    procedure SetModalReferences(AValue: TModalReferences);
+    procedure SetTemplate(AValue: String);
+  protected
+    Function BootstrapHide(Event : TJSEvent) : Boolean;
+    Function DoRenderHTML(aParent, aElement: TJSHTMLElement): TJSHTMLElement; override;
+    Function GetTemplateHTML: String; override;
+    Procedure RefreshReferences; override;
+    Function CreateReferences: TWebWidgetReferences; override;
+  Public
+    procedure GetValues(aList: TStrings);
+    Procedure Show;
+    Procedure Hide;
+    Property Showing : Boolean Read FShowing;
+  Published
+    Property ShowOnRender: Boolean Read FShowOnRender Write FShowOnrender;
+    Property BackDrop : Boolean Read FBackDrop Write FBackDrop;
+    Property KeyBoard : Boolean Read FKeyBoard Write FKeyBoard;
+    Property Focus : Boolean Read FFocus Write FFocus;
+    Property Template : String Read FTemplate Write SetTemplate;
+    Property OnHide : TOnModalHideEvent Read FOnHide Write FOnHide;
+    Property References : TModalReferences Read GetModalReferences Write SetModalReferences;
+  end;
+
+
 Const
   ContextualNames : Array[TContextual] of string = ('','primary','secondary','success','danger','warning','info','light','dark');
 
@@ -527,4 +596,192 @@ begin
   JQuery(Element).Toast('hide');
 end;
 
+{ TModalReferenceItem }
+
+procedure TModalReferenceItem.Assign(Source: TPersistent);
+begin
+  if Source is TModalReferenceItem then
+    Self.Kind:=TModalReferenceItem(Source).Kind
+  else
+    inherited Assign(Source);
+end;
+
+function TModalReferenceItem.GetValue: String;
+begin
+  if (Kind=mikValue) and (Element<>Nil) then
+    Result:=TJSHTMLInputElement(Element).value;
+end;
+
+procedure TModalReferenceItem.SetValue(aValue: String);
+begin
+  if (Kind=mikValue) and (Element<>Nil) then
+    TJSHTMLInputElement(Element).value:=aValue;
+end;
+
+{ TModalReferences }
+
+function TModalReferences.GetMR(aIndex : Integer): TModalReferenceItem;
+begin
+  Result:=TModalReferenceItem(Items[aIndex])
+end;
+
+procedure TModalReferences.SetMR(aIndex : Integer; AValue: TModalReferenceItem);
+begin
+  Items[aIndex]:=aValue;
+end;
+
+function TModalReferences.Add(const aName: String; aSelector: String; aKind: TModalItemKind): TModalReferenceItem;
+begin
+  Result:=TModalReferenceItem(Inherited Add(aName,aselector));
+  Result.Kind:=aKind;
+end;
+
+{ TBootstrapModal }
+
+procedure TBootstrapModal.Hide;
+
+begin
+  if Assigned(Element) then
+    jQuery(Element).ModalHide;
+end;
+
+function TBootstrapModal.HideClick (Event : TJSEvent): Boolean;
+
+begin
+  // Writeln('In hide click');
+  FHideEl:=TJSHtmlElement(Event.targetElement);
+  Hide;
+end;
+
+function TBootstrapModal.GetModalReferences: TModalReferences;
+begin
+  Result:=TModalReferences(Inherited References);
+end;
+
+procedure TBootstrapModal.SetModalReferences(AValue: TModalReferences);
+begin
+  References.Assign(aValue);
+end;
+
+procedure TBootstrapModal.SetTemplate(AValue: String);
+begin
+  if FTemplate=AValue then Exit;
+  if Showing Then
+    Raise EWidgets.Create('Cannot set template while showing bootstrap modal');
+  FTemplate:=AValue;
+  If IsRendered then
+    Refresh;
+end;
+
+procedure TBootstrapModal.GetValues(aList: TStrings);
+
+Var
+  I : integer;
+  Itm : TModalReferenceItem;
+
+begin
+  For I:=0 to references.Count-1 do
+    begin
+    Itm:=references[i];
+    if (itm.Kind=mikValue) and assigned(itm.Element) then
+      aList.Values[Itm.Name]:=Itm.Value
+    end;
+end;
+
+
+function TBootstrapModal.BootstrapHide(Event: TJSEvent): Boolean;
+
+Var
+  L : Tstrings;
+  I,C : integer;
+
+begin
+  Result:=False;
+  FShowing:=False;
+  // Writeln('In bootstraphide callback ', assigned(onhide));
+  If Assigned(OnHide) then
+    begin
+    C:=0;
+    L:=Nil;
+    For I:=0 to references.Count-1 do
+      if references[i].Kind=mikValue then Inc(C);
+    if C>0 then
+      begin
+      L:=TStringList.Create;
+      GetValues(L);
+      end;
+    Try
+      OnHide(Self,FHideEl,L);
+    finally
+      L.Free;
+    end;
+    end;
+end;
+
+function TBootstrapModal.DoRenderHTML(aParent, aElement: TJSHTMLElement): TJSHTMLElement;
+
+begin
+  FHideEl:=Nil;
+  Result:=inherited DoRenderHTML(aParent, aElement);
+  JQuery(Result).modal(New([
+    'backdrop', BackDrop,
+    'keyboard', keyboard,
+    'focus',Focus,
+    'show',ShowOnRender
+  ]));
+  jQuery(Result).on_('hidden.bs.modal',@BootstrapHide);
+end;
+
+function TBootstrapModal.GetTemplateHTML: String;
+begin
+  Result:=FTemplate;
+end;
+
+procedure TBootstrapModal.RefreshReferences;
+
+Var
+  I : Integer;
+  E : TJSHTMLElement;
+  MR : TModalReferenceItem;
+
+begin
+  inherited RefreshReferences;
+  E:=References.FindElementByName('OK');
+  if (E<>Nil) then
+    jQuery(E).on_('click',@HideClick);
+  for I:=0 to References.Count-1 do
+    begin
+    MR:=References[i];
+    if (MR.Kind=mikClose) then
+      begin
+      if MR.Exists then
+        if Not MR.IsArray then
+          jQuery(MR.Element).on_('click',@HideClick)
+        else
+          For E in MR.Elements do
+            jQuery(E).on_('click',@HideClick);
+        end
+    else if (MR.Kind=mikValue) then
+      begin
+      if (MR.element<>Nil) and (MR.InitialValue<>'') then
+        MR.Value:=MR.InitialValue;
+      end;
+    end;
+end;
+
+function TBootstrapModal.CreateReferences: TWebWidgetReferences;
+begin
+  Result:=TModalReferences.Create(Self,TModalReferenceItem);
+end;
+
+procedure TBootstrapModal.Show;
+begin
+  FHideEl:=Nil;
+  if not IsRendered then
+    Refresh;
+  JQuery(Element).ModalShow;
+  FShowing:=True;
+end;
+
+
 end.