This is an ActionScript blog, however, I’m going to show my support for a very good friend of mine (and very successful entrepreneur) who has started: PSDTemple. A service that allows designers to turn their PSDs into functional user interfaces. Great price and great service deserves a bit of attention Thank you for understanding the off topic post. If all goes well PSDTemple will soon be creating Flash websites as well. Which would definitely make my day!
Anchor Tags in ActionScript Textfields
This example is for anyone who needs to use anchor tags in ActionScript TextFields. If using AIR than the best route is to use an HTMLLoader to load in the raw HTML. If an HTMLLoader is not an option you can use this example to create a wrapper class that mimics the anchor tag functionality. Before we get started it is important to note that TextFields have a number of properties, formats and styles available which all have an effect on the way text is rendered. This example takes advantage of a specific set of properties in order to accurately determine the line number and char location of certain strings. Variables may require some adjustments / tweaks (or may not work at all) if the TextField properties are changed.
To get started lets take a look at the HTML we plan to load in:
<b>Index</b> <a href="#sectionA"><u>Jump to Section A</u></a> <a href="#sectionB"><u>Jump to Section B</u></a> <a href="#sectionC"><u>Jump to Section C</u></a> <a href="#sectionD"><u>Jump to Section D</u></a> <a href="#sectionE"><u>Jump to Section E</u></a> <span name="sectionA"><b>Section A</b></span> <p>...</p> <p>...</p> <a href="#top">Back to Top</a> <span name="sectionB"><b>Section B</b></span> <p>...</p> <p>...</p> <a href="#top">Back to Top</a> <span name="sectionC"><b>Section C</b></span> <p>...</p> <p>...</p> <a href="#top">Back to Top</a> <span name="sectionD"><b>Section D</b></span> <p>...</p> <p>...</p> <a href="#top">Back to Top</a> <span name="sectionE"><b>Section E</b></span> <p>...</p> <p>...</p> <a href="#top">Back to Top</a>
The content of the paragraph files has been removed to save space (you can view the source below to get a copy of the full file). Notice that the ‘a name’ tags have been replaced with ‘span name.’ This was a quick way to prevent the styling of the link tags from modifying the style of the headers. There is probably a better way to get around this but it’s not within scope of this example. Speaking of the style sheet… here it is:
/* CSS file */ a:hover { color: #0000FF; } a:link { color: #555555; text-decoration: underline; } a:active { color: #FF0000; } a:visited { color: #555555; text-decoration: underline; }
Lets start by loading in the HTML text:
import com.cb.util.AnchorText; import flash.text.TextField; import flash.events.TextEvent; private var _htmlLoader:URLLoader = new URLLoader(); private var html_url:String = "assets/test.html"; private var myText:AnchorText; private function init():void { _htmlLoader.addEventListener(Event.COMPLETE, htmlLoadHandler); _htmlLoader.load(new URLRequest(html_url)); } private function htmlLoadHandler(event:Event):void { myText = new AnchorText(_htmlLoader.data, 300); myTextComponent.addChild(myText); }
Now lets take a look at some of the key functions within the Anchor Text class. First we will want to replace the a href # tags with something ActionScript can understand:
// Replaces '#' with 'event:' to trigger actionscript events protected function createAnchors():void { var regEx:RegExp = new RegExp("<a href=\"#", "ig"); _text = _text.replace(regEx, "<a href=\"event:"); }
Next we will want to add event listeners for the event and set up our dynamic text field:
// Constructor public function AnchorText(text:String, width:Number = 200, height:Number = 300) { _width = width; _height = height; _text = text; // Add event dispatching to the a href tags createAnchors(); _dynamicText = new TextField(); _dynamicText.addEventListener(TextEvent.LINK, anchorText); this.addChild(_dynamicText); _styleSheet = new StyleSheet(); // Comment out the following three lines if you don't have an external stylesheet _styleLoader = new URLLoader(); _styleLoader.addEventListener(Event.COMPLETE, styleLoadHandler); _styleLoader.load(new URLRequest(css_url)); updateFormat(); } // Set up the TextField protected function updateFormat():void { _dynamicText.width = _width; _dynamicText.height = _height; _dynamicText.styleSheet = _styleSheet; _dynamicText.wordWrap = true; _dynamicText.htmlText = _text; _dynamicText.selectable = true; // Text MUST be selectable }
Finally we will want to handle the mouse clicks to the events that we set up within the text string:
protected function anchorText(event:TextEvent):void { // Recognize 'back to top' links if(event.text == "top"){ _dynamicText.scrollV = 0; return; } // Set up ghost text field to match properties of the current one var anchorText:TextField = new TextField(); anchorText.wordWrap = true; anchorText.width = _width; anchorText.styleSheet = _styleSheet; // This is REQUIRED // Replace the name tag with a unique pattern (^#^) var regEx:RegExp = new RegExp("<span name=\""+ event.text +"\">", "ig"); anchorText.htmlText = _text.replace(regEx, "^#^"); // Replace newlines with '&' to keep char count consistant regEx = new RegExp("^", "gm"); anchorText.htmlText = anchorText.htmlText.replace(regEx, "&"); // Remove duplicate newlines regEx = new RegExp("&&", "g"); anchorText.htmlText = anchorText.htmlText.replace(regEx, "x"); // Find the char location of the unique pattern var myIndex:int = anchorText.text.indexOf("^#^") + 3; // Set the scroll index to the line number of the char index var scrollIndex:int = _dynamicText.getLineIndexOfChar(myIndex) + 1; // Scroll to the necessary line _dynamicText.scrollV = scrollIndex; }
Some key things to note would be:
- The TextField MUST be selectable
- A StyleSheet must be applied to the TextField (even if you don’t load one in)
- This example assumes ‘^#^’ and ‘&&’ are unique sequences
- A TextFormat can not be used along with a StyleSheet
- There are always exception cases when dealing with RegExp and TextFields (no warranty provided)
View Sample / Source Files
Here are a few resources I found helpful along the way:
http://www.kirupa.com/forum/showthread.php?t=303186
http://troyworks.com/blog/2008/03/14/flash-textfield-actionscript-hyperlink-in-as30/
Post to TwitPic from Adobe AIR
TwitPic is a service that lets you share photos on Twitter by generating a tiny url to the image being uploaded. The flash.filesystem.File class allows Adobe AIR to post an image to TwitPic. By specifying the username, password and posting method it is possible to submit a query to the TwitPic API.
package com.cb.twitpic { import flash.events.DataEvent; import flash.events.Event; import flash.filesystem.File; import flash.net.FileFilter; import flash.net.URLRequest; import flash.net.URLRequestMethod; import flash.net.URLVariables; public class TwitPic { private var _file:File; public function TwitPic() { _file = new File(); _file.addEventListener(DataEvent.UPLOAD_COMPLETE_DATA,uploadCompleteDataHandler); browse(); } private function browse():void { _file.addEventListener(Event.SELECT, fileSelected); _file.browse( new Array( new FileFilter( "Images (*.jpg, *.jpeg, *.gif, *.png)", "*.jpg;*.jpeg;*.gif;*.png" ) ) ); } private function fileSelected(event:Event):void { var urlRequest:URLRequest = new URLRequest("http://twitpic.com/api/upload"); // The API requires the request be sent via POST urlRequest.method = URLRequestMethod.POST; // Enter a valid Twitter username / password combination var urlVars:URLVariables = new URLVariables(); urlVars.username = TWITTER_USERNAME; urlVars.password = TWITTER_PASSWORD; urlRequest.data = urlVars; // The API requires the file be labeled as 'media' _file.upload(urlRequest, 'media'); } private function uploadCompleteDataHandler(event:DataEvent):void { var resultXML:XML = new XML(event.text); // Trace the path to the resulting image tiny url (mediaurl) trace(resultXML.child("mediaurl")[0]); } } }
This can be used within an AIR application by importing TwitPic and initializing the class.
Sample Code
http://www.blackcj.com/PostTwitPicFromAIR.zip
SQLite in AIR
When doing research on integrating a SQLite Database into AIR I came across the following useful resources:
Learn what SQLite is About:
Introduction to the SQLite Database – David Tucker
Getting Started:
Introduction to SQLite in Adobe AIR
Tool for Creating and Modifying SQLite Databases:
SQLite Firefox Extension
By using a SQLite database it will be easy to filter data returned by services based on tags. A demo application that uses SQLite will be coming soon. Feel free to comment with any additional resources or cool demo applications that use SQLite.