Semantic XHTML for Flash

April 22, 2007

One of the problems that I’ve always had with Flash is that all of the good stuff stays buried in the actual .swf file, away from spiders, screen readers and lower technology enabled browsers. It strikes me as odd that there isn’t a standard method for treating Flash (or other types of rich media) in a similar fashion to CSS. With the exception of video assets, there really aren’t many types of content on the web these days that can’t be at least partially displayed in some form of textual representation.

Wouldn’t it be neat if you could take a single piece of XHTML content <div id="welcome_text">
<a href=”http://www.jamesv.org” title=”A fresh look at Semantic XHTML and Flash”>
<img src=”img/tools.png” alt=”Toolkit” />
</a>
<h1>Taking a better look inside XHTML for Flash</h1>
<p>Not only does this allow you to better content manage the data that resides within your Flash elements, you can also use this method to appease search engines and screen readers for better 508 compliance.</p>
</div>

and have it work for screen readers, spiders, Bare XHTML

CSS and mobile platforms

Toolkit

Taking a better look inside XHTML for Flash

Not only does this allow you to better content manage the data that resides within your Flash elements, you can also use this method to appease search engines and screen readers for better 508 compliance.

and Flash enabled browsers?

I thought it was a nifty enough idea to take on. Read on for a breakdown of what powers the above bits and pieces or for the impatient:

Behind the scenes there isn’t a ton of ground breaking code, just a lot of solutions to a lot of small sequential problems. The basic flow through the page acrobatics is:

  • XHTML page is requested and served.
  • CSS styling is applied.
  • UFO.js is called and places Flash elements on the stage.
  • On start up, the Flash instantiates the XHTMLParser class and give it pointers to a) the element on the XHTML page containing the content to be loaded, b) the Flash object (usually self) that wants the data, in the context of the DOM tree and c) a microformat to parse the soon-to-be content against.
  • A timer is started to listen for return data (I couldn’t find an event for incoming SetVariable data).
  • XHTMLParser.LoadHTML kicks off a Javascript call back to the page requesting the guts of the selected node.
  • The innerHTML contents of the node in question are cleaned up (Firefox appears to have a nasty habit of breaking the formatting on self-closing tags), wrapped in an empty copy of their parent node tags and sent back to the Flash via SetVariable.
  • The timer in the Flash catches the new data and the XHTML contents (in string form) are parsed into a Flash XML object.
  • Our freshly squeezed XML content is piped over to a microformat parser and converted into a Flash object.
  • Upon finish the content is registered to an array in the class and an event is broadcast to the initial calling Flash movie.
  • A developer works their magic on the content and dazzles audiences around the globe.

As a quick demo, the below flash movie shows the input and output states of data through the system. They are alternate displays of the div #welcome_text

Microformat Parsers

By creating standard input and output formats for the content that will eventually power your Flash movie, you are saved from having to create either a general purpose XML parser that requires your data to be in a fairly rigid state -or- writing semantic XHTML the way you want and ending up with a bunch of extra junk in your final content object.

public function WelcomeTextParser(pageName) {
/* Data Formats

Input XHTML:
———————————————-
<div>
<a href=”$linkURL” title=”$imageText”>
<img src=”$imageURL” alt=”$imageText” />
</a>
<h1>$welcomeCopy</h1>
<p>
$bodyCopy
</p>
</div>

Output Flash Object:
———————————————-
[]
.rootNodeID
.welcomeCopy
.bodyCopy
.linkURL
.imageURL
.imageText

*/

//Parse this mess into a content object

sectionContent = _scope.loadedContent[pageName].contentObj;
_sectionXML = _scope.loadedContent[pageName].sourceXML.firstChild;

_sectionContent.welcomeCopy = XPathAPI.selectSingleNode(
sectionXML, “/div/h1″).firstChild.toString();
sectionContent.bodyCopy = XPathAPI.selectSingleNode(sectionXML, “/div/p”).firstChild.toString();
sectionContent.linkURL = XPathAPI.selectSingleNode(sectionXML, “/div/a”).attributes.href;
sectionContent.imageURL = XPathAPI.selectSingleNode(sectionXML, “/div/a/img”).attributes.src;
sectionContent.imageText = XPathAPI.selectSingleNode(sectionXML, “/div/a/img”).attributes.alt;

//Fire event for callback function
scope.events.FireEvent(pageName + ‘loaded’);

return true;
}

Enough chit chat, take a look at the code. Tear into it, pull it apart, let me know what you think. I have no doubts that this will be an evolving piece of code (this particular technique have been rolling around in one incarnation or another for over a year already). Thanks.

  • Digg
  • del.icio.us
  • feedmelinks
  • Reddit
  • NewsVine
  • StumbleUpon
  • Technorati

One Comment

  1. Posted October 6, 2007 at 9:08 pm | Permalink

    Hi… stumbled across ¥our site & thoughts on flash generation, spiders & such.

    You may or may not know this but that is a (ill-supported) project called Ming that llows on the fly creation of swfs vis ming lib called from PHP. The XAMPP bundle includes everything installed & configured & is the best way to get this tricky s/w working. Syntax is a bit of a discovery but not too hard once ¥ou figure out the required calls.

    I aso used OpenLaszlo a lot to create swf ajax based content (& use this extensively on my merlinprotocol.com website). A SOLO based OpenLaszlo code is std swf but a spider may be able to crawl the .LZX file to get info about the swf.

    Best & good luck, //GHudd

Post a Comment

Your email is never published nor shared. Required fields are marked *

*
*