Skip to main content

Ajax and XML: Ajax for media

Use Ajax techniques to show movies and slide shows

Jack D Herrington (jherr@pobox.com), Senior Software Engineer, Leverage Software Inc.
Jack D. Herrington is a senior software engineer with more than 20 years of experience. He's the author of three books: Code Generation in Action, Podcasting Hacks, and PHP Hacks. He has also written more than 30 articles. You can reach Jack at jherr@pobox.com.

Summary:  With the advent of widely available broadband, media, movies, images, and sound drive the Web 2.0 revolution. Learn to combine media with technologies such as PHP and Asynchronous JavaScript™ + XML (Ajax) to create a compelling experience for your customers.

View more content in this series

Date:  23 Oct 2007
Level:  Intermediate
Activity:  5837 views

Ask people which site is most representative of the new wave of applications on the Web, and most will answer YouTube. It's a site that has not only embraced new technology in a compelling way but changed how we view media and our relationship to it. Major stories can break on YouTube well before they appear on traditional media outlets, and when they don't, YouTube acts like one big TiVo for the world.

Media sharing is changing the world, and from a technology standpoint, it's not hard to do. This article shows how to put an Ajax front end on a simple Web video-hosting application.

Simple video selection

I start with a Web site that holds a movie list and uses that list to select from one of several movies—a site on which you can change movies without actually moving from one page to another. Listing 1 shows the code for the page.


Listing 1. index.html
                
<html>
<head>
<script src="prototype.js"></script>
</head>
<body>

<div id="movieHost">
</div>

<div id="movieList">
</div>

<script>
function setMovie( url )
{
  $('movieHost').innerHTML = '';
  var elEmbed = document.createElement( 'embed' );
  elEmbed.src = url;
  $('movieHost').appendChild( elEmbed );
}

new Ajax.Request( 'movies.xml', { 
  method: 'get',
  onSuccess: function( transport ) {
    var movieTags = transport.responseXML.getElementsByTagName( 'movie' );

    $('movieList').innerHTML = '';

    var bFirst = true;
    for( var b = 0; b < movieTags.length; b++ ) {
      var url = movieTags[b].getAttribute('url');
      var title = movieTags[b].getAttribute('title');
      if ( bFirst )
      {
        setMovie( url );
        bFirst = false;
      }
      var html = '<a href="javascript:void setMovie(\''+url+'\');">';
      html += title+'</a><br/>';
      $('movieList').innerHTML += html;
    }
  }
} );
</script>
</body>
</html>

This page uses the excellent Prototype.js JavaScript library to make an Ajax request of the movies.xml data source. When the data is returned, the code finds all the movie tags using the getElementsByTagName() method. Then, for each movie tag, the code retrieves both the URL and the title. If the retrieved tag is for the first movie in the list, the script starts to play that movie right away. Otherwise, it adds an anchor tag, which acts as a movie selector to the movieList <div> tag.

This movie selector anchor calls the setMovie() function to start a particular movie. To start a movie, I simply set the contents of the movieHost <div> tag to empty, which removes any previous movie. Then, I set the contents to an <embed> tag whose URL is specified by the movie list.

The <embed> tag is the simplest way to get a movie onto a page, but it can have issues between browsers. Another option is to use both an <object> and an <embed> tag. (Yet another method is to use Macromedia Flash Player: I get into that a little later in the article.)

In this simple example, the movies.xml file is just a flat file with some references to short home movies of mine. Listing 2 shows the file.


Listing 2. movies.xml
                
<movies>
  <movie url="spider.mov" title="Spider" />
  <movie url="swing.mov" title="Swing Set" />
  <movie url="water.mov" title="Water Splash" />
</movies>

When I navigate to the page, I see the something like Figure 1.


Figure 1. The simple movie list page
The simple movie list page

The movie is at the top of the page, being played by the <embed> tag, and a list of available movies appears below it. If I click any of those links, the movie changes to the one I clicked.

Obviously, this system isn't going to scale particularly well to large video repositories, so I need a way to do some searching on the movie list.


Searchable movie lists

To add search functionality, I need to add a search box, which you can see in Listing 3. I've also added a search input field named q.


Listing 3. Add search functionality
                
<html>
<head>
<script src="prototype.js"></script>
</head>
<body>

<table><tr><td valign="top">
  <input type="text" id="q" onkeyup="search()">
  <div id="movieList">
  </div>
</td><td valign="top">
  <div id="movieHost">
  </div>
</td>
</tr></table>

<script>
function setMovie( url )
{
  $('movieHost').innerHTML = '';
  var elEmbed = document.createElement( 'embed' );
  elEmbed.src = url;
  $('movieHost').appendChild( elEmbed );
}

function search()
{
  new Ajax.Request( 'search.php?q='+escape($('q').value), { 
    method: 'get',
    onSuccess: function( transport ) {
      var movieTags = transport.responseXML.getElementsByTagName( 'movie' );

      $('movieList').innerHTML = '';

      var bFirst = true;
      for( var b = 0; b < movieTags.length; b++ ) {
        var url = movieTags[b].getAttribute('url');
        var title = movieTags[b].getAttribute('title');
        if ( bFirst )
        {
          setMovie( url );
          bFirst = false;
        }
        var html = '<a href="javascript:void setMovie(\''+url+'\');">';
        html += title+'</a><br/>';
        $('movieList').innerHTML += html;
      }
    }
  } );
}
</script>
</body>
</html>

On the key-up event, I specified that the search() method should be called. That search() method is like the Ajax.Request call, with the exception that it now passes along the query string to a page called search.php. The search.php script returns the same XML format as the original, so the code that does the XML parsing doesn't need to change.

I admit that a search() function on key-up is a bit too responsive for my taste. Ideally, the system would wait for a second or so before running the search so that I could finish a complete search text without having the list flicker in the meantime. You can easily implement such behavior by using the window.setTimeout() method.

Listing 4 shows the revised search.php script.


Listing 4. search.php
                
<?php
header( 'content-type: text/xml' );

$movies = array();
$movies['spider.mov'] = 'Spider';
$movies['swing.mov'] = 'Swing Set';
$movies['water.mov'] = 'Water Splash';
?>
<movies>
<?php
foreach( $movies as $k => $v ) {
if ( strlen( $_GET['q'] ) > 0 &&
  preg_match( '/'.$_GET['q'].'/i', $v ) ) {
?>
<movie url="<?php echo($k) ?>" title="<?php echo($v) ?>" />
<?php
} }
?>
</movies>

At the top of the script, I create an array that holds all the movies. For simplicity's sake, I hard-coded the movies. But in reality, these elements are likely to come from a database of movie listings.

The code then iterates through the list and applies a regular expression of the search query to each movie title. When they match, a <movie> tag is output with the URL and the name.

When I start the page and type s, I get the page shown in Figure 2.


Figure 2. The movie query page with a simple query
The movie query page with a simple query

If I press Delete and type water, I get the page shown in Figure 3.


Figure 3. The movie query page looking for "water" movies
The movie query page looking for       water movies

While the point of this article is mainly to show how you could create a front end using Dynamic HTML (DHTML) and Ajax, there's a lot more to creating a video sharing site.


Video sharing basics

Jumping from the practical to the more theoretical for a moment, let me talk about how to handle some of the trickier video-sharing issues. There are three main issues to cover:

  • How to store and stream the video
  • How to handle different video formats
  • How to get thumbnail images and video information from the uploaded files

Video storage is a real problem—particularly for small applications. Video files are large, so expensive hardware is required to store them. And there are bandwidth charges for feeding them down the wire to your customers. You could buy your own equipment and put it in a hosting facility. Or you could use a service such as S3 from Amazon, which allows you to upload any material (database backups, images, movies, and so on) and feed them out of the Amazon datacenters for a reasonable cost. It's probably worth looking into one of these services before bankrolling a datacenter roll-out.

The next issue—video formats—presents an interesting challenge. Many video formats exist, and not all players handle all formats. In fact, most players handle just their video format of choice. To make it easier on the customer, it's probably best to standardize on a particular format, and then convert all the incoming video into that format. One particularly handy tool for doing that is a command-line application called FFmpeg. Not only can it convert from one video format to another, but it can also take frame snapshots and thus provide a thumbnail of the video before customers view it.

The choice of which video format to standardize on can be complex. Flash video is the clear winner at the moment, but Windows Media®, particularly with the release of Microsoft Silverlight (formerly WPF/Everywhere), is gaining ground. FFmpeg can export almost any movie to the Flash video format, which is compelling. And there are several free and open source Flash movie players that you can easily embed in your site. You can combine those players with the code above to make a complete end-to-end video-sharing solution with an Ajax front end.

But video isn't the only thing going on with the Web: Image sharing is also important.


Slide shows

Listing 5 shows a simple DHTML-based slide show that sources its data from an XML file.


Listing 5. index.html
                
<html>
<head>
<script src="prototype.js"></script>
</head>
<body bgcolor="black">
<div style="text-align:center;">
<img id="imgItem" src="" style="display:none;"><br>
<div id="imgTitle" style="color:white;font-family:arial;font-size:24pt;">
</div>
</div>
<script>
var g_images = [];
var g_slideIndex = 0;

function showSlide()
{
  $('imgTitle').hide();
  $('imgItem').hide();

  var height = 600;
  var width = ( height / g_images[ g_slideIndex ].height ) * 
    g_images[ g_slideIndex ].width;

  $('imgItem').src = g_images[ g_slideIndex ].src;
  $('imgItem').width = width;
  $('imgItem').height = height;

  $('imgTitle').innerHTML = g_images[ g_slideIndex ].title;

  $('imgTitle').show();
  $('imgItem').show();

  g_slideIndex++;
  if ( g_slideIndex >= g_images.length )
    g_slideIndex = 0;
}

new Ajax.Request( 'images.xml', { 
  method: 'get',
  onSuccess: function( transport ) {
    var imageTags = transport.responseXML.getElementsByTagName( 'image' );

    for( var b = 0; b < imageTags.length; b++ ) {
      g_images.push( {
        src: imageTags[b].getAttribute('src'),
        title: imageTags[b].getAttribute('title'),
        width: imageTags[b].getAttribute('width'),
        height: imageTags[b].getAttribute('height')
      } );
    }

    showSlide();

    window.setInterval( showSlide, 5000 );
  }
} );
</script>
</body>
</html>

The code is based on the Prototype.js JavaScript library. It uses the Ajax.Request object to get the list of images to show. The returned XML code is then parsed to get the URL as well as the width, height, and title of each image. The showSlide() function is then called to get the slide show ball rolling. A timer is set to go off every five seconds to move the show onto the next slide.

The slide show is implemented by having one <image> tag for the current image and one <div> tag for the title. The slide show simply hides the current image and title, sets the source of the image and the text of the title to the new slide contents, and then shows them. If you want something that fades in and out, I recommend using the Effects classes in the Scriptaculous library, which is built on Prototype.js.

Listing 6 shows the data images file.


Listing 6. images.xml
                
<images>
 <image src="images/megan1_875_700.jpg" title="Megan" width="875" height="700" />
 <image src="images/oso1_875_700.jpg" title="Oso 1" width="875" height="700" />
 <image src="images/oso2_873_700.jpg" title="Oso 2" width="873" height="700" />
</images>

This one is hard-coded, but you can just as easily generate the XML code using a PHP script. The slide show is shown in progress in Figure 4.


Figure 4. The simple slide show
The simple slide show

Note: I previously published a much more elaborate version of the slide show (see Resources for a link). This one differs in that it uses the Prototype.js library and is much simpler in its transitions between slides.


Conclusion

Sites like Flikr and YouTube show just the tip of the full potential for media on the Web. This article provides some easy implementations of video and image browsing that you can use in your own project. If it works for you, please let me know by joining the developerWorks Ajax forum (see Resources) to talk about your success.



Download

DescriptionNameSizeDownload method
Sample codex-ajaxxml7-media.zip1090KB HTTP

Information about download methods


Resources

Learn

Discuss

About the author

Jack D. Herrington is a senior software engineer with more than 20 years of experience. He's the author of three books: Code Generation in Action, Podcasting Hacks, and PHP Hacks. He has also written more than 30 articles. You can reach Jack at jherr@pobox.com.

Comments (Undergoing maintenance)



Trademarks  |  My developerWorks terms and conditions

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=XML, Web development, Open source
ArticleID=259752
ArticleTitle=Ajax and XML: Ajax for media
publish-date=10232007
author1-email=jherr@pobox.com
author1-email-cc=dwxed@us.ibm.com

My developerWorks community

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere).

My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Rate a product. Write a review.

Special offers