You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by hn...@apache.org on 2021/04/30 06:40:22 UTC

[myfaces-tobago] branch master updated: feature(popup): bootstrap modal

This is an automated email from the ASF dual-hosted git repository.

hnoeth pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/myfaces-tobago.git


The following commit(s) were added to refs/heads/master by this push:
     new e337e8c  feature(popup): bootstrap modal
e337e8c is described below

commit e337e8cd2eb65126954ea26ee42fbe4054b9e8c6
Author: Henning Noeth <hn...@apache.org>
AuthorDate: Wed Apr 28 16:28:21 2021 +0200

    feature(popup): bootstrap modal
    
    * add 'footer' facet
    * impl label, bar, footer for tc:popup
    * adjust theme
    * adjust popup demo
    * set autoSpacing=false for footer facet
    
    Issue: TOBAGO-2076
---
 .../apache/myfaces/tobago/component/Facets.java    |   2 +
 .../tobago/component/SupportsAutoSpacing.java      |   3 +-
 .../internal/renderkit/renderer/PopupRenderer.java |  49 ++++++++++
 .../tobago/renderkit/css/BootstrapClass.java       |   4 +
 .../content/20-component/060-popup/Popup.xhtml     | 101 ++++++++++++---------
 tobago-theme/src/main/scss/_tobago.scss            |  25 ++++-
 6 files changed, 136 insertions(+), 48 deletions(-)

diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/component/Facets.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/component/Facets.java
index 49b4802..989fecd 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/component/Facets.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/component/Facets.java
@@ -33,6 +33,7 @@ public enum Facets {
    */
   @Deprecated
   contextMenu,
+  footer,
   label,
   pagerPage,
   pagerPageDirect,
@@ -53,6 +54,7 @@ public enum Facets {
    */
   @Deprecated
   public static final String CONTEXT_MENU = "contextMenu";
+  public static final String FOOTER = "footer";
   public static final String LABEL = "label";
   public static final String PAGER_PAGE = "pagerPage";
   public static final String PAGER_PAGE_DIRECT = "pagerPageDirect";
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/component/SupportsAutoSpacing.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/component/SupportsAutoSpacing.java
index 56c66d3..130c57c 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/component/SupportsAutoSpacing.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/component/SupportsAutoSpacing.java
@@ -46,7 +46,8 @@ public interface SupportsAutoSpacing {
           && attributes.get(Facets.before) == null
           && attributes.get(Facets.after) == null
           && attributes.get(Facets.label) == null
-          && attributes.get(Facets.bar) == null;
+          && attributes.get(Facets.bar) == null
+          && attributes.get(Facets.footer) == null;
     }
   }
 }
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/PopupRenderer.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/PopupRenderer.java
index 42096f6..f33dd77 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/PopupRenderer.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/PopupRenderer.java
@@ -19,9 +19,11 @@
 
 package org.apache.myfaces.tobago.internal.renderkit.renderer;
 
+import org.apache.myfaces.tobago.component.Facets;
 import org.apache.myfaces.tobago.context.Markup;
 import org.apache.myfaces.tobago.internal.component.AbstractUIPopup;
 import org.apache.myfaces.tobago.internal.util.HtmlRendererUtils;
+import org.apache.myfaces.tobago.internal.util.RenderUtils;
 import org.apache.myfaces.tobago.model.CollapseMode;
 import org.apache.myfaces.tobago.renderkit.css.BootstrapClass;
 import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
@@ -30,6 +32,7 @@ import org.apache.myfaces.tobago.renderkit.html.HtmlRoleValues;
 import org.apache.myfaces.tobago.util.ComponentUtils;
 import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
 
+import javax.faces.component.UIComponent;
 import javax.faces.context.FacesContext;
 import java.io.IOException;
 
@@ -42,6 +45,9 @@ public class PopupRenderer<T extends AbstractUIPopup> extends CollapsiblePanelRe
     final String clientId = component.getClientId(facesContext);
     final boolean collapsed = component.isCollapsed();
     final Markup markup = component.getMarkup();
+    final UIComponent labelFacet = ComponentUtils.getFacet(component, Facets.label);
+    final UIComponent barFacet = ComponentUtils.getFacet(component, Facets.bar);
+    final UIComponent footerFacet = ComponentUtils.getFacet(component, Facets.footer);
 
     // this makes the popup NOT closable with a click to the background
     ComponentUtils.putDataAttribute(component, "backdrop", "static");
@@ -68,12 +74,55 @@ public class PopupRenderer<T extends AbstractUIPopup> extends CollapsiblePanelRe
     if (component.getCollapsedMode() != CollapseMode.none) {
       encodeHidden(writer, clientId, collapsed);
     }
+
+    if (labelFacet != null || barFacet != null) {
+      writer.startElement(HtmlElements.DIV);
+      writer.writeClassAttribute(BootstrapClass.MODAL_HEADER);
+
+      writer.startElement(HtmlElements.H5);
+      writer.writeClassAttribute(BootstrapClass.MODAL_TITLE);
+      insideBegin(facesContext, Facets.label);
+      for (final UIComponent child : RenderUtils.getFacetChildren(labelFacet)) {
+        child.encodeAll(facesContext);
+      }
+      insideEnd(facesContext, Facets.label);
+      writer.endElement(HtmlElements.H5);
+
+      insideBegin(facesContext, Facets.bar);
+      for (final UIComponent child : RenderUtils.getFacetChildren(barFacet)) {
+        child.encodeAll(facesContext);
+      }
+      insideEnd(facesContext, Facets.bar);
+
+      writer.endElement(HtmlElements.DIV);
+    }
+    if (labelFacet != null || barFacet != null || footerFacet != null) {
+      writer.startElement(HtmlElements.DIV);
+      writer.writeClassAttribute(BootstrapClass.MODAL_BODY);
+    }
   }
 
   @Override
   public void encodeEndInternal(final FacesContext facesContext, final T component) throws IOException {
 
     final TobagoResponseWriter writer = getResponseWriter(facesContext);
+    final UIComponent labelFacet = ComponentUtils.getFacet(component, Facets.label);
+    final UIComponent barFacet = ComponentUtils.getFacet(component, Facets.bar);
+    final UIComponent footerFacet = ComponentUtils.getFacet(component, Facets.footer);
+
+    if (labelFacet != null || barFacet != null || footerFacet != null) {
+      writer.endElement(HtmlElements.DIV);
+    }
+    if (footerFacet != null) {
+      writer.startElement(HtmlElements.DIV);
+      writer.writeClassAttribute(BootstrapClass.MODAL_FOOTER);
+      insideBegin(facesContext, Facets.footer);
+      for (final UIComponent child : RenderUtils.getFacetChildren(footerFacet)) {
+        child.encodeAll(facesContext);
+      }
+      insideEnd(facesContext, Facets.footer);
+      writer.endElement(HtmlElements.DIV);
+    }
     writer.endElement(HtmlElements.DIV);
     writer.endElement(HtmlElements.DIV);
     writer.endElement(HtmlElements.TOBAGO_POPUP);
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/css/BootstrapClass.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/css/BootstrapClass.java
index 2b1b2b6..b75fdfe 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/css/BootstrapClass.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/css/BootstrapClass.java
@@ -407,10 +407,14 @@ public enum BootstrapClass implements CssItem {
   MS_SM_AUTO("ms-sm-auto"),
   MS_XL_AUTO("ms-xl-auto"),
   MODAL("modal"),
+  MODAL_BODY("modal-body"),
   MODAL_CONTENT("modal-content"),
   MODAL_DIALOG("modal-dialog"),
+  MODAL_FOOTER("modal-footer"),
+  MODAL_HEADER("modal-header"),
   MODAL_LG("modal-lg"),
   MODAL_SM("modal-sm"),
+  MODAL_TITLE("modal-title"),
   ME_0("me-0"),
   ME_1("me-1"),
   ME_2("me-2"),
diff --git a/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/060-popup/Popup.xhtml b/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/060-popup/Popup.xhtml
index 104e5be..e4e043d 100644
--- a/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/060-popup/Popup.xhtml
+++ b/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/060-popup/Popup.xhtml
@@ -56,55 +56,66 @@
         It contain the ID of the popup on which the transition should be executed.</p>
 
       <demo-highlight language="markup">&lt;tc:button label="Open" omit="true">
-  &lt;tc:operation name="show" for="clientPopup"/>
-&lt;/tc:button></demo-highlight>
+        &lt;tc:operation name="show" for="clientPopup"/>
+        &lt;/tc:button>
+      </demo-highlight>
       <tc:button id="open" label="Open" omit="true">
         <tc:operation name="show" for="clientPopup"/>
       </tc:button>
       <tc:out id="out" label="Text from Popup" value="#{popupController.popup2Text}"/>
 
       <tc:popup id="clientPopup" collapsedMode="hidden">
-        <tc:box label="Client Side Popup">
-          <tc:panel id="clientPopupMessages">
-            <tc:messages id="messages"/>
-          </tc:panel>
-          <p>This is a popup dialog with an input field.</p>
-
-          <b>Submit</b>
-          <demo-highlight language="markup">&lt;tc:button label="Submit">
-  &lt;f:ajax execute="in" render="in :::out clientPopupMessages"/>
-&lt;/tc:button></demo-highlight>
-          <p>The 'Submit'-button send an ajax request to submit the value in the input field.
-          </p>
-
-          <b>Submit &amp; Close</b>
-          <demo-highlight language="markup">&lt;tc:button label="Submit &amp; Close">
-  &lt;tc:operation name="hide" for="clientPopup"/>
-&lt;/tc:button></demo-highlight>
-          <p>The 'Submit &amp; Close'-button execute a submit and run the operation 'hide' to close the popup.</p>
-
-          <b>Cancel</b>
-          <demo-highlight language="markup">&lt;tc:button label="Cancel" omit="true">
-  &lt;tc:operation name="hide" for="clientPopup"/>
-&lt;/tc:button></demo-highlight>
-          <p>The 'Cancel'-button execute a 'hide'-operation to close the popup.
-            Also the attribute <code>omit="true"</code> is set to prevent submit.</p>
-
-          <tc:in id="in2" label="Required Field" required="true" value="#{popupController.popup2Text}"/>
-          <tc:date id="d2" label="Date Field"/>
-          <tc:buttons>
-            <tc:button id="submit2" label="Submit">
-              <f:ajax execute="in2" render="in2 :::out clientPopupMessages"/>
-            </tc:button>
-            <tc:button id="submitClose2" label="Submit &amp; Close">
-              <tc:operation name="hide" for="clientPopup"/>
-              <f:ajax execute="in2" render="in2 :::out clientPopupMessages"/>
-            </tc:button>
-            <tc:button id="cancel2" label="Cancel" omit="true">
-              <tc:operation name="hide" for="clientPopup"/>
-            </tc:button>
-          </tc:buttons>
-        </tc:box>
+        <f:facet name="label">
+          Client Side Popup
+        </f:facet>
+        <f:facet name="bar">
+          <tc:link image="fa-times" omit="true">
+            <tc:operation name="hide" for="clientPopup"/>
+          </tc:link>
+        </f:facet>
+        <tc:panel id="clientPopupMessages">
+          <tc:messages id="messages"/>
+        </tc:panel>
+        <p>This is a popup dialog with an input field.</p>
+
+        <b>Submit</b>
+        <demo-highlight language="markup">&lt;tc:button label="Submit">
+          &lt;f:ajax execute="in" render="in :::out clientPopupMessages"/>
+          &lt;/tc:button>
+        </demo-highlight>
+        <p>The 'Submit'-button send an ajax request to submit the value in the input field.
+        </p>
+
+        <b>Submit &amp; Close</b>
+        <demo-highlight language="markup">&lt;tc:button label="Submit &amp; Close">
+          &lt;tc:operation name="hide" for="clientPopup"/>
+          &lt;/tc:button>
+        </demo-highlight>
+        <p>The 'Submit &amp; Close'-button execute a submit and run the operation 'hide' to close the popup.</p>
+
+        <b>Cancel</b>
+        <demo-highlight language="markup">&lt;tc:button label="Cancel" omit="true">
+          &lt;tc:operation name="hide" for="clientPopup"/>
+          &lt;/tc:button>
+        </demo-highlight>
+        <p>The 'Cancel'-button execute a 'hide'-operation to close the popup.
+          Also the attribute <code>omit="true"</code> is set to prevent submit.</p>
+
+        <tc:in id="in2" label="Required Field" required="true" value="#{popupController.popup2Text}"/>
+        <tc:date id="d2" label="Date Field"/>
+
+        <f:facet name="footer">
+          <tc:button id="submit2" label="Submit">
+            <f:ajax execute="in2" render="in2 :::out clientPopupMessages"/>
+          </tc:button>
+          <tc:button id="submitClose2" label="Submit &amp; Close">
+            <tc:operation name="hide" for="clientPopup"/>
+            <f:ajax execute="in2" render="in2 :::out clientPopupMessages"/>
+          </tc:button>
+          <tc:button id="cancel2" label="Cancel" omit="true">
+            <tc:operation name="hide" for="clientPopup"/>
+          </tc:button>
+        </f:facet>
       </tc:popup>
     </tc:form>
   </tc:section>
@@ -139,6 +150,10 @@
     </tc:popup>
   </tc:section>
 
+  <tc:section label="Plain Popup">
+
+  </tc:section>
+
   <tc:section label="Refresh Content">
     <p>The content of the popup will be refreshed with AJAX after opening the popup. The refresh method waits two
       seconds before execution.</p>
diff --git a/tobago-theme/src/main/scss/_tobago.scss b/tobago-theme/src/main/scss/_tobago.scss
index 28f62cc..e090e82 100644
--- a/tobago-theme/src/main/scss/_tobago.scss
+++ b/tobago-theme/src/main/scss/_tobago.scss
@@ -861,12 +861,29 @@ tobago-panel {
 tobago-popover {
 }
 
-/* popup ------------------------------------------------------------- */
 tobago-popup {
-}
+  .modal-header {
+    .modal-title {
+      margin-right: auto;
+    }
 
-.modal-content > .card {
-  margin-bottom: 0;
+    .tobago-link {
+      color: $btn-close-color;
+      opacity: $btn-close-opacity;
+
+      &:hover {
+        opacity: $btn-close-hover-opacity;
+      }
+
+      &:focus {
+        opacity: $btn-close-focus-opacity;
+      }
+    }
+  }
+
+  .modal-content > .card {
+    margin-bottom: 0;
+  }
 }
 
 /* progress ---------------------------------------------------------- */