October 2009 List of Useful Drupal Modules

October 22nd, 2009

This is a wonderful list of useful Drupal modules compiled by Lee-Yan Marquez (argentofchange.com) from the discussion in last week’s Auckland Drupal Meetup group:

Content Management

date
The date module is a flexible date/time field type for the CCK content module.

Content Aggregation & Distribution

feedapi
FeedAPI aggregates feeds on a Drupal website by generating light weight items or nodes from feeds. It provides a straightforward configuration for most use cases and is extensible through an API. FeedAPI integrates with OG (but does not require it).

tattler
Tattler (app) is a Drupal Distribution, an open source topic monitoring tool for today’s Web. Tattler finds and aggregates content from the Web on topics you ask it to monitor. Using semantic Web technologies, Tattler mines news, websites, blogs, multimedia sites, and other social media like Twitter, to find mentions of the issues most relevant to your organization.

Content Relationships

context
Context allows you to manage contexts for different portions of your site. You can think of each context as representing a “section” of your site. For each context, you can choose the conditions that trigger the context to be active and choose different aspects of Drupal that should react to this active context.

flag
Flag is a flexible flagging system that is completely customizable by the administrator. Using this module, the site administrator can provide any number of flags for nodes, comments, or users. Some possibilities include bookmarks, marking important, friends, or flag as offensive. With extensive views integration, you can create custom lists of popular content or keep tabs on important content.

location
The location module allows real-world geographic locations to be associated with Drupal nodes, including people, places, and other content. The location module allows admins to collect addresses, geocode them (translate addresses to latitude/longitude), and associate locations with Drupal nodes and users. Location data is automatically used to generate GeoRSS within your existing RSS feeds. Location also provides an API so that other modules may take advantage of its address storage and geocoding features.

node reference auto-create (drupal 6 dev version only)
Provides an additional CCK widget type for the base field node reference. The auto-create widget type provides a text-field for input of the node title like standard node reference fields, but instead of linking to existing nodes it creates a node with the specified title on save. When the title is changed during subsequent node saves the referenced node title is changed as well.

node reference field (drupal 6 dev version only)
Allows fields on the node referenced by a node reference auto-create field to be viewed and edited. In other words a node reference is created to a particular node which has additional CCK fields. The additional fields can also be edited along side the node title provided by node reference.

spaces
Spaces allows features (a blog, calendar, casetracker, shoutbox, gallery, etc.) to be enabled and customized in different configurations in different spaces.

E-Commerce

ubercart
An e-commerce suite developed for Drupal.

Ubercart Payment Express (DPS PXAccess and PXPost) (in development)
Payment processor implementation for DPS (Direct Payment Solutions) Payment Express payment gateway.

Filters

better formats
Better formats is a module to add more flexibility to Drupal’s core input format system.

html purifier
HTML Purifier is a standards-compliant HTML filter library. HTML Purifier will not only remove all malicious code (better known as XSS) with a thoroughly audited, secure yet permissive whitelist, it will also make sure your documents are standards compliant, something only achievable with a comprehensive knowledge of W3C’s specifications.

flexifilter
Flexifilter is a module that allows non-admins to create their own, configurable custom filters. It is not limited to simple text replacement or regex replacement; it includes logic such as if() and while() statements, and is easily extendable by other modules.

Image Processing

imagecache
ImageCache allows you to setup presets for image processing.

Package and Deploy

deployment (drupal 6 dev version only)
The deployment framework is a series of modules which are designed to allow developers to easily stage Drupal data from one site to another. This includes content (nodes, taxonomy, users, etc) as well as configuration (views, content types, system settings, etc.).

drush
A command line shell and Unix scripting interface for Drupal, a veritable Swiss Army knife designed to make life easier for those of us who spend some of our working hours hacking away at the command prompt.

features
Features provides a UI and API for taking different site building components from modules with exportables and bundling them together in a single feature module.

legacy (drupal 5 core module)
The legacy module provides legacy handlers for upgrades from older installations. These handlers help automatically redirect references to pages from old installations and prevent page not found errors for your site.

node import (some limitations)
Allows you to import a set of nodes from a Comma Seperated Values (CSV) or Tab Seperated Values (TSV) text file.

table wizard
The Table Wizard facilitates dealing with database tables:

  • It allows surfacing any table in the Drupal default database through Views 2.
  • Relationships between the tables it manages can be defined, so views combining data in the tables can be constructed.
  • It performs analysis of the tables it manages, reporting on empty fields, data ranges, ranges of string lengths, etc.
  • It provides an API for other modules to views-enable their tables.
  • It provides an API for importing data into tables in the Drupal default database (automatically doing the views integration above).
  • It is bundled with an implementation of this API, for importing comma- and tab-delimited files.

Paths & Navigation

admin menu
Administration menu module provides a theme-independent administration interface (a navigation menu for the admin side of a site). It’s a helper for novice Drupal users coming from another CMS, a real time-saver for Drupal site administrators, and definitely a must for Drupal developers and site builders (also includes integration with Devel ).

menu block
Provides configurable blocks of menu trees starting with any level of any menu.

menu trails
This module adds some common-sense usability to Drupal’s menu system

  • Menu Trails implements primary/secondary links which keep the current menu trail “active” or highlighted. A handy snippet ready to go into your template.php is included.

  • The module provides a means of broadly categorizing nodes (by type or taxonomy) as falling “under” a known menu item. These nodes are not added to the menu tree (keeping the menu admin system sane) but they will trigger the functionality above — preserving navigation state for the user — when viewed.

pathauto
Automatically generates path aliases for various kinds of content (nodes, categories, users) without requiring the user to manually specify the path alias. This allows you to get aliases like /category/my-node-title.html instead of /node/123. The aliases are based upon a “pattern” system which the administrator can control.

Performance

varnish (Drupal 7 only)
This module provides integration between your Drupal site and the Varnish HTTP Accelerator, an advanced and very fast reverse-proxy system. Basically, Varnish handles serving static files and anonymous pageviews for your site much faster than any webserver.

Security

mollom
Mollom provides a one stop solution for all spam problems and can protect the following Drupal forms. It offers and intelligently combines:

  • CAPTCHAs — both image and audio CAPTCHAs.
  • text analysis.
  • user reputations.

and can:

  • block comment form spam.
  • block contact form spam.
  • protect the user registration form against fake user accounts.
  • protect the password request form.
  • block spam on any node form, such as forum topics, articles, stories, pages, and more.

Site Stats

google analytics
Adds the Google Analytics web statistics tracking system to your website.
The module allows you to add the following statistics features to your site:

  • Selectively track certain users, roles and pages.
  • Monitor what type of links are tracked (downloads, outgoing and mailto).
  • Monitor what files are downloaded from your pages.
  • Cache the Google Analytics code on your local server for improved page loading times.
  • Track user segmentation from Drupal profile data.
  • Site Search support.
  • AdSense support.

UI

flot
This module provides an API for using the flot graphing library. It is designed to make it simple for developers to add flot graphs to their modules or applications.

jquery media
The jQuery Media plugin will automatically turn links to media into their embedded media equivalents. The module works best in conjuction with the File Field module, but may be used in other cases as well.

jquery ui
A wrapper module around the jQuery UI effects library that lets module developers add swooshy, swishy effects to their code.

slider
Slider module creates an effect called the “Coda slider”, which was made famous by the site: http://www.panic.com/coda/.

thickbox
ThickBox is a webpage UI dialog widget written in JavaScript on top of the jQuery library. Its function is to show a single image, multiple images, inline content, iframed content, or content served through AJAX in a hybrid modal.

vertical tabs
Provides vertical tabs like http://drupal.geek.nz/static/node-form/default/summaries2.html on the node add form.

User Management

node profile
This module builds user profiles as nodes, which opens the opportunity to use the Content Construction Kit (CCK), since it’s possible to make use of the field types, which are available for CCK. The integration of the views module allows one to easily build customizable user listings or even user searches.

user points
This module provides an API for users to gain or lose points for performing certain actions on your site.
In conjunction with other modules, such as the userpoints nodes and comments users can accumulate points for actions such as posting nodes, commenting or moderation duties.

Views

views bulk operations
This module augments Views by allowing bulk operations to be executed on the nodes displayed by a view. It does so by showing a checkbox in front of each node, and adding a select box containing operations that can be applied on the selected nodes.

calendar
This module will display any Views date field in calendar formats, including CCK date fields, node created or updated dates, etc. Switch between year, month, and day views. Back and next navigation is provided for all views.

draggable views
DraggableViews makes rows of a view “draggable” which means that they can be rearranged by Drag’n'Drop. This module makes it possible to organize complex structures with just a few clicks.

views showcase
This module integrates with Views module, so you can use any content type and fields to be displayed as Showcase. In this first release Views Showcase provides 3 slots where you can put an image, a title and a teaser. The fields are provided by Views module, so you can virtually put any field in these 3 slots. In future versions more slots will be provided.

views imageflow
This solution is known as the Cover Flow technique, which has been developed by the artist Andrew Coulter Enright. Now – since being acquired by Apple – it is used in iTunes and the file browser of Apples OSX.

Auckland September Web Meetup Recap

September 17th, 2009

I just attended the September Auckland Web Meetup, which had a full house of 200, free beer and pizza, and interesting presentations on the direction of web browsers.

To kick things off Microsoft technical evangelist Giorgio Sardo introduced IE8, which looks to be the most standards compliant browser from MS yet. Giorgio emphasized the large number of test cases IE8 has undergone. Giorgio showed some scripting and JSON encoding/decoding in IE8. He then went on to demo a cross-browser comparison tool, SuperPreview, which can be run as a stand-alone app or as part of Expression Web 3. A free version to compare the different versions of Internet Explorer is available here. The paid version includes other browsers in the comparison beyond Internet Explorer.

After pizza and drinks, Robert O’Callahan and the Mozilla team showed some of the upcoming features of Firefox. Some highlights included:

  • Support for accelerometers – with the necessary hardware the browser can recognize the tilt and orientation of the viewing device.
  • WebWorkers – An API for asynchronous JavaScript threaded processes (multiple processes running at the same time). Quite interesting!
  • Drag and Drop, between browser windows, and from the desktop.
  • 2D drawing using the Canvas tag – A simple vector example with apparent rigid body dynamics was shown.
  • 3D rendering using WebGL – This was the classic “3D teapot” demo, and I was quite impressed since performance seemed very good in the example.
  • Video tag – A variety of video scenarios were shown, such as a plain video tag with the browser’s built-in controls (for play, etc.), one that used JavaScript/CSS to overlay subtitles on the video, and some impressive examples that introduced an image into a green-screened video using just the browser. Also shown was overlaying and manipulating pictures, video, text, and Canvas elements on top of a video that had two reference points, a sort of augmented reality demo. This reminded me a lot of what can be done with BitmapData in ActionScript. A final demo on motion tracking was too cutting edge and crashed the browser.
  • DOM storage – an better alternative to cookies for local storage.
  • Client-side database storage – Robert cautioned that this may be a bit in the future yet, but the idea is to have a database on the client that can be used for storage, with the potential to have web applications that when offline work better than previously possible.
  • Geolocation – Allows the browser to notify websites where you are located.

It was all very interesting. I wouldn’t say I saw anything terribly innovative in its own right, since overall these are technologies that currently or will shortly exist through other means (such as Flash, AIR, Silverlight, etc.), but to see these built directly in a browser is interesting and may open these tools up to a wider field of developers.

UPDATE October 4, 2009: I forgot to mention Geolocation, it’s been added.

This isn’t right… MovieClip nested inside Button throwing null object reference error in Flash CS4

September 10th, 2009

A great thing about teaching is that your students approach problems in ways you haven’t done before and run into problems that you never knew existed. This is one such problem in Flash CS4 and a curious one at that.

THE PROBLEM: A Button symbol is placed on the Stage on a frame other than the first frame and given an instance name in the Properties panel. In the Actions panel, ActionScript is added that references the instance name of the button on the same frame that the button instance first appears on. The movie is tested and the following error occurs:

TypeError: Error #1009: Cannot access a property or method of a null object reference.
at MovieClipInsideButton_fla::MainTimeline/frame2()

Normally this error means that a particular instance has not been given an instance name in the Properties panel on the frame where the ActionScript appears. However, nothing looks amiss in the ActionScript or on the Stage. Adding a trace statement, such as trace(myButton); reveals null in the output window, meaning the trace statement has run before the instance name has been set to the button instance on the Stage. Hmm… very perplexing, since you may have other buttons and movieclips that work fine when referenced from ActionScript.

THE SOLUTION: From what I found, one scenario will produce this error. If a MovieClip symbol (instance) appears inside a Button symbol and the button appears on any frame other than the first frame, and the frame where the ActionScript references it is the same frame it first appears on—then this behavior will result.

MC_inside_button

There are a few workarounds:

  1. Retrieve the instance from the display list of its parent. Instead of referencing the Button instance on the stage directly, use getChildByName(.) to retrieve a reference to the instance, this can even be set to instance name at the beginning of your timeline code, like so:
    // myButton is the name of the instance as set in the Properties panel.
    // Retrieved child is cast as a SimpleButton, since this is the 
    // class of the Button symbol
    myButton = SimpleButton(getChildByName("myButton"));
  2. Do not nest a MovieClip inside a Button symbol. A Button nested inside a Button, a MovieClip nested inside a MovieClip, and a Button nested inside a MovieClip work fine.
  3. Place the first occurance of the Button instance on any frame before the frame where ActionScript first references it. This behavior appears to indicate Flash is taking too long to parse over the MovieClip inside a Button and runs the ActionScript on the timeline prematurely. Having the instance appear on a frame prior to the frame the ActionScript appears on ensures the instance is completely present in memory before it is referenced.
  4. Place the instance referencing code inside an enter frame event handler function. To ensure the entire frame has been parsed before any ActionScript code is run, enclose the offending code inside the event handler function of the enter frame event, and only make it run once, like so:
    addEventListener( Event.ENTER_FRAME , ensureRendered );
     
    function ensureRendered( evt:Event ) : void
    {
    	removeEventListener( Event.ENTER_FRAME , ensureRendered );
    	// All instance referencing code appears below this point
    	// In this case, instance is named "myButton" on the Stage
    	myButton.width = 200;
    }

This behavior doesn’t seem right to me and even seems it could be a bug. If anyone has an explanation for this behavior, I would love to hear it. You may download an example FLA here: Download Source

UPDATE September 20, 2009: I added a new workaround, which is probably the most succinct and reliable one yet to use. See Retrieve the instance from the display list of its parent in the list of workarounds.

How to add a webpage fade-in effect using JQuery

August 28th, 2009

THE PROBLEM: HTML pages that have numerous and complex nested <div> tags and CSS can sometimes have a jumbled “assembling” appearance that happens as the page is loading and the various elements are being rendered by the browser. The appearance of this process can look quite unrefined and detract from professional appearance of the site.

A SOLUTION: JQuery includes a function to fade-in a hidden tag. If the content of the page is initially hidden using CSS, it then can be faded-in using JQuery once the whole page has been processed and is ready for display.

Step 1

Inside the page’s <body> tag, enclose the content in a <div> tag with a unique CSS id (see this post for the difference between CSS ids and classes).

<body>
 
<div id="content-wrapper">
 
The page content goes here!
 
</div><!-- content-wrapper -->
 
</body>

Step 2

Inside the page’s <head> tag, import the JQuery library (download it here) and create a fade-in effect on the <div> tag surrounding the page’s content. Key to this solution is that the effect gets placed inside JQuery’s $(document).ready() function, ensuring the fade begins after the document’s DOM has been completely parsed.

<script type="text/javascript" src="jquery.min.js"></script>
 
<script type="text/javascript">
$(document).ready(function() 
{
		// fade in content.
		$( '#content-wrapper' ).fadeIn("slow");		
});
</script>

Step 3

At this point the fade-in effect will not occur, because the content is not hidden to begin with. To correct this add some CSS styling underneath the JavaScript above to hide the page content initially.

<style type="text/css">
 
#content-wrapper
{
	display:none;	
}
 
</style>

Step 4

Now the fade-in effect will work, however, a problem exists. If someone visits the page and has JavaScript turned off in their browser, the CSS to hide the content will be applied, but the JQuery to fade it back into visibility will not run, leaving the page effectively blank. This is a serious accessibility issue. To correct this, instead of hardcoding the <div> tag that is wrapping the content, write the tag using JavaScript. That way if JavaScript is turned off, the tag will not be rendered and won’t hide its containing content. Change what was written in Step 1 to the following:

<body>
 
<script type="text/javascript">
<!--//--><![CDATA[//><!--
document.write( '<div id="content-wrapper">' );
//--><!]]>
</script>
 
The page content goes here!
 
<script type="text/javascript">
<!--//--><![CDATA[//><!--
document.write( '</div><!-- content-wrapper -->' );
//--><!]]>
</script>
 
</body>

Putting it all together you end up with this (remember to include the JQuery library in the same folder as this HTML page):

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Fade-in effect example</title>
 
<script type="text/javascript" src="jquery.min.js"></script>
 
<script type="text/javascript">
$(document).ready(function() 
{
		// fade in content.
		$( '#content-wrapper' ).fadeIn("slow");		
});
</script>
 
<style type="text/css">
 
#content-wrapper
{
	display:none;	
}
 
</style>
 
</head>
 
<body>
 
<script type="text/javascript">
<!--//--><![CDATA[//><!--
document.write( '<div id="content-wrapper">' );
//--><!]]>
</script>
 
The page content goes here!
 
<script type="text/javascript">
<!--//--><![CDATA[//><!--
document.write( '</div><!-- content-wrapper -->' );
//--><!]]>
</script>
 
</body>
</html>

The dilemma of Twitter

August 19th, 2009

Twitter. Love it, perhaps hate it, or don’t get it. One thing is clear, Twitter has experienced profound media exposure, perhaps surprisingly out of proportion with the service it actually provides. No, there are no tools to help you sell things, no you can’t create galleries of your favorite pictures, no there isn’t a lengthy profile to fill out, no you can’t embed video. Twitter is simply 140 characters of whatever you want. Twitter is the bottled water of the Internet, in foresight dubiously useful, in hindsight surprisingly popular. With all this exposure has Twitter reached maturity and left the realm of novelty, or is it still riding a honeymoon through the limelight?

The tinkerers new toy

Twitter’s simple elegance has led many to explore creative ways of utilizing their 140 characters. Take Mario Klingemann’s (Quasimondo) Mona Lisa stored in a single tweet, whose rendering certainly needs no reference image to be recognizable. Or Grant Skinner’s Tweetcoding contest, a challenge to create something in ActionScript 3 within 140 characters. The small message footprint is seen as a challenge to mold and work within instead of an obstacle to overcome. It has the appeal of tinkering with an old toy, whose functionality may seem limited, but that very limitation makes it appealing to extend with modern tools, to see what is possible with what is available.

Taking a stroll down The Museum of Modern Betas, a website devoted to showcasing emerging beta websites, more often than not a new service showcased is one that aims to extend the functionality of Twitter.

Why extend the functionality of a site that could have more built into it to begin with, or spend time beating the most out of 140 characters when there are options available to disseminate texts of much larger length? The answer may lie in the special place Twitter holds within the eyes of its devotees, as well as the surprising versatility its simplicity allows.

A failure made for a t-shirt

Take for instance, the appearance of the Fail Whale—which, let us remember, denotes a failure of the system to function. On a whole, the flying whale’s appearance is met with mild irritation, but eventual forgiving acceptance. As if we’ve just missed the bus, but it’s a beautiful day out so why not wait a little longer. The whale appears, but it will pass. What other service enjoys such forgiveness on failing?
Perhaps it is because Twitter has no aura of presumptuousness or expectation. Twitter didn’t tell you to use its service, or how to use it. Twitter didn’t try to sell you something. Twitter didn’t promise something big. Twitter just gives one simple service with clearly defined boundaries, the rest is up to you.

Prior to being usurped by Facebook in popular favor and acquiring a reputation of ugliness, MySpace followed a similar road to success. It gave you the tools to create a webpage, link it to your friends (and strangers), and decorate it any way you saw fit. Its tools enabled something without being overbearing. Twitter’s format enables a particular kind of messaging to take place, and even more subtly, Twitter enhances its service within its limitations. The short message format forces conciseness, producing messages that are composed of the bare essentials. This format offers an effective way to convey information quickly in a way that is analogous to the “sound bites” of broadcast media.

Riding the honeymoon

Fundamentally, no matter the length of the message, Twitter is just like other media, it is nothing without the content it contains. The millions and millions of tweets. From the mundane and trivial, to the very present and important. They are the daily messages from people across the globe, some of which have been the first to report breaking news (for example, US Airways Flight 1549’s landing in the Hudson River). Twitter has been a face for citizen journalism and along with sites like Facebook have brought the term “social media” into mainstream use. Lest we forget, however, the Web has always been social media from its roots. The World Wide Web established a protocol for linking documents together through hyperlinks, the very type of links you click on webpages today. These were documents created by people, with links added by people elsewhere to make sharing information easier. The effort of masses of people created a vast network of documents, linked in (hopefully) relevant ways. This group effort is the basis of what makes the Internet so wonderful. Incrementally a vast library of information has accumulated, accessible from around the world. Google’s mission of “organizing the world’s information” is as noble as it is important. Web development should, as it always has, concern itself with organizing what information is on the Internet.

It is no surprise then that there are so many services appearing that attempt to utilize and extend the information on Twitter. The challenge is how to extract the useful information from the trivial and meaningless tweets. However, as the saying goes “one man’s trash is another man’s treasure,” and what is “useful information” is not always clear. And herein lies the dilemma of Twitter. Its flexibility within its confines is powerful, yet limiting. It is a versatile tool for the goals of many audiences, but without a clear way to target any particular one. All users are sending tweets into the pool without any inherent way of organizing them, since tweets lack any user generated metadata outside of the messages themselves. Yes, there are the existing hashtags, however, these rely on formatting conventions, and as with any system without standards they may become disparate in implementation, reducing their efficacy. Twitter’s advanced search is certainly useful, but it is a way to mine information, not consume relevant information in a passive way, the latter of which would be more appropriate to Twitter’s format.

Additionally, the character limit of messages, while keeping things concise, does not work with long URLs. Encouraging the spread of URL shortening services does nothing for the reliability of the information Twitter holds (see my other post: Why URL shortening is bad), unless Twitter itself acquires one of these services. If Twitter is more than a novelty or tinkerers toy, whose database of moments is to be taken as an important resource to be preserved on the Internet, tackling these issues may become tied with the continued sustainability of Twitter. At very least Twitter will need to utilize its own information in a way that offers a financial gain, since as of yet Twitter, the actual company, has yet to have any revenue from their namesake. For the time being, if the acceptance of the Fail Whale is any indication, Twitter may still be riding its way through the limelight.

Why URL shortening as we know it is bad

August 17th, 2009

There was a time when computers on the Internet were accessed via a numerical address. Early on, even before TCP/IP, the idea to map these sets of numbers to human-readable addresses seemed like a good one. The precursor of what is today the Domain Name System (DNS) was born. Fast forward to today and the Web is filled with millions of domain names. Familiar ones such as http://google.com are typed daily instead of http://74.125.45.100. As more and more domains were added and more and more server-side technologies emerged, URLs of webpage addresses became long and cumbersome. A need for a shortened URL was needed.

Early in the 2000s a new website, tinyurl.com, became the first notable site to provide such a service. Using TinyURL any website address could be given an alias that redirected to the actual address, but the alias often contained many fewer characters than the actual address. This was seemingly ideal for pasting to chat windows, sending in email (where email clients would sometimes not parse web addresses that contained long query strings with question marks and ampersands correctly), etc.

Then in 2006, Twitter appeared on the scene, and with its character limited message format of 140 characters, the need for a URL shortening method was all the more in demand. With Twitter’s meteoric rise to prominence, URL shorteners were given a large helping hand to mainstream visibility. In the time since, dozens have sprung up. But without a revenue stream to sustain them these services often folded just as quickly. And herein lies the problem. The Internet is built upon links of information that are relevant and accessible. For the most part these links are created by humans, and once created add to the organization and usefulness of the Internet as an information resource. Through Twitter and elsewhere URL shorteners are creating a vast catalog of links that are dependent on one website service to exist. If the service disappears, the alias no longer redirects, and the link is dead. Unlike most dead links it also doesn’t offer a hint as to what the original resource was, because the address has been obscured beyond recognition (although, at least one service, twi.bz, attempts to retain some hint of the original address). This contradicts the very idea of the Internet itself, whose beginnings began in de-centralization.

Little more than a year and a half ago mashable.com had an article that listed “90+ URL Shortening Services.” Browsing through this list it can be discovered that many are already defunct. With so many services to choose from who’s to know which may be solid, sustainable enterprises and which may be a mere pet project. Here today, gone tomorrow. Smalltime services may not have the resources, financial or otherwise to sustain themselves, yet their aliases persist on the Internet. Take cli.gs, who lost many aliases earlier this year due to being hacked. While this could happen to any website, it emphasizes the centralized vulnerability of these services. A similar problem can occur in cloud computing, as was illustrated by the demise of Ma.gnolia due to a hardware failure.

There are so many of these services because they do offer something valuable that is not possible with the current Internet protocols. Take tr.im, who announced last week that they would be shutting their doors at the end of the year. The public reaction that followed made them change their mind. This certainly illustrates the demand for these services, and is good that for the time being, tr.im aliases will remain alive, but it is a band aid on a problem that needs a grander solution than one popular website can provide.

Projects such as shortlink and short_url aim to tackle this problem by removing the third-party aspect of URL shortening and creating a specification for creating shortened URLs on the site that hosts a particular URL. These projects are not yet polished, but it is a start.

Taken as inspiration from this article about a service called Vanish, one interesting use for URL shortening that uses aliases may be in links that are intentionally made to “expire” after a certain period of time. Since a particular URL shortening service controls where an alias redirects to, they also can control for how long as well. However, if such a service was used more generally it would lead to the same issues of dead links (linkrot) as above.

Creating a date countdown timer in ActionScript 3 / Flash

August 3rd, 2009

Creating a countdown timer in ActionScript is quite easy. The essentials of it are:

  1. Specify a target date to countdown to using the Date class.
  2. Create a Timer instance to check the countdown time each second or so.
  3. At each tick of the timer calculate the number of milliseconds between now and the target date.
  4. Determine how many days, hours, minutes, seconds, etc. that number of milliseconds is equal to.
  5. Update the graphics to reflect the amount of time left.

The following is an example of a countdown timer, with a link to the source code below. This utilizes a reusable class file for the countdown timer. All code specific to this particular implementation can be found in com/anselmbradford/Main.as.

This movie requires Flash Player 9

Download Source

Teaching at Auckland University of Technology (AUT)

July 23rd, 2009

Auckland University of Technology
After all the rewards and hard work of putting together the 2009 Spring <br /> Conference last month, as well as finishing up my Master’s degree, I rather quickly and surprisingly found myself opening up an exciting new chapter in my life. I am now living in Auckland, New Zealand working as a lecturer at AUT teaching Interactive Media Production I & II. Hopefully between exploring and teaching I’ll have some time to get more posts out here soon.

How to build an Object-Oriented ActionScript 3 Preloader in Flash CS4: 2 Methods

June 20th, 2009

The magic of creating a preloader in ActionScript 3 lies in the LoaderInfo class. Every instantiated DisplayObject instance (all objects that appear on the stage, plus the stage itself) have a loaderInfo property that returns a LoaderInfo instance that contains information about the loading progress of that particular display object. Creating a preloader for the whole application is a matter of monitoring these LoaderInfo instances.

Method 1: Monitor Stage LoaderInfo instance

Under this method the loading progress is monitored via the LoaderInfo instance associated with the stage. Since all assets that will appear in the application need to be attached to the stage, the stage’s LoaderInfo instance will reflect the loading of all these assets.

Graphics

  1. Go to File → New… and select Flash File (ActionScript 3.0).
  2. Using the Rectangle tool create a rectangle (include a stroke) on the stage that is 100 pixels wide by 10 pixels high.
  3. Click on the fill of the newly created rectangle and select Modify → Convert to Symbol… Name the new instance ProgBar and set the registration point to left-middle. This will be the progress bar of the preloader.

    preloader_pbar

  4. With the new ProgBar instance selected on the stage, go to the Properties panel and name the instance progBar.
  5. Select the whole rectangle (stroke and progress bar instance). Select Modify → Convert to Symbol… Name the new instance Preloader and set the registration point to left-middle. Check the Export for ActionScript button.
  6. Click OK. If you get a warning that says the “definition for this class could not be found” click OK again.
  7. With the new Preloader instance selected, go to the Properties panel and name the newly created instance preloader. Your library should look like the following:

    preloader_library

  8. Select frame 2 of the main timeline, go to Insert → Timeline → Blank Keyframe. All content for the application will appear on frame 2 and beyond.
  9. Go to Insert → New Symbol… Name the new instance Content. If you check Export for ActionScript be sure to uncheck Export in frame 1, otherwise the preloader will not function properly.
  10. Place all content of the application on the timeline of the newly created Content instance.
  11. Return to the main timeline. Select frame 2 and drag an instance of the Content symbol from the library and place it on the stage.
  12. In the Properties panel of the stage name the document class Main. If you get a warning that says the “definition for this class could not be found” click OK.

    preloader_docclass

  13. Save the file.

Code

  1. Go to File → New… and select ActionScript File.
  2. Paste the following code and save the file as Preloader.as in the same directory as the .fla file saved earlier.
    package
    {
    	import flash.display.Sprite;
    	import flash.display.LoaderInfo;
    	import flash.events.Event;
     
    	public class Preloader extends Sprite
    	{
    		/**
    		* Alias for stage LoaderInfo instance
    		*/
    		private var _targetLoaderInfo:LoaderInfo;
     
    		/**
    		* The percent loaded
    		*/
    		private var _loadPercent:Number = 0;
     
    		/**
    		* Constructor
    		* Listen for when the preloader has been added to the stage 
    		* so that the progress of the remaining load can be monitored.
    		*/
    		public function Preloader()
    		{
    			this.addEventListener( Event.ADDED_TO_STAGE , _init );
    		}
     
    		/**
    		* Initialize variables.
    		* Set initial width of the progress bar to 0 
    		* and listen for enter frame event.
    		*/
    		private function _init(evt:Event):void
    		{
    			_targetLoaderInfo = stage.loaderInfo;
     
    			progBar.scaleX = 0;
     
    			this.removeEventListener( Event.ADDED_TO_STAGE , _init );
    			this.addEventListener(Event.ENTER_FRAME, _onCheckLoaded);
    		}
     
    		/**
    		* Check the status of the load, once complete dispatch a complete event.
    		*/
    		private function _onCheckLoaded(evt:Event):void 
    		{
    			_loadPercent = _targetLoaderInfo.bytesLoaded / _targetLoaderInfo.bytesTotal;
    			progBar.scaleX = _loadPercent;
    			if (progBar.scaleX == 1)
    			{
    				this.removeEventListener(Event.ENTER_FRAME, _onCheckLoaded);
    				this.dispatchEvent( new Event(Event.COMPLETE) );
    			}
    		}
    	}	
    }
  3. Go to File → New… and select ActionScript File a second time.
  4. Paste the following code and save the file as Main.as in the same directory as the .fla file saved earlier.
    package 
    {
    	import flash.display.MovieClip;
    	import flash.events.Event;
     
    	public class Main extends MovieClip 
    	{
    		/**
    		* Constructor
    		* Stop timeline and add event listener to preloader.
    		*/
    		public function Main() 
    		{
    			this.stop();
    			preloader.addEventListener( Event.COMPLETE , _initContent );
    		}
     
    		/**
    		* Load has finished, remove preloader and preceed to next frame.
    		*/
    		private function _initContent(evt:Event):void 
    		{
    			preloader.removeEventListener( Event.COMPLETE , _initContent );
    			this.removeChild(preloader);
    			nextFrame();
    		}
    	}
    }
  5. To test the preloader go to Control → Test Movie. Go to View → Simulate Download.
  6. Download method 1 complete source

Method 2: Monitor content SWF LoaderInfo instance

Under this method two SWFs are created, one encapsulating the preloader and the other encapsulating all content. The content SWF is loaded inside of the preloader SWF, which monitors the loading progress.

Graphics

  1. Follow steps 1 – 7 in the previous method.
  2. In the Properties panel of the stage name the document class PreloaderWrapper. If you get a warning that says the “definition for this class could not be found” click OK.
  3. Save the file.
  4. Go to File → New… and select Flash File (ActionScript 3.0).
  5. Add the content for your application to the timeline of this file.
  6. Save the file as content.fla.
  7. Go to Control → Test Movie to create the content.swf that will be loaded by the preloader SWF.

Code

  1. Go to File → New… and select ActionScript File.
  2. Paste the following code and save the file as PreloaderWrapper.as in the same directory as the .fla file saved earlier.
    package 
    {
    	import flash.display.Sprite;
    	import flash.display.Loader;
    	import flash.display.LoaderInfo;
    	import flash.display.DisplayObject;
    	import flash.events.Event;
    	import flash.events.ProgressEvent;
    	import flash.net.URLRequest;
     
    	public class PreloaderWrapper extends Sprite 
    	{
    		/**
    		* Alias for content LoaderInfo instance
    		*/
    		private var _targetLoaderInfo:LoaderInfo;
     
    		/**
    		* The percent loaded
    		*/
    		private var _loadPercent:Number = 0;
     
    		/**
    		* Constructor
    		* Creates Loader instance, adds event listeners and begins loading content SWF.
    		*/
    		public function PreloaderWrapper() 
    		{
    			var loader:Loader = new Loader();
    			_targetLoaderInfo = loader.contentLoaderInfo;
    			_targetLoaderInfo.addEventListener( ProgressEvent.PROGRESS, _loadingData );
    			_targetLoaderInfo.addEventListener( Event.COMPLETE , _finishedLoading );
    			loader.load( new URLRequest("content.swf") );
     
    		}
     
    		/**
    		* Monitor loading progress and update progress bar.
    		*/
    		private function _loadingData( evt:ProgressEvent ):void 
    		{
    			_loadPercent = _targetLoaderInfo.bytesLoaded / _targetLoaderInfo.bytesTotal;
    			preloader.progBar.scaleX = _loadPercent;	
    		}
     
    		/**
    		* Remove event listeners and preloader, and attach content SWF to stage.
    		*/
    		private function _finishedLoading( evt:Event ):void 
    		{
    			_targetLoaderInfo.removeEventListener( ProgressEvent.PROGRESS, _loadingData );
    			_targetLoaderInfo.removeEventListener( Event.COMPLETE , _finishedLoading );
    			this.removeChild(preloader);
    			this.addChild( DisplayObject(LoaderInfo(evt.target).content) );
    		}
    	}
    }
  3. To test the preloader go to Control → Test Movie. Go to View → Simulate Download.
  4. Download method 2 complete source

UPDATE July 30, 2009: I noticed I forgot the private designation on two of the methods in the PreloaderWrapper class. They have been added.

Learning Flash CS4 Professional published

May 5th, 2009

learncs4

Once again I had the pleasure of working as a technical editor with O’Reilly Media and author Rich Shupe on his latest title, Learning Flash CS4 Professional. It has just recently been published. Check it out!