Archive for March, 2009

Actionscript Syntax Highlighter

Monday, March 9th, 2009

A syntax highlighter written in actionscript for actionscript.

Seeing I will be posting code snippets on this blog I thought it might be fun to write a syntax highlighter. I have never written anything like this before and I am sure there are be better ways to do it. However, for my purposes it is good enough :)

You can download the AS class here.

Or here it is highlighted below

Note: Care must be taken with the following characters > <

//
// CodeFormatter
//
// Created by Simon Rodwell on 2008-11-19.
//

package com.roddeh.text{

public class CodeFormatter{

//==================================================================
// PUBLIC PROPERTIES

public static var defaultColour:String = "#EEEEEE";
public static var keywordColour:String = "#FBDE2C";
public static var commentColour:String = "#AEAEA9";
public static var quoteColour:String = "#5BB231";
public static var typeColour:String = "#779ECE";
public static var constantColour:String = "#D14DEE";

//==================================================================
// PROTECTED PROPERTIES

//==================================================================
// PRIVATE PROPERTIES

private static const KEYWORDS:Array = [
"dynamic",
"final",
"internal",
"native",
"override",
"private",
"protected",
"public",
"static",
"class",
"const",
"extends",
"function",
"get",
"implements",
"interface",
"namespace",
"package",
"set",
"var",
"include",
"import",
"false",
"null",
"this",
"true",
"break",
"case",
"continue",
"do",
"while",
"else",
"for",
"each",
"in",
"if",
"label",
"return",
"super",
"switch",
"try",
"catch",
"finally",
"throw",
"with",
":",
"="
];

private static const TYPES:Array = [
"Number",
"String",
"Boolean",
"int",
]

private static const BREAK_CHARS:Array = [
" ",
" ",
"(",
")",
":",
";",
"+",
"-",
"*",
"/",
"%",
"n"
]

//==================================================================
// CONSTRUCTOR

public function CodeFormatter(){

}

//==================================================================
// PUBLIC METHODS

public static function format(code:String, colours:Object = null):String{
if(colours){
for(var i:String in colours){
try{
CodeFormatter[i] = colours[i];
}
catch(e:Error){};
}
}

var coloured:String = “”;
var counter:int = 0;
var quoting:Boolean = false;
var openQuoteChar:String;
var commenting:Boolean = false;
var lineCommenting:Boolean = false;
var c:String;
var chunk:String = “”;
while(counter < code.length){
c = code.charAt(counter);

// Check to see if we are quoting.
if(quoting){
chunk += c;
if((c == “"” || c == “‘”) && c == openQuoteChar){
quoting = false;
coloured += setTextColour(chunk, quoteColour, false);
chunk = “”;
}
counter++;
continue;
}

// Check to see if we are commenting
if(commenting){
chunk += c;
if(c == “*” && code.charAt(counter + 1) == “/”){
commenting = false;
chunk += “/”;
coloured += setTextColour(chunk, commentColour, false);
chunk = “”;
counter++; // Increment a second time to allow for the closing comment
}
counter++;
continue;
}

// Check to see if we are line commenting.
if(lineCommenting){
chunk += c;
if(c.charCodeAt(0) == 13){
lineCommenting = false;
coloured += setTextColour(chunk, commentColour, false);
chunk = “”;
}
counter ++
continue;
}

// Check to see if we need to start quoting.
if(c == “"” || c == “‘”){
if(!commenting && !lineCommenting){
quoting = true;
openQuoteChar = c;
coloured += colourText(chunk);
chunk = c;
counter++;
continue;
}
}

// Check to see if we need to start commenting.
if(c == “/”){
if(code.charAt(counter + 1) == “/”){
lineCommenting = true;
coloured += colourText(chunk);
chunk += c;
counter++
continue;
}
if(code.charAt(counter + 1) == “*”){
commenting = true;
coloured += colourText(chunk);
chunk = c + “*”;
counter += 2;
continue;
}
}

// Otherwise we are writing normal code.
if(BREAK_CHARS.indexOf(c) != - 1){
coloured += colourText(chunk);
coloured += colourText(c);
chunk = “”;
counter++;
continue;
}

chunk += c;
counter++;
}

if(chunk != “”){
coloured += colourText(chunk);
}

function colourText(text:String):String{
if(KEYWORDS.indexOf(text) != - 1){
return setTextColour(text, keywordColour, false);
}
if(TYPES.indexOf(text) != - 1){
return setTextColour(text, typeColour, false);
}
if(isConstant(text)){
return setTextColour(text, constantColour, false);
}
return text;
}

// TODO: I am sure this could be rewritten more robustly as a RegExp
function isConstant(t:String):Boolean{
var i:int = 0;
while(i < t.length){
var charCode:int = t.charCodeAt(i);
if(!((charCode &gts 47 && charCode < 58) || (charCode > 64 && charCode < 91) || charCode == 46 || charCode == 95)){
return false;
}
i++
}
return true;
}

// Colour everything else to the default text colour.
coloured = setTextColour(coloured, defaultColour, false);
// Replace tabs with 4 spaces.
return coloured.replace(/t/g, ” “);
}

//==================================================================
// PROTECTED METHODS

//==================================================================
// PRIVATE METHODS

private static function setTextColour(text:String, colour:int, stripInner:Boolean = true):String{
if(stripInner){
text = stripInnerColour(text);
}
return “<font color="” + getHTMLColour(colour) + “">” + text + “</font>”;
}

private static function stripInnerColour(text:String):String{
var reg:RegExp
reg = /<fontb[^>]*>/g
text = text.replace(reg, “”);
reg = /</font>/g;
text = text.replace(reg, “”);
return text;
}

private static function stripWhite(text:String):String{
var reg:RegExp = /^[ t]+|[t]+$/
return text.replace(reg, “”);
}

private function getHTMLColour(color:int):String{
var col:Colour = new Colour(color);

function getHexString(hex:int):String{
return getHexChar(Math.floor(hex / 0×10)) + getHexChar(hex % 0×10);
}

function getHexChar(hex:int):String{
if(hex < 10){
return String(hex);
}
else{
switch(hex){
case 10: return “A”;
case 11: return “B”;
case 12: return “C”;
case 13: return “D”;
case 14: return “E”;
case 15: return “F”;
}
}
return String(hex);
}

return “#” + getHexString(col.red) + getHexString(col.green) + getHexString(col.blue);
}

//==================================================================
// SET METHODS

//==================================================================
// GET METHODS

}
}

Flash SEO and Wordpress

Sunday, March 8th, 2009

SEO for “All Flash Websites” using Wordpress.

Having worked almost exclusively as a flash developer for the past 5 years I determined that my own site should have a strong flash flavour to it. I considered combining standard HTML with flash elements for navigation, headers etc but I was never really at peace with any of the concepts I came up with. At the same time I didn’t want to suffer not being indexed by search engines because I elected to build my site as an all flash website. So after much research and experimentation I have come to the current implementation that uses the following technologies to achieve an all flash website that will still be indexed by search engines.

  • Flash/Actionscript 3 for the body of the site.
  • SWFObject to embed the flash content.
  • Wordpress to manage the content.
  • SWFAddress to manage deep linking.

Hiding the HTML

When a user such as yourself navigates to my site what you see is an all flash website. However if you view the source of the page you will notice there is a lot of HTML that never gets displayed. This is achieved with the following CSS.


html {
height: 100%;
overflow: hidden;
}
#flashContent {
height: 100%;
font-family:arial;
font-size:12px;
}
body {
height: 100%;
margin: 0;
padding: 0;
background-color: #ffffff;
}


So, when a user in a browser visits the site they will see the flash content. But a search engine crawling my site will see the flash and the HTML and index my site accordingly. Who knows how long this will work before search engines ignore HTML that “overflows” but for now, it works ;)

Wordpress as a CMS (Content Management System)

Functionally I wanted my site to behave pretty much like a blog. After a bit of research I settled on Wordpress as a blogging engine as it offered all the features I needed. I then created a WP theme that would allow the flash content to take over the page (using CSS as described above). I also needed to create a way for flash to retrieve the content from wordpress. This was achieved with a fairly simple script that accessed the WP database, retrieved the specified content and returned it as JSON (Javascript Object Notation) though you could just as easily return it as XML.

You can download the Wordpress to JSON script here. Be sure to change the variables on lines 132-135.

Storyz Canvas

Saturday, March 7th, 2009

Tilefile later became Storyz and produced a Ruby on Rails app that focussed again on media sharing but this time with an element of “timeliness”.

While working as a project manager I kept my sanity by working on a side flash project that used the media from Storyz and allowed users to arrange it spatially, apply effects add stamps etc. I was also responsible for building the server in RoR that supported saving the canvases, sending them to friends and so on.

The Storyz Canvas app was never deployed publicly but here is a video cap of it in action.

Tilefile

Saturday, March 7th, 2009

Tilefile was a web 2.0 company that focussed on social media sharing.

As the lead flash developer I worked with a group of talented programmers to produce the fully flash front end to the product.

Unfortunately the service is no longer running but here are a couple of video captures.

Version 1 built in AS2

Version 2 built in AS3 using Flex 2