Programming is a wonderful mix of art and science; source code is both a poem and a math problem. It should be as simple and elegant as it is functional and fast. This blog is about that (along with whatever else I feel like writing about).

Tuesday, January 08, 2008

Flex: Automatically Compile and Deploy to Server

One thing that's been irking me a little bit about my Flex development process is that I have to upload the SWF to the server in order to test it. Normally you don't have to, but I'm using HTTPService to load XML from the server to populate the components. I really like that feature, but for security reasons, it doesn't allow cross-domain access.

One option is to put a crossdomain.xml file on my web server, but since I'd be testing from a local machine, I'd have to define the allowed domains as "*" ... which probably isn't the best idea. Also, I'm not that excited about hard-coding the domain name of my server into the application. (I currently have them just using absolute URL's, without the domain, ie "/server/api.php".)

Up until now, I've been uploading the file manually with scp after the compile successfully finishes. For that, I have to enter the compile command, check if it was successful, enter the upload command, type my password, and then I'm done. Figuring there must be a way to automate that, I learned that Flex works with Ant, which can do all these things (and allegedly supports FTP and SCP).

After setting up my build.xml file, I learned that Ant doesn't support FTP and SCP without some esoteric libraries ... which I didn't really feel like hunting down. I thought to myself ... "Why do I have to use Ant, when there must be a way to do this with roughly the same effort as this build.xml file, but that actually does the work?"

Enter Python.

#!/usr/bin/python

import commands
import pexpect

sourceFile = name of source file
outputFile = name of output file

username = remote username
password = remote password
serverAddress = remote server
remoteDir = path to destination folder on remote server

print "BUILDING..."
(compileStatus, compileOutput) = commands.getstatusoutput('mxmlc -file-specs ' + sourceFile + ' -output="' + outputFile + '"')

if (compileStatus > 0):
#the build failed, display the output
print "BUILD FAILED!"
print compileOutput
else:
#the build was successful, upload it
print compileOutput
print "UPLOADING..."
scpCommand = 'scp ' + outputFile + ' ' + username + '@' + serverAddress + ':' + remoteDir + '/' + outputFile

scp = pexpect.spawn(scpCommand)
scp.expect('Password:')
scp.sendline(password)
try:
scp.interact()
except:
print "(exception)"
finally:
print "Done!"

This script uses pexpect, which is a cool little program that lets you programmatically interact with the command line. This is necessary to enter your password into scp (which doesn't allow you to pass it into the command as a parameter, for obvious security reasons).

It's pretty simple. Basically, you compile using mxmlc, and if it was unsuccessful you display all the errors. If it worked ... you upload it to the server and you're done. Much easier than doing everything manually every time.

You have to set the constants in the file before executing, which isn't really a problem. I could make it so it takes parameters, but that almost defeats the point. I'm looking at this as a build.xml replacement, not as a full-bore program. So there shouldn't be a problem with setting some constants inside.

Enjoy the 3-5 seconds you'll repeatedly save! I know I have.

Saturday, January 05, 2008

An Awesome Flex HTML Escaper

One of the problems I frequently come across when trying to post code online is that the characters need to be escaped. For example, when entering a bunch of MXML code, the browser vainly attempts to display the code in the mistaken belief that it's actually HTML.

So one of the simple applications I like to make in any new language is an HTML escaper. Since I'm playing with Flex right now, I figured I'd make one (and hopefully it'll be useful, since I'll be using it to post the code).

It took a couple of minutes, but here's the code:

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" backgroundColor="#f6f6f6">
<mx:Script>
<![CDATA[

public function escapeHTML(str:String):String {
str = str.replace(/&/g, "&amp;");
str = str.replace(/</g, "&lt;");
str = str.replace(/>/g, "&gt;");
return str;
}

public function outputClickHandler(event:Event):void {
System.setClipboard(output.text);
}

]]>
</mx:Script>

<mx:VBox>
<mx:Label text="Original" fontSize="14" fontWeight="bold" />
<mx:TextArea id="input" width="800" height="200" />

<mx:Label text="Escaped" fontSize="14" fontWeight="bold" />
<mx:TextArea id="output" text="{escapeHTML(input.text)}" click="outputClickHandler(event)" width="800" height="200" />
</mx:VBox>
</mx:Application>

The cool things about this little application are:
  • The data binding
    • Note that the second TextArea's text attribute is defined as text="{escapeHTML(input.text)}". What that means is that the two text fields are bound together, with the ActionScript function between them as a sort of filter. Any change you make in the first box will immediately show up in the second box.
  • The event handler
    • The second box has an event listener set inline by the click attribute. It calls the outputClickHandler() method, which simply sets the your clipboard to be the result of the escaping. That way you don't have to manually select everything when you're ready to copy the results.
While this is a really small, simple application, it demonstrates the power of Flex pretty well. The event model is nice, clean, and simple ... but the data binding is what gives you real power. It's the best kind of magic: the kind that you very explicitly tell it what you want, and raise you eyebrows in pleasant surprise when it works better than you could have imagined.

This is by far the best HTML escaper program I've written, and it's all thanks to Flex. Awesome.

(Feel free to use the HTML Escaper Application to your heart's content.)

Flex Layouts Make Things Much Simpler

A while ago, when I discovered Flex, I wrote about a simple application that calculates a QB Rating for both the NFL and the NCAA. It was meant to demonstrate how you get started using Flex.

From my perspective, the main limitation of that program was that it used absolute layout, meaning each element needed to be manually placed using the x and y attributes. Frankly, that's pretty lame. Even as I wrote it, I knew I'd have to learn about Flex's layouts.

Since that time, I have. And thus far, they seem to be both powerful and simple. They beat the pants off of both HTML and Swing, which were the UI technologies I had compared Flex to.

The layouts are based on the concept of containers. A container is an element in which other elements can be placed (whether they're other containers or actual UI components). The containers have different properties that control how things are laid out inside them.

For example, if you wanted to put two buttons right next to each other, you'd use an HBox, like this:

<mx:HBox>
<mx:Button label="One" />
<mx:Button label="Two" />
</mx:hbox>

That's much nicer than having to define the x/y coordinates and the width of both buttons.

So what did I decide to do to update my QB Rating application? I used a Form Container, with a set of FormItem containers inside it, to lay out the TextInput fields where you enter the QB's stats. And below that, I have a VBox for the results. It looks like this:

<mx:Form left="10" top="10">
<mx:FormHeading label="Calculate QB Rating" fontSize="20" fontWeight="bold" />

<mx:FormItem label="Completions">
<mx:TextInput id="completions" />
</mx:FormItem>

<mx:FormItem label="Attempts">
<mx:TextInput id="attempts" />
</mx:FormItem>

<mx:FormItem label="Yards">
<mx:TextInput id="yards" />
</mx:FormItem>

<mx:FormItem label="TDs">
<mx:TextInput id="touchdowns" />
</mx:FormItem>

<mx:FormItem label="INTs">
<mx:TextInput id="interceptions" />
</mx:FormItem>

<mx:FormItem>
<mx:Button id="calcButton" label="Calculate QB Rating" click="{calcRatings();}" />
</mx:FormItem>

<mx:VBox>
<mx:Label id="nflRating" text="" fontsize="16" />
<mx:Label id="ncaaRating" text="" fontsize="16" />
</mx:VBox>
</mx:Form>

And my oh my, is that nicer than the previous version. If you looked at the old version of the QB Rating application, it had a Label and a TextInput for each field, and the left and top attributes were set for each one. The new version actually takes up a few more lines of code, but it requires you to have less extensive knowledge of the size of the elements. For example, if you decide to change the font size of one of the elements, you won't have to change the "top" attribute on everything below it. If you change the title of one of the labels, you won't have to change the "left" attribute on all the TextInputs so they all line up and don't overlap their labels. I think that's worth a couple more lines of code.

So ... why did I learn about the absolute positioning first? Well, that's how the examples on Adobe's sites all work. At first glance that doesn't make sense, but I've recently learned that absolute positioning is the default in Flex Builder 2 (which I don't have). So it looks like the guys writing these examples are building their applications in Flex Builder 2 and then going through the generated code in their articles. I don't have a problem with that in general, but it seems to me that if you're ostensibly teaching someone about writing the code, it should be code that was actually written. That's a pretty minor quibble though, especially since Adobe's online documentation about layouts and containers is pretty excellent.

If you want to check out the new app or source code, by all means do so.

Flex: MXML Highlighting in VIM

For the first couple of weeks I've been using Flex, I've had to do it without syntax highlighting. My editor of choice is vim, which doesn't support MXML and ActionScript out of the box. However, syntax highlighting is a great invention, and now that I'm in the middle of a sizable Flex project, I figured I needed to get my hands on some syntax highlighting. (It'll be a whole lot cheaper than buying Flex Builder 2!)

The first thing you need to do is download the following two files:
actionscript.vim
mxml.vim

(Even if you only plan on editing MXML files, you need both of these. The MXML syntax depends on the ActionScript syntax, because MXML files can include ActionScript code.)

(Thanks to Abdul Qabiz for these files.)

You need to put these files into vim's syntax folder. On Ubuntu 7.10, it's /usr/share/vim71/syntax. (Make sure you install vim-full, using sudo aptitude install vim-full ... for some reason my installation of Ubuntu came with vim-tiny, which doesn't support syntax highlighting.)

Once that's done, you need to make sure the following lines are in your ~/.vimrc file:

au BufNewFile,BufRead *.mxml set filetype=mxml
au BufNewFile,BufRead *.as set filetype=actionscript
syntax on

Now ... the next time you open up an mxml file in vim, it'll have syntax highlighting for you. Excellent. My development environment just got a little bit better.

Thursday, January 03, 2008

Modal Dialog Box in Javascript

Occasionally you want to be able to pop up a modal dialog box over your web page, so you can force the user to enter something before they continue. You could just use confirm(), but that's pretty lame and doesn't allow you to exercise much control over the user's input options. Yes/No? Okay/Cancel? Lame.

Well, the way to do it, of course, is with a transparent div! That'd be the background, and then you have another div that you put right in the middle of the screen, mimicking a popup window. You'll be able to see through the background div (kind of), but you can't click through it ... which makes it perfect.

First, you need to throw in the HTML:

<div id="modalBackgroundDiv" class="modalPopupTransparent" style="display: none;"> </div>

<div id="modalWindow" class="modalPopupWindow" style="display: none; width: 560px;">
It's awesome that you can put whatever you want in here.
</div>

Then you need some CSS to make it so they actually work as planned:

div.modalPopupTransparent {
filter: alpha(opacity=75);
-moz-opacity: .75;
background: #CCCCCC;
position: absolute;
top: 0px;
left: 0px;
}

div.modalPopupWindow {
position: absolute;
background-color: #FFFFFF;
border: 2px solid black;
padding: 8px;
text-align: left;
}

The most important thing here is that the background div's style has its opacity set to 75%. It has to be done twice because IE and Firefox use different commands for this. (Typical.) The second most important thing to notice is the absolute positioning. That's what allows them to display on top of everything else. It's not that useful if your transparent div shows up below the page, is it?

It's also not that useful if the modal dialog has no functionality and can't pop up. Which is why we now have to add in the Javascript:

function openModalWindow() {
var div = $('modalWindow');
var bgDiv = $('modalBackgroundDiv');

var docDim = Element.getDimensions(document.body);

//get the size of the window and calculate where the box should be placed
var wDim = getBrowserWindowSize();
var dDim = Element.getDimensions(div);

div.style.top = ((wDim.height - dDim.height*2) / 2) + 'px';
div.style.left = ((wDim.width - dDim.width) / 2) + 'px';

if (docDim.height > wDim.height) {
wDim.height = docDim.height;
}

bgDiv.style.width = wDim.width + 'px';
bgDiv.style.height = wDim.height + 'px';

Element.show(div);
Element.show(bgDiv);
}

function closeModalWindow() {
Element.hide('modalWindow');
Element.hide('modalBackgroundDiv');
}

function getBrowserWindowSize() {
var winW = 630, winH = 460;

if (parseInt(navigator.appVersion)>3) {
if (navigator.appName=="Netscape") {
winW = window.innerWidth;
winH = window.innerHeight;
}
if (navigator.appName.indexOf("Microsoft")!=-1) {
winW = document.body.offsetWidth;
winH = document.body.offsetHeight;
}
}

var rval = {
width: winW,
height: winH
};

return rval;
}

To open the modal window, the first thing we need to do is grab a reference to the window, the background, and the document body. We then determine the size of the visible browser window (using a custom function, shown above) and the size of the modal dialog (using Prototype's handy method).

Since we want the transparent background to cover the entire page (not just what's visible), we set the height of the background to be the height of the document body instead of the browser window -- if necessary. That way the user can't scroll down and click something lower on the page if there's a modal dialog up.

Then we center the popup, make the background as big as it should be, and display them. Simple enough. Similarly, in order to close the window, we just hide both elements.

And there you have it. A nice, simple modal dialog, with a transparent gray background that dims out everything else on the page so the user knows what to focus on. I wouldn't use it too often, but in some cases it can be exactly what you want.

Enjoy!

Wednesday, January 02, 2008

PHP usort(): Sort an array of objects

PHP is nice enough to include a nice, fast sort() function that works on simple datatypes like numbers and strings. Saves you the time of having to write your own sorting functions. However, how often is your important data in an array of integers or strings? Considerably more often, you have an array of more complex data structures that you'd like sorted. And the sort() function just can't do it.

One option you have is to write your own sorting function, as I've already mentioned. In fact, I've done this numerous times. But why should I have to type out a quicksort algorithm -- slightly modified to compare objects or associative arrays -- rather than having the libraries do it and move on to more important things. This isn't CS class any more. I shouldn't have to "prove" that I understand the quicksort algorithm ... I need to get things done!

Well, as it turns out, PHP does indeed offer the capability to sort an array of objects. And it's not so bad. Check out usort. The basic concept is that you pass it the array of objects and a function (or static method) that'll act as a comparison function between two objects. This function is something you write yourself, since you're the one who knows about your classes. I usually put it right in the class itself, acting as a static method. Here's a quick example:


class Item {
var $a;
var $b;

function Item($pA, $pB) {
$this->a = $pA;
$this->b = $pB;
}

function _cmpAscA($m, $n) {
if ($m->a == $n->a) {
return 0;
}

return ($m->a < $n->a) ? -1 : 1;
}

function _cmpDescA($m, $n) {
if ($m->a == $n->a) {
return 0;
}

return ($m->a > $n->a) ? -1 : 1;
}
}

//let's make an array
$arr = array();
$arr[] = new Item(1, 2);
$arr[] = new Item(4, 3);
$arr[] = new Item(2, 3);

//now we can sort it!
$sorted = usort($arr, array('Item', '_cmpAscA'));


Note that the second parameter to the usort() function is an array. This is because I'm calling a static method. The first item('Item') denotes the class, and the second item('_cmpAscA') denotes the method name. If I had simply made a comparison function that wasn't in a class, the second parameter to usort() would have been a string, not an array.

I typically make two comparison functions per sortable field in my objects; I want to be able to sort ascending and descending, without having to muck with strrev(). My way is a bit faster ... but may force you to use a bit more code. It seems to me that that's a matter of personal preference. And I have this preference because I feel that it allows you to more accurately describe what you want. If you want to sort in descending order, you say "sort this in descending order," rather than "sort this and then reverse it."

Anyhow, usort() is a powerful tool to add to the toolbox. I know I'll be using it in the future for all my object-sorting needs. Hope you find it as useful.