The Space For App Developers

Beyond Plain Old HTML Objects

Twitter-like syntax formatter with smart truncation

without comments

Recently I needed to format a Twitter-like input string, replacing the @UserName, #Tag and http://some.url syntax with an html a tag and adding the proper event: prefix to the href content so that it could dispatch a Flex link event (more info about link events Listening for the link event in a Flex Label control). Additionally I wanted to intelligently truncate the input string to the specified maximum length. I used RegExp for syntax parsing and also extended mx.formatters.Formatter. I guess RegExp expression might be more elegant but this way was good enough for my purposes.

Formatter code:

package net.riaspace
{
	import mx.formatters.Formatter;
 
	public class TwitterFormatter extends Formatter
	{		
 
		public var truncate:Number = NaN;
 
		protected var regExp:RegExp = /((@|#)\w+)|((ht|f)tp(s?):\/\/)(\S+)/ig;
 
		public function TwitterFormatter()
		{
			super();
		}
 
		override public function format(value:Object):String
		{
			if (value != null)
			{
				var str:String = String(value);
 
				if (!isNaN(truncate) && str.length > truncate - 3)
				{
					var index:int = lastWhiteSpaceIndex(str.substr(0, truncate - 2)); // truncate - 2 checks if after last char there is no white-space
					if (index > 0)
						str = str.substring(0, index); // truncates after last white-space
					else
						str = str.substr(0, truncate - 3); // truncates at specified truncate index -3 for ...
 
					str = str + "...";
				}
 
				return str.replace(regExp, "<u><a href='event:$&'>$&</a></u>");
			}
			return null;
		}
 
		protected function lastWhiteSpaceIndex(str:String):int
		{
			return Math.max(
				str.lastIndexOf(" "), 
				str.lastIndexOf("\n"), 
				str.lastIndexOf("\r"), 
				str.lastIndexOf("\t"));
		}
	}
}

Usage example:

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
			   xmlns:s="library://ns.adobe.com/flex/spark" 
			   xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="1024" minHeight="768" xmlns:riaspace="net.riaspace.*">
 
	<fx:Script>
		<![CDATA[
			import mx.controls.Alert;
			protected function txt_linkHandler(event:TextEvent):void
			{
				Alert.show("Clicked: " + event.text);
			}
		]]>
	</fx:Script>
 
	<fx:Declarations>
 
		<riaspace:TwitterFormatter id="formatter" truncate="100" />
 
		<fx:String id="twitterString">
			#Lorem @ipsum http://dolor sit amet, consectetur adipiscing elit. In vehicula mollis velit a lobortis. Vivamus quis turpis non odio aliquet mattis. Proin vel nisi in nisi condimentum ornare eget porttitor tortor. Phasellus et nulla est, sit amet cursus nunc. Maecenas sit amet nisi augue, in euismod mauris. Nulla facilisi. Curabitur hendrerit aliquam magna, facilisis pellentesque justo semper eget. Quisque eleifend nisi non risus elementum ut feugiat urna ultricies. Morbi elementum augue non velit tempus tempus hendrerit sit amet diam. Mauris eleifend odio sit amet tellus luctus pellentesque. Curabitur nec massa dui, at imperdiet purus. 
		</fx:String>
 
	</fx:Declarations>
 
	<mx:Text id="txt" link="txt_linkHandler(event)" htmlText="{formatter.format(twitterString)}" 
			 width="100%" height="100%" />
 
</s:Application>

Written by Piotr Walczyszyn

January 4th, 2010 at 6:20 pm

Posted in Examples

Tagged with

Leave a Reply