Skip to content

Commit d828a27

Browse files
Fix for #230 and #231: when using the input type NUMBER, the browser
takes care of the formatting and parsing of the value, taking account the i18n preferences of the user.
1 parent 5223233 commit d828a27

File tree

7 files changed

+161
-66
lines changed

7 files changed

+161
-66
lines changed

gwt-material/src/main/java/gwt/material/design/client/base/FloatParser.java

Lines changed: 27 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -35,40 +35,43 @@
3535
* #L%
3636
*/
3737

38+
import java.text.ParseException;
39+
3840
import com.google.gwt.i18n.client.NumberFormat;
3941
import com.google.gwt.text.shared.Parser;
4042

41-
import java.text.ParseException;
42-
4343
/**
4444
* A localized parser based on {@link NumberFormat#getDecimalFormat}.
4545
*/
4646
public class FloatParser implements Parser<Float> {
4747

48-
private static FloatParser INSTANCE;
48+
private static FloatParser INSTANCE;
4949

50-
/**
51-
* @return the instance of the no-op renderer.
52-
*/
53-
public static Parser<Float> instance() {
54-
if (INSTANCE == null) {
55-
INSTANCE = new FloatParser();
56-
}
57-
return INSTANCE;
58-
}
50+
/**
51+
* @return the instance of the no-op renderer.
52+
*/
53+
public static Parser<Float> instance() {
54+
if (INSTANCE == null) {
55+
INSTANCE = new FloatParser();
56+
}
57+
return INSTANCE;
58+
}
5959

60-
protected FloatParser() {
61-
}
60+
protected FloatParser() {
61+
}
6262

63-
public Float parse(CharSequence object) throws ParseException {
64-
if ("".equals(object.toString())) {
65-
return null;
66-
}
63+
/*
64+
* Note: this method is NOT called by MaterialFloatBox, the parsing is done by the browser
65+
*/
66+
public Float parse(CharSequence object) throws ParseException {
67+
if (object == null || object.length() == 0) {
68+
return null;
69+
}
6770

68-
try {
69-
return new Float(object.toString().replaceFirst(",", "."));
70-
} catch (NumberFormatException e) {
71-
throw new ParseException(e.getMessage(), 0);
72-
}
73-
}
71+
try {
72+
return new Float(NumberFormat.getDecimalFormat().parse(object.toString()));
73+
} catch (NumberFormatException e) {
74+
throw new ParseException(e.getMessage(), 0);
75+
}
76+
}
7477
}

gwt-material/src/main/java/gwt/material/design/client/base/FloatRenderer.java

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -43,26 +43,33 @@
4343
* A localized renderer based on {@link NumberFormat#getDecimalFormat}.
4444
*/
4545
public class FloatRenderer extends AbstractRenderer<Float> {
46-
private static FloatRenderer INSTANCE;
46+
private static FloatRenderer INSTANCE;
4747

48-
/**
49-
* Returns the instance.
50-
*/
51-
public static Renderer<Float> instance() {
52-
if (INSTANCE == null) {
53-
INSTANCE = new FloatRenderer();
48+
/**
49+
* Returns the instance.
50+
*/
51+
public static Renderer<Float> instance() {
52+
if (INSTANCE == null) {
53+
INSTANCE = new FloatRenderer();
54+
}
55+
return INSTANCE;
5456
}
55-
return INSTANCE;
56-
}
5757

58-
protected FloatRenderer() {
59-
}
60-
61-
public String render(Float object) {
62-
if (object == null) {
63-
return "";
58+
protected FloatRenderer() {
6459
}
6560

66-
return NumberFormat.getDecimalFormat().format(object);
67-
}
61+
public String render(Float object) {
62+
if (object == null || object.isNaN()) {
63+
return "";
64+
}
65+
66+
/*
67+
* When using the <input type="number"> the browser expects a number in
68+
* american format (when using the API). The actual output is rendered
69+
* by the browser using i18n configuration from the user, so the
70+
* application doesn't have to take care about formatting.
71+
*/
72+
return object.toString();
73+
74+
}
6875
}

gwt-material/src/main/java/gwt/material/design/client/ui/MaterialDoubleBox.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,16 @@ public class MaterialDoubleBox extends MaterialNumberBox<Double> {
3838

3939
public MaterialDoubleBox() {
4040
super(new DoubleBox());
41+
setStep("any");
42+
}
43+
44+
@Override
45+
public Double getValue() {
46+
double number = getValueAsNumber();
47+
if (Double.isNaN(number)){
48+
return null;
49+
}
50+
return number;
4151
}
4252

4353
}

gwt-material/src/main/java/gwt/material/design/client/ui/MaterialFloatBox.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@
3030
* <pre>
3131
*{@code <m:MaterialFloatBox placeholder="Your integer" step=100/>}
3232
* </pre>
33+
*
34+
* The parsing and formatting of the number are done natively by the browser, using the
35+
* i18n settings from the user.
36+
*
3337
* @see <a href="http://gwt-material-demo.herokuapp.com/#forms">Material FloatBox</a>
3438
* @author paulux84
3539
*/
@@ -41,4 +45,14 @@ public MaterialFloatBox() {
4145
super(new FloatBox());
4246
setStep("any");
4347
}
48+
49+
@Override
50+
public Float getValue() {
51+
double number = getValueAsNumber();
52+
if (Double.isNaN(number)){
53+
return null;
54+
}
55+
return Float.valueOf((float)number);
56+
}
57+
4458
}

gwt-material/src/main/java/gwt/material/design/client/ui/MaterialIntegerBox.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,16 @@ public class MaterialIntegerBox extends MaterialNumberBox<Integer> {
3838

3939
public MaterialIntegerBox() {
4040
super(new IntegerBox());
41+
setStep("1");
42+
}
43+
44+
@Override
45+
public Integer getValue() {
46+
double number = getValueAsNumber();
47+
if (Double.isNaN(number)){
48+
return null;
49+
}
50+
return (int) Math.rint(number);
4151
}
4252

4353
}

gwt-material/src/main/java/gwt/material/design/client/ui/MaterialNumberBox.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,10 @@
2020
* #L%
2121
*/
2222

23+
import com.google.gwt.dom.client.Element;
2324
import com.google.gwt.uibinder.client.UiConstructor;
2425
import com.google.gwt.user.client.ui.ValueBoxBase;
26+
2527
import gwt.material.design.client.constants.InputType;
2628

2729
//@formatter:off
@@ -87,5 +89,21 @@ public String getMax(){
8789
public String getText() {
8890
return valueBoxBase.getText();
8991
}
92+
93+
/**
94+
* Returns the value parsed natively by the browser.
95+
*
96+
* @return the value set on the component, or NaN if none is set
97+
*/
98+
public double getValueAsNumber(){
99+
return getValueAsNumber(valueBoxBase.getElement());
100+
}
101+
102+
/**
103+
* Native call to element.valueAsNumber.
104+
*/
105+
protected native double getValueAsNumber(Element el)/*-{
106+
return el.valueAsNumber;
107+
}-*/;
90108

91109
}

gwt-material/src/main/java/gwt/material/design/client/ui/MaterialValueBox.java

Lines changed: 58 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -20,32 +20,78 @@
2020
* #L%
2121
*/
2222

23+
import gwt.material.design.client.base.HasCounter;
24+
import gwt.material.design.client.base.HasError;
25+
import gwt.material.design.client.base.HasIcon;
26+
import gwt.material.design.client.base.HasInputType;
27+
import gwt.material.design.client.base.HasPlaceholder;
28+
import gwt.material.design.client.base.MaterialWidget;
29+
import gwt.material.design.client.base.mixin.CounterMixin;
30+
import gwt.material.design.client.base.mixin.ErrorMixin;
31+
import gwt.material.design.client.constants.IconPosition;
32+
import gwt.material.design.client.constants.IconSize;
33+
import gwt.material.design.client.constants.IconType;
34+
import gwt.material.design.client.constants.InputType;
35+
import gwt.material.design.client.ui.html.Label;
36+
37+
import java.util.List;
38+
2339
import com.google.gwt.dom.client.Document;
2440
import com.google.gwt.dom.client.Style;
2541
import com.google.gwt.editor.client.EditorError;
2642
import com.google.gwt.editor.client.HasEditorErrors;
2743
import com.google.gwt.editor.client.IsEditor;
2844
import com.google.gwt.editor.ui.client.adapters.ValueBoxEditor;
29-
import com.google.gwt.event.dom.client.*;
45+
import com.google.gwt.event.dom.client.BlurHandler;
46+
import com.google.gwt.event.dom.client.ChangeHandler;
47+
import com.google.gwt.event.dom.client.ClickHandler;
48+
import com.google.gwt.event.dom.client.DoubleClickHandler;
49+
import com.google.gwt.event.dom.client.DragEndHandler;
50+
import com.google.gwt.event.dom.client.DragEnterHandler;
51+
import com.google.gwt.event.dom.client.DragHandler;
52+
import com.google.gwt.event.dom.client.DragLeaveHandler;
53+
import com.google.gwt.event.dom.client.DragOverHandler;
54+
import com.google.gwt.event.dom.client.DragStartHandler;
55+
import com.google.gwt.event.dom.client.DropHandler;
56+
import com.google.gwt.event.dom.client.FocusHandler;
57+
import com.google.gwt.event.dom.client.GestureChangeHandler;
58+
import com.google.gwt.event.dom.client.GestureEndHandler;
59+
import com.google.gwt.event.dom.client.GestureStartHandler;
60+
import com.google.gwt.event.dom.client.HasAllDragAndDropHandlers;
61+
import com.google.gwt.event.dom.client.HasAllFocusHandlers;
62+
import com.google.gwt.event.dom.client.HasAllGestureHandlers;
63+
import com.google.gwt.event.dom.client.HasAllKeyHandlers;
64+
import com.google.gwt.event.dom.client.HasAllMouseHandlers;
65+
import com.google.gwt.event.dom.client.HasAllTouchHandlers;
66+
import com.google.gwt.event.dom.client.HasChangeHandlers;
67+
import com.google.gwt.event.dom.client.HasClickHandlers;
68+
import com.google.gwt.event.dom.client.HasDoubleClickHandlers;
69+
import com.google.gwt.event.dom.client.HasKeyUpHandlers;
70+
import com.google.gwt.event.dom.client.KeyDownHandler;
71+
import com.google.gwt.event.dom.client.KeyPressHandler;
72+
import com.google.gwt.event.dom.client.KeyUpEvent;
73+
import com.google.gwt.event.dom.client.KeyUpHandler;
74+
import com.google.gwt.event.dom.client.MouseDownHandler;
75+
import com.google.gwt.event.dom.client.MouseMoveHandler;
76+
import com.google.gwt.event.dom.client.MouseOutHandler;
77+
import com.google.gwt.event.dom.client.MouseOverHandler;
78+
import com.google.gwt.event.dom.client.MouseUpHandler;
79+
import com.google.gwt.event.dom.client.MouseWheelHandler;
80+
import com.google.gwt.event.dom.client.TouchCancelHandler;
81+
import com.google.gwt.event.dom.client.TouchEndHandler;
82+
import com.google.gwt.event.dom.client.TouchMoveHandler;
83+
import com.google.gwt.event.dom.client.TouchStartHandler;
3084
import com.google.gwt.event.logical.shared.ValueChangeHandler;
3185
import com.google.gwt.event.shared.HandlerRegistration;
3286
import com.google.gwt.i18n.client.AutoDirectionHandler;
3387
import com.google.gwt.i18n.shared.DirectionEstimator;
3488
import com.google.gwt.i18n.shared.HasDirectionEstimator;
3589
import com.google.gwt.uibinder.client.UiChild;
3690
import com.google.gwt.user.client.DOM;
37-
import com.google.gwt.user.client.ui.*;
91+
import com.google.gwt.user.client.ui.HasName;
92+
import com.google.gwt.user.client.ui.HasText;
93+
import com.google.gwt.user.client.ui.HasValue;
3894
import com.google.gwt.user.client.ui.ValueBoxBase;
39-
import gwt.material.design.client.base.*;
40-
import gwt.material.design.client.base.mixin.CounterMixin;
41-
import gwt.material.design.client.base.mixin.ErrorMixin;
42-
import gwt.material.design.client.constants.IconPosition;
43-
import gwt.material.design.client.constants.IconSize;
44-
import gwt.material.design.client.constants.IconType;
45-
import gwt.material.design.client.constants.InputType;
46-
import gwt.material.design.client.ui.html.Label;
47-
48-
import java.util.List;
4995

5096
//@formatter:off
5197

@@ -169,19 +215,6 @@ public void setType(InputType type) {
169215
lblError.setVisible(false);
170216
add(lblError);
171217
}
172-
if(type.equals(InputType.NUMBER)) {
173-
valueBoxBase.addKeyPressHandler(new KeyPressHandler() {
174-
@Override
175-
public void onKeyPress(KeyPressEvent event) {
176-
if (!Character.isDigit(event.getCharCode())
177-
&& event.getNativeEvent().getKeyCode() != KeyCodes.KEY_TAB
178-
&& event.getNativeEvent().getKeyCode() != KeyCodes.KEY_BACKSPACE
179-
&& event.getNativeEvent().getKeyCode() != 190) {
180-
((TextBox) event.getSource()).cancelKey();
181-
}
182-
}
183-
});
184-
}
185218
}
186219

187220
public boolean isValid() {

0 commit comments

Comments
 (0)