Flex RichTextEditor, AS3 and RegEx annoyances

In my never ending desire to learn something new every day, RegEx (Regular Expression) has brought me my “ah ha!” moment of the week.

As part of my Meetup Organizer Tool application, I am providing an editable area for the Event description. This will allow the Organizer to view the current description and make some changes using a WYSIWYG tool. Flex provides the RichTextEditor control for easily creating rich text and converting it to HTML. Meetup provides a limited set of BBCode on their site for creating Event descriptions. In fact, the description area is even more limited than the Message Board area. The first thing I had to do with the RichTextEditor is only provide the functionality allowed on Meetup. This wasn’t too difficult to do, I just removed all the button controls and added the ones I needed. I even limited the number of colors to just those used by Meetup. appscreenshot_eventeditor
Plus, I added a new button for clipping the BBCode to the user’s clip board in order to paste it into Meetup Event edit page. The biggest issue with this was formatting the text from the Meetup BBCode into HTML and then turning it back into BBCode when it was clipped.

If you have ever worked with RegEx, you know that it is a pain in the behind. To most people it just looks like a bunch of slashes and characters without any particular meaning. Trying to test RegEx in your code almost makes it seem like there isn’t any rhyme or reason as to why it works. And, to make things worse, ActionScript 3 has a slightly different RegEx syntax.

Instead of just plopping out a bunch of RegEx into a replace string, I figured it would be easier to the String method. String by declaring variables for the pattern and the returnString. I passed in either the HTML or BBCode to the returnString and started working on patterns from there.

var pattern:RegExp;
var returnString:String;

For each tag, I created a new RegExp pattern and then passed that into the replace method for the String. In this example, I am finding all the bold tags and replacing them with the BBCode version. As you can see, the RegExp starts with a \ instead of a /. And then you need to make sure the special characters (,/) don’t cause issues with the search. I found most of the RegEx in a forum somewhere, but in the end, I had to change those codes in order for it to work with AS3.

// format the bold tags: <b></b>
// becomes: [b][/b]
pattern = new RegExp("\\<b\>\(.+?)\\<\\/b\>", regExFlags);
returnString = returnString.replace(pattern, "[b]$1[/b]");

Here is the code for turning the BBCode back into HTML code.

// format the bold tags: [b][/b]
// becomes: <b></b>
pattern = new RegExp("\\[b\]\(.*?)\\[\\/b\]", regExFlags);
returnString = returnString.replace(pattern, "<b>$1</b>");

The issue I had the biggest problem with is the list format from the BBCode. A list item is represented as [*]. Which is all fine and dandy until you try to convert it using RegEx. The main issue is that the [ and the * and also the ] are all special characters that you have to cancel out in order your you to search on them. And, to top things off, the list item from the BBCode doesn’t have a closing [/*] tag, which also caused issues. Well, after tying to get it to work on multiple RegEx evaluators, I finally by chance figured it out.

// format the center tags: [*]List Item
// becomes: <li>List Item
pattern = new RegExp("\\[[*\]\]", regExFlags);
returnString = returnString.replace(pattern, "<li>");

If you look at the RegExp, you will see that I have two [ characters, where as in the previous example I didn’t need an extra one. I also have another ] character to end the expression. The second [ character makes the * part of the search string. Honestly, it was just by accident that I figured that out. I’m sure there is some obvious text in the manual that points to this, but all I could find was that the \ character would cancel any special characters.

To make the fun continue, when the HTML is passed back during the clip board process, the RichTextEditor adds extra format tags and doesn’t include a <ul> tag. Instead it just wraps each bullet point in <li></li> tags. Luckily, that is all that is needed when pasting the BBCode back into the Meetup Event editor on the site.

As I mentioned at the start, I set the Color Picker button to only use the colors that Meetup allows. Part of making this work was creating an array of color names (used by Meetup) and color Hex values (used by Flex).

// Color list used by Meetup
public static const DARKRED:String = "darkred";
public static const DARKRED_VALUE:String 	= "0x8B0000";
public static const FIREBRICK:String = "firebrick";
public static const FIREBRICK_VALUE:String	= "0xB22222";
public static const CRIMSON:String = "crimson";
public static const CRIMSON_VALUE:String	= "0xDC143C";
public static const RED:String = "red";
public static const RED_VALUE:String = "0xFF0000";
public static const TOMATO:String = "tomato";
public static const TOMATO_VALUE:String = "0xFF6347";

[Bindable]
public static var colorArray:ArrayCollection = new ArrayCollection([
 {label:MeetupUtils.BLACK, color:MeetupUtils.BLACK_VALUE, hex:MeetupUtils.flashToHex(MeetupUtils.BLACK_VALUE)},
 {label:MeetupUtils.WHITE, color:MeetupUtils.WHITEVALUE, hex:MeetupUtils.flashToHex(MeetupUtils.WHITEVALUE)},
 {label:MeetupUtils.DARKRED, color:MeetupUtils.DARKRED_VALUE, hex:MeetupUtils.flashToHex(MeetupUtils.DARKRED_VALUE)},
 {label:MeetupUtils.FIREBRICK, color:MeetupUtils.FIREBRICK_VALUE, hex:MeetupUtils.flashToHex(MeetupUtils.FIREBRICK_VALUE)},
 {label:MeetupUtils.CRIMSON, color:MeetupUtils.CRIMSON_VALUE, hex:MeetupUtils.flashToHex(MeetupUtils.CRIMSON_VALUE)},
 {label:MeetupUtils.RED, color:MeetupUtils.RED_VALUE, hex:MeetupUtils.flashToHex(MeetupUtils.RED_VALUE)},
 {label:MeetupUtils.TOMATO, color:MeetupUtils.TOMATO_VALUE, hex:MeetupUtils.flashToHex(MeetupUtils.TOMATO_VALUE)});

I created a little function that works inside of the replace method. All I do is use the Filter method on an Array and find either the color name or Hex value and return the other. All I have to do with the RegEx is find the color value, which is passed into the function with the string value between the color tags. If I ever need to add more colors, I just add them to the constants and the array.

pattern = new RegExp("\\<FONT COLOR=\"(.+?)\\\"\>(.*?)\\</FONT\>", regExFlags);
returnString = returnString.replace(pattern, replaceHexPattern);

About DeanLogic
Dean has been playing around with programming ever since his family got an IBM PC back in the early 80's. Things have changed since BASICA and Dean has dabbled in HTML, JavaScript, Action Script, Flex, Flash, PHP, C#, C++, J2ME and SQL. On this site Dean likes to share his adventures in coding. And since programming isn't enough of a time killer, Dean has also picked up the hobby of short film creation.

About DeanLogic

Dean has been playing around with programming ever since his family got an IBM PC back in the early 80's. Things have changed since BASICA and Dean has dabbled in HTML, JavaScript, Action Script, Flex, Flash, PHP, C#, C++, J2ME and SQL. On this site Dean likes to share his adventures in coding. And since programming isn't enough of a time killer, Dean has also picked up the hobby of short film creation.