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"><tc:button label="Open" omit="true">
- <tc:operation name="show" for="clientPopup"/>
-</tc:button></demo-highlight>
+ <tc:operation name="show" for="clientPopup"/>
+ </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"><tc:button label="Submit">
- <f:ajax execute="in" render="in :::out clientPopupMessages"/>
-</tc:button></demo-highlight>
- <p>The 'Submit'-button send an ajax request to submit the value in the input field.
- </p>
-
- <b>Submit & Close</b>
- <demo-highlight language="markup"><tc:button label="Submit & Close">
- <tc:operation name="hide" for="clientPopup"/>
-</tc:button></demo-highlight>
- <p>The 'Submit & Close'-button execute a submit and run the operation 'hide' to close the popup.</p>
-
- <b>Cancel</b>
- <demo-highlight language="markup"><tc:button label="Cancel" omit="true">
- <tc:operation name="hide" for="clientPopup"/>
-</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 & 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"><tc:button label="Submit">
+ <f:ajax execute="in" render="in :::out clientPopupMessages"/>
+ </tc:button>
+ </demo-highlight>
+ <p>The 'Submit'-button send an ajax request to submit the value in the input field.
+ </p>
+
+ <b>Submit & Close</b>
+ <demo-highlight language="markup"><tc:button label="Submit & Close">
+ <tc:operation name="hide" for="clientPopup"/>
+ </tc:button>
+ </demo-highlight>
+ <p>The 'Submit & Close'-button execute a submit and run the operation 'hide' to close the popup.</p>
+
+ <b>Cancel</b>
+ <demo-highlight language="markup"><tc:button label="Cancel" omit="true">
+ <tc:operation name="hide" for="clientPopup"/>
+ </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 & 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 ---------------------------------------------------------- */