GWT: How to get width of text in TextBox?
I need to determine the width of the text in a TextBox in Google Web Toolkit.
I have a proportional font, so I can't just use something like getText().length() * characterWidth
.
What I'm trying to do is resize the text so it always fits into the TextBox. That's why I need width of the text to calculate needed font size.
Only solution I can think of is to make开发者_开发技巧 a map of widths of characters of the font I use and calculate the width of the text as a sum of widths of its individual characters.
I solved the problem as Corvus did, by introducing an additional Label
element and hiding it with CSS. I copy the text from the TextBox
to the Label
and retrieve the width by Label.getOffsetWidth()
.
However, I needed additional code to
- handle repeated spaces correctly,
- handle style changes on the text box, and
- avoid text jumping when the user was typing.
I found that I could match styles by calling
label.setStyleName(textBox.getStyleName() + " prewrap");
The prewrap style referenced in the above statement must be defined somewhere as
.prewrap { white-space: pre-wrap; }
This extra style is required because the built-in style for the textbox contains a pre-wrap
directive which does not appear in the style list returned by textbox.getStyleName()
.
I also added an extra two spaces at the end of the label's text string when calculating the width so that the text won't jump back and forth so much when the user is typing.
I solved the problem by introducing additional Label
element and hiding it with CSS. I copy the text from the TextBox
to the Label
and retrieve the width by Label.getOffsetWidth()
.
I'm not really proud of this solution, but hey, it works.
I would go with the number of characters times the width of the letter "m", which is the classic way of defining the upper bound. Far be it from me to critique what you're going to do, but I find that forms that shift elements around might be efficient in terms of space, but dreadful to use. The user sees the text box here, then data is loaded, and suddenly the text box has moved. The user has expend the time to re-examine the form to orient himself again, re-establishing the landmarks that are going to shift anyway once a new piece of text is loaded. You've traded space for time, and come out poorer in the bargain. Maybe this doesn't apply to what you're doing, but in case it does, consider it.
There's a reason why there is no obvious way to do what you want to do.
Update:
From corvus: "So user can see the whole text.. there has to be lower limit of course, but I start with quite high font size ;) –"
Ah, ok. Some thoughts about this. Presumably, your data field has an upper limit in terms of size anyway. Say 80 characters. A fixed field of that size is better than a field that snaps back and forth, for the reason I gave above. But also know that the "proper" length of a line of text is about 60 characters or so. That comes from hundreds of years of typesetting experience going back to Gutenberg. Even that's just an average, and you can follow this link for a detailed heuristic for estimating the ideal line length. If the text that user is going to interact with (either reading or entering) is longer than 60 characters (or whatever ideal line length you determine), then maybe you need a multi-line TextArea instead.
You can use a TextArea instead of a TextBox and use its scroll width (textArea.getElement().getScrollWidth()
) to determine the width of the text, as long at it is wider than the text area.
Drawback: The scroll width won't fall below the text area's offset width in case the text fits into it!
As a workaround you may increase the font size, test if the text exceeds the text area width, and stick with the old font size in case it does. I don't know, if there is a more direct way...
To make the TextArea look & feel like a single-row TextBox you need to set the following css attributes:
overflow: hidden; // get rid of scrollbars
resize: none; // get rid of resize triangle
And also set the (no css) attribute:
wrap="off" // css "white-space: nowrap;" not working here
Last but not least adjust the height to single-row height (default height is 2 or 3 rows).
Altough I am not sure why are you doing this, but I can say that there is no real, robust solution for this. You can use heuristics just as @Steve J suggested, but you won't be able to calculate the exact size of the text.
I will give you just one point why your solution won't work. What if the font-style, size, etc declared in the user's own stylesheet as !important
?
精彩评论