October 2003 Archives

Avalon: Microsoft's Answer to Flash?

| 1 Comment

With more and more details of Longhorn evolving we can glean a little more information about Microsoft's possible answer to Flash - Avalon. The release of Longhorn is still 2+ years away so there's no need to get worried about anything yet, but this could be the next big thing just waiting to happen.

From what I can gather, Avalon is the new UI that will be introduced with the release of Longhorn and will become the defacto standard for desktop applications. It's capabilities are very similar to Flash and SVG, and it will, in all likelihood, be competing against Flash in the "sometimes connected desktop" category and on the desktop in general.

So what does programming with Avalon look like? It's strikingly easy, and uses XAML, a spin-off of XML...

<Button Background="LightSeaGreen" FontSize="24pt">
    Calculate
</Button>

Looks like something that might be fed into Royale, right? Exactly...

But.. by the time Longhorn is released Central and Royale will be 2+ years old as well, and we'll probably be on Flash 8 by then. Still, I can't help but think that Macromedia is going to need to create a tool like ScreenWeaver if it wants to stand firm in the desktop environment.

Anyone else think these are exciting times? I'm looking forward to seeing this play out. I think Royale combined with some sort of ScreenWeaver-like tool that Macromedia needs to make is Macromedia's best chance at competing with Microsoft's UI of the future. They might not need to make a separate build tool like ScreenWeaver, but I think they need to bundle something with the IDE that lets Flash access the OS if it's going to compete on the desktop market... that is, if Macromedia wants Flash to play in that space to begin with.

But please, don't take my word on any of this.. it's is all speculation. We can only play the guessing game right now. I encourage you to check out some links that you can use to form your own conclusions, and keep checking the headlines as it might affect whether or not you'll be using Flash in 3 or 4 years..


Creating Real Apps with Avalon (woo baby, check out the code samples)
Avalon: A new UI for Windows
Microsoft Readying 'Avalon' Framework for Longhorn
Microsoft to reveal more Longhorn details

Better XML Parsing

| 11 Comments

A lot of the XML parsing information on the internet related to Flash deals with looping over the childNodes array to extract data from an XML file. While this approach works, its lacking in two areas: speed and readability. I'm going to show you something that isn't new, but rather, seemingly under-utilized.

First, XML parsing is the act of extracting data from an XML document and creating an internal representation of that data. Typically, we'll want to load in a XML file and populate an array of objects that corresponds to the data that we can easily use in our Flash movie.

The reason behind parsing the XML document into an object or an array of objects is multi-part. We can save memory space as the XML object in Flash is a little bulky, and we can speed up the data access when trying to use the data loaded from the XML file. Additionally, its a little more convenient to say something like "playlist_array[1].artist" rather than having to find that information in the XML document.

For starters, let's take a look at an example XML file that might be used in a Flash based MP3 player.....

Speaking at MXDU 2004

| No Comments

Like Oscar Trelles, I've been a little busy and totally forgot to mention that I was confirmed as a speaker at MX Down Under 2004 in Sydney, Australia.

I've never been to Australia before... anything I should watch out for? I'm very excited to make the trip, and looking forward to getting into a fight with a kangaroo, if possible.. If that happens I'll be sure to take some pictures of it.

SharpFlash File System Support

| No Comments

Normally I don't post my updates to SharpFlash on my weblog, but I hit a pretty big milestone this weekend. I finished up support for accessing the local file system in projectors created with SharpFlash. This means that SharpFlash can finally start being used to build "useful" applications.

Here is a list of the methods available in the sfFile class.

sfFile.copy(from, to, overwrite, callback, scope);
sfFile.deleteFile(path, callback, scope);
sfFile.exists(path, callback, scope);
sfFile.move(from, to, callback, scope);
// the above is the rename function as well

sfFile.loadObject(file, callback, scope);
sfFile.saveObject(file, obj, callback, scope);
sfFile.loadText(file, callback, scope);
sfFile.saveText(file, text, append, callback, scope);

sfFile.getAttributes(path, callback, scope);
sfFile.setAttributes(path, attributeMask, callback, scope);
sfFile.getCreationTime(path, callback, scope);
sfFile.setCreationTime(path, creationTime, callback, scope);
sfFile.getCreationTimeUtc(path, callback, scope);
sfFile.setCreationTimeUtc(path, creationTime, callback, scope);
sfFile.getLastAccessTime(path, callback, scope);
sfFile.setLastAccessTime(path, accessTime, callback, scope);
sfFile.getLastAccessTimeUtc(path, callback, scope);
sfFile.setLastAccessTimeUtc(path, accessTime, callback, scope);
sfFile.getLastWriteTime(path, callback, scope);
sfFile.setLastWriteTime(path, writeTime, callback, scope);
sfFile.getLastWriteTimeUtc(path, callback, scope);
sfFile.setLastWriteTimeUtc(path, writeTime, callback, scope);

There is still a lot of work that needs to be done, but I'm happy to have something to cross off of the "to-do" list. I hope that I can get this program to where I want it to be, but it's taking me longer than I anticipated. Such is life...

You can download the newest release off of SourceForge. Snag the example files too -- it'll help you get started until I can get the documentation updated.

Flash MX 2004 - MenuBar example

| 59 Comments

I've been using the MenuBar component a lot lately and wanted to share an example since I've seen a few questions popping up here and there about it. Most of this information can be found somewhere in the documentation, but I thought I'd put together a code example showing some of the various techniques of using the MenuBar component.

A lot of people learn better by code examples over reading... so here we go. Note that this example is really just the tip of the iceberg - there's a lot more you can do with this component not illustrated here. To explain everything would require a lengthy tutorial. Also, the MenuBar component is available in Flash MX 2004 Professional only.

The finished product will look this:

To get started, drag a MenuBar on the stage and name it "my_mb" and line it up at (0,0). Then drag a TextArea named "selected_ta" on the stage as well. Copy and paste the code below onto the time then export the movie to see everything work.

import mx.controls.Menu;
import mx.controls.MenuBar;
import mx.controls.TextArea;

// instances on the stage
var my_mb:MenuBar;
var selected_ta:TextArea;

// variables in this script
var file_menu:Menu;
// recent_menu (below) _should_ be of type Menu, but because 
// menu.addMenuItem  returns an Object, we have to declare
// submenus as type Object, and not type Menu or else the 
// compiler will complain with an error.
var recent_menu:Object;
var edit_menu:Menu;
var view_menu:Menu;
var help_menu:Menu;

var view_xml:XML; // to illustrate creating a menu with xml


/*=================
	FILE MENU
=================*/
file_menu = my_mb.addMenu("File");

// "new" is the linkage id of the movie clip to be used as the icon for the "New" menu item.
file_menu.addMenuItem({label:"New", instanceName:"newInstance", icon:"new"});
file_menu.addMenuItem({label:"Open", instanceName:"openInstance"});

// recent menu is a submenu
recent_menu = file_menu.addMenuItem({label:"Open Recent", instanceName:"recentInstance"});
recent_menu.addMenuItem({label: "Recent Doc 1", instanceName:"doc1Instance"});
recent_menu.addMenuItem({label: "Recent Doc 2", instanceName:"doc2Instance"});

file_menu.addMenuItem({label:"Exit", instanceName:"exitInstance"});

/*=================
	EDIT MENU
=================*/
edit_menu = my_mb.addMenu("Edit");

edit_menu.addMenuItem({ label:"Item 1", type:"radio", selected:true, enabled:true, instanceName:"radioItem1", groupName:"group1" } );
edit_menu.addMenuItem({ label:"Item 2", type:"radio", selected:false, enabled:true, instanceName:"radioItem2", groupName:"group1" } );
edit_menu.addMenuItem({type:"separator"});
edit_menu.addMenuItem({ label:"Item 3", type:"radio", selected:false, enabled:true, instanceName:"radioItem3", groupName:"group2" } );
edit_menu.addMenuItem({ label:"Item 4", type:"radio", selected:true, enabled:true, instanceName:"radioItem4", groupName:"group2" } );
edit_menu.addMenuItem({type:"separator"});
edit_menu.addMenuItem({ label:"Item 5", type:"check", selected:false, enabled:true, instanceName:"checkItem1" } );
edit_menu.addMenuItem({ label:"Item 6", type:"check", selected:true, enabled:false, instanceName:"checkItem2" } );

/*=================
	VIEW MENU
=================*/
// in this menu, the menu options are controlled by an xml data provider
view_xml = new XML();
view_xml.ignoreWhite = true;
view_xml.parseXML("<menuitem label=\"expand me\"><menuitem label=\"expanded1\" instanceName=\"expanded1Instance\" /><menuitem label=\"check me\" type=\"check\" instanceName=\"expanded2Instance\" /></menuitem><menuitem label=\"option 1\" instanceName=\"option1Instance\" /><menuitem label=\"option 2\" instanceName=\"option2Instance\" />");

view_menu = my_mb.addMenu("View", view_xml);


/*=================
	HELP MENU
=================*/
help_menu = my_mb.addMenu("Help");
help_menu.addMenuItem({label:"About", instanceName:"helpInstance"});


// The listenered for the file menu (and submenus)
var fileListener:Object = new Object();
fileListener.change = function(eventObj : Object) : Void {
	selected_ta.text = "Selected item: " + eventObj.menuItem;
	
	// determine which menu item was selected, 
	// and call the correct action function - the functions
	// are commented out (I didn't write them), and are just
	// there to give you an idea of how to write an event 
	// handler
	switch (eventObj.menuItem) {
		case eventObj.menu.newInstance: /* new_Click(); */ break;
		case eventObj.menu.openInstance: /* open_Click(); */ break;
		case eventObj.menu.doc1Instance: /* openRecent_Click(1) */ ; break;
		case eventObj.menu.doc2Instance: /* openRecent_Click(2) */; break;
		// etc...
	}

}

// A generic listener used for the edit, view 
//and help menus (and their submenus)
change = function(eventObj : Object) : Void  {
	selected_ta.text = "Dumping eventObj... ";
	
	for (var i in eventObj) {
		selected_ta.text += newline + "eventObj[" + i + "] = " + eventObj[i];
	}
}

// register the listeners with the separate menus
file_menu.addEventListener("change", fileListener);
edit_menu.addEventListener("change", this);
view_menu.addEventListener("change", this);
help_menu.addEventListener("change", this);

Enjoy!

SWFHeaderInfo 1.3 - minor update

| No Comments

Thanks to the comments posted by jose (see this entry), I've made a minor update to my SWFHeaderInfo class. The FrameRate was not calculated correctly if the movie used a floating point value (such as 12.2). Additionally, the xMax and yMax were not calculated correctly either (again, floating point values were parsed incorrectly). This has been fixed, and you can download the new version here.

Note that the data types of xMin, xMax, yMin, yMax, and FrameRate have been changed to float. If you incorporate this new version into your project, you might need to change your data types as well.

Tracking in Flash

| 3 Comments

After reading an article on Macromedia's DevNet (Advanced Flash Tracking), I thought I would offer up a solution that has been working successfully for me for the past year and a half. It is clear that Macromedia has spent a lot of time drafting that document. The solution I'm going to show you is not quite as advanced as their proposed solutions, but has some advantages on it's own. It's very easy to implement and it does not rely on JavaScript.

For every action you want to track, you simply need to add a function call to the event handler. The track function looks something like this:

function trackUser (whichAction, userId) {
       // dummy.html is just a blank html page
      loadVariables("/tracking/dummy.html?action="+whichAction+"&userId="+userId);
}

You'll need to set up a blank html page somewhere on your website for this to work (in the above example, place a blank html page "dummy.html" in the "tracking" folder under the web root). The reason this works is because Flash will attempt to load information from the html page and in doing so it will pass along some parameters to that page. Because the html page is blank, nothing is ever returned to the movie. However, an event is recorded in the server log that the page was requested, and the parameters passed to the page are recorded as well.

An example use case might look like this (using the function defined above):

// userId will need to be passed into the
// movie via the object/embed tags
// more info on passing variables into a movie: 
//   http://www.macromedia.com/support/flash/ts/documents/set_variables.htm

portfolio_btn.onRelease = function() {
    // record that a user with id "userId" has
    // clicked on the view portfolio button
    trackUser("portfolio", this._parent.userId);
    
    // handle the button click action now that
    // we've tracked the click
    this._parent.gotoAndStop("portfolio");
}

You can then analyze your server logs to see which actions have been taken, how many times they have been taken, etc. With a tracking package such as WebTrends, you can set up "parameter analysis" and it will automatically parse the server logs for you and display the results in a nice easy to read format.

Note that I've been using this approach successfully with IIS and WebTrends. Your results may vary.

I recommend you read Macromedia's take on tracking first before trying to implement a tracking solution in your Flash application. My propsed solution is easy to implement and doesn't rely on JavaScript so it may be better suited to fit your tracking needs.

ColdFusion Mappings Headache

| No Comments

This one drove me nuts.. I would consider this behavior to be a bug in CFMX and I wanted to share my experience so no one else runs into this and wastes time.

First, the server is a Windows 2k box with CFMX 6.1. I'm not sure how earlier versions of CF behave, but I would guess that they act the same.

We have 7 different sites running off of one server. In the CF Admin under mappings, we have a mapping for each site so we can use absolute paths in <cfinclude> buy saying <cfinclude template="/site1/whatever.cfm">. This is useful as all of the sites share some content that we don't want to duplicate across the sites, and each site can access files outside of its own wwwroot folder.

Now, we also have some custom UDF's defined in site1, the main site. But, it got to be a pain always <cfinclude>ing "/site1/gloablUDF/something.cfm" in every other site, so we made a mapping in the CF Admin for "/" to point to wwwroot of site 1. This worked perfectly, as now we can use <cfinclude template="/globalUDF/something.cfm"> from any site and it will pull the file off of the main site, site1. We've been doing this for a long time and haven't experienced any issues.... until...

I went to add a new mapping to the CF Admin for a project I was working on. Without really thinking, I just clicked "Add Mapping" expecting a pop-up window to appear. Of course, the page refreshed and said I need to specify a name and location in order to add a mapping. That's a big "duh" on my part, as I just glazed over the form without thinking. Ok, so now I have the form in front of me again. I fill it out to add the mapping, click "Add Mapping" and the server blows up.

Well, it didn't explode or anything, but all of a sudden all of the other sites couldn't access any of the global UDF's we defined in site 1. So what happened?

It turns out that when I submitted the empty form to add a mapping, the CF Admin defaulted it to "editing" the "/" mapping that we had for site1 - except that it didn't auto-populate the Directory Path. Because of this, when I filled out the form again and added in my new mapping, I didn't know that I was actually overwriting the "/" mapping already in place.

It was easy enough to just add the "/" mapping back, but it took me a little bit to figure out what the problem was and why it was caused. I would consider this a bug, as attempting to add an "empty" mapping should not default to editing the "/" mapping, in my opinion.

Anyway, I hope this doesn't happen to you. I'll get off the soap box now…

Using Java Objects in ColdFusion

| 1 Comment

This is just a quick little code snippet for you ColdFusion users out there. With all of the hype of Java lately in the ColdFusion community, a lot of people have been taking the initiative to learn Java. However, it may not be obvious how you can apply your newfound knowledge of Java to ColdFusion development.

Below is a very simple code snippet of leveraging a built in Java class inside of a CFML template. Note that the color highlighting isn't quite right.. you'll be best copying and pasting this into Dreamweaver MX 2004 to view the code as it should be displayed.

<cfscript>
	/*	First, we create a Java object that references the built in
	StringTokenizer class, available in the java.util package.  This
	line only declares the variable and its type, it does not call
	the object's constructor.
		
	It is similar to just doing the following in Java:
		java.util.StringTokenizer stringTokenizer;	*/
	stringTokenizer = createObject("Java", "java.util.StringTokenizer");
	
	/* 	Next, we call the constructor.  The way to do this in ColdFusion is
	actually 2 part.  If we call any non-static method of the object
	the default constructor is implicity called.  If you do not want to
	call the default constructor, you can use the "init" method to have
	ColdFusion call the object's constructor.
	
	The code below is similar to doing the following in Java:
		stringTokenizer = new java.util.StringTokenizer("This is my string", " ", false);
		
	I won't explain the parameters.. they can be found here:
		http://java.sun.com/j2se/1.4.1/docs/api/java/util/StringTokenizer.html
		
	The java docs online should definitely be in your bookmark list.	*/
	stringTokenizer.init("This is my string to break apart", " ", false);
	
	/* Display the token count */
	writeOutput("Tokens:" & stringTokenizer.countTokens() & "<br/>");
	
	/* Loop over the tokens... */
	while (stringTokenizer.hasMoreTokens()) {
		/* And display the token followed by a line break */
		writeOutput(stringTokenizer.nextToken() & "<br/>");
	}
</cfscript>

It's that easy! Now you know how to start leveraging all of those built in Java classes that you've been using in your Java projects. Additionally, now you have an idea how to take advantage of Java classes that you can find all over the internet. Good luck!



About this Archive

This page is an archive of entries from October 2003 listed from newest to oldest.

September 2003 is the previous archive.

November 2003 is the next archive.

Find recent content on the main index or look in the archives to find all content.

Archives

OpenID accepted here Learn more about OpenID
Powered by Movable Type 5.02