Listing 1
Flex 2 UI code
dvdLibrary.mxml:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" pageTitle="DVD Library" creationComplete="pageLoaded()"
layout="vertical" backgroundColor="black" viewSourceURL="srcview/index.html">
<mx:HTTPService id="AWSECommerceService" resultFormat="e4x" result="getImages_handler(event)"
fault="ro_fault(event)" showBusyCursor="true"/> (1)
<mx:HTTPService id="AWSECommerceServiceFinal" resultFormat="e4x" result="getImageFinal_handler(event)"
fault="ro_fault(event)" showBusyCursor="true"/>
<mx:RemoteObject id="roMovies"
destination="ColdFusion"
source="flextraining.movies.info.flexination.cfc.movieGateway"
showBusyCursor="true">
<mx:method name="save" result="save_handler(event)" fault="ro_fault(event)"/>
<mx:method name="getAllAsQuery" result="getAllAsQuery_handler(event)" fault="ro_fault(event)"/>
<mx:method name="writeAmzWSToXML" result="writeAmzWSToXML_handler(event)" fault="ro_fault(event)"/>
<mx:method name="cleanupXML" result="cleanupXML_handler(event)" fault="ro_fault(event)"/>
<mx:method name="proxyToYouTube" result="getTrailer_handler(event)" fault="ro_fault(event)"/>
<mx:method name="getAllByTitle" result="getAllByTitle_handler(event)" fault="ro_fault(event)"/>
</mx:RemoteObject>
<mx:Style>
Panel {
borderColor: #666666;
borderAlpha: 0.4;
roundedBottomCorners: true;
headerHeight: 22;
backgroundAlpha: 1;
backgroundColor: #000000;
titleStyleName: "mypanelTitle";
}
.mypanelTitle {
color: #ff3300;
textAlign: left;
fontSize: 12;
fontWeight: bold;
fontStyle: italic;
paddingLeft: 20;
}
</mx:Style>
<mx:Script>
<![CDATA[
import mx.managers.PopUpManager;
import mx.rpc.events.ResultEvent;
import mx.rpc.events.FaultEvent;
import mx.controls.Alert;
import mx.utils.ObjectUtil;
import mx.collections.ArrayCollection;
import mx.managers.PopUpManager;
import mx.containers.TitleWindow;
import mx.events.ValidationResultEvent;
import mx.controls.ToolTip;
import mx.managers.ToolTipManager;
import info.flexination.actionscripts.movie;
[Bindable] private var arcMovies:ArrayCollection;
[Bindable] private var oMovie:movie = new movie;
[Bindable] private var iMovie:Number = 0;
[Bindable] private var sGenre:String = "";
[Bindable] private var sRating:String = "";
[Bindable] private var sSearchType:String = "Title";
[Bindable] private var blnCleanupSuccess:Boolean = false;
[Bindable] private var XMLFileName:String = "";
[Bindable] private var xmlSuccess:XML;
[Bindable] private var TrailerURL:String;
[Bindable] private var ImgURL:String = "";
[Embed(source="images/search-icon.png")]
[Bindable] private var imgSearch:Class;
private var vResult:ValidationResultEvent; (3)
private var msg:String = ""; (3)
private var count:Number = 0; (3)
private var msgprefix:String = ""; (3)
private var ErrorTip:ToolTip; (3)
private function pageLoaded():void {
//retrieve all the movies
roMovies.getAllAsQuery();
}
private function doSave():void {
// call the roMovies save method
if (iMovie>0) {
oMovie.Index = iMovie;
progressUpdateIndicator();
} else {
oMovie.Index = iMovie;
progressSaveIndicator();
}
oMovie.MediaType = "DVD";
oMovie.Title = tiTitle.text;
oMovie.Genre = sGenre;
oMovie.MPAARating = sRating;
oMovie.Starring = "";
oMovie.Credits = "";
oMovie.Studio = "";
oMovie.MovieReleaseDate = dteRelease.text;
oMovie.DVDReleaseDate = "";
oMovie.AspectRatio = "";
oMovie.SoundMix = "";
oMovie.RunningTime = tiTime.text;
oMovie.Keywords = "";
oMovie.Date_Purchased = "";
oMovie.MSRP = 0;
oMovie.PurchasePrice = 0;
oMovie.Vendor = "";
oMovie.Notes = "";
oMovie.Image = ImgURL;
oMovie.Date_Added = date_updated();
//Alert.show(ObjectUtil.toString(oMovie));
//create a new movie
roMovies.save(oMovie);
//retrieve all the active movies
roMovies.getAllAsQuery();
// clear out all the fields
}
private function clearForm():void {
iMovie = 0;
tiTitle.text = '';
sGenre = "";
cbxGenre.selectedIndex = 0;
sRating = "";
cbxRating.selectedIndex = 0;
tiTime.text = '';
dteRelease.text = '';
oMovie.Trailer = "";
imgCoverArt.source = null;
ImgURL = '';
btnSave.label = 'Save';
}
private function date_updated():String {
var date:Date = new Date;
var current:String = dateformatter.format(date.getMonth() + 1 + '/' + date.getDate() + '/' +
date.getFullYear()) + ' ' + date.getHours() + ':' + date.getMinutes() + ':' + date.getSeconds();
//Alert.show(current);
return current;
}
private function save_handler(event:ResultEvent): void {
iMovie = event.result as Number; // change flag to an update one
}
private function getAllAsQuery_handler(event:ResultEvent): void {
arcMovies = event.result as ArrayCollection;
}
private function getAllByTitle_handler(event:ResultEvent): void {
arcMovies = event.result as ArrayCollection;
}
private function ro_fault(event:FaultEvent): void {
// dump error message
Alert.show(ObjectUtil.toString(event.fault));
}
private function doView(): void {
if (dgMovies.selectedItem.Trailer!="") {
var tw:MovieTrailer=MovieTrailer(PopUpManager.createPopUp(this, MovieTrailer , false));
tw.movietitle = dgMovies.selectedItem.Title;
tw.trailer = dgMovies.selectedItem.Trailer;
tw.x = 620;
tw.y = 150;
} else {
Alert.show("Trailer unavailable...", "Ooops");
}
}
private function getGenre(selIdx:Number): void {
//Alert.show(selIdx.toString());
switch (selIdx) {
case 0:
sGenre = "Select Genre...";
break;
case 1:
sGenre = "Action";
break;
case 2:
sGenre = "Animation";
break;
case 3:
sGenre = "Comedy";
break;
case 4:
sGenre = "Drama";
break;
case 5:
sGenre = "Family";
break;
case 6:
sGenre = "Horror";
break;
case 7:
sGenre = "Musical";
break;
case 8:
sGenre = "Romance";
break;
case 9:
sGenre = "Sci-Fi";
break;
case 10:
sGenre = "Western";
break;
}
}
private function getRating(selIdx:Number): void {
//Alert.show(selIdx.toString());
switch (selIdx) {
case 0:
sRating = "Select Rating...";
break;
case 1:
sRating = "G";
break;
case 2:
sRating = "PG";
break;
case 3:
sRating = "PG-13";
break;
case 4:
sRating = "R";
break;
case 5:
sRating = "NC-17";
break;
case 6:
sRating = "Adult";
break;
}
}
private function getSearchType(selIdx:Number): void {
//Alert.show(selIdx.toString());
switch (selIdx) {
case 1:
sSearchType = "Title";
break;
case 2:
sSearchType = "Genre";
break;
case 3:
sSearchType = "MPAARating";
break;
case 4:
sSearchType = "RunningTime";
break;
case 5:
sSearchType = "MovieReleaseDate";
break;
default:
sSearchType = "Title";
break;
}
}
private function progressSaveIndicator():void {
var myTimer:Timer = new Timer(2000, 0);
myTimer.addEventListener("timer", onTimer);
myTimer.start();
lblProgress.setStyle("color", "green");
lblProgress.setStyle("fontWeight", "bold");
lblProgress.text = "Saving";
}
private function progressUpdateIndicator():void {
var myTimer:Timer = new Timer(2000, 0);
myTimer.addEventListener("timer", onTimer);
myTimer.start();
lblProgress.setStyle("color", "green");
lblProgress.setStyle("fontWeight", "bold");
lblProgress.text = "Updating";
}
private function onTimer(event:TimerEvent):void {
lblProgress.text = "";
}
private function validateForm():void { (3)
msg = "";
count = 0;
// Validate the title.
vResult = vTitle.validate();
// If the title is invalid.
if (vResult.type==ValidationResultEvent.INVALID) {
msg = "You must enter a movie title for the DVD.\n\n";
count++;
}
if (msg!="") {
if (count>1) {
msgprefix = "You must correct the following issues:";
}
mx.controls.Alert.show(msgprefix + "\n\n" + msg, "Required Fields Alert...");
return;
} else {
doSave();
}
}
private function displayDate(date:Date):void {
if (date == null) {
dteRelease.text = "";
} else {
dteRelease.text = (date.getMonth()+1).toString() + '/' + date.getDate() + '/' +
date.getFullYear().toString();
}
}
private function getImages(): void {
if (tiTitle.text!="") {
AWSECommerceService.url (1) = "http://webservices.amazon.com/onca/xml?Service=AWSECommerceService&SubscriptionId=your_amazon_API_key&Operation=
ItemSearch&SearchIndex=DVD&Title=" + tiTitle.text + "&ResponseGroup=Images";
AWSECommerceService.send();
}
}
private function getImages_handler(event:ResultEvent): void {
xmlSuccess = event.result as XML;
roMovies.writeAmzWSToXML(xmlSuccess);
}
private function writeAmzWSToXML_handler(event:ResultEvent): void {
XMLFileName = event.result as String;
//Alert.show(XMLFileName);
if (XMLFileName!="") {
AWSECommerceServiceFinal.url = "/flextraining/movies/wsxml/" + XMLFileName;
AWSECommerceServiceFinal.send();
}
}
private function getImageFinal_handler(event:ResultEvent): void {
xmlSuccess = event.result as XML;
if (xmlSuccess..TotalResults>0) {
parseMediumImages(xmlSuccess);
} else {
roMovies.cleanupXML(XMLFileName);
Alert.show(xmlSuccess..Error[0].Code + "\n" + xmlSuccess..Error[0].Message + "\n\nYou may proceed,
but there will not be any cover art saved.", "Warning! No Cover Art For This Title");
}
}
private function parseMediumImages(xml:XML): void {
for each (var xmldata:XML in xml..MediumImage[0].URL) {
//Alert.show(ObjectUtil.toString(xmldata));
imgCoverArt.source = xmldata;
ImgURL = String(imgCoverArt.source);
}
roMovies.cleanupXML(XMLFileName);
}
private function cleanupXML_handler(event:ResultEvent): void {
blnCleanupSuccess = event.result as Boolean;
}
private function getTrailer(): void {
if (tiTitle.text!="") {
roMovies.proxyToYouTube(tiTitle.text);
}
}
private function getTrailer_handler(event:ResultEvent): void {
TrailerURL = event.result as String;
if (TrailerURL!="") {
oMovie.Trailer = TrailerURL;
} else {
oMovie.Trailer = "";
}
//Alert.show(oMovie.Trailer);
}
private function doSearch(): void {
roMovies.getAllByTitle(sSearchType, tiSearch.text);
}
]]>
</mx:Script>
<mx:Style>
ToolTip { font-family: "Verdanna"; font-size: 12; font-weight: "normal"; background-color: "0x7B68EE"; color:
"0xFFFFFF"; }
</mx:Style>
<!-- Define validators. -->
<mx:StringValidator id="vTitle" source="{tiTitle}" property="text" requiredFieldError="Please enter a movie
title for the DVD."/> (3)
<mx:DateFormatter id="dateformatter" formatString="YYYY-MM-DD"/>
<mx:states>
<mx:State name="addDVD">
<mx:RemoveChild target="{dgMovies}"/>
<mx:RemoveChild target="{btnAdd}"/>
<mx:RemoveChild target="{cbxSearchType}"/>
<mx:RemoveChild target="{tiSearch}"/>
<mx:RemoveChild target="{btnSearch}"/>
<mx:AddChild relativeTo="{pnlLibrary}" position="lastChild">
<mx:target>
<mx:Form id="frmAddDVD">
<mx:FormItem id="fitTitle" required="true">
<mx:HBox width="100%">
<mx:Label text="Title:" fontFamily="Verdanna" fontSize="14" color="white"/>
<mx:TextInput id="tiTitle" width="200" focusOut="getImages();getTrailer()"/>
</mx:HBox>
</mx:FormItem>
<mx:FormItem id="fitGenre">
<mx:HBox width="100%">
<mx:Label text="Genre:" fontFamily="Verdanna" fontSize="14" color="white"/>
<mx:ComboBox id="cbxGenre" change="getGenre(cbxGenre.selectedIndex)" toolTip="Select
the genre for this movie...">
<mx:dataProvider>
<mx:Array>
<mx:String>Select Genre...</mx:String>
<mx:String>Action</mx:String>
<mx:String>Animation</mx:String>
<mx:String>Comedy</mx:String>
<mx:String>Drama</mx:String>
<mx:String>Family</mx:String>
<mx:String>Horror</mx:String>
<mx:String>Musical</mx:String>
<mx:String>Romance</mx:String>
<mx:String>Sci-Fi</mx:String>
<mx:String>Western</mx:String>
</mx:Array>
</mx:dataProvider>
</mx:ComboBox>
</mx:HBox>
</mx:FormItem>
<mx:FormItem id="fitRating">
<mx:HBox width="100%">
<mx:Label text="Rating:" fontFamily="Verdanna" fontSize="14" color="white"/>
<mx:ComboBox id="cbxRating" change="getRating(cbxRating.selectedIndex)"
toolTip="Select the rating for this movie...">
<mx:dataProvider>
<mx:Array>
<mx:String>Select Rating...</mx:String>
<mx:String>G</mx:String>
<mx:String>PG</mx:String>
<mx:String>PG-13</mx:String>
<mx:String>R</mx:String>
<mx:String>NC-17</mx:String>
<mx:String>Adult</mx:String>
</mx:Array>
</mx:dataProvider>
</mx:ComboBox>
</mx:HBox>
</mx:FormItem>
<mx:FormItem id="fitTime">
<mx:HBox width="100%">
<mx:Label text="Time (in minutes):" fontFamily="Verdanna" fontSize="14"
color="white"/>
<mx:TextInput id="tiTime" width="100"/>
</mx:HBox>
</mx:FormItem>
<mx:FormItem id="fitRelease">
<mx:HBox width="100%">
<mx:Label text="Release Date:" fontFamily="Verdanna" fontSize="14" color="white"/>
<mx:Label id="dteRelease" color="white" width="0" height="0" visible="false"/>
<mx:DateChooser id="dteReleaseChooser" yearNavigationEnabled="true"
change="displayDate(DateChooser(event.target).selectedDate)"/>
</mx:HBox>
</mx:FormItem>
<mx:FormItem id="fitCoverArt">
<mx:HBox width="100%">
<mx:Label text="Cover Image:" fontFamily="Verdanna" fontSize="14" color="white"/>
<mx:Image id="imgCoverArt" height="{(imgCoverArt.source!=null)?140:24}"
width="{(imgCoverArt.source!=null)?98:0}"/>
</mx:HBox>
</mx:FormItem>
</mx:Form>
</mx:target>
</mx:AddChild>
<mx:AddChild relativeTo="{controlbar1}" position="lastChild">
<mx:ControlBar>
<mx:HBox width="100%">
<mx:Button id="btnSave" label="Save" click="validateForm()(3)"
enabled="{(iMovie==0)?true:false}" fontFamily="Verdanna" fontSize="14" fontWeight="bold"
toolTip="Click to save this Movie..."/>
<mx:Button id="btnEdit" label="Edit" click="validateForm()(3)"
enabled="{(iMovie>0)?true:false}" fontFamily="Verdanna" fontSize="14" fontWeight="bold"
toolTip="Click to edit this Movie..."/>
<mx:Button id="btnClear" label="Clear" click="clearForm()" fontFamily="Verdanna"
fontSize="14" fontWeight="bold" toolTip="Click to clear the form and enter a new Movie..."/>
<mx:Spacer width="20"/>
<mx:Button id="btnReturn" label="Library" click="currentState=''" fontFamily="Verdanna"
fontSize="14" fontWeight="bold" toolTip="Click to return to the DVD Library..."/>
<mx:Label id="lblProgress" color="#000000" fontStyle="italic" fontWeight="bold"/>
</mx:HBox>
</mx:ControlBar>
</mx:AddChild>
</mx:State>
</mx:states>
<mx:Panel id="pnlLibrary" title="{(currentState=='')?'DVD Library':'Add a DVD'}">
<mx:DataGrid id="dgMovies" dataProvider="{arcMovies}" rowCount="4" rowHeight="48" height="492" width="800"
doubleClickEnabled="true" itemDoubleClick="doView()" toolTip="Double-click to view the movie trailer (be
patient :-)..." cornerRadius="4" headerColors="[0xF0FCFF, 0x93EAFF]" headerHeight="22">
<mx:columns>
<mx:DataGridColumn headerText="Title" dataField="Title" itemRenderer="renderers.TitleRenderer"
width="180"/>
<mx:DataGridColumn headerText="Genre" dataField="Genre" itemRenderer="renderers.GenreRenderer"
width="110"/>
<mx:DataGridColumn headerText="Rating" dataField="MPAARating"
itemRenderer="renderers.RatingRenderer" width="60"/>
<mx:DataGridColumn headerText="Time" dataField="RunningTime" itemRenderer="renderers.TimeRenderer"
width="100"/>
<mx:DataGridColumn headerText="Release Date" dataField="MovieReleaseDate"
itemRenderer="renderers.ReleaseDateRenderer" width="90"/>
<mx:DataGridColumn headerText="Trailer" dataField="Trailer" visible="false" width="0"/>
<mx:DataGridColumn headerText="Cover" dataField="Image" itemRenderer="renderers.CoverRenderer"
width="100"/>
</mx:columns>
</mx:DataGrid>
<mx:ControlBar id="controlbar1" paddingLeft="10" paddingRight="10">
<mx:Button id="btnAdd" label="Add a DVD" click="currentState='addDVD'" fontFamily="Verdanna"
fontSize="14" fontWeight="bold" toolTip="Click to add a new DVD..."/>
<mx:Spacer width="{(currentState=='')?270:0}"/>
<mx:ComboBox id="cbxSearchType" change="getSearchType(cbxSearchType.selectedIndex)" toolTip="Select the
search type...">
<mx:dataProvider>
<mx:Array>
<mx:String>Search Criteria...</mx:String>
<mx:String>Title</mx:String>
<mx:String>Genre</mx:String>
<mx:String>Rating</mx:String>
<mx:String>Time</mx:String>
<mx:String>Release Date</mx:String>
</mx:Array>
</mx:dataProvider>
</mx:ComboBox>
<mx:TextInput id="tiSearch" fontWeight="normal" color="#000000" toolTip="Enter a DVD title..."/>
<mx:Button id="btnSearch" label="Search" icon="{imgSearch}" click="doSearch()" fontFamily="Verdanna"
fontSize="14" fontWeight="bold" toolTip="Click to start the search..."/>
</mx:ControlBar>
</mx:Panel>
</mx:Application>
MovieTrailer.mxml (4):
<?xml version="1.0" encoding="utf-8"?>
<mx:TitleWindow xmlns:mx="http://www.adobe.com/2006/mxml" title="{movietitle + ' Trailer'}"
creationComplete="twLoaded()" showCloseButton="true" close="closeDialog()" layout="vertical" width="244" height="156">
<mx:Script>
<![CDATA[
import mx.events.FlexEvent;
import mx.managers.PopUpManager;
import mx.controls.Alert;
[Bindable] public var movietitle:String;
[Bindable] public var trailer:String;
private function twLoaded(): void {
if (trailer.substr(11, 7)!='youtube') {
swfTrailer.source = 'swfs/' + trailer;
swfTrailer.addEventListener(Event.COMPLETE, loadedSWF);
swfTrailer.addEventListener(IOErrorEvent.IO_ERROR, errorSWF);
} else {
var u:URLRequest = new URLRequest("javascript:var myWin1; if(!myWin1 || myWin1.closed){
myWin1=window.open('"+trailer+"','Trailer_View','width=785,height=610,left='+((screen.width - 785)
/ 2)+',top='+((screen.height - 610) / 2)+',menubar=yes,resizable=yes,scrollbars=yes')} else {
myWin1.focus();};void(0);");
navigateToURL(u,"_self");
closeDialog();
}
}
private function loadedSWF(event:Event): void {
if (movietitle.length > 15) {
movietitle = "Playing " + movietitle.substr(0, 13) + "...";
} else {
movietitle = "Playing " + movietitle;
}
}
private function errorSWF(ioe:IOErrorEvent): void {
Alert.show(ioe.text.toString());
}
// The event handler for the TitleWindow close button.
public function closeDialog(): void {
swfTrailer.source = null;
PopUpManager.removePopUp(this);
}
]]>
</mx:Script>
<mx:SWFLoader id="swfTrailer" horizontalAlign="center" verticalAlign="middle" width="100%" height="100%"/>
</mx:TitleWindow>
CoverRenderer.mxml:
<?xml version="1.0" encoding="utf-8"?>
<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml" horizontalAlign="center" verticalAlign="middle" width="100%"
height="100%">
<mx:Script>
<![CDATA[
import mx.core.Application;
import mx.managers.PopUpManager;
import mx.controls.Alert;
// Event handler for the effectEnd event.
private function popupImageHandler():void {
if (data.Image!="") {
var tw:ImageViewer=ImageViewer(PopUpManager.createPopUp(this, ImageViewer , false));
tw.imageurl = data.Image;
tw.movietitle = mx.core.Application.application.dgMovies.selectedItem.Title;
tw.moviefulltitle = mx.core.Application.application.dgMovies.selectedItem.Title;
tw.x = 620;
tw.y = 150;
} else {
Alert.show("Image unavailable...", "Ooops");
}
}
]]>
</mx:Script>
<mx:Image id="imgCover" source="{data.Image}" click="popupImageHandler()" horizontalAlign="center"
verticalAlign="middle" width="100%" height="100%" toolTip="Click to see a larger view..."/>
</mx:VBox>
movie.as:
package info.flexination.actionscripts
{
[RemoteClass(alias="flextraining.movies.info.flexination.cfc.movie")]
[Bindable]
public class movie
{
public var Index:Number = 0;
public var MediaType:String = "";
public var Title:String = "";
public var Genre:String = "";
public var MPAARating:String = "";
public var Starring:String = "";
public var Credits:String = "";
public var Studio:String = "";
public var MovieReleaseDate:String = "";
public var DVDReleaseDate:String = "";
public var AspectRatio:String = "";
public var SoundMix:String = "";
public var RunningTime:String = "";
public var Keywords:String = "";
public var Date_Purchased:String = "";
public var MSRP:Number = 0;
public var PurchasePrice:Number = 0;
public var Vendor:String = "";
public var Trailer:String = "";
public var Notes:String = "";
public var Image:String = "";
public var Date_Added:String = null;
public function movie()
{
}
}
}
Listing 2
ColdFusion Components code
movie.cfc:
<cfcomponent output="false" alias="flextraining.movies.info.flexination.cfc.movie">
<!---
These are properties that are exposed by this CFC object.
These property definitions are used when calling this CFC as a web services,
passed back to a flash movie, or when generating documentation
NOTE: these cfproperty tags do not set any default property values.
--->
<cfproperty name="Index" type="numeric" default="0">
<cfproperty name="MediaType" type="string" default="">
<cfproperty name="Title" type="string" default="">
<cfproperty name="Genre" type="string" default="">
<cfproperty name="MPAARating" type="string" default="">
<cfproperty name="Starring" type="string" default="">
<cfproperty name="Credits" type="string" default="">
<cfproperty name="Studio" type="string" default="">
<cfproperty name="MovieReleaseDate" type="string" default="">
<cfproperty name="DVDReleaseDate" type="string" default="">
<cfproperty name="AspectRatio" type="string" default="">
<cfproperty name="SoundMix" type="string" default="">
<cfproperty name="RunningTime" type="string" default="">
<cfproperty name="Keywords" type="string" default="">
<cfproperty name="Date_Purchased" type="string" default="">
<cfproperty name="MSRP" type="numeric" default="0">
<cfproperty name="PurchasePrice" type="numeric" default="0">
<cfproperty name="Vendor" type="string" default="">
<cfproperty name="Trailer" type="string" default="">
<cfproperty name="Notes" type="string" default="">
<cfproperty name="Image" type="string" default="">
<cfproperty name="Date_Added" type="string" default="">
<cfscript>
//Initialize the CFC with the default properties values.
variables.Index = 0;
variables.MediaType = "";
variables.Title = "";
variables.Genre = "";
variables.MPAARating = "";
variables.Starring = "";
variables.Credits = "";
variables.Studio = "";
variables.MovieReleaseDate = "";
variables.DVDReleaseDate = "";
variables.AspectRatio = "";
variables.SoundMix = "";
variables.RunningTime = "";
variables.Keywords = "";
variables.Date_Purchased = "";
variables.MSRP = 0;
variables.PurchasePrice = 0;
variables.Vendor = "";
variables.Trailer = "";
variables.Notes = "";
variables.Image = "";
variables.Date_Added = "";
</cfscript>
<cffunction name="init" output="false" returntype="movies">
<cfreturn this>
</cffunction>
<cffunction name="getIndex" output="false" access="public" returntype="any">
<cfreturn variables.Index>
</cffunction>
<cffunction name="setIndex" output="false" access="public" returntype="void">
<cfargument name="val" required="true">
<cfif (IsNumeric(arguments.val)) OR (arguments.val EQ "")>
<cfset variables.Index = arguments.val>
<cfelse>
<cfthrow message="'#arguments.val#' is not a valid numeric"/>
</cfif>
</cffunction>
<cffunction name="getMediaType" output="false" access="public" returntype="any">
<cfreturn variables.MediaType>
</cffunction>
<cffunction name="setMediaType" output="false" access="public" returntype="void">
<cfargument name="val" required="true">
<cfset variables.MediaType = arguments.val>
</cffunction>
<cffunction name="getTitle" output="false" access="public" returntype="any">
<cfreturn variables.Title>
</cffunction>
<cffunction name="setTitle" output="false" access="public" returntype="void">
<cfargument name="val" required="true">
<cfset variables.Title = arguments.val>
</cffunction>
<cffunction name="getGenre" output="false" access="public" returntype="any">
<cfreturn variables.Genre>
</cffunction>
<cffunction name="setGenre" output="false" access="public" returntype="void">
<cfargument name="val" required="true">
<cfset variables.Genre = arguments.val>
</cffunction>
<cffunction name="getMPAARating" output="false" access="public" returntype="any">
<cfreturn variables.MPAARating>
</cffunction>
<cffunction name="setMPAARating" output="false" access="public" returntype="void">
<cfargument name="val" required="true">
<cfset variables.MPAARating = arguments.val>
</cffunction>
<cffunction name="getStarring" output="false" access="public" returntype="any">
<cfreturn variables.Starring>
</cffunction>
<cffunction name="setStarring" output="false" access="public" returntype="void">
<cfargument name="val" required="true">
<cfset variables.Starring = arguments.val>
</cffunction>
<cffunction name="getCredits" output="false" access="public" returntype="any">
<cfreturn variables.Credits>
</cffunction>
<cffunction name="setCredits" output="false" access="public" returntype="void">
<cfargument name="val" required="true">
<cfset variables.Credits = arguments.val>
</cffunction>
<cffunction name="getStudio" output="false" access="public" returntype="any">
<cfreturn variables.Studio>
</cffunction>
<cffunction name="setStudio" output="false" access="public" returntype="void">
<cfargument name="val" required="true">
<cfset variables.Studio = arguments.val>
</cffunction>
<cffunction name="getMovieReleaseDate" output="false" access="public" returntype="any">
<cfreturn variables.MovieReleaseDate>
</cffunction>
<cffunction name="setMovieReleaseDate" output="false" access="public" returntype="void">
<cfargument name="val" required="true">
<cfset variables.MovieReleaseDate = arguments.val>
</cffunction>
<cffunction name="getDVDReleaseDate" output="false" access="public" returntype="any">
<cfreturn variables.DVDReleaseDate>
</cffunction>
<cffunction name="setDVDReleaseDate" output="false" access="public" returntype="void">
<cfargument name="val" required="true">
<cfset variables.DVDReleaseDate = arguments.val>
</cffunction>
<cffunction name="getAspectRatio" output="false" access="public" returntype="any">
<cfreturn variables.AspectRatio>
</cffunction>
<cffunction name="setAspectRatio" output="false" access="public" returntype="void">
<cfargument name="val" required="true">
<cfset variables.AspectRatio = arguments.val>
</cffunction>
<cffunction name="getSoundMix" output="false" access="public" returntype="any">
<cfreturn variables.SoundMix>
</cffunction>
<cffunction name="setSoundMix" output="false" access="public" returntype="void">
<cfargument name="val" required="true">
<cfset variables.SoundMix = arguments.val>
</cffunction>
<cffunction name="getRunningTime" output="false" access="public" returntype="any">
<cfreturn variables.RunningTime>
</cffunction>
<cffunction name="setRunningTime" output="false" access="public" returntype="void">
<cfargument name="val" required="true">
<cfset variables.RunningTime = arguments.val>
</cffunction>
<cffunction name="getKeywords" output="false" access="public" returntype="any">
<cfreturn variables.Keywords>
</cffunction>
<cffunction name="setKeywords" output="false" access="public" returntype="void">
<cfargument name="val" required="true">
<cfset variables.Keywords = arguments.val>
</cffunction>
<cffunction name="getDate_Purchased" output="false" access="public" returntype="any">
<cfreturn variables.Date_Purchased>
</cffunction>
<cffunction name="setDate_Purchased" output="false" access="public" returntype="void">
<cfargument name="val" required="true">
<cfset variables.Date_Purchased = arguments.val>
</cffunction>
<cffunction name="getMSRP" output="false" access="public" returntype="any">
<cfreturn variables.MSRP>
</cffunction>
<cffunction name="setMSRP" output="false" access="public" returntype="void">
<cfargument name="val" required="true">
<cfif (IsNumeric(arguments.val)) OR (arguments.val EQ "")>
<cfset variables.MSRP = arguments.val>
<cfelse>
<cfthrow message="'#arguments.val#' is not a valid numeric"/>
</cfif>
</cffunction>
<cffunction name="getPurchasePrice" output="false" access="public" returntype="any">
<cfreturn variables.PurchasePrice>
</cffunction>
<cffunction name="setPurchasePrice" output="false" access="public" returntype="void">
<cfargument name="val" required="true">
<cfif (IsNumeric(arguments.val)) OR (arguments.val EQ "")>
<cfset variables.PurchasePrice = arguments.val>
<cfelse>
<cfthrow message="'#arguments.val#' is not a valid numeric"/>
</cfif>
</cffunction>
<cffunction name="getVendor" output="false" access="public" returntype="any">
<cfreturn variables.Vendor>
</cffunction>
<cffunction name="setVendor" output="false" access="public" returntype="void">
<cfargument name="val" required="true">
<cfset variables.Vendor = arguments.val>
</cffunction>
<cffunction name="getTrailer" output="false" access="public" returntype="any">
<cfreturn variables.Trailer>
</cffunction>
<cffunction name="setTrailer" output="false" access="public" returntype="void">
<cfargument name="val" required="true">
<cfset variables.Trailer = arguments.val>
</cffunction>
<cffunction name="getNotes" output="false" access="public" returntype="any">
<cfreturn variables.Notes>
</cffunction>
<cffunction name="setNotes" output="false" access="public" returntype="void">
<cfargument name="val" required="true">
<cfset variables.Notes = arguments.val>
</cffunction>
<cffunction name="getImage" output="false" access="public" returntype="any">
<cfreturn variables.Image>
</cffunction>
<cffunction name="setImage" output="false" access="public" returntype="void">
<cfargument name="val" required="true">
<cfset variables.Image = arguments.val>
</cffunction>
<cffunction name="getDate_Added" output="false" access="public" returntype="any">
<cfreturn variables.Date_Added>
</cffunction>
<cffunction name="setDate_Added" output="false" access="public" returntype="void">
<cfargument name="val" required="true">
<cfif (IsDate(arguments.val)) OR (arguments.val EQ "")>
<cfset variables.Date_Added = arguments.val>
<cfelse>
<cfthrow message="'#arguments.val#' is not a valid date"/>
</cfif>
</cffunction>
</cfcomponent>
movieDAO.cfc (CRUD):
<cfcomponent output="false">
<cffunction name="read" output="false" access="public" returntype="flextraining.movies.info.flexination.cfc.movie">
<cfargument name="id" required="true">
<cfset var qRead="">
<cfset var obj="">
<cfquery name="qRead" datasource="movies">
select Index, MediaType, Title, Genre, MPAARating, Starring,
Credits, Studio, MovieReleaseDate, DVDReleaseDate, AspectRatio,
SoundMix, RunningTime, Keywords, Date_Purchased, MSRP,
PurchasePrice, Vendor, Trailer, Notes, Image,
Date_Added
from movies
where Index = <cfqueryparam cfsqltype="CF_SQL_INTEGER" value="#arguments.id#" />
</cfquery>
<cfscript>
obj = createObject("component", "flextraining.movies.info.flexination.cfc.movie").init();
obj.setIndex(qRead.Index);
obj.setMediaType(qRead.MediaType);
obj.setTitle(qRead.Title);
obj.setGenre(qRead.Genre);
obj.setMPAARating(qRead.MPAARating);
obj.setStarring(qRead.Starring);
obj.setCredits(qRead.Credits);
obj.setStudio(qRead.Studio);
obj.setMovieReleaseDate(qRead.MovieReleaseDate);
obj.setDVDReleaseDate(qRead.DVDReleaseDate);
obj.setAspectRatio(qRead.AspectRatio);
obj.setSoundMix(qRead.SoundMix);
obj.setRunningTime(qRead.RunningTime);
obj.setKeywords(qRead.Keywords);
obj.setDate_Purchased(qRead.Date_Purchased);
obj.setMSRP(qRead.MSRP);
obj.setPurchasePrice(qRead.PurchasePrice);
obj.setVendor(qRead.Vendor);
obj.setTrailer(qRead.Trailer);
obj.setNotes(qRead.Notes);
obj.setImage(qRead.Image);
obj.setDate_Added(qRead.Date_Added);
return obj;
</cfscript>
</cffunction>
<cffunction name="create" output="false" access="public" returntype="numeric">
<cfargument name="bean" required="true" type="flextraining.movies.info.flexination.cfc.movie">
<cfset var qCreate="">
<cfset var qGetId="">
<cfset var local1=arguments.bean.getMediaType()>
<cfset var local2=arguments.bean.getTitle()>
<cfset var local3=arguments.bean.getGenre()>
<cfset var local4=arguments.bean.getMPAARating()>
<cfset var local5=arguments.bean.getStarring()>
<cfset var local6=arguments.bean.getCredits()>
<cfset var local7=arguments.bean.getStudio()>
<cfset var local8=arguments.bean.getMovieReleaseDate()>
<cfset var local9=arguments.bean.getDVDReleaseDate()>
<cfset var local10=arguments.bean.getAspectRatio()>
<cfset var local11=arguments.bean.getSoundMix()>
<cfset var local12=arguments.bean.getRunningTime()>
<cfset var local13=arguments.bean.getKeywords()>
<cfset var local14=arguments.bean.getDate_Purchased()>
<cfset var local15=arguments.bean.getMSRP()>
<cfset var local16=arguments.bean.getPurchasePrice()>
<cfset var local17=arguments.bean.getVendor()>
<cfset var local18=arguments.bean.getTrailer()>
<cfset var local19=arguments.bean.getNotes()>
<cfset var local20=arguments.bean.getImage()>
<cfset var local21=arguments.bean.getDate_Added()>
<cftransaction isolation="read_committed">
<cftry>
<cfquery name="qCreate" datasource="movies" result="status">
insert into movies (MediaType, Title, Genre, MPAARating, Starring, Credits, Studio, MovieReleaseDate,
DVDReleaseDate, AspectRatio, SoundMix, RunningTime, Keywords, Date_Purchased, MSRP, PurchasePrice, Vendor,
Trailer, Notes, Image, Date_Added, bVisible)
values (
<cfqueryparam value="#local1#" cfsqltype="CF_SQL_VARCHAR" />,
<cfqueryparam value="#local2#" cfsqltype="CF_SQL_VARCHAR" />,
<cfqueryparam value="#local3#" cfsqltype="CF_SQL_VARCHAR" />,
<cfqueryparam value="#local4#" cfsqltype="CF_SQL_VARCHAR" />,
<cfqueryparam value="#local5#" cfsqltype="CF_SQL_VARCHAR" />,
<cfqueryparam value="#local6#" cfsqltype="CF_SQL_LONGVARCHAR" />,
<cfqueryparam value="#local7#" cfsqltype="CF_SQL_VARCHAR" />,
<cfqueryparam value="#local8#" cfsqltype="CF_SQL_VARCHAR" />,
<cfqueryparam value="#local9#" cfsqltype="CF_SQL_VARCHAR" />,
<cfqueryparam value="#local10#" cfsqltype="CF_SQL_VARCHAR" />,
<cfqueryparam value="#local11#" cfsqltype="CF_SQL_VARCHAR" />,
<cfqueryparam value="#local12#" cfsqltype="CF_SQL_VARCHAR" />,
<cfqueryparam value="#local13#" cfsqltype="CF_SQL_VARCHAR" />,
<cfqueryparam value="#local14#" cfsqltype="CF_SQL_VARCHAR" />,
<cfqueryparam value="#local15#" cfsqltype="CF_SQL_DOUBLE" null="#iif((local15 eq ""), de("yes"), de("no"))#" />,
<cfqueryparam value="#local16#" cfsqltype="CF_SQL_DOUBLE" null="#iif((local16 eq ""), de("yes"), de("no"))#" />,
<cfqueryparam value="#local17#" cfsqltype="CF_SQL_VARCHAR" />,
<cfqueryparam value="#local18#" cfsqltype="CF_SQL_VARCHAR" />,
<cfqueryparam value="#local19#" cfsqltype="CF_SQL_LONGVARCHAR" />,
<cfqueryparam value="#local20#" cfsqltype="CF_SQL_VARCHAR" />,
<cfqueryparam value="#local21#" cfsqltype="CF_SQL_VARCHAR" null="#iif((local21 eq ""), de("yes"), de("no"))#"
/>,
1
)
</cfquery>
<cfcatch type="database">
<cfthrow message="#cfcatch.Message# #cfcatch.Detail#">
<cflog file="MovieInsert" application="no" text="#status.sql#">
</cfcatch>
</cftry>
<cftry>
<!--- If your server has a better way to get the ID that is more reliable, use that instead --->
<cfquery name="qGetID" datasource="movies" result="status">
select COUNT(Title) AS ID
from movies
</cfquery>
<cfcatch type="database">
<cfthrow message="#cfcatch.Message# #cfcatch.Detail#">
<cflog file="MovieID" application="no" text="#status.sql#">
</cfcatch>
</cftry>
</cftransaction>
<cfscript>
arguments.bean.setIndex(qGetID.ID);
</cfscript>
<cfreturn qGetID.ID>
</cffunction>
<cffunction name="update" output="false" access="public" returntype="numeric">
<cfargument name="bean" required="true" type="flextraining.movies.info.flexination.cfc.movie">
<cfset var qUpdate="">
<cftry>
<cfquery name="qUpdate" datasource="movies" result="status">
update movies
set MediaType = <cfqueryparam value="#arguments.bean.getMediaType()#" cfsqltype="CF_SQL_VARCHAR" />,
Title = <cfqueryparam value="#arguments.bean.getTitle()#" cfsqltype="CF_SQL_VARCHAR" />,
Genre = <cfqueryparam value="#arguments.bean.getGenre()#" cfsqltype="CF_SQL_VARCHAR" />,
MPAARating = <cfqueryparam value="#arguments.bean.getMPAARating()#" cfsqltype="CF_SQL_VARCHAR" />,
Starring = <cfqueryparam value="#arguments.bean.getStarring()#" cfsqltype="CF_SQL_VARCHAR" />,
Credits = <cfqueryparam value="#arguments.bean.getCredits()#" cfsqltype="CF_SQL_LONGVARCHAR" />,
Studio = <cfqueryparam value="#arguments.bean.getStudio()#" cfsqltype="CF_SQL_VARCHAR" />,
MovieReleaseDate = <cfqueryparam value="#arguments.bean.getMovieReleaseDate()#" cfsqltype="CF_SQL_VARCHAR" />,
DVDReleaseDate = <cfqueryparam value="#arguments.bean.getDVDReleaseDate()#" cfsqltype="CF_SQL_VARCHAR" />,
AspectRatio = <cfqueryparam value="#arguments.bean.getAspectRatio()#" cfsqltype="CF_SQL_VARCHAR" />,
SoundMix = <cfqueryparam value="#arguments.bean.getSoundMix()#" cfsqltype="CF_SQL_VARCHAR" />,
RunningTime = <cfqueryparam value="#arguments.bean.getRunningTime()#" cfsqltype="CF_SQL_VARCHAR" />,
Keywords = <cfqueryparam value="#arguments.bean.getKeywords()#" cfsqltype="CF_SQL_VARCHAR" />,
Date_Purchased = <cfqueryparam value="#arguments.bean.getDate_Purchased()#" cfsqltype="CF_SQL_VARCHAR" />,
MSRP = <cfqueryparam value="#arguments.bean.getMSRP()#" cfsqltype="CF_SQL_DOUBLE" null="#iif((arguments.bean.getMSRP() eq ""), de("yes"), de("no"))#" />,
PurchasePrice = <cfqueryparam value="#arguments.bean.getPurchasePrice()#" cfsqltype="CF_SQL_DOUBLE" null="#iif((arguments.bean.getPurchasePrice() eq ""), de("yes"), de("no"))#" />,
Vendor = <cfqueryparam value="#arguments.bean.getVendor()#" cfsqltype="CF_SQL_VARCHAR" />,
Trailer = <cfqueryparam value="#arguments.bean.getTrailer()#" cfsqltype="CF_SQL_VARCHAR" />,
Notes = <cfqueryparam value="#arguments.bean.getNotes()#" cfsqltype="CF_SQL_LONGVARCHAR" />,
Image = <cfqueryparam value="#arguments.bean.getImage()#" cfsqltype="CF_SQL_VARCHAR" />,
Date_Added = <cfqueryparam value="#arguments.bean.getDate_Added()#" cfsqltype="CF_SQL_VARCHAR" null="#iif((arguments.bean.getDate_Added() eq ""), de("yes"), de("no"))#" />
where movies.Index = <cfqueryparam value="#arguments.bean.getIndex()#" cfsqltype="CF_SQL_INTEGER">
</cfquery>
<cfcatch type="database">
<cfthrow message="#cfcatch.Message# #cfcatch.Detail#">
<cflog file="MovieUpdate" application="no" text="#status.sql#">
</cfcatch>
</cftry>
<cfreturn arguments.bean.getIndex()>
</cffunction>
<cffunction name="delete" output="false" access="public" returntype="void">
<cfargument name="bean" required="true" type="flextraining.movies.info.flexination.cfc.movie">
<cfset var qDelete="">
<cfquery name="qDelete" datasource="movies" result="status">
delete
from movies
where Index = <cfqueryparam cfsqltype="CF_SQL_INTEGER" value="#arguments.bean.getIndex()#" />
</cfquery>
</cffunction>
</cfcomponent>
movieGateway.cfc:
<cfcomponent output="false">
<cffunction name="getById" output="false" access="remote">
<cfargument name="id" required="true" />
<cfreturn createObject("component", "moviesDAO").read(arguments.id)>
</cffunction>
<cffunction name="save" output="false" access="remote" returntype="numeric">
<cfargument name="obj" required="true" />
<cfset Index = 0>
<cfscript>
if( obj.getIndex() eq 0 )
{
Index = createObject("component", "movieDAO").create(arguments.obj);
} else {
Index = createObject("component", "movieDAO").update(arguments.obj);
}
</cfscript>
<cfreturn Index>
</cffunction>
<cffunction name="deleteById" output="false" access="remote">
<cfargument name="id" required="true" />
<cfset var obj = getById(arguments.id)>
<cfset createObject("component", "moviesDAO").delete(obj)>
</cffunction>
<cffunction name="getAll" output="false" access="remote" returntype="flextraining.movies.info.flexination.cfc.movie[]">
<cfset var qRead="">
<cfset var obj="">
<cfset var ret=arrayNew(1)>
<cfquery name="qRead" datasource="movies">
select Index
from movies
</cfquery>
<cfloop query="qRead">
<cfscript>
obj = createObject("component", "moviesDAO").read(qRead.Index);
ArrayAppend(ret, obj);
</cfscript>
</cfloop>
<cfreturn ret>
</cffunction>
<cffunction name="getAllAsQuery" output="false" access="remote" returntype="query">
<cfargument name="fieldlist" default="*" hint="List of columns to be returned in the query.">
<cfset var qRead="">
<cfquery name="qRead" datasource="movies">
select #arguments.fieldList#
from movies
where bVisible = 1
order by Title
</cfquery>
<cfreturn qRead>
</cffunction>
<cffunction name="getAllByTitle" output="false" access="remote" returntype="query">
<cfargument name="searchtype" default="Title" hint="search type.">
<cfargument name="searchkeyword" default="" hint="Title search keyword.">
<cfset var qRead="">
<cfquery name="qRead" datasource="movies">
select *
from movies
where bVisible = 1
and #arguments.searchtype# LIKE '%#arguments.searchkeyword#%'
order by Title
</cfquery>
<cfreturn qRead>
</cffunction>
<cffunction name="writeAmzWSToXML" output="false" access="remote" returntype="string">
<cfargument name="newxmldata" type="xml" required="true" />
<cfset var myUUID = "">
<cfset var XMLFileName = "">
<cfset blnSuccess = false>
<cftry>
<cfscript>
myUUID = CreateUUID();
XMLFileName = myUUID & ".xml";
searchforstart = "<Items>";
searchforend = "</ItemSearchResponse>";
charsbefore = #Find(searchforstart, arguments.newxmldata , 1)#;
tmpdisplaythis = #RemoveChars(arguments.newxmldata, 1, (charsbefore-1))#;
charsafter = #Find(searchforend, tmpdisplaythis , 1)#;
tmpdisplaythis = #RemoveChars(tmpdisplaythis, charsafter, len(tmpdisplaythis) - len(charsafter))#;
</cfscript>
<cffile action="write" file="C:\inetpub\wwwroot\flextraining\movies\wsxml\#XMLFileName#" output="#tmpdisplaythis#">
<cfset blnSuccess = true>
<cfcatch type="any">
<cfthrow message="#cfcatch.message# #cfcatch.detail#">
</cfcatch>
</cftry>
<cfif blnSuccess>
<cfreturn XMLFileName />
<cfelse>
<cfreturn "" />
</cfif>
</cffunction>
<cffunction name="cleanupXML" output="false" access="remote" returntype="boolean">
<cfargument name="XMLFileName" type="string" required="true" />
<cfset blnSuccess = false>
<cftry>
<cffile action="delete" file="C:\inetpub\wwwroot\flextraining\movies\wsxml\#XMLFileName#">
<cfset blnSuccess = true>
<cfcatch type="any">
<cfthrow message="#cfcatch.message# #cfcatch.detail#">
</cfcatch>
</cftry>
<cfreturn blnSuccess />
</cffunction>
<cffunction name="proxyToYouTube" output="false" access="remote" returntype="string"> (2)
<cfargument name="title" type="string" required="true" />
<cfset var myUUID = "">
<cfset var XMLFileName = "">
<cfscript>
apiurl = "http://www.youtube.com/api2_rest?method=youtube.videos.list_by_category_and_tag&dev_id=your_YouTube_API_key&category
_id=24&tag=" & arguments.title & "&page=1&per_page=1";
</cfscript>
<cftry>
<cfhttp url="#apiurl#" method="get">
<cfcatch type="any">
<cfthrow message="#cfcatch.message# #cfcatch.detail#">
</cfcatch>
</cftry>
<cftry>
<cfscript>
myUUID = CreateUUID();
XMLFileName = myUUID & ".xml";
searchforstart = '<url>';
searchforend = "<thumbnail_url>";
charsbefore = #Find(searchforstart, cfhttp.fileContent, 1)#;
tmpdisplaythis = #RemoveChars(cfhttp.fileContent, 1, (charsbefore-1))#;
charsafter = #Find(searchforend, tmpdisplaythis , 1)#;
tmpdisplaythis = #RemoveChars(tmpdisplaythis, charsafter, len(tmpdisplaythis) - len(charsafter))#;
tmpdisplaythis = MID(tmpdisplaythis, 6, len(tmpdisplaythis) - 6);
tmpdisplaythis = LEFT(tmpdisplaythis, len(tmpdisplaythis) - 5);
tmpdisplaythis = trim(tmpdisplaythis);
</cfscript>
<cfset blnSuccess = true>
<cfcatch type="any">
<cfthrow message="#cfcatch.message# #cfcatch.detail#">
</cfcatch>
</cftry>
<cfif blnSuccess>
<cfreturn tmpdisplaythis />
<cfelse>
<cfreturn "" />
</cfif>
</cffunction>
</cfcomponent>
About the Author
Michael Givens is the CTO of U Saw It Enterprises, a Web technology consulting firm based in Marietta, GA. As an experienced Web technology specialist, he is willing to shift gears at a moments notice to the client's technology of choice. He is both an Adobe Community Expert and an Adobe Corporate Champion known to share his experience and evangelism of all things Adobe. Certified in both ColdFusion 5 and as an Advanced CFMX Developer, he has been using ColdFusion since the days of Allaire Spectra. Michael blogs at http://www.flexination.info/.
info@webmxml.com