New Blog Web Address

on Wednesday, November 18, 2009

This blog has moved to interactivelearning.mattstoner.net

Flash, XSLT, and show-hide controls

on Wednesday, July 8, 2009

A recent project I worked on involved creating a flash-based display of related information with a more usable interface. Previously the content was displayed in tables with javascript and css divs. There are both advantages and disadvantages to using the javascript method. Advances with ajax and css have greatly improved functionality since the time of the initial implementation of using showhides to present the learning content. When presented with the request, I came up with the following sketch in my instructional design idea book.

As I've previously blogged about re-usability, the first step I took was consideration of how this display object could created for that purpose. I settled on a pretty simple XML structure. This structure is not at all content dependent.


 Foo for you
 foo.jpg
 all you wanted to know about foo

One of disadvantages of displaying content in flash is how to allow users to print that information. The javascript/css showhide didn't have this limitation because a simple function could reveal all the CSS divs when printed. In order to overcome this limitation I turned to Extensible Stylesheet Language Transformations (XSLT) since my content was already written in XML. I know I could have approach this problem on the server side, but this client will be switching application servers and it didn't make sense.

XSLT is an XML-based language used for the transformation of XML documents into other XML or "human-readable" documents (more info at wikipedia entry). XSL files are included at the top of an XML file and allow all newer browsers to render the XML in HTML/XHTML format. All major browsers support XSLT, see list here. Knowledge of XPath is required to traverse the XML structure and output the content desired.

Useful tutorials

Since I already load the XML into the flash project at runtime, I had the path to the XML file available to place on a button on the flash stage.

 public function initApp():void
 {

 var thisXML:String = Application.application.parameters.thisXML;

  var loader:URLLoader = new URLLoader(new URLRequest(thisXML));
  loader.addEventListener(Event.COMPLETE, loadNewXML);

 }

 public function loadNewXML(event:Event):void
        {
     
         loadedXML = new XML(event.target.data);
      
        }

In this post I am not going to go into details about the actual actionscript code which generates this swf and instead focus on the XSL commands used to generate the HTML appear content from the button. You can see an example of the project below. To quickly replace the actual content used in this project, I grabbed some state flag images off google and text descriptions from wikipedia..

The actual XSL file is relatively simple and easy to read. I'm basically looping thru the XML nodes with an xsl:for-each select="data/node" tag. Then within the for-each block, I output the title, the image, and text associated with that node. For the text based output I used the xsl:value-of tag. For the image, I used the xsl:variable tag so I could embedded the variable within an img src tag.

N.B. the html and body tag had to be removed to post on blogger. Also the node "title" had to be renamed nodeTitle.







Samples XSLT of States



In conclusion

So XSLT was extremely useful to generate a printable/human readable rendering of the XML that was used in the flash generated display object. The SWF is re-usable and only needs a different XML file to be used on another web page with different content.

Links week of July 5th

on Sunday, July 5, 2009

Here are some links that caught my attention in the last week.

E-Learning

Web Dev/Design

My tool box

on Thursday, July 2, 2009

Computer failures are never fun and mine today brought to mind how much I am thankful for certain applications and cloud computing. So I thought I would share what's in my tool box.

Productivity


This program helps you organize and share your notes. The genius of the application is that it works on the web, macs, pcs, and mobile devices. You can store text, PDFs, snapshots, etc. I've used it in meetings to bring my notes on the agenda as well as snapping a picture of the whiteboard at the end of the discussion. I used to carry spiral notebooks for different projects I was working on, but now with evernote I can make a specific notebook for a project and the notes are always available to me. I still have a sketch book for instructional design ideas, but I either scan my drawings or snap a photo with the iphone. Another amazing feature of evernote is that it can do character recognition on photos/images. My handwriting isn't the best and it has done a great job recognizing words. The Evernote Web Clipper also is handy to store information for later review from webpages. Learn more at www.evernote.com


I've used quite a few personal information managers over the last 20 years. Until I started using gCal all my data was stored locally. I remember getting my first 3Com PDA in 1996 (that would rather become Palm) and being able to sync. But it was still far from ideal and if you were away from the computer and your PDA, you were out of luck. With google supporting CalDav, I can sync my calendars between multiple computers and add events from the web, my iphone or iCal. When I'm on the go, if something gets added to a calendar (say at work), it will get pushed to my iphone. It's like Microsoft Exchange for the little guy. www.google.com/calendar/


I've been a pro user for Remember the Milk (RTM) for nearly a year. While google has come out with its Tasks, I don't intend to switch anytime soon. RTM is a really powerful todo manager. You can manage multiple lists, share lists with contacts, receive text message reminders, and more. RTM has a really great iphone application and now with the recent upgrade push notifications. Third-party developers have created a bunch of add-ons to RTM to make viewing and adding todos very easy (link). I use the QuickSilver plugin to add todos without even having to go to the RTM website. I also really like the being able to forward emails I receive to RTM and even assign the task to a specific list and given due date. www. rememberthemilk.com

Utilities

Carbon Copy Cloner: This MacOS program makes a bootable backup of my hard drive. I do use Apple Time Machine as well, but the redundancy gives me piece of mind. Both are backed up to an external Drobo drive, that currently is 2 gigs. The Drobo is RAID-like so there is redundancy there as well.

TextWrangler: I used BBEdit for many years and TextWrangler is everything I need in a text editor. It is great for coding and cleaning up text files. It is always on the top of my list to install on a new computer.

Growl: Growl is a notification manager for Mac. Several of the applications I use have Growl notifications support. Growl pops up alert messages when I get a new email, iTunes starts playing a new track, a download is completed, etc. It's very handy. www. growl.info

Development

Navicat MySQL: MySQL is my primary database of choice for projects and Navicat offers a nice GUI to view/edit tables. The PC version has more options than the Mac, but it is a very strong database development tool. navicat.com


All my coding projects are backed up to a subversion server. In the past, I've also used hosts such as spring loops and assembla. If you are developing any type of elearning, you really should be incorporating version control into your development process. I have slide deck from a talk I gave on the topic available here

Flex Builder built on Eclipse: While I could have installed the flex plug-in into standard Eclipse, I instead modified my Flex Builder with several plugins/frameworks. My installation includes plug-ins for:

Adobe CS4: I recently updated from the dark ages (ie before Adobe called their web/image programs CS 1,2,3). I used dreamweaver primarily, but I'm in code view most of the time. When I have a need for graphics I will use Fireworks and after eons of not having photoshop I'm starting to use it again. CS4 has subversion built right into it, which is quite convenient adobe.com.

Audacity: This is a great tool for editing and recording audio. It's open source/free. I've used it primarily when creating podcasts and it works great. download link.

Cyberduck: This is mac file transfer client that supports multiple protocols. I use SFTP quite a bit and its bookmarking feature makes it so easy to get where I need to go. download link.

So what is in your toolbox? Leave a comment and share.

Developing Interactive Case Studies, Part 1

on Wednesday, July 1, 2009

Advancing acquisition and demonstration of medicine competencies

This post is the first in a series on interactive case learning. I will review the rationale for development; my experiences with developing the model into reality; working with faculty/SME to develop cases; and lessons learned. My posts will be in the context of medical training, but the knowledge translates to other subject areas.

Dilemma :        How do you educate med students and MDs about core competencies in medicine at a distance and then assess them without clinical practicum?

Thesis :           These posts will demonstrate that it is indeed possible to educate adult learners in the acquisitions of new knowledge, skills and competencies similar to in-person training but with an online curriculum. The ICS model is argued to be a vehicle for additional acquisition and synthesis new knowledge and skills, as well as an analytically tool for measuring core competencies.

Definitions:

Interactive Case Studies (ICS)

ICS are iterative, dynamic clinical cases built on the principles of problem-based learning (PBL).

Core Competencies

  • Being able to access high-quality, high-value information
  • Being able to think critically
  • Being able to advise patients intelligently
  • Being able to communicate effectively with patients and peers
  • Being able to listen, understand, guide, and comfort patients
  • Being able to facilitate change, when needed
  • Being respectful to humans' needs and experiences

Learning Object

A structured, standalone resource that encapsulates high quality information in a manner that facilitates learning and pedagogy.

Rationale

The ICS Model was developed specifically to (1) meet a need for a more interactive and engaging learning object, and (2) aid in the presentation of the curriculum.

ICS are iterative, dynamic clinical cases built on the principles of problem-based learning (PBL). The design of the ICS is adapted from a design established in the field of organizational management (Moberg & Caldwell, 1989). PBL facilitates not only the acquisition of new knowledge and skills through active engagement of the learner, but also provides for evaluation of the demonstration of knowledge, skills, and competencies through real-world interactive situations. ICS’s present video-snippets of typical physician-patient interactions and allow the learner to practice and demonstrate clinical counseling skills and integrate knowledge from the full curriculum. The ICS model is not solely a model of multiple choice testing, though multiple choice options are a primary mechanism for navigation in the decision tree. Instead, the learner is prompted at various points for qualitative responses and encouraged to reflect on their clinical reasoning which has lead them to a particular point in the case.

In a case, the learner is presented with multiple options of course of action in communicating with the patient. The cases can be produced with specific learning/assessment goals (e.g. patient centered communication, advising on referral, intake, etc). Through the programming, assessment feedback is provided to the learner. Some particular cases can be presented solely for the purpose of synthesis and practice of clinical knowledge and skills, while others can be presented in terms of evaluation.

The initial presentation

I first presented this learning model in 2002, although it was not developed for some time due to resources and other issues. Below is my slide deck from that initial presentation.

Next Post: My next post will focus on taking this initial instructional design and getting buy-in to develop the model.

Links week of June 28

on Sunday, June 28, 2009

Just some links that caught my attention this week.

General Web Design ELearning

Building a flash video player

on Saturday, June 27, 2009

Before I get into the technical details, I wanted to present some reasons why you may want to make your own customized/skinned flash video player instead of using YouTube, iTunes podcast or some other tool. In no particular order, you may need to build a custom player, if

  • custom branding of the user interface
  • protecting video content from unauthorized distribution and copying
  • copyright issues
  • customization with other flash feature in a project

The flash videoPlayer class is not without its quirks, especially in Flex3/Actionscript 3. There are some changes in the beta for Flex 4 (now renamed Flash Builder) to make creating a custom video player easier. I'm going to go over creating a single and multi-clip video player in actionscript using three different ways to get the data to the video player.

Method 1:

With the static method you embedded the video clip/s in the player and compile the project into a SWF to be placed on your website. This protects the video files from being accessible to others, but the downside is you must compile a new SWF every time you want to display video on your website.

Method 2:

With this dynamic method, the video player is passed some information on which clips to display and then queries a database to get information on the track/s titles, duration, and file path. This method requires a web service to be executed on a local or remote server which will return the query. Depending on your web environment, this option may not be available to you.

Method 3:

With this dynamic method, the video player is passed a file path to an XML file with information on the track/s title, duration, and file path. This information could be formatted in the exact same manner as a query would be returned by the web service. In fact, most web services return data in the XML format. Since the XML document is authored and dynamically acquired by the video player, you can reuse the video player by just pointing it to load a different XML file at run time.

I've used both method 2 and 3 for projects. If you catalog and store meta-data about your video assets in a database and have a web application server (Cold Fusion, PHP, etc), I think its the best option. If you do not, I would recommend method 3 and statically writing an XML file. I strongly discourage method 1.

Building the code

I build my projects in Flex Builder 3 and depending on the task choose to use either Actionscript 3 or MXML or a combination of both. In this section, I will discuss implementing both method 2 and 3. In each case, the first step is the same. Upon the application being created is for a function to be executed to load the dynamic data. In my projects I call this function with the CreationComplete attribute on the <mx:Application tag> and for consistency sake, I normally call this function initApp.

Example for method 3 (dynamic XML)

 public function initApp():void
 {

 var thisXML:String = Application.application.parameters.thisXML;

  var loader:URLLoader = new URLLoader(new URLRequest(thisXML));
  loader.addEventListener(Event.COMPLETE, loadNewXML);

 }

 public function loadNewXML(event:Event):void
        {
     
         loadedXML = new XML(event.target.data);
      
        }

In this implementation, the XML file is passed to the Flash SWF by FlashVars. For more information on using Flash Vars, read this adobe technical note.

Example for method 2 (Media Database)

In MXML, you can setup the web service with the RemoteObject tag by defining the which web service to call and functions to handle the result and fault event. Then in my InitApp function, I actually make the call to execute the Remote Object.



public function initApp():void
 {

        //list of video clip IDs passed into the SWF via Flash Vars on the html code block to load the SWF
  theseClip = Application.application.parameters.videoIDs;
   
       //executes the web service
 getClip.VideoClip(theseClip);
      
        }

In this implementation, the videoIDs are the IDs from the media database and they are passed to the Flash SWF by FlashVars. Depending on your database schema, you can return whatever columns you want, but at a minimum you would want track title, duration, and file path. For both method 2 and 3, I have formed the XML the same way.




 
  
   Clinical Pearl: Screening for Prostate Cancer
   http://localhost/Screening_Randy.m4v
   2:47
  
          
   < clip_title >Clinical Pearl: Screening for Breast Cancer
   http://localhost/Screening_Victoria.m4v
   3:25
  
 


Instead of creating a multi clip and single clip video player, I let the programming determine how many clips exist in the XML.

 private function processClips():void {
 
       thisResult= getClip.VideoClip.lastResult;
    
 if(thisResult.length > 1) {
   multiClip();
 } else {
     
  singleClip();
 }
  
    
}

Depending on how many clips are return, I resize the canvas and display the clip selector panel if there is more than one clip. Below are examples of each view and then I will explain the code.


Multi-Clip View


Single-Clip View

Rendering the Video Clip component

The processClips function execute either the singleClip or multiClip function depending on the number of clips contained in the XML. In the case of the single Clip function, it changes the visibility on the clipSelectionPanel and instantiates a custom video component. The same custom component is rendered with the multiclip view, but changes depending on what is selected in the clipSelectionPanel.


 private function singleClip ():void {
   
    //hides the clipSelectorPanel
    clipSelectorPanel.visible = false;

    file_path = thisResult[0].file_path.toString();
    
    //removes placeholder image that displays before video is loaded
    vidScreen.removeAllChildren();
       
       //custom component
        var thisVid:customVideoComponent = new customVideoComponent;
            thisVid.data =   file_path;
         vidScreen.addChild(thisVid); 

 }

 private function multiClip ():void {
  clipSelectorPanel.visible = true;
      
               //expands the canvas size variables
  canvas_width = 535;
  canvas_height = 400;
 }

In the case of a single clip, the function immediately loads the video and auto-plays the clip. For the multi-clip display, the clipSelectionPanel has a click handler. The clipSelection panel is an MXML list control with a custom itemRender.

  
    
  

When a user clicks on any item in the list, the following function is executed:


   private function clickHandler():void {
        
       // stops any video if it is currently playing
       this.thisVid.stop();
      
       //clears any video player on the canvas and/or the placeholder graphic
       vidScreen.removeAllChildren();

    //file path of the selected clip
       var thisvidFile:String =  videoSelector.selectedItem.file_path.toString();

    //custom video component     
          var thisVid:customVideoComponent = new customVideoComponent;
        thisVid.data =   thisvidFile;
        vidScreen.addChild(thisVid); 

       } 

In the code for the customVideoComponent I have an important event listener for when it is removed from the stage. This is because of a particular issue I discovered with the videoPlayer class when you remove them from the stage:

  • while the video display disappears, the audio will continue to play
  • if a clip is not fully downloaded it will continue to download even if the user is viewing another clip

To remedy this issue, I created the videoInterupt function.

  private function vidInterupt(event:Event):void{
   
   
    if(event.currentTarget.thisVideoDisplay.state != "disconnected") {
     event.currentTarget.thisVideoDisplay.stop();
    }
   
    if(event.currentTarget.thisVideoDisplay.state != "disconnected") {
     event.currentTarget.thisVideoDisplay.close();
    }

         SoundMixer.stopAll();
    

   } 

UI Considerations

From the sample images above you'll notice that the video player displays a default image until a clip is selected/loaded rather than leave a void for the video display on the canvas. The image also serves to direct users to use the clip selection panel to choose a clip in the multi-clip state. The video controls are also displayed in the image but are dimmed out.

In actionscript/mxml there is a lot of flexibility in designing the user interface. Originally I used MXML buttons for the play/pause/stop functions, but later switched to the graphical icons you see in the sample images. The interface also has a load controller display, which is especially useful for users who may have a slow connection to know the video is loading. Most video players I see on the net follow youTube like conventions for the UI. Below is the code for the custom video component.





 
    import mx.events.FlexEvent;
    import flash.media.Video;
    import flash.media.SoundMixer;
    import flash.events.ProgressEvent;
    import mx.events.VideoEvent;
    import mx.controls.Image;
   
   [Bindable]
   public var thisVid:String;
   
      
   private function initVideo():void{
    
    //get source from event target
    
    thisVid = this.data.toString();
    
    thisVideoDisplay.addEventListener(Event.REMOVED_FROM_STAGE,vidInterupt);
     
    
   } 
   
   private function vidInterupt(event:Event):void {
    
                       if(event.currentTarget.thisVideoDisplay.state != "disconnected") {
                       event.currentTarget.thisVideoDisplay.stop();
                       }
   
                      if(event.currentTarget.thisVideoDisplay.state != "disconnected") {
                       event.currentTarget.thisVideoDisplay.close();
                      }

                      SoundMixer.stopAll();
    
   }
   
 
   private function showInfo(event:VideoEvent):void {
   trace('stateChange: ' + event.state + ' ' + event); var foo:Timer = new Timer(2000, 100); foo.addEventListener(TimerEvent.TIMER, timerComplete); foo.start(); 
   trace('Clip: ' +  thisVideoDisplay); } 
 
   private function timerComplete(event:TimerEvent):void {
   trace('timerComplete: ' + thisVideoDisplay.state + ' ' + event); } 
   
   private function Vidplay(event:MouseEvent):void{

        
      thisVideoDisplay.play();
       }
       
      private function Vidpause(event:MouseEvent):void{
        
      thisVideoDisplay.pause();
       }
       
      private function Vidstop(event:MouseEvent):void{
        
        
      thisVideoDisplay.stop();
       }
       
   private function formatPositionToolTip(value:int):String{
  
    
    var result:String = (value % 60).toString();
          if (result.length == 1){
              result = Math.floor(value / 60).toString() + ":0" + result;
          } else {
              result = Math.floor(value / 60).toString() + ":" + result;
          }
          return result;
   } 
   
 



  
   
  
  
   
   

  
    
  

 
 
   
   
    
  


In conclusion

In this tutorial, I have reviewed why you would create a custom video player in actionscript/mxml and how you would do it. I hope you found it useful and benefit from what I've learned when using the videoPlayer class. Let me know if you have any questions or have a suggestion for different approaches.

Technorati Profile