Reputation: 1397
I have some textboxes that I want to format as the user types. For example I want to have the value appear as a currency, $4506.98. I am using the TextBox.addKeyUpHandler to catch every change as the user types and format it; however, I might be displaying $4506.98 and the user pushes the 5 key, it will show $4506.985 until the user lifts up on the key when it finally updates it to $45069.85 (which is what I want it to show). I don't like how it shows 4506.985 for the short time the key is being pressed, and would like to fix that.
I couldn't get the KeyDownHandler to work properly either.
Here is my KeyDown handler
final TextBox This = this;
this.addKeyUpHandler(new KeyUpHandler(){
public void onKeyUp(KeyUpEvent event) {
String v = This.getText();
if(v.equalsIgnoreCase("0.0")){
This.setText("");
return;
}
v = v.replaceAll("\\D+",""); //Get only digits
v= v.replaceFirst("^0+(?!$)", ""); //remove leading zeros
if(v.length() > 2){
This.setText("$"+v.substring(0, v.length()-2) + "." + v.substring(v.length()-2));
} else if (v.length() == 2){
This.setText("$0." + v);
} else if (v.length() == 1){
This.setText("$0.0"+v);
}
}
});
Upvotes: 0
Views: 325
Reputation: 1397
I found the best way to do this is to use a KeyDownHandler. With KeyDown the TextBox.getText() doesn't return the new key so a lot more work is required. We have to look at event.getNativeKeyCode to find out the new key and add it to the text and format the text. In my case I had to handle a lot of keys, all the number keys, and allow for backspace, delete, copy, paste, cut, home and end. I also needed to handle cursor position of the text since I might be adding or deleting text to get the format right.
For the most part this code works. If the user has selected text this won't work as the user expects, but adding more code you should be able to catch that case.
import com.google.gwt.core.shared.GWT;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.dom.client.KeyDownEvent;
import com.google.gwt.event.dom.client.KeyDownHandler;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.dom.client.KeyPressHandler;
import com.google.gwt.event.dom.client.KeyUpEvent;
import com.google.gwt.event.dom.client.KeyUpHandler;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.logging.client.ConsoleLogHandler;
import com.google.gwt.user.client.ui.TextBox;
import static com.google.gwt.event.dom.client.KeyCodes.*;
public class MoneyBox extends TextBox {
MoneyBox(){
final MoneyBox This = this;
this.addKeyDownHandler(new KeyDownHandler(){
@Override
public void onKeyDown(KeyDownEvent event) {
if(event.isLeftArrow()
|| event.isRightArrow()
|| event.getNativeKeyCode() == KEY_SHIFT
|| event.getNativeKeyCode() == KEY_CTRL
|| event.getNativeKeyCode() == KEY_END
|| event.getNativeKeyCode() == KEY_HOME
|| event.getNativeKeyCode() == KEY_TAB
|| (event.getNativeKeyCode() == KEY_V && event.isControlKeyDown()) //paste
|| (event.getNativeKeyCode() == KEY_C && event.isControlKeyDown()) //copy
|| (event.getNativeKeyCode() == KEY_X && event.isControlKeyDown()) //cut
) {
return;
}
String numbersOnlyText = This.getText().replaceAll("\\D+","");
int curPosition = This.getCursorPosNumber();
if(!event.isAnyModifierKeyDown()){
if(event.getNativeKeyCode() == KEY_ZERO
|| event.getNativeKeyCode() == KEY_NUM_ZERO){
if(curPosition != 0){ //puttint a
numbersOnlyText = numbersOnlyText.substring(0, curPosition).concat("0" + numbersOnlyText.substring(curPosition));
curPosition++;
}
} else if (event.getNativeKeyCode() == KEY_ONE
|| event.getNativeKeyCode() == KEY_NUM_ONE) {
numbersOnlyText = numbersOnlyText.substring(0, curPosition).concat("1" + numbersOnlyText.substring(curPosition));
curPosition++;
} else if (event.getNativeKeyCode() == KEY_TWO
|| event.getNativeKeyCode() == KEY_NUM_TWO) {
numbersOnlyText = numbersOnlyText.substring(0, curPosition).concat("2" + numbersOnlyText.substring(curPosition));
curPosition++;
} else if (event.getNativeKeyCode() == KEY_THREE
|| event.getNativeKeyCode() == KEY_NUM_THREE) {
numbersOnlyText = numbersOnlyText.substring(0, curPosition).concat("3" + numbersOnlyText.substring(curPosition));
curPosition++;
} else if (event.getNativeKeyCode() == KEY_FOUR
|| event.getNativeKeyCode() == KEY_NUM_FOUR) {
numbersOnlyText = numbersOnlyText.substring(0, curPosition).concat("4" + numbersOnlyText.substring(curPosition));
curPosition++;
} else if (event.getNativeKeyCode() == KEY_FIVE
|| event.getNativeKeyCode() == KEY_NUM_FIVE) {
numbersOnlyText = numbersOnlyText.substring(0, curPosition).concat("5" + numbersOnlyText.substring(curPosition));
curPosition++;
} else if (event.getNativeKeyCode() == KEY_SIX
|| event.getNativeKeyCode() == KEY_NUM_SIX) {
numbersOnlyText = numbersOnlyText.substring(0, curPosition).concat("6" + numbersOnlyText.substring(curPosition));
curPosition++;
} else if (event.getNativeKeyCode() == KEY_SEVEN
|| event.getNativeKeyCode() == KEY_NUM_SEVEN) {
numbersOnlyText = numbersOnlyText.substring(0, curPosition).concat("7" + numbersOnlyText.substring(curPosition));
curPosition++;
} else if (event.getNativeKeyCode() == KEY_EIGHT
|| event.getNativeKeyCode() == KEY_NUM_EIGHT) {
numbersOnlyText = numbersOnlyText.substring(0, curPosition).concat("8" + numbersOnlyText.substring(curPosition));
curPosition++;
} else if (event.getNativeKeyCode() == KEY_NINE
|| event.getNativeKeyCode() == KEY_NUM_NINE) {
numbersOnlyText = numbersOnlyText.substring(0, curPosition).concat("9" + numbersOnlyText.substring(curPosition));
curPosition++;
} else if (event.getNativeKeyCode() == KEY_BACKSPACE) {
numbersOnlyText = numbersOnlyText.substring(0, curPosition-1)+numbersOnlyText.substring(curPosition);
curPosition--;
} else if (event.getNativeKeyCode() == KEY_DELETE) {
numbersOnlyText = numbersOnlyText.substring(0, curPosition)+numbersOnlyText.substring(curPosition+1);
}
}
// if(numbersOnlyText.length() == 1 ){
// curPosition += 2;
// } else if (numbersOnlyText.length() == 2 ){
// curPosition += 1;
// }
String newText = formatMoney(numbersOnlyText);
curPosition += newText.replaceAll("\\D+","").length() - numbersOnlyText.length();
This.setText(newText);
event.preventDefault();
This.setCursorPosNumber(curPosition);
}
});
this.addChangeHandler(new ChangeHandler(){
@Override
public void onChange(ChangeEvent event) {
This.setText(formatMoney(This.getText()));
}
});
}
private static String formatMoney(String v){
v = v.replaceAll("\\D+",""); //Get only digits
v= v.replaceFirst("^0+(?!$)", ""); //remove leading zeros
if(v.length() > 2){
v = "$"+v.substring(0, v.length()-2) + "." + v.substring(v.length()-2);
} else if (v.length() == 2){
v = "$0." + v;
} else if (v.length() == 1){
v = "$0.0"+v;
}
int count = 0;
for(int i = v.indexOf('.')-1; i>0; i--){
if(count%3==0 && count !=0){
v = v.substring(0, i+1) + "," + v.substring(i+1);
}
count++;
}
if (v.equalsIgnoreCase("$0.00"))
return "";
else
return v;
}
public int getCursorPosNumber() {
int superPos = super.getCursorPos();
int count = 0;
for(int i =0; i< superPos; i++){
if(this.getText().charAt(i) != '.'
&& this.getText().charAt(i) != ','
&& this.getText().charAt(i) != '$'){
count++;
}
}
// GWT.log("getCursorPos " + String.valueOf(count) + " " + String.valueOf(superPos));
return count;
}
public void setCursorPosNumber(int pos) {
int count = 0;
for(int i =0; i<this.getText().length(); i++){
if(this.getText().charAt(i) != '.'
&& this.getText().charAt(i) != ','
&& this.getText().charAt(i) != '$'){
count++;
}
if (count == pos){
super.setCursorPos(i+1);
// GWT.log("setCursorPos " + String.valueOf(i+1) + " " + String.valueOf(pos));
return;
}
}
GWT.log("setCursorPos " + String.valueOf(this.getText().length()) + " " + String.valueOf(pos));
super.setCursorPos(this.getText().length());
}
}
Upvotes: 1
Reputation: 413
KeyUpHandler
is the way to go if you want to manipulate the value of the TextBox. Also note that most of the String helper methods are not working in GWT, like equalsIgnoreCase
, replaceAll
and replaceFirst
! You have to use the GWT Regexp class to use regular expression.
Here's a little working example:
final TextBox currencyTextBox = new TextBox();
currencyTextBox.addKeyUpHandler(new KeyUpHandler() {
@Override
public void onKeyUp(final KeyUpEvent event) {
final String value = currencyTextBox.getText();
final RegExp regExp = RegExp.compile("^[0-9]*$");
final boolean onlyNumbers = regExp.test(value);
if (onlyNumbers) {
currencyTextBox.getElement().getStyle().clearBackgroundColor();
} else {
// there are not only digits
currencyTextBox.getElement().getStyle().setBackgroundColor("red");
}
}
});
Upvotes: 0