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 2019/09/09 15:31:31 UTC
[myfaces-tobago] branch master updated: TOBAGO-1921 Bootstrap file
upload; TOBAGO-1633 TS refactoring
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 2e472db TOBAGO-1921 Bootstrap file upload; TOBAGO-1633 TS refactoring
2e472db is described below
commit 2e472db97372b71c96e8a4096ad2b38a277381fe
Author: Henning Noeth <hn...@apache.org>
AuthorDate: Mon Sep 9 17:31:12 2019 +0200
TOBAGO-1921 Bootstrap file upload; TOBAGO-1633 TS refactoring
* implement tobago-file as custom elements
* render tobago-file with custom-file-* CSS class from bootstrap
---
.../tobago/internal/component/AbstractUIFile.java | 2 +-
.../internal/renderkit/renderer/FileRenderer.java | 65 +++++++------------
.../tobago/renderkit/css/BootstrapClass.java | 3 +
.../myfaces/tobago/renderkit/css/TobagoClass.java | 3 +-
.../tobago/renderkit/html/HtmlElements.java | 1 +
tobago-core/src/main/resources/scss/_tobago.scss | 32 ++++------
.../src/main/npm/ts/tobago-file.ts | 74 +++++++++++++---------
7 files changed, 85 insertions(+), 95 deletions(-)
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIFile.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIFile.java
index 3a4e670..16b5ba2 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIFile.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIFile.java
@@ -73,7 +73,7 @@ public abstract class AbstractUIFile extends UIInput implements SupportsLabelLay
@Override
public String getFieldId(final FacesContext facesContext) {
- return getClientId(facesContext) + ComponentUtils.SUB_SEPARATOR + "real";
+ return getClientId(facesContext) + ComponentUtils.SUB_SEPARATOR + "field";
}
public boolean isLabelLayoutSkip() {
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/FileRenderer.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/FileRenderer.java
index 4a58f30..e29695e 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/FileRenderer.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/FileRenderer.java
@@ -27,11 +27,9 @@ import org.apache.myfaces.tobago.internal.util.JsonUtils;
import org.apache.myfaces.tobago.internal.util.PartUtils;
import org.apache.myfaces.tobago.internal.util.RenderUtils;
import org.apache.myfaces.tobago.renderkit.css.BootstrapClass;
-import org.apache.myfaces.tobago.renderkit.css.Icons;
import org.apache.myfaces.tobago.renderkit.css.TobagoClass;
import org.apache.myfaces.tobago.renderkit.html.DataAttributes;
import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
-import org.apache.myfaces.tobago.renderkit.html.HtmlButtonTypes;
import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
import org.apache.myfaces.tobago.renderkit.html.HtmlInputTypes;
import org.apache.myfaces.tobago.util.ComponentUtils;
@@ -121,6 +119,7 @@ public class FileRenderer extends MessageLayoutRendererBase implements Component
final String clientId = file.getClientId(facesContext);
final String fieldId = file.getFieldId(facesContext);
final String accept = createAcceptFromValidators(file);
+ final String placeholder = file.getPlaceholder();
final boolean multiple = file.isMultiple() && !file.isRequired();
final boolean disabled = file.isDisabled();
final boolean readonly = file.isReadonly();
@@ -130,74 +129,54 @@ public class FileRenderer extends MessageLayoutRendererBase implements Component
final TobagoResponseWriter writer = getResponseWriter(facesContext);
- writer.startElement(HtmlElements.DIV);
+ writer.startElement(HtmlElements.TOBAGO_FILE);
if (file.isLabelLayoutSkip()) {
writer.writeIdAttribute(clientId);
}
writer.writeClassAttribute(
- TobagoClass.FILE,
+ BootstrapClass.CUSTOM_FILE,
TobagoClass.FILE.createMarkup(file.getMarkup()),
file.getCustomClass());
HtmlRendererUtils.writeDataAttributes(facesContext, writer, file);
- // visible fake input for a pretty look
- writer.startElement(HtmlElements.DIV);
- writer.writeClassAttribute(BootstrapClass.INPUT_GROUP);
- writer.startElement(HtmlElements.INPUT);
- writer.writeAttribute(HtmlAttributes.TYPE, HtmlInputTypes.TEXT);
- writer.writeAttribute(HtmlAttributes.ACCEPT, accept, true);
- writer.writeAttribute(HtmlAttributes.TABINDEX, -1);
- writer.writeAttribute(HtmlAttributes.DISABLED, disabled || readonly);
- writer.writeAttribute(HtmlAttributes.READONLY, readonly);
- if (!disabled && !readonly) {
- writer.writeAttribute(HtmlAttributes.PLACEHOLDER, file.getPlaceholder(), true);
- }
-
- writer.writeClassAttribute(
- TobagoClass.FILE__PRETTY,
- BootstrapClass.FORM_CONTROL,
- BootstrapClass.borderColor(ComponentUtils.getMaximumSeverity(file)));
- // TODO Focus
- //HtmlRendererUtils.renderFocus(clientId, file.isFocus(), ComponentUtils.isError(file), facesContext, writer);
- writer.endElement(HtmlElements.INPUT);
-
- // invisible file input
writer.startElement(HtmlElements.INPUT);
writer.writeAttribute(HtmlAttributes.MULTIPLE, multiple);
writer.writeAttribute(HtmlAttributes.TYPE, HtmlInputTypes.FILE);
writer.writeAttribute(HtmlAttributes.ACCEPT, accept, true);
writer.writeAttribute(HtmlAttributes.TABINDEX, -1);
writer.writeIdAttribute(fieldId);
- writer.writeClassAttribute(TobagoClass.FILE__REAL);
+ writer.writeClassAttribute(
+ BootstrapClass.CUSTOM_FILE_INPUT,
+ BootstrapClass.borderColor(ComponentUtils.getMaximumSeverity(file)));
writer.writeNameAttribute(clientId);
final String multiFormat = ResourceUtils.getString(facesContext, "file.selected");
writer.writeAttribute(DataAttributes.dynamic("tobago-file-multi-format"), multiFormat, true);
// readonly seems not making sense in browsers.
writer.writeAttribute(HtmlAttributes.DISABLED, disabled || readonly);
writer.writeAttribute(HtmlAttributes.READONLY, readonly);
+ if (!disabled && !readonly) {
+ writer.writeAttribute(HtmlAttributes.PLACEHOLDER, placeholder, true);
+ }
writer.writeAttribute(HtmlAttributes.REQUIRED, file.isRequired());
+ // TODO Focus
+ //HtmlRendererUtils.renderFocus(clientId, file.isFocus(), ComponentUtils.isError(file), facesContext, writer);
final String title = HtmlRendererUtils.getTitleFromTipAndMessages(facesContext, file);
if (title != null) {
writer.writeAttribute(HtmlAttributes.TITLE, title, true);
}
-
writer.writeCommandMapAttribute(JsonUtils.encode(RenderUtils.getBehaviorCommands(facesContext, file)));
-
writer.endElement(HtmlElements.INPUT);
- writer.startElement(HtmlElements.SPAN);
- writer.writeClassAttribute(BootstrapClass.INPUT_GROUP_APPEND);
- writer.startElement(HtmlElements.BUTTON);
- writer.writeAttribute(HtmlAttributes.TABINDEX, file.getTabIndex());
- writer.writeClassAttribute(BootstrapClass.BTN, BootstrapClass.BTN_SECONDARY);
- writer.writeAttribute(HtmlAttributes.TYPE, HtmlButtonTypes.BUTTON);
- writer.writeAttribute(HtmlAttributes.DISABLED, disabled || readonly);
- writer.startElement(HtmlElements.I);
- writer.writeClassAttribute(Icons.FA, Icons.FOLDER_OPEN);
- writer.endElement(HtmlElements.I);
- writer.endElement(HtmlElements.BUTTON);
- writer.endElement(HtmlElements.SPAN);
- writer.endElement(HtmlElements.DIV);
+ writer.startElement(HtmlElements.LABEL);
+ writer.writeClassAttribute(
+ BootstrapClass.CUSTOM_FILE_LABEL,
+ placeholder != null ? TobagoClass.FILE__PLACEHOLDER : null
+ );
+ writer.writeAttribute(HtmlAttributes.FOR, fieldId, false);
+ if (placeholder != null && !disabled && !readonly) {
+ writer.writeText(placeholder);
+ }
+ writer.endElement(HtmlElements.LABEL);
}
private String createAcceptFromValidators(final AbstractUIFile file) {
@@ -221,7 +200,7 @@ public class FileRenderer extends MessageLayoutRendererBase implements Component
@Override
protected void encodeEndField(final FacesContext facesContext, final UIComponent component) throws IOException {
final TobagoResponseWriter writer = getResponseWriter(facesContext);
- writer.endElement(HtmlElements.DIV);
+ writer.endElement(HtmlElements.TOBAGO_FILE);
}
@Override
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 b62151e..3d3b21c 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
@@ -240,6 +240,9 @@ public enum BootstrapClass implements CssItem {
COL_XS_12("col-12"),
CONTAINER("container"),
CONTAINER_FLUID("container-fluid"),
+ CUSTOM_FILE("custom-file"),
+ CUSTOM_FILE_INPUT("custom-file-input"),
+ CUSTOM_FILE_LABEL("custom-file-label"),
CUSTOM_SELECT("custom-select"),
D_FLEX("d-flex"),
D_INLINE("d-inline"),
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/css/TobagoClass.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/css/TobagoClass.java
index 324cdbd..e8ac261 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/css/TobagoClass.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/css/TobagoClass.java
@@ -122,8 +122,7 @@ public enum TobagoClass implements CssItem {
COLLAPSED("tobago-collapsed"),
DATE("tobago-date"),
FILE("tobago-file"),
- FILE__PRETTY("tobago-file-pretty"),
- FILE__REAL("tobago-file-real"),
+ FILE__PLACEHOLDER("tobago-file-placeholder"),
FLEX_LAYOUT("tobago-flexLayout"),
FLOW_LAYOUT("tobago-flowLayout"),
FIGURE("tobago-figure"),
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/html/HtmlElements.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/html/HtmlElements.java
index b84f6e1..b7efb4d 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/html/HtmlElements.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/html/HtmlElements.java
@@ -133,6 +133,7 @@ public enum HtmlElements {
VIDEO("video"),
WBR("wbr", Qualifier.VOID),
+ TOBAGO_FILE("tobago-file"),
TOBAGO_IN("tobago-in"),
TOBAGO_PANEL("tobago-panel"),
TOBAGO_POPUP("tobago-popup"),
diff --git a/tobago-core/src/main/resources/scss/_tobago.scss b/tobago-core/src/main/resources/scss/_tobago.scss
index e4c2b75..906256d 100644
--- a/tobago-core/src/main/resources/scss/_tobago.scss
+++ b/tobago-core/src/main/resources/scss/_tobago.scss
@@ -72,6 +72,7 @@ $input-btn-focus-color: rgba(theme-color("primary"), .25) !default;
$input-btn-focus-box-shadow: 0 0 0 $input-btn-focus-width $input-btn-focus-color !default;
$input-focus-box-shadow: $input-btn-focus-box-shadow !default;
$form-check-inline-input-margin-x: 0.75rem;
+$input-placeholder-color: $gray-600 !default;
/* used icons ---------------------------------------------------- */
@@ -236,23 +237,18 @@ XXX workaround for Bootstrap with datetimepicker needed for popups
}
/* file -------------------------------------------------------------- */
+.tobago-file {} //TODO remove
+tobago-file {
+ .custom-file-label {
+ &:after {
+ font-family: FontAwesome;
+ content: "\f07c";
+ }
-.tobago-file {
- position: relative;
-}
-
-.tobago-file-pretty {
- text-overflow: ellipsis;
-}
-
-.tobago-file-real {
- position: absolute;
- right: 0;
- top: 0;
- bottom: 0;
- opacity: 0;
- width: 100%;
- z-index: 2;
+ &.tobago-file-placeholder {
+ color: $input-placeholder-color;
+ }
+ }
}
/* flexLayout -------------------------------------------------------------- */
@@ -281,7 +277,7 @@ XXX workaround for Bootstrap with datetimepicker needed for popups
.tobago-flexLayout.tobago-label-container > {
.form-control, .form-control-plaintext, .twitter-typeahead,
.tobago-input-group-outer, .tobago-messages-container,
- .tobago-file, .tobago-selectManyShuttle {
+ .tobago-selectManyShuttle {
flex: 1 0 0px;
}
}
@@ -502,7 +498,7 @@ a.tobago-messages-button, a.tobago-help-button {
}
.tobago-flexLayout.tobago-messages-container > {
- .twitter-typeahead, .tobago-input-group-outer, .tobago-selectManyShuttle, .tobago-file {
+ .twitter-typeahead, .tobago-input-group-outer, .tobago-selectManyShuttle {
flex: 1 0 0px;
}
}
diff --git a/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-file.ts b/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-file.ts
index 8b57f39..03cbdb7 100644
--- a/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-file.ts
+++ b/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-file.ts
@@ -15,38 +15,50 @@
* limitations under the License.
*/
-import {Listener, Phase} from "./tobago-listener";
-import {DomUtils} from "./tobago-utils";
-
-class File {
-
- static init(element: HTMLElement) {
- for (const e of DomUtils.selfOrQuerySelectorAll(element, ".tobago-file-real")) {
- const real = e as HTMLInputElement;
- real.addEventListener("change", function () {
- const pretty = real.parentElement.querySelector(".tobago-file-pretty") as HTMLInputElement;
- let text: string;
- if (real.multiple) {
- const format: string = real.dataset["tobagoFileMultiFormat"];
- text = format.replace("{}", String(real.files.length));
- } else {
- text = <string>real.value;
- // remove path, if any. Some old browsers set the path, others like webkit uses the prefix "C:\path\".
- const pos: number = Math.max(text.lastIndexOf('/'), text.lastIndexOf('\\'));
- if (pos >= 0) {
- text = text.substr(pos + 1);
- }
+export class File extends HTMLElement {
+
+ constructor() {
+ super();
+ }
+
+ connectedCallback() {
+ this.input.form.enctype = "multipart/form-data";
+
+ this.input.addEventListener("change", this.select.bind(this));
+ }
+
+ get input(): HTMLInputElement {
+ return this.querySelector(".custom-file-input");
+ }
+
+ get label(): HTMLInputElement {
+ return this.querySelector(".custom-file-label");
+ }
+
+ select(event: MouseEvent) {
+ if (this.input.value === "") {
+ this.label.classList.add("tobago-file-placeholder");
+ this.label.textContent = this.input.placeholder;
+ } else {
+ this.label.classList.remove("tobago-file-placeholder");
+
+ let text: string;
+ if (this.input.multiple) {
+ const format: string = this.input.dataset["tobagoFileMultiFormat"];
+ text = format.replace("{}", String(this.input.files.length));
+ } else {
+ text = this.input.value;
+ // remove path, if any. Some old browsers set the path, others like webkit uses the prefix "C:\path\".
+ const pos: number = Math.max(text.lastIndexOf('/'), text.lastIndexOf('\\'));
+ if (pos >= 0) {
+ text = text.substr(pos + 1);
}
- pretty.value = text;
- });
- // click on the button (when using focus with keyboard)
- real.parentElement.querySelector("button").addEventListener("click", function () {
- real.click();
- });
- real.form.enctype = "multipart/form-data";
+ }
+ this.label.textContent = text;
}
- };
+ }
}
-Listener.register(File.init, Phase.DOCUMENT_READY);
-Listener.register(File.init, Phase.AFTER_UPDATE);
+document.addEventListener("DOMContentLoaded", function (event) {
+ window.customElements.define('tobago-file', File);
+});