Order Matters When Creating a TextField

It may be obvious to most Flash programmers that order of operation is key to running a program. What may not be so apparent is to what order to apply properties to a TextField class so that it gets rendered properly at runtime.

Issues With TextField in Some Browsers

Recently I was pulling out my hair wondering why my TextField looked one way in one browser, but a bit differently in another. I had always been under the impression that the Flash Player always worked the same regardless of the browser. Apparently, this isn’t always the case. As seen with the TextField, if some properties were not applied in the correct order, not only can the visual output be different, but some properties will not be available at runtime.

Below is an example of how I was creating my TextField which proved to cause issues when view in (could you believe) IE. The example illustrates that when the width is set after a string has been put into the TextField, the calculation of certain properties of the TextField can be off. Anything relating to the numLines can also be miscalculated (such as getLineOffset(), etc.).

var myText_txt:TextField= new TextField();
myText_txt.text = myString; // string with enough characters to cause multiple lines
myText_txt.setTextFormat(_txtFormat);
myText_txt.width = 100;
myText_txt.wordWrap = true;
myText_txt.multiline = true;
myText_txt.autoSize = TextFieldAutoSize.LEFT;
addChild(myText_txt)
trace(myText_txt.numLines) // output in IE is 1 --output in other browsers gives the correct numLines

Finding the Solution

I went through much painstaking trial and error to pinpoint where the problem was. At first, I thought it came because the browser in question could not render all the properties of the TextField until it was added to the stage (so I applied a listener to be added to the stage. This is true for the most part, but it was not where the root of the issue was coming from. Finally, I discovered the issue wasn’t complex at all. I found that the width MUST be set BEFORE text is applied to the TextField. Wordwrap and multiline should also be set before text is applied.

Some things that require being called AFTER the text is applied is setTextFormat() and autoSize. You cannot apply format to a TextField if there is no text in it because setTextFormat actually sets the format of the text and not the TextField. The same goes for autoSize: there is nothing to autosize to if there is no text in it to begin with. Also, if the TextField is not applied to the stage, some of the properties will not be available (or at least rendered) either.

Here is the fixed code with the everything in the correct order:

var myText_txt:TextField= new TextField();
myText_txt.width = 100;  // set the width before adding text
myText_txt.text = myString; // string with enough characters to cause multiple lines
myText_txt.wordWrap = true;
myText_txt.multiline = true;
myText_txt.setTextFormat(_txtFormat);
myText_txt.autoSize = TextFieldAutoSize.LEFT;
addChild(myText_txt)
trace(myText_txt.numLines) // output in all browsers gives the correct numLines

Conclusion

Order of operation really does make a big difference when dealing with a dynamic TextField. If you are ever unsure the optimal order of operation, just remember, the solution may be easier than you think.

  • http://twitter.com/IQAndreas Andreas Renberg

    Did you test “defaultFormat” and see what difference that makes? Will it work properly and the same in all browsers if you set the default format after you have set the text?

  • http://graphnickdesign.com Nicholas Thane Haroldsen

    Andreas, I have found that the TextFormat must be applied to the TextField AFTER text has be put into the TextField regardless of the browser (or CPU). I have seen that if the text gets changed, the default textFormat can also get reset and may need reapplied to the TextField after the new text is set.

    Thanks.

  • http://graphnickdesign.com Nicholas Thane Haroldsen

    Andreas, I have done some additional tests using the “defaultTextFormat” property (one I just realized is available) and it works better than the setTextFormat() method where it can be set prior to the text being imputed.

    Thanks for leading me to the additional tests.

  • Rich Rodecker

    I have always found it best to wait a frame to let the text field render before trying to get info about it.

  • http://graphnickdesign.com Nicholas Thane Haroldsen

    Rich, That may work as a hack when you are using a frame based application, but that is not a great option if an option at all. It is best to either add a listener event and/or dig down to find out why the properties on an object is not available or not getting set otherwise other bugs could popup.

  • Rich Rodecker

    Heh…flash/flex devs have been “waiting a frame” since the beginning of flash development. You’ve heard of callLater()?

  • http://graphnickdesign.com Nicholas Thane Haroldsen

    Correct Rich; It has been used, but it is not best practice to use it. It does not attack the root of the problem as to why certain properties are not available until later. It can actually cause other problems later on in the code. It is bandaid that may work on the surface, but could leave the sore festering. Here is someone’s explanation on why callLater is a bad idea.

  • Rich Rodecker

    Thanks for linking to that article – the last paragraph was my original point exactly. I mentioned that out of lots of experience in dealing with textfields in flash, not sloppy coding practices (nor did I mention anything about best practices).

  • http://graphnickdesign.com Nicholas Thane Haroldsen

    Thanks Rich. It certainly is an option, but I have run into instances where it was not a working solution to the underlying problem. I have found that many of the problems arise as a result of the textfield not being added to the stage yet. There are certain properties with display objects that are not available until it has been added to the stage, so when it is an issue I use my_txt.addEventListener(Event.ADDED_TO_STAGE) and it seems to help. However, in some cases as explained in my article it is the order of operations that were really the cause of the issues. This synchronistic approach becomes a simpler solution than adding cumbersome listeners or even callLater() events.

  • Azharul

    this tips really help me great:)