
Page 4 of 4
JT Paasch
This user is yet to take control of their account and provide a biography. If you are the author of this article, please contact us via support AT actionscript DOT org.
View all articles by JT Paasch1.5 Modifying the stylesheet with actionscript
Before moving on, I should mention that one feature of this class is that you can build a 'stylesheet', as it were, solely with actionscript, without any external stylesheets. Since the styles and properties are simply stored as objects and properties in the class's styles dictionary, there is nothing preventing you from using the setStyle () and setProperty () methods to build your own set of style objects and properties in the styles dictionary. These styles could then be made available just as if they were loaded from a stylesheet. This might be useful if you need to add or modify some styles which weren't included in a stylesheet or which came from a different source. With the setStyle () and setProperty () methods you can modify and build the styles dictionary however you see fit. Then you can extract those styles and make them available to other Flash entities just as if all those properties were in the original stylesheet.
2 Applying styles to Flash objects
Now that we have a working Stylesheet class, we can look at ways to apply those styles to Flash objects. There are many different ways you can do this, it's limited only by your imagination. Here I will look at how to apply styles to two different Flash objects. First I will discuss one way to apply styles to a TextField. Second I will briefly mention ways to apply styles to non-textual entities such as strokes and fills. Applying styles to strokes and fills shows how useful this technique can be, for both Actionscript 1.0 and 2.0. Our Stylesheet class can load any property in a stylesheet and make it available for use in your Flash movie. Thus, you can style not just your text but also strokes, fills, colors, and even animation with external stylesheets.
2.1 Styling text
The most obvious object to which we would want to apply these styles is the TextField. This is a simple task once we have our styles and properties stored in our styles dictionary. As I mentioned earlier, the CSS properties Flash supports corresponds more or less to its TextFormat properties. To use our styles to format a TextField, we simply need to match up our CSS properties with TextFormat properties, build a TextFormat object with those properties and values, and then apply that TextFormat to our TextField.
To make this an easy task, we'll add a method to our Stylesheet class which will build a TextFormat object from a style in the style dictionary. The programmer can then simply apply that TextFormat object to the relevant TextField. We'll name this method getTextFormat (style) , where style is the name of the style from which to build the TextFormat. For example, if style is 'style1', this method will build a TextFormat out of the properties and values defined by the style1 style object. In our myStyles.css stylesheet, style1 has two properties: font-family and font-size. The returned TextFormat will thus have two corresponding properties: font and size.
Stylesheet.prototype.getTextFormat = function (style) {
// create and return a TextFormat object from 'style'
} // end getTextFormat () method
First we need to create an empty TextFormat which we will fill with properties and values and return:
Stylesheet.prototype.getTextFormat = function (style) {
// create a TextFormat object
var tf = new TextFormat ();
// add properties to the TextFormat
return tf;
} // end getTextFormat () method
Next we need to loop through all the properties in style . For each CSS property we want to find the corresponding TextField property and assign to it the property's value. First, the loop:
Stylesheet.prototype.getTextFormat = function (style) {
// create a TextFormat object
var tf = new TextFormat ();
// loop through every property in the style object,
// matching the CSS property up with the
// TextFormat property
for (var x in this.getStyle (style)) {
// match CSS properties up to TextFormat properties
} // end looping through properties in the style object
return tf;
} // end getTextFormat () method
Now we need to try and match up the properties. There are many properties available here, so it will be more efficient to use a switch statement rather than a series of if statements:
Stylesheet.prototype.getTextFormat = function (style) {
// create a TextFormat object
var tf = new TextFormat ();
// loop through every property in the style object,
// matching the CSS property up with the
// TextFormat property
for (var x in this.getStyle (style)) {
switch (x) {
// each case goes here
} // end switch (x)
} // end looping through properties in the style object
return tf;
} // end getTextFormat () method
Inside the switch statement, we need to create a series of case statements. It is these case statements which match CSS properties up to TextFormat properties. Each case statement should test for a CSS property, and if true, it should create the corresponding TextFormat property. Let's start with a simple example. The CSS property font-family corresponds to the TextFormat property font . So our first case should test for font-family , and if true, it should set the TextFormat's font property to the value of the style's property:
Stylesheet.prototype.getTextFormat = function (style) {
// create a TextFormat object
var tf = new TextFormat ();
// loop through every property in the style object,
// matching the CSS property up with the
// TextFormat property
for (var x in this.getStyle (style)) {
switch (x) {
case "font-family":
tf.font = this.getProperty (style, x);
break;
} // end switch (x)
} // end looping through properties in the style object
return tf;
} // end getTextFormat () method
Let's step through this case statement bit by bit. First of all, we are looping through each property in the style object. That property is represented as x in this loop. The switch statement then takes x and tests if there is any case which matches x . If x is 'font-family', then our code sets tf.font to the value of the property as it is stored in the styles dictionary, and we use getProperty to retreive value of x from style .
If you run test this code by loading myStyles.css, then getTextFormat ("style1") will return a TextFormat object with the font property set to 'Arial'. If you then applied that textFormat object to a TextField, the TextField would be rendered in an Arial typeface.
We can create other case statements to handle other properties. For example, we can write a 'font-size' case :
Stylesheet.prototype.getTextFormat = function (style) {
// create a TextFormat object
var tf = new TextFormat ();
// loop through every property in the style object,
// matching the CSS property up with the
// TextFormat property
for (var x in this.getStyle (style)) {
switch (x) {
case "font-family":
tf.font = this.getProperty (style, x);
break;
case "font-size":
tf.size = Number (this.getProperty (style, x));
break;
} // end switch (x)
} // end looping through properties in the style object
return tf;
} // end getTextFormat () method
Notice that we converted the property value to a number with Number () . The reason is that all style values are strings, since the styles all came from a text file. If you need to convert a style value, you must do it here in the case statement.
Other properties require a little more work. The CSS font-weight property can have 'bold' or 'normal' as its value, but the corresponding TextFormat bold value must have 'true' or 'false' as its value. To assign the proper TextFormat value, we must check if the CSS value has a value of 'bold'. If it does, we can set the TextFormat value to 'true':
Stylesheet.prototype.getTextFormat = function (style) {
// create a TextFormat object
var tf = new TextFormat ();
// loop through every property in the style object,
// matching the CSS property up with the
// TextFormat property
for (var x in this.getStyle (style)) {
switch (x) {
case "font-family":
tf.font = this.getProperty (style, x);
break;
case "font-size":
tf.size = this.getProperty (style, x);
break;
case "font-weight":
if (this.getProperty (style, x) == "bold") tf.bold = true;
break;
} // end switch (x)
} // end looping through properties in the style object
return tf;
} // end getTextFormat () method
Other properties might require some reformatting. In CSS, hexadecimal colors are prefixed with a hash (for example, #006699 ), but in Flash they are prefixed with a '0x' (for example, 0x006699 ). Thus, to get the right value from a stylesheet, we can just extract the last 6 characters, and then add a '0x' to the beginning:
Stylesheet.prototype.getTextFormat = function (style) {
// create a TextFormat object
var tf = new TextFormat ();
// loop through every property in the style object,
// matching the CSS property up with the
// TextFormat property
for (var x in this.getStyle (style)) {
switch (x) {
case "font-family":
tf.font = this.getProperty (style, x);
break;
case "font-size":
tf.size = this.getProperty (style, x);
break;
case "font-weight":
if (this.getProperty (style, x) == "bold") tf.bold = true;
break;
case "color":
tf.color = "0x" + this.getProperty (style, x).substr (1);
break;
} // end switch (x)
} // end looping through properties in the style object
return tf;
} // end getTextFormat () method
Similarly, you might have CSS font-size values with a 'pt' or 'px' value (e.g. font-size: 14pt; ). Since Flash treats points and pixels the same, you can just strip the 'pt' or 'px' from the value before assigning it to the TextFormat.size property:
Stylesheet.prototype.getTextFormat = function (style) {
// create a TextFormat object
var tf = new TextFormat ();
// loop through every property in the style object,
// matching the CSS property up with the
// TextFormat property
for (var x in this.getStyle (style)) {
switch (x) {
case "font-family":
var font_size = this.getProperty (style, x);
if (font_size.indexOf ("p") > -1) font_size = font_size.substring (0, font_size.indexOf ("p"));
tf.font = font_size
break;
case "font-size":
tf.size = this.getProperty (style, x);
break;
case "font-weight":
if (this.getProperty (style, x) == "bold") tf.bold = true;
break;
case "color":
tf.color = "0x" + this.getProperty (style, x).substr (1);
break;
} // end switch (x)
} // end looping through properties in the style object
return tf;
} // end getTextFormat () method
As you can see, you can tailor these case statements to convert values from CSS to TextFormat properties however you like. There are many more properties to implement, so I won't write case statements for them all here. You can look through the list of TextFormat properties and CSS properties in MX 2004 and see which properties you can implement (you can implement almost all of them). By filling out this getTextFormat () method, you can provide robust CSS capabilities for your Flash MX movies.
Before moving on, we'll look at a brief example of how to use a stylesheet and the getTextFormat () method to style a TextField. Suppose we have a TextField named myTextField . We can use the following code to apply a style from our myStyles.css stylesheet to the TextField:
var myStylesheet = new Stylesheet ();
myStylesheet.onLoad = function (ok) {
myTextField.setTextFormat (myStylesheet.getTextFormat ("style1"));
} // end onLoad ()
myStylesheet.load ("myStyles.css");
First we create a new instance of the Stylesheet class. Then we define an onLoad () method which will be triggered when the stylesheet is completely loaded and parsed. Inside that onload () method we use setTextFormat () to apply the TextFormat to myTextField . The getTextFormat () method is used to retreive the TextFormat, which is built from the properties stored in the style1 style. Finally, we invoke the load () method. This sets the whole thing in motion, the Stylesheet class loads the stylesheet, parses the styles and stores them in the styles dictionary, then invokes the onLoad () method. The getTextFormat () method is then used to retreive a TextFormat object (built from the CSS properties of style1 ). By using this technique, you can easily use external CSS stylesheets to style TextFields in Flash MX.
2.2 Styling non-text entities
This technique is not, however, limited to TextFields in Flash MX 2004. Since the Stylesheet class does not care which properties you define in your stylesheets, you can define any property you like. You might define some CSS properties not supported by Flash MX 2004 such as stroke , stroke-opacity , and fill , or you might create your own set of properties for use with styling a component. The list can be endless.
For example, you might write a method called getStrokeProperties () which operates much like our getTextFormat () method. Rather than retreive TextFormat properties, however, getStrokeProperties () might return an object with line width, line color, and line opacity values, and these values were derived from CSS stroke-width , stroke , and stroke-opacity properties in a stylesheet. You could then use those properties when you draw any shapes or run any components. You could also write a similar method called getFillProperties () which returned fill color and opacity properties derived from CSS fill and fill-opacity . By defining your stroke and fill properties in an external stylesheet and then using those values at runtime can give you stylesheet control over not just text but also graphics. For two examples which have implement CSS in Flash MX to style text and graphics in this fashion, see Thoth and DENG .
Further, you could define all sorts of other things with stylesheets. You might define _x, _y, and _rotation properties in stylesheets. You might even define animation properties such as acceleration constants or gravity. You could even define non-textual and non-graphical properties in your stylesheets and use those too. Perhaps you want to set some data properties for use in a datagrid component, or perhaps you want to set the number of visible rows and columns for a table component, or perhaps you want to define a list of movieclips in the Library to use as skins for yet another component. All of this is easily possible with a class such as our Stylesheet class, because it simply parses a stylesheet and makes those styles and properties available as objects which are easily retreivable. And all of this is applicable to Actionscript 1.0 and Actionscript 2.0.
3 Conclusion
In this article we have examined a way to bring CSS into Flash MX. Our Stylesheet class provides a simple way to load a stylesheet, parse it, and make those styles available as objects and properties. Once we have that much, we can implement methods to apply those styles to different sorts of Flash entities. We looked at how to apply CSS styles to TextFields, and we suggested ways to apply CSS to strokes, fills, and other sorts of Flash entities, both visual and non-visual. You can further build on this technique too. Perhaps you want to introduce support for CSS classes and IDs. You can easily extending this Stylesheet class or even build your own with a slightly different approach. Be creative. The potential of stylesheets in Flash is only beginning to be tapped.

