Fixed AS3 Flash TextArea – CSS incompatibility
Posted by: wytze on
Jul 8th, 2008 |
Filed under: flash
When working with flash components we often run into disadvantages. As with the TextArea class (fl.controls.TextArea) we encountered that it is not possible to use a CSS on its 'textField' property. Once again we thought to have the fast way to an end with components, but nothing of the sort.:'(
Since the 'styleSheet' property returns a standard TextField instance it struck us as weird that setting its 'styleSheet' property didn't work. The TextArea class was trying to set textFormat which fails after setting the stylesheet of the textfield.
Error message:
This pointed us to the 'drawTextFormat()' function in the TextArea class. After taking a look we figured out what to do.
The problem turned out to be that every time you add text to your textarea the class tries to add a designated, or default flash-textFormat to the textfield. Adding Flash TextFormat objects to textfields conflicts with stylesheets. Our solutions was relatively simple: a small class extends of the textArea class.
Click continue for the fixing source
import fl.controls.TextArea; /** * @makes it possible to do textArea.textField.styleSheet * @author Tim de Jong - Dooping VOF 2008 - tim -AT- dooping.nl * @version 001 */ public class doopingTextArea extends TextArea { public function doopingTextArea() { super(); } override protected function drawTextFormat():void { if(!this.textField.styleSheet) super.drawTextFormat(); else { setEmbedFont(); if(_html) textField.htmlText = _savedHTML; } } }
Then load the stylesheet by passing it to the textField object inside the textArea.
var myTextArea = new doopingTextArea(); myTextArea.textField.styleSheet = styleSheetObject;
As you can see we simply check if a styleSheet exists and than decide whether or not to do the original text formatting or not. Now we're able to use CSS on TextArea's and keep styling and code neatly separated.
Did this help you? Wanna help too?
Tags: 
July 23rd, 2008 at 5:59 pm
Thanks so much Wytze and Tim. Works like a charm!!
Would this also work with existing TextAreas? iow: Can I cast a TextArea to a doopingTextArea?
groet,
Willem van den Goorbergh
July 24th, 2008 at 4:50 pm
Hi,
What do you mean by “existing TextArea”?
If you mean instanciated Textarea’s, than no. But I don’t think that’s what you mean, is it?
greetz Wytze
August 14th, 2008 at 8:42 pm
Hi,
I am fairly new to actionscript, so please bear with me.
I created a custom class that creates a textArea and loads my css, but I don’t know how to apply your fix so that I can apply the stylesheet to my textArea.
I think I need to call your doopingTextArea class from within my CSSFormatTextArea class. Is that correct, and, if so, would you mind showing me how?
Thanks in advance… and extra thanks for the fix!!
b.
August 14th, 2008 at 9:06 pm
i figured out how to do it.
i imported the doopintTextArea class into my CSSFormatTextArea class and created the doopingTextArea instead of a regular textArea.
thanks again for the fix! it works perfectly!
bunny007 =)
August 18th, 2008 at 9:32 am
Glad it works bunny007,
Although I’m not sure why you created the CSSFormatTextArea class. The doopingTextArea class has all you need for css styling properties.
My suggestion (for the sake of neat coding) would be to simply import the doopingTextArea into your code, load your css-file, add that to a newly created doopingTextArea like the sample above and fill the text area with your specific text. Something like this:
import flash.gui.text.Stylesheet;
var cssReq:URLRequest = new URLRequest("http://www.whateveryourdomainmybe.net");
var cssLoader:URLLoader = new URLLoader(cssReq);
cssLoader.addEventListener(Event.COMPLETE, cssComplete);
private function cssComplete(e:Event):void{
var CSS:Stylesheet = Stylesheet.parse(e.target.data);
var myTxtArea:doopingTextArea = new doopingTextArea();
myTxtArea.textField.styleSheet = CSS;
/* now the onlything to do is filling it with text and adding it to the stage */
}
November 29th, 2008 at 3:18 am
I’d love to see a working example for this. I’m new to AS3 and classes and find it extremey difficult to follow.
December 24th, 2008 at 4:47 pm
Hi,
on july 24th Wytse wrote:
> What do you mean by “existing TextArea”?
> If you mean instanciated Textarea’s, than no. But I don’t think > that’s what you mean, is it?
what I meant was using a TextArea created on the stage at authoring time instead of creating a doopingTextArea through Actionscript and cast that somehow to a doopingTextArea.
Possible?
Thanks
Willem van den Goorbergh
December 26th, 2008 at 2:53 pm
Hi Willem,
I think it’s possible. You might want to try to change the baseclass of the component that you selected from your library to the doopingTextArea. Than you can drag it to your stage and do what ever you want with it. Dont forget to add your CSS
Wytze
February 5th, 2009 at 6:34 pm
thanks!
February 19th, 2009 at 4:59 am
5 – the correct syntax:
function cssComplete(e:Event):void{
var CSS:StyleSheet = new StyleSheet;
CSS.parseCSS(e.target.data);
var myTxtArea:doopingTextArea = new doopingTextArea();
myTxtArea.textField.styleSheet = CSS;
addChild(myTxtArea);
February 19th, 2009 at 5:52 am
and “import flash.text.StyleSheet”
February 19th, 2009 at 6:23 am
worked! CS4.
fyi:
field.textField.htmlText = exampleText;
addChild(field.textField);
and
in case you get 2 errors saying:
1. can’t find TextArea when trying to extend
2. can’t override the function
then you need to put in the correct path to the fl. folder by going to Edit > Preferences > ActionScript, ActionScript 3.0 settings…
Then add the following path:
$(AppConfig)/Component Source/ActionScript 3.0/User Interface
And watch out for correctly formatting CSS and source text.
Thanks to wytze for the script!
Wishing nice coding to everyone!
March 24th, 2009 at 6:41 am
A bit out of topic but… When loading external stylesheets I’ve created this little loader class. It is in no way perfect – but I find it quite usefull.
package {
import flash.text.StyleSheet;
import flash.net.URLLoader;
import flash.net.URLRequest;
import flash.events.Event;
import flash.events.IOErrorEvent;
public class StyleSheetLoader extends StyleSheet {
public var loader:URLLoader;
public function StyleSheetLoader(css:String=”"):void {
super();
loader=new URLLoader();
if (css!=”")load(css);
}
public function load(css:String):void {
loader.load(new URLRequest(css));
loader.addEventListener(Event.COMPLETE,completeHandler,false,0,true);
loader.addEventListener(IOErrorEvent.IO_ERROR,ioErrorHandler,false,0,true);
}
private function completeHandler(e:Event):void {
parseCSS(e.target.data);
dispatchEvent(e);
destroy();
}
private function ioErrorHandler(e:Event):void {
dispatchEvent(e);
destroy();
}
private function destroy():void {
loader.removeEventListener(Event.COMPLETE,completeHandler);
loader.removeEventListener(IOErrorEvent.IO_ERROR,ioErrorHandler);
}
}
}
Usage Example 1:
var DTA:doopingTextArea = new doopingTextArea();
DTA.textField.styleSheet=new StyleSheetLoader(“css.css”)
DTA.htmlText=”HEADER”
Usage Example 2:
var css:StyleSheetLoader=new StyleSheetLoader(“css.css”)
var DTA1:doopingTextArea = new doopingTextArea();
DTA1.textField.styleSheet=scc
DTA1.htmlText=”HEADER”
var DTA2:doopingTextArea = new doopingTextArea();
DTA2.textField.styleSheet=scc
DTA2.htmlText=”FOOTER”
March 24th, 2009 at 6:44 am
Hmm… Seems like the span tags got removed (around HEADER and FOOTER) and scc should be css
March 24th, 2009 at 11:55 am
Hi Jacob,
Thanks for posting your handy StyleSheet class extend. Seems to save a few lines of code, each time you load a StyleSheet.
One remark though. Don’t forget to listen to the onComplete event before you fill your textarea with HTML. Although you do dispath the event in your class. This way the HTML/Text won’t render becase it’s still missing the stylesheet (it’s still loading and parsing it), so it doesn’t have any style apply (yet).
Your adjusted example:
//Usage Example 1: var DTA:doopingTextArea = new doopingTextArea(); DTA.textField.styleSheet=new StyleSheetLoader(”css.css”); DTA.textField.styleSheet.addEventListener(Event.COMPLETE,completeHandler); //the function called when the StyleSheet is loaded function completeHandler(e:Event):void{ DTA.htmlText=”HEADER”; } //Usage Example 2: var css:StyleSheetLoader=new StyleSheetLoader(”css.css”); var DTA1:doopingTextArea = new doopingTextArea(); DTA1.textField.styleSheet=css; css.addEventListener(Event.COMPLETE,completeHandler1); //the function called when the StyleSheet is loaded function completeHandler1(e:Event):void{ DTA.htmlText=”HEADER”; } var DTA2:doopingTextArea = new doopingTextArea(); DTA2.textField.styleSheet=css; css.addEventListener(Event.COMPLETE,completeHandler2); //the function called when the StyleSheet is loaded function completeHandler2(e:Event):void{ DTA.htmlText=”FOOTER”; }March 24th, 2009 at 5:04 pm
Hi Wytze,
The good part is that you don’t need to listen for the complete event – the css is automatically applied when done loading (the parseCSS part).
Try this example:
// StyleSheetLoader
// Create a loader and delay the load method with two seconds.
var css:StyleSheetLoader=new StyleSheetLoader();
setTimeout(loadStyles,2000);
function loadStyles():void {
css.load(“css.css”);
}
// Dooping TextArea
// Create the DTA and apply the StyleSheetLoader
// … again just imagine the span tags
var DTA:doopingTextArea=new doopingTextArea();
DTA.textField.styleSheet=css;
DTA.htmlText=”Loerm ipsum dolor sit amet “;
addChild(DTA);
What ought to happen is the DTA displaying the text
unstyled for two seconds and then turn styled. Give it a try and please let me know if this does not work (it does for me)
March 24th, 2009 at 5:28 pm
Hi Jakob,
It turns out I was wrong! I ran your test and it seems to render the HTML after the after all. I think it’s leftover as2 habits
Thanks for your addition
March 24th, 2009 at 5:42 pm
You are welcome
March 31st, 2009 at 1:20 pm
somehow after applying stylesheet, textArea doesnt allow me to edit text, any clue how to make it editable?
March 31st, 2009 at 2:58 pm
Hi Nehal,
Did you try to set the textfield type to input?
textArea.textField.type = TextFieldType.INPUT;
Don’t Forget to import the TextFieldType class.
Greetz Wytze
April 17th, 2009 at 7:21 pm
Thanks a lot for this great trick!
I have 1 problem: I can’t change the fontFamily (doopingTextArea just ignores what I’ve put in the stylesheet => can’t get it to Arial).
Any hints would be highly appreciated as I’m struggling with this for hours now.
Thanks!
Thomas
May 9th, 2009 at 7:28 pm
I’m having the same fontFamily problem. Any solution? Is there a way to use an embedded font?
May 27th, 2009 at 10:16 am
Hi Thomas,
Sorry for the late response, but the mail function of this Wordpress-distribution seems to have stopped working (will be working on that).
I’m not sure what the problem could be. The fontFamily-cssproperty is supported by AS3…
Are you embedding fonts? And is your DoopingTextArea’s embedFonts-property set to true?
If so, try setting it to false. If not, then make sure you’ve embedded the font. And make sure you initialize it at least once before using the DoopingTextArea.
So In your case it means just adding:
hope to have helped you…
Greetz Wytze
May 27th, 2009 at 10:17 am
Hi Kevin,
See my response to Thomas, the same goes for you.
Cheers Wytze
August 18th, 2009 at 8:14 pm
Thanks for this component. It saved me hours of work!
October 8th, 2009 at 12:58 am
Many many thanks for sharing this invaluable class. Perhaps someday I’ll be able to similarly pick apart source code and return the favor.
October 22nd, 2009 at 8:43 pm
Guess I got here to late to download the full source?
If not, I when I copy/paste the text above I get the following error:
1114: The public attribute can only be used inside a package.
October 22nd, 2009 at 8:47 pm
I guess it’s just implied to wrap it in a package…
November 13th, 2009 at 11:46 am
works fine! thanks for the post….
Add A Comment