Flex: detecting when text does and doesn't fit in `mxTextArea` - apache-flex

My bottom-line problem is that I need the TextArea to be up to 2 lines long to accommodate large amounts of text and then shrink to 1 line when 2 aren't necessary. The answer should be obvious, right?
private function OnScroll(evt:ScrollEvent):void {
if (!isNaN(evt.position)) DoWhatNeedsDoneWhenAScrollAppears();
}
...
<mx:TextArea scroll="OnScroll(event)" />
This way, a scroll bar should appear when there's more text than can be fit in the control, and I know I need 2 lines. Unfortunately, this doesn't work when I assign text to the text member, and I don't see any way to detect hidden text.
I've also tried:
public override function set text(s:String):void {
super.text = s;
invalidateSize();
invalidateDisplayList();
invalidateProperties();
}
Of course, even if I solved this problem, I'm left w/the problem of knowing when the shrink the line, and I wouldn't know that unless the text is an empty string.
I'm using the Flex 3.5 SDK.

My solution so far is to use measureText(). Whenever text is changed (by overriding the text set or by handing the change event) I see if measuredText() indicates that the string is wider than the control, in which case I make the TextArea twice as high. At least I tried that, until I saw just how unreliable measureText() is for that sort of thing. Now I double the height if measureText() indicates that the text is 95% of the control's width. And, it's still unreliable, but the lesser or 2 evils.

Related

Flex TextArea scroll down

I have a TextArea that shows the conversation from selected chat room. For valueCommit event I use: verticalScrollPosition = maxVerticalScrollPosition; And it works fine scrolling text to the bottom. However in one case it doesn't work as expected. There's verylittle text, so TextArea has no scrollbar and then I put a lot of text and a scrollbar is necessary. The text is scrolled almost to the bottom (still a few lines need to be scrolled down). I am pretty sure it gets maxVerticalScrollPosition as if there was no scrollbar. So the question is how can I wait with updating verticalScrollPosition with respect to TextArea's new size (that is now with a scrollbar). I tried calling validateSize and other methods that start with 'validate' but unfortunately with no luck. I also tried the old trick of putting caret at the end of text. So the TextArea's scrollbar makes a difference when getting maxVerticalScrollPosition and I need to update verticalScrollPosition once all measurements are done.
I forgot to mention. I use htmlText.
In the comments of the answer you accepted you mentioned a more elegant solution. Yeah, a timer probably isn't the best option -- you have eventListener cleanup if you remove the component from the stage; if you use the component more than once, you have another timer instance; etc., etc.
If you don't have a lot of post-commit-property actions, the quickest solution would be a call later on the setter of text or htmlText
override public function set text(value:String):void
{
super.text = value;
callLater( scrollToEndAfterTextCommitted );
}
protected function scrollToEndAfterTextCommitted():void
{
this.verticalScrollPosition = this.maxVerticalScrollPosition;
}
I hope that helps.
Best of luck!
Assuming the issue is fixed after you add additional text again, you could probably get by using a Timer, or a call to setTimeout and have the verticalScrollPosition = maxVerticalScrollPosition called a fraction of a second later and see if that fixes it.

How do I truncate a Flex StyleableTextField after two lines?

In my Flex 4.5 mobile app, I have an actionScript item renderer (that derives from Flex's LabelItemRenderer). I want to fit in exactly 2 lines of text, and then truncate the rest. The width and height of the label are fixed and known statically.
How can I do this? The StyleableTextField.truncateToFit() method only works for one line of text.
I've set wordWrap = true, so the text now flows into the second line - but I need to truncate the text if it doesn't fit in two lines.
I need it to show all the text if there is only one line. (in both cases the label should be vertically middle-aligned in my renderer)
I know how to override layoutContents to do sizing and positioning etc of the StyleableTextField. So I'm looking specifically for ideas to implement custom text truncation with the StyleableTextField).
Any ideas?
Unless you're using something specific to the StyleableTextField try the s:Label. It has a property maxDisplayedLines which you could set to 2 and it will handle the truncation.

How to truncate text with ellipsis (...) in flex?

In my flex app, I have a <mx:Text> control with a fixed height and width enough to show two lines. Now if the text is too long to be shown in two lines, I would like to have it truncated with showing ellipsis (...). The default truncation with ellipsis seems to be present with label, but label cannot show text in two lines.
How do I mimic this behavior in <mx:Text> control in flex? Thanks in advance!!!
The spark.components.Label component inherits the maxDisplayedLines property from spark.components.supportClasses.TextBase. Here is the help for that particular property:
An integer which determines whether, and where, the text gets truncated.
Truncating text means replacing excess text with a truncation indicator such as "...". The truncation indicator is locale-dependent; it is specified by the "truncationIndicator" resource in the "core" resource bundle.
If the value is 0, no truncation occurs. Instead, the text will simply be clipped if it doesn't fit within the component's bounds.
If the value is is a positive integer, the text will be truncated if necessary to reduce the number of lines to this integer.
If the value is -1, the text will be truncated to display as many lines as will completely fit within the height of the component.
Truncation is only performed if the lineBreak style is "toFit"; the value of this property is ignored if lineBreak is "explicit".
The default value is 0.
From this we can see that if you set the maxDisplayedLines property to -1, the component will display as much text as it can, and append the "..." if it had to truncate the text.
It so happens that the Text class in Flex 3 is a subclass of Label. Which means setting "truncateToFit" property on your Text control to true should be enough.
The best solution I've found is via the spark Label and the maxDisplayedLines property, like so:
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:s="library://ns.adobe.com/flex/spark" >
<s:Label text="{data.Name}" maxDisplayedLines="3" verticalAlign="middle" />
</mx:Canvas>
Worked perfectly for me.
In general I've found the spark Label to be better than the mx Label, but YMMV.
I know this is an old post, but lots of people still developing and maintaining mixed Spark/MX projects. So I will give my two cents for people that are still facing this problem, specially when using MX lists and datagrids and in need of a multiline truncation in the renderer.
As far as I can tell, the question is about MX components, using Spark would be a good choice, but only if possible.
So, in case a "s:Label" is not a choice, I would think that the best approach is to extend the MX Label component and set its textField's multiline property to true. That should do the trick, I'd first try adding that logic in the override of the updateDisplayList method.
I have a blog post on this topic here, that works well regardless of the version of Flex you are using:
http://www.tjdownes.com/post.cfm/easy-string-truncation-with-ellipsis-using-ternary-operators-in-as3
The short of it is this:
myString.slice(0, 150).concat(myString.length > 150 ? "..." : "");
This will truncate the string to 150 characters and if the string is longer than 150 characters it adds an ellipsis.
On flex 4 you need to set the Label#maxDisplayedLines to something above 0 and it will do the clipping for you.
See this to see how to customize the "..."
spark component Does have the trancion propert:#see.
http://blog.flexexamples.com/2009/06/15/determining-if-a-spark-simpletext-control-is-truncated-in-flex-4/

InvalidateSize without screen flash?

Here's the scenario: I wait for a creationComplete event to occur for an mx:Text object at which point I can access the setTextFormat method of its protected member textField. (textField is not valid until creationComplete.) At that point the text formatting done through textField.setTextFormat increases the height of the text. But the mx:Text itself does not pick up this height change until I call invalidateSize. However, in my case invalidateSize causes the entire text to be redrawn, causing it to flash on the screen. However, if I just manually change the browser window size, the Text height change is made without the text flashing like that. So how could I through a function call accomplish what is taking place when I manually change the browser window size. (I just want mx:Text to pick up the height change accomplished through textfield.setTextFormat.)
did you tried to put your textfield inside a sprite or movieclip and scale it with your callback?
to invertedspear
I was in fact able to avoid the screen flash by calling
txt1.invalidateSize();
txt1.validateNow();
immediately after the calls to txt1.ui_txtfld().setTextFormat(....)
(ui_txtfld() is how I'm making the protected property textField visible.)
However, elsewhere in my code, it was also necessary to not reference txt1.height directly, but instead,
(txt1.ui_txtfld().textHeight+4)*txt1.scaleY,
as the txt1.textField.textHeight property is valid immediately after changing the height of a textField, whereas txt1.height is not.

Set max char (as visibility allows) on multiline textbox

Is it possible to have a multi-line textbox (im using asp.net c#) where the maximum characters inputted cannot exceed the visible textbox size?
I have taken scrollbars off vertically (overflow: hidden).
Now I want it so that say if the multi-line textbox shows say 100px height (or say 5 rows), the user cannot type more than the height of the textbox?
There must be a JS/JQuery hack for this?
No, it is not possible.
Because ASP.NET textbox finally turns into HTML textarea which does not support text limit.
You can do this trick with JavaScript, sure, but what concerns visible area, it may not be so easy. You will need to somehow calculate metrics of the current font in use, then try to render in memory to see if the limits of the box are exceeded. One could such tricks when programming for Windows, but with web pages it is likely not possible.
Although it finally turns into a textarea you COULD do this, but it is hacky.
With JQuery on textarea keypress, check length of value, if it is over your threshold, remove last character.
Like I said hacky.
Good luck,
Dan
You can limit text max. char as following.
Client Side
function ValidateLength()
{
if(document.forms[0].txtFlightRemarks.value.length > MAX_LENGTH)
{
document.forms[0].txtFlightRemarks.value = document.forms[0].txtFlightRemarks.value.substring(0,MAX_LENGTH);
document.forms[0].txtFlightRemarks.focus();
return false;
}
}
Server Side (Page_Load): attach onchange and onkeyup events to required textarea.
txtFlightRemarks.Attributes.Add("onchange", "ValidateLength();");
txtFlightRemarks.Attributes.Add("onKeyUp", "ValidateLength();");

Resources