O'Reilly NetworkO'Reilly.com
BooksAll ArticlesSafari BookshelfO'Reilly GearFree NewslettersSearch
Web Services DevCenter Tech Jobs | Forum | Articles

O'Reilly Network: Web Services DevCenter


 Topics


ebXML

Hailstorm

JAXx

JXTA

Security

SOAP

Syndication/RSS

UDDI

WSDL

XML-RPC



DevCenters
Subject-specific articles, news, and more:

O'Reilly Network subject-specific sites
LinuxDevCenter.com
MacDevCenter.com
ONJava.com
ONLamp.com
OpenP2P.com
OSDir.com
Perl.com
WebServices.XML.com
WindowsDevCenter.com
XML.com

Subject-specific articles, news, and more
Apache
BSD
Java
Linux
Mac
Mozilla
Open Source
P2P
Perl
Policy
PHP
Python
Web Development
Windows
Wireless
XML


Scripting Collaborative Applications with Flash Communication Server MX
Pages: 1, 2

The right approach, I concluded, was to clone the Chat component and add a ClearHistory button to it. Since I'm a complete Flash novice, I admit I fumbled around quite a bit trying to figure out how. Thanks to some helpful guidance from Mike Chambers I muddled through. (It helps if you unlock the widgets you're trying to edit!) Once I opened up the Chat component, I saw that it already had the needed function, along with a namespace prefix:

FCChatClass.prototype.clearHistory = function() {
    this.nc.call( this.prefix + "clearHistory", null );
}



All I had to do was add a ClearHistory button to the Chat component, and name its click handler clearHistory.

The next idea was to add a label called clearedBy to the Chat component, in order to record who last cleared the transcript. There are probably a dozen ways to do this. The one I came up with uses a transient shared object as a messaging channel between the server and all the connected clients.

On the client side, in the Chat component's connect() method, I added:


this.clearedBy_so =                                
// create the shared object
   SharedObject.getRemote(this.prefix + "clearedBy",
        this.nc.uri,false);

this.clearedBy_so.clearHistory = function  (who)   
// declare callback function
  { gChat.clearedBy.text = "by: " + who; }

this.clearedBy_so.connect(this.nc);                
// connect the object

The first client to call SharedObject.getRemote creates an object on the server which, in this case, ends up being called FCChat.chat_mc.clearedBy. (If the third argument to SharedObject.getRemote is true, the object persists to the file /flashcom/applications/mychat/sharedobjects/_definst_/fcchat.chat_mc.clear edBy.) Subsequent clients connect to that same object.

In the server-side Chat component's constructor, I connected it to the clearedBy_so shared object like so:


this.clearedBy_so = SharedObject.get( this.prefix + 
     "clearedBy", false );

Then, in the server-side Chat component's clearHistory method--the one invoked remotely by the function I'd wired to the ClearHistory button--I added:


user = this.getClientGlobalStorage(client).username;
this.clearedBy_so.send( "clearHistory", 
     "[" + username + "]" );

This code unpacks the username from the per-client data managed by the server, and passes it to the clearHistory function attached to the client-side clearedBy_so shared object, which calls the local function that assigns the passed username to the clearedBy label.

Synchronized Persistent Objects

The PeopleList component is built using a transient shared object. That's appropriate for a real-time presence indicator, but suppose you also want to log and count the users of your chat application. Exploring this idea gave me a chance to try out persistent shared objects. I started by dragging a ListBox--an ordinary Flash UI component, not a special Communication Component--onto the Chat stage.

Here's the client-side code to create a persistent shared object in which to remember all the users who have signed in.


users_so = SharedObject.getRemote(this.prefix + 
     "users", this.nc.uri, true);
users_so.connect(this.nc);

On the server, as before, I mirrored this connection in the Chat constructor:


this.users_so = SharedObject.get( this.prefix + 
     "users", true );

In the server's connect() method, I added:


this.users = this.users_so.getProperty("users"); 
// unpack the shared object

if ( this.users == null )
    this.users = new Array;

found = 0;

for (i in this.users)                            
// look for our user
    {
    if  ( this.users[i][0] == cglobal.username ) 
    // if found
        {
        this.users[i][1]++;                      
        // increment visit count
        found = 1;
        }
    }

if (! found )                                    
// otherwise
    { this.users.push([cglobal.username,1]); }   
	// record first visit

this.users_so.setProperty("users", this.users);  
// save shared object

All clients connected to this shared object automatically receive a synchronization message when its data changes. Back on the client side, here's the handler I wrote for that synch message:


users_so.onSync = function (list)
    {
    users_mc.removeAll();              
	// clear the ListBox
    for (i in users_so.data.users)     
	// and refill it
        {
        users_mc.addItem (
            users_so.data.users[i][0] + " (" +
            users_so.data.users[i][1] + ")" );
        }
   };

The result is a listbox, on each client, that counts visitors and visits like so:


Jon (3)
Doug (4)
Gus (1)

Something Different, Something New

The demo applications included with FlashComm do a good job of sketching further possibilities. I particularly like the presentation example. A speaker sends an AV stream to an audience, along with a slide show (which is itself an embedded Flash movie). As the speaker advances through the slides, the audience stations are, by default, synched. However, they can optionally decouple and view slides independently. Audience members can ask questions using chat, or by sending an AV stream to the speaker. It doesn't take much imagination to spin out lots of useful variations on this theme.

Flash MX and the FlashComm server together deliver event-driven peer networking, streaming-media services, a productive scripting environment that targets networked teams of people, and powerful components that embody the essential tools of collaboration. We've seen all these ingredients before, but Macromedia has combined them to create something different and new: a killer framework for the rapid development of collaborative software.

Jon Udell is an author, information architect, software developer, and new media innovator.

Editor's Note: For many more details on client-side ActionScript programming, see ActionScript: The Definitive Guide. The first edition covers Flash 5, but 99 percent of it still applies to Flash MX. The revised Flash MX edition is due out in the fourth quarter of 2002. For anyone wanting to learn the JavaScript syntax for server-side programming, check out JavaScript: The Definitive Guide, 4th Edition.


Return to Web Services DevCenter








Sponsored by:

Get Red Hat training and certification.

Contact UsMedia KitPrivacy PolicyPress NewsJobs @ O'Reilly
Copyright © 2000-2006 O’Reilly Media, Inc. All Rights Reserved.
All trademarks and registered trademarks appearing on the O'Reilly Network are the property of their respective owners.
For problems or assistance with this site, email

Have you seen Meerkat?