diff --git a/src/main/java/net/bootsfaces/component/inputText/InputTextRenderer.java b/src/main/java/net/bootsfaces/component/inputText/InputTextRenderer.java index 1e6db7ddc..50a684a11 100644 --- a/src/main/java/net/bootsfaces/component/inputText/InputTextRenderer.java +++ b/src/main/java/net/bootsfaces/component/inputText/InputTextRenderer.java @@ -306,7 +306,7 @@ public void encodeEnd(FacesContext context, UIComponent component) throws IOExce } /** - * Add script to enable the input mask. If the mask attribute starts with {@code {}} the value is expected to be a + * Add script to enable the input mask. If the mask attribute starts with {@code {} the value is expected to be a * JSON object (and can for example be used to set a regular expression: {@code {regex:'[0-9\u0600-\u06FF]*'}}). * * See https://github.com/RobinHerbots/Inputmask. diff --git a/src/main/java/net/bootsfaces/component/slider2/Slider2Core.java b/src/main/java/net/bootsfaces/component/slider2/Slider2Core.java index 6ee546387..949cc9258 100644 --- a/src/main/java/net/bootsfaces/component/slider2/Slider2Core.java +++ b/src/main/java/net/bootsfaces/component/slider2/Slider2Core.java @@ -38,6 +38,26 @@ public String toString() { return ((this.toString != null) ? this.toString : super.toString()); } } + + /** + * Convert object to number. To be backwards compatible with bound integers to properties where we now also want + * to accept floats now. + * + * @param object Object to convert to number. Should be either a number or a string. + * + * @return Object converted to number. + * + * @throws IllegalArgumentException When an incorrect type is provided. + */ + private static Number toNumber(Object object) { + if (object instanceof Number) { + return (Number) object; + } + if (object instanceof String) { + return Float.valueOf((String) object); + } + throw new IllegalArgumentException("Use number or string"); + } /** * Setting this flag updates the widget on every AJAX request.

@@ -267,32 +287,32 @@ public void setLabelledBy(String _labelledBy) { * The maximum value of the slider. (default 100)

* @return Returns the value of the attribute, or 100, if it hasn't been set by the JSF file. */ - public int getMax() { - return (int) (Integer) getStateHelper().eval(PropertyKeys.max, 100); + public Object getMax() { + return getStateHelper().eval(PropertyKeys.max, 100); } /** * The maximum value of the slider. (default 100)

* Usually this method is called internally by the JSF engine. */ - public void setMax(int _max) { - getStateHelper().put(PropertyKeys.max, _max); + public void setMax(Object _max) { + getStateHelper().put(PropertyKeys.max, toNumber(_max)); } /** * The maximum value of the slider. (default 0)

* @return Returns the value of the attribute, or 0, if it hasn't been set by the JSF file. */ - public int getMin() { - return (int) (Integer) getStateHelper().eval(PropertyKeys.min, 0); + public Object getMin() { + return getStateHelper().eval(PropertyKeys.min, 0); } /** * The maximum value of the slider. (default 0)

* Usually this method is called internally by the JSF engine. */ - public void setMin(int _min) { - getStateHelper().put(PropertyKeys.min, _min); + public void setMin(Object _min) { + getStateHelper().put(PropertyKeys.min, toNumber(_min)); } /** @@ -427,16 +447,16 @@ public void setSpan(int _span) { * Increment step

* @return Returns the value of the attribute, or 1, if it hasn't been set by the JSF file. */ - public int getStep() { - return (int) (Integer) getStateHelper().eval(PropertyKeys.step, 1); + public Object getStep() { + return getStateHelper().eval(PropertyKeys.step, 1); } /** * Increment step

* Usually this method is called internally by the JSF engine. */ - public void setStep(int _step) { - getStateHelper().put(PropertyKeys.step, _step); + public void setStep(Object _step) { + getStateHelper().put(PropertyKeys.step, toNumber(_step)); } /** diff --git a/src/main/java/net/bootsfaces/component/slider2/Slider2Renderer.java b/src/main/java/net/bootsfaces/component/slider2/Slider2Renderer.java index 2a05d0217..e6a311695 100644 --- a/src/main/java/net/bootsfaces/component/slider2/Slider2Renderer.java +++ b/src/main/java/net/bootsfaces/component/slider2/Slider2Renderer.java @@ -21,16 +21,15 @@ import java.io.IOException; import java.lang.reflect.Method; import java.util.Map; - import javax.faces.component.UIComponent; import javax.faces.context.FacesContext; import javax.faces.context.ResponseWriter; -//!//import javax.faces.convert.DoubleConverter; import javax.faces.render.FacesRenderer; - import net.bootsfaces.component.ajax.AJAXRenderer; import net.bootsfaces.component.badge.BadgeRenderer; import net.bootsfaces.render.A; +import static net.bootsfaces.render.CoreRenderer.getRequestParameter; +import static net.bootsfaces.render.CoreRenderer.getValueType; import net.bootsfaces.render.R; import net.bootsfaces.render.Tooltip; import net.bootsfaces.utils.BsfUtils; @@ -57,26 +56,14 @@ public void decode(FacesContext context, UIComponent component) { decodeBehaviors(context, slider); String clientId = slider.getClientId(context); - String submittedValue = (String) context.getExternalContext().getRequestParameterMap().get(clientId); + Number submittedValue = convert(component, Float.valueOf(getRequestParameter(context, clientId))); if (submittedValue != null) { slider.setSubmittedValue(submittedValue); } new AJAXRenderer().decode(context, component, clientId); } -/* ! - @Override - public Object getConvertedValue(FacesContext fc, UIComponent c, Object sval) throws ConverterException { - Converter cnv = resolveConverter(fc, c); - if (cnv != null) { - return cnv.getAsObject(fc, c, (String) sval); - } else { - cnv = new DoubleConverter(); - return cnv.getAsObject(fc, c, (String) sval); - } - } -*/ /** * This methods generates the HTML code of the current b:slider2. * @param context the FacesContext. @@ -93,35 +80,67 @@ public void encodeBegin(FacesContext context, UIComponent component) throws IOEx encodeHTML(slider, context, rw); } + /** + * Returns converted value of the provided float value (to the type that is used on the component's value + * attribute). + * + * @param component Component to convert value for. + * @param value Float value to convert. + * + * @return Converted value of the provided float value (to the type that is used on the component's value + * attribute). + */ + private Number convert(UIComponent component, Float value) { + return convert((Class) getValueType(component), value); + } + + /** + * Returns converted value of the provided float value (to the provided type). + * + * @param type Type to convert float to. Currently only {@link Float} and {@link Integer} are supported. + * @param value Float value to convert. + * + * @return Converted value of the provided float value (to the provided type). + * + * @throws IllegalArgumentException If an unsupported type is provided. + */ + private Number convert(Class type, Float value) { + if (int.class.isAssignableFrom(type) || Integer.class.isAssignableFrom(type)) { + return value.intValue(); + } + if (float.class.isAssignableFrom(type) || Float.class.isAssignableFrom(type)) { + return value; + } + throw new IllegalArgumentException("Use integer or float"); + } + private void encodeHTML(Slider2 slider, FacesContext context, ResponseWriter rw) throws IOException { String clientId = slider.getClientId(context); String mode = slider.getMode(); String label = slider.getLabel(); + Class type = (Class) getValueType(slider); + if (type == null) { + type = Integer.class; + } - int min = slider.getMin(); - int max = slider.getMax(); + float min = ((Number) slider.getMin()).floatValue(); + float max = ((Number) slider.getMax()).floatValue(); Object v = slider.getSubmittedValue(); if (v == null) { v = slider.getValue(); } if (v == null) { - v = slider.getValue(); - slider.setValue(v); - } - if (v == null) { - v = max / 2; - slider.setValue(v); + v = min + (max - min) / 2; } - //!//double val = A.toDouble(v); - int val = A.toInt(v); + Float val = A.toFloat(v); if (val > max) { val = max; } if (val < min) { val = min; } - //!//String valS = Double.toString(val); + slider.setValue(convert(type, val)); String o; if (slider.getOrientation() != null) { o = slider.getOrientation(); @@ -167,7 +186,7 @@ private void encodeHTML(Slider2 slider, FacesContext context, ResponseWriter rw) rw.startElement("div", null); rw.writeAttribute("class", "row", "class"); } - encodeInput(slider, rw, mode, context, val, clientId, isVertical, min, max); + encodeInput(slider, rw, mode, context, convert(type, val), clientId, isVertical, convert(type, min), convert(type, max)); if (!bottom) { rw.endElement("div"); /* Row */ @@ -218,7 +237,7 @@ private void encodeHTML(Slider2 slider, FacesContext context, ResponseWriter rw) rw.startElement("div", null); rw.writeAttribute("class", "row", "class"); - encodeInput(slider, rw, mode, context, val, clientId, isVertical, min, max); + encodeInput(slider, rw, mode, context, convert(type, val), clientId, isVertical, convert(type, min), convert(type, max)); encodeSliderInput(slider, rw, isVertical, span, clientId, val); rw.endElement("div");/* Row */ @@ -246,8 +265,8 @@ private void encodeVLabel(Slider2 slider, ResponseWriter rw, String label) throw rw.endElement("div"); // Column } - private void encodeInput(Slider2 slider, ResponseWriter rw, String mode, FacesContext context, int val, - String clientId, boolean vo, int min, int max) throws IOException { + private void encodeInput(Slider2 slider, ResponseWriter rw, String mode, FacesContext context, Number val, + String clientId, boolean vo, Number min, Number max) throws IOException { int cols = (vo ? 12 : slider.getBadgeSpan()); if (!mode.equals("basic")) { /* @@ -257,7 +276,7 @@ private void encodeInput(Slider2 slider, ResponseWriter rw, String mode, FacesCo R.encodeColumn(rw, null, cols, cols, cols, cols, 0, 0, 0, 0, null, null); if (mode.equals("badge")) { generateBadge(context, slider, rw, clientId, slider.getBadgeStyleClass(), slider.getBadgeStyle(), - Integer.toString(val), "_badge"); + val.toString(), "_badge"); } } removeMisleadingType(slider); @@ -315,7 +334,7 @@ private void removeMisleadingType(Slider2 slider) { } - private void encodeSliderInput(Slider2 slider, ResponseWriter rw, boolean vo, int span, String clientId, int val) + private void encodeSliderInput(Slider2 slider, ResponseWriter rw, boolean vo, int span, String clientId, float val) throws IOException { int cols = span; if (!slider.getMode().equals("basic")) { diff --git a/src/main/java/net/bootsfaces/render/CoreRenderer.java b/src/main/java/net/bootsfaces/render/CoreRenderer.java index b48b2788d..00e415840 100644 --- a/src/main/java/net/bootsfaces/render/CoreRenderer.java +++ b/src/main/java/net/bootsfaces/render/CoreRenderer.java @@ -21,7 +21,6 @@ import java.lang.annotation.Annotation; import java.util.List; import java.util.Map; - import javax.el.ValueExpression; import javax.faces.FacesException; import javax.faces.application.ProjectStage; @@ -37,7 +36,6 @@ import javax.faces.convert.Converter; import javax.faces.convert.ConverterException; import javax.faces.render.Renderer; - import net.bootsfaces.beans.ELTools; import net.bootsfaces.component.ajax.AJAXRenderer; import net.bootsfaces.component.form.Form; @@ -566,7 +564,45 @@ protected Converter resolveConverter(FacesContext context, UIComponent c, Object return null; } } + + /** + * Returns request parameter value for the provided parameter name. + * + * @param context Faces context. + * @param name Parameter name to get value for. + * + * @return Request parameter value for the provided parameter name. + */ + public static String getRequestParameter(FacesContext context, String name) { + return context.getExternalContext().getRequestParameterMap().get(name); + } + + /** + * Returns type of the value attribute's {@link ValueExpression} of the provided component. + * + * @param component Component to get attribute type for. + * + * @return Type of the value attribute's {@link ValueExpression} of the provided component. + */ + public static Class getValueType(UIComponent component) { + return getAttributeType(component, "value"); + } + /** + * Returns type of the provided attribute name's {@link ValueExpression} of the provided component. + * + * @param component Component to get attribute type for. + * @param attribute Attribute to get type for. + * + * @return Type of the provided attribute name's {@link ValueExpression} of the provided component. + */ + public static Class getAttributeType(UIComponent component, String attribute) { + ValueExpression valueExpression = component.getValueExpression(attribute); + return valueExpression == null + ? null + : valueExpression.getType(FacesContext.getCurrentInstance().getELContext()); + } + public static void endDisabledFieldset(IContentDisabled component, ResponseWriter rw) throws IOException { if (component.isContentDisabled()) { rw.endElement("fieldset"); diff --git a/src/main/meta/META-INF/bootsfaces-b.taglib.xml b/src/main/meta/META-INF/bootsfaces-b.taglib.xml index fe889d4c4..b541122df 100644 --- a/src/main/meta/META-INF/bootsfaces-b.taglib.xml +++ b/src/main/meta/META-INF/bootsfaces-b.taglib.xml @@ -25611,13 +25611,13 @@ max false - java.lang.Integer + java.lang.Object min false - java.lang.Integer + java.lang.Object @@ -25677,7 +25677,7 @@ step false - java.lang.Integer + java.lang.Object diff --git a/xtext/BootsFaces.jsfdsl b/xtext/BootsFaces.jsfdsl index 225f99491..c0062ef67 100644 --- a/xtext/BootsFaces.jsfdsl +++ b/xtext/BootsFaces.jsfdsl @@ -2211,8 +2211,8 @@ widget slider2 label-style "The CSS inline style of the label." label-style-class "The CSS class of the label." labelled-by "Labels for the slider handle's, Use array for multiple values in a range slider." - max Integer default "100" "The maximum value of the slider. (default 100)" - min Integer default "0" "The maximum value of the slider. (default 0)" + max Object default "100" "The maximum value of the slider. (default 100)" + min Object default "0" "The maximum value of the slider. (default 0)" mode default "badge" "Mode of the Slider Widget. There are three modes available : badge, edit and basic. In basic mode, only the slider and the label(if present) will be shown and the slider value will be hidden. In badge mode, the default, the slider value will be shown in a badge. In edit mode, an editable input field showing the slider value will be shown; in this mode you can change the value by sliding or editing the value in the field." natural_arrow_keys Boolean default "false" "The natural order is used for the arrow keys. Arrow up select the upper slider value for vertical sliders, arrow right the righter slider value for a horizontal slider - no matter if the slider was reversed or not. By default the arrow keys are oriented by arrow up/right to the higher slider value, arrow down/left to the lower slider value." orientation default "horizontal" "Set the orientation. Accepts 'vertical' or 'horizontal'" @@ -2222,7 +2222,7 @@ widget slider2 scale default "linear" "Set to 'logarithmic' to use a logarithmic scale." selection default "before" "Selection placement. Accepts: 'before', 'after' or 'none'. In case of a range slider, the selection will be placed between the handles." span Integer default "12" "The column span of the slider." - step Integer default "1" "Increment step" + step Object default "1" "Increment step" tooltip-visibility default "show" "Whether to show the tooltip on drag, hide the tooltip, or always show the tooltip. Accepts: 'show', 'hide', or 'always'." tooltip-split Boolean default "false" "If false show one tootip if true show two tooltips one for each handler." tooltip-slider-position "Position of tooltip, relative to slider. Accepts 'top'/'bottom' for horizontal sliders and 'left'/'right' for vertically orientated sliders. Default positions are 'top' for horizontal and 'right' for vertical slider."