Ajax

Drag and Drop Ajax Applications

Tagged:  

Now that Ajax applications have become a must for most enterprises many companies are looking for ways to make Ajax application development easier. There are a few tools that promise to make it much easier to create Ajax applications.

WaveMaker has released WaveMaker Visual Ajax Studio. The tool boasts an easy to use drag and drop development environment. The studio claims to improve development time by 67% and to reduce code by as much as 98%.
Key features include:

  • Drag & Drop Assembly
  • LiveLayout™
  • Push to Deploy™: One-touch application deployment
  • Visual Data Binding
  • SOAP, REST and RSS web services
  • Leverage existing CSS, HTML and Java
  • Deploys a standard Java .war file
  • Free

The application offers an open source license as well as enterprise licenses.

You can view a screen cast of the product here.

TIBCO also has an easy to use drag an drop Ajax development environment called General Interface. The development tool is used by many large organizations for Ajax application development such as H&R Block. As with WaveMaker General Interface offers both open source and enterprise licensing.

You can take a look at General Interface here. You can view a demo of an application developed with General Interface here.

These tools can be great for some use cases however they tend to be much too heavy weight for public facing sites. Another thing to look out for is that some JavaScript development libraries may not work well with these tools. Both tools run in the browser which is something that I personally think is a bad idea as it can slow down the application due to the browsers own limitations. For me personally I would prefer to use a library like GWT for Ajax application development, but I'm not big into the whole drag and drop programming.

Bad Object Detection

Tagged:  

John Resig has written another great post, this time about bad object detection. The article talks about classic bad object detection such as checking if the document.all object exists to test for Internet Explorer (I admit it I've been guilty of this one).

Below is an excerpt from the post.

Fringe Cases From Global Variables

While they don't happen often for those that they do happen to they can be a living hell. Specifically when object detection takes place within the global object (e.g. window.opera) then all bets are off as to its cross-browser applicability. Let's take a look at an example:

<html>
<head>
<script>

window.onload = function(){
  if ( window.opera ) {
    alert("You're using Opera, pick me!");
  }
};
</script>

</head>
<body> 
  <h1>Which browser?</h1>
  <a href="http://mozilla.com/" id="firefox"> Firefox</a><br/>

  <a href="http://apple.com/" id="safari"> Safari</a><br/>
  <a href="http://opera.com/" id="opera"> Opera</a><br/>

  <a href="http://microsoft.com/" id="ie"> Internet Explorer</a>
</body>
</html>

You would expect the alert to pop up when the user visits the page in Opera - and it does - however the alert also comes up in Internet Explorer. This is because all elements with an ID are automatically introduced as global variables (in the above there are four globals: firefox, safari, opera, and ie that all reference their associated elements). This is a fantastically difficult bug to spot and work around - thus you should be very cautious when doing any form of object detection on the global object.

Of course, it almost goes without saying, that there could exist an 'opera' variable elsewhere in the site that could interfere with this detection. Although that would, arguably, be easier to detect as it would make every browser trigger a false positive.

There's two morals here:

  1. Only use object detection to detect exactly what you need to use.
  2. Be wary of detecting properties on the global object - it's capable of lying to you.

You can read the full post here.

This is a great post and something that I hadn't thought much about. I really like John's blog and I find his posts very informative. I have often found information on his blog that I haven't seen anywhere else on the web (I know that I've said it before, but if you don't have John's blog on your feed reader, I would recommend adding it).

OpenSocial Videos

Tagged:  

With all the buzz about OpenSocial (especially with MySpace jumping on board) you probably are interested in using the API. Well if you are anything like me you find it easier to learn by watching a video than reading a boring post. Well the OpenSocial API blog has posted a few videos to help you in your development.

Using JSON in Your Widgets

Tagged:  

Yesterday I posted an article on the del.icio.us Spy Widget. After writing the post I thought that other developers may be interested in how the communication was accomplished between the widget and the server. Since the browser stops cross-domain calls using the XMLHTTPRequest object (at least until Firefox 3 takes over the web) we have to turn to using JSON with a dynamic script tag.

So now that I've given a brief overview of how it will work let's get right down to the code. The below code would be used to dynamically create the script tag and load the JSON feed. Since the script tag does not have a cross-domain security restraint we can use it to load the feed from any domain.

var TimeStamp = new Date().getTime();
		var JSONCode=document.createElement("script");
       	JSONCode.setAttribute('type', 'text/javascript');
       	JSONCode.setAttribute("src", "http://someurl.com/somefeed.php?timestamp=" + TimeStamp);
        document.getElementById('codeholder').appendChild(JSONCode);

The important things to note in the above code is the timestamp variable passed in the URL and the codeholder DOM element. The timestamp variable is just a simple time stamp that is passed in the URL to prevent client side caching issues. In the URL is also where you would pass any additional variables to get the JSON feed. The codeholder DOM element (in the example code codeholder would be the id of the DOM element, but this could be a different id) is a DOM element that can hold a script tag such as a div tag.

Below we have an example of the JSON feed that would be received.

callbackfunction([{"title":"House of Marathon: A Very Brady Conservative","url":"http://houseofmarathon.blogspot.com/2008/01/very-brady-conservative-unlikeliest.html","tags":"BobbyJindal Louisiana RonaldReagan conservative ethics government health politics","user":"nathanm_mn"},{"title":"æ³¨æ„äº‹é …...請看這邊... - NoName Information Team XPE - Yahoo!å¥‡æ‘©éƒ¨è½æ ¼","url":"http://tw.myblog.yahoo.com/noname-team/article?mid=432&l=f&fid=9","tags":"XP","user":"square12"},{"title":"Retail-Menswear-Freemans Sporting Club - New York Times","url":"http://www.nytimes.com/2007/03/01/fashion/01CRITIC.html?_r=2&oref=slogin&oref=slogin","tags":"style","user":"MJDAOG"}]);

The important thing is that the feed has a call back function. This callback function could be named anything and is the JavaScript function that would be called to handle the JSON object.

The below code is an example of what a call back function might look like.

function callbackfunction(obj){
		alert(obj);
	}

In the above code the function would just display the object in an alert. This is where you would put the logic to go through the JSON object and then use it however you would like to in your application.

If you are using this in a widget you would have the user putting the widget on their site or blog copy and past some code and put it into the site or blog code. While you may have multiple lines of HTML for the user to copy you would need to have a script tag calling either a .JS file or a server side script that would produce dynamic JavaScript. The code that the script tag references would have the call back function and the portion of code that dynamically creates the script tag.

The above method allows you to create some more interactive widgets to make the web more interactive. While the above is all "hand rolled" code you can use many libraries to accomplish the dynamic creation of the script tag such as jQuery.

If you have ever created a widget that used this type of connection then I would love to hear about it. You can leave it in the comments or you can write a blog post with your free Ajaxonomy account.

JavaScript Debugging in Internet Explorer

For those of us who have lamented the sad state of debugging in Microsoft's Internet Explorer (and no, the Microsoft Script Debugger doesn't count), some relief is here. Complementing the IE Developer Toolbar, the Microsoft Visual Studio 2008 Web Developer Express Edition (and previously the 2005 Express Edition) gives you full JavaScript debugging ability from within the VS development environment without needing the paid version. The only drawback vis-a-vis the professional edition is that the page must be launched from with the IDE (rather than from IE itself). A small price to pay for desperately needed functionality.

Here's some quick steps to get you started:

1. Download the Web Developer Express Edition for free (though registration is required to activate it).
2. Create an empty web site, File-->Web Site...-->Empty Web Site.
3. Deposit the files you wish to debug in the web site folder, and open the file you wish to debug. Place desired break points. (Or you can skip this step if you just intend to just navigate to a URL later.)
4. Click the "Start Debugging" button. If you skipped step #3 and wish to navigate to a URL, then you may want to put at least one debugger statement in your JavaScript code so that the debugger will stop at this statement. Breakpoints can then be set within the IDE elsewhere.
5. Controls are in the Debug menu. F10 will step over, F11 will step into, etc.
6. All the expected debugging views are there: Call Stack, Locals (variables), Watch, and so forth.

Not quite as convenient as having Firebug directly in your browser, but a first-class JavaScript debugger (as JavaScript debuggers go...) nonetheless.

Upload Files Asynchronously

Tagged:  

You are familiar with Ajax and I'm sure that you've used it (or seen it used) in many applications. Of course Ajax is used to transfer data through XML or JSON (or plain text) so the data is never binary data. However, what if you are making an application that needs to be able to upload a binary file asynchronously? Well I've run across an interesting article that explains how to accomplish this.

The article has updated code from the initially released code. Below is the initial code.

Source code for index.html   (Download source code)

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US" lang="en-US">

<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title>Iframe Ajax</title>
    <script type="text/javascript" src="webtoolkit.aim.js"></script>

    <script type="text/javascript">
        function startCallback() {
            // make something useful before submit (onStart)
            return true;
        }

        function completeCallback(response) {
            // make something useful after (onComplete)
            document.getElementById('nr').innerHTML = parseInt(document.getElementById('nr').innerHTML) + 1;
            document.getElementById('r').innerHTML = response;

        }
    </script>
</head>

<body>

    <form action="index.php" method="post" onsubmit="return AIM.submit(this, {'onStart' : startCallback, 'onComplete' : completeCallback})">

        <div><label>Name:</label> <input type="text" name="form[name]" /></div>
        <div><label>File:</label> <input type="file" name="form[file]" /></div>

        <div><input type="submit" value="SUBMIT" /></div>
    </form>

    <hr/>

    <div># of submited forms: <span id="nr">0</span></div>

    <div>last submit response (generated by form action - index.php file): <pre id="r"></pre></div>

</body>
</html>

Source code for webtoolkit.aim.js   (Download source code)

/**
*
*  AJAX IFRAME METHOD (AIM)
*  http://www.webtoolkit.info/
*
**/

AIM = {

    frame : function(c) {

        var n = 'f' + Math.floor(Math.random() * 99999);
        var d = document.createElement('DIV');

        d.innerHTML = '<iframe style="display:none" src="about:blank" id="'+n+'" name="'+n+'" onload="AIM.loaded(\''+n+'\')"></iframe>';

        document.body.appendChild(d);

        var i = document.getElementById(n);
        if (c && typeof(c.onComplete) == 'function') {
            i.onComplete = c.onComplete;
        }

        return n;
    },

    form : function(f, name) {
        f.setAttribute('target', name);
    },

    submit : function(f, c) {

        AIM.form(f, AIM.frame(c));
        if (c && typeof(c.onStart) == 'function') {
            return c.onStart();
        } else {
            return true;
        }
    },

    loaded : function(id) {
        var i = document.getElementById(id);
        if (i.contentDocument) {
            var d = i.contentDocument;
        } else if (i.contentWindow) {
            var d = i.contentWindow.document;

        } else {
            var d = window.frames[id].document;
        }
        if (d.location.href == "about:blank") {
            return;
        }

        if (typeof(i.onComplete) == 'function') {
            i.onComplete(d.body.innerHTML);
        }
    }

}

You can see the demo of the code here.

Below is an excerpt (including the code) from the updated post.

How to upload files asynchronously?

As I described above You can’t upload files using AJAX. Some time ago I wrote a JavaScript file upload object which as You already understood can help developers make forms which upload files asynchronously.

Today I made some modifications to this code and I want You to try it. Its simple, really fast to implement. Just paste this code into your document or external JavaScript (ajaxupload.js) file:

AsyncUpload = {
 
	createFrame : function(formElement, completeCallback) {
		var frameName = 'f' + Math.floor(Math.random() * 99999);
		var divElement = document.createElement('DIV');
		divElement.innerHTML = '<iframe style="display:none" src="about:blank" id="'+frameName+'" name="'+frameName+'" onload="AsyncUpload.documentLoaded(\''+frameName+'\')"></iframe>';
		document.body.appendChild(divElement);

 
		var frameElement = document.getElementById(frameName);
		if (completeCallback && typeof(completeCallback) == 'function') {

			frameElement.completeCallback = completeCallback;
		}
		formElement.setAttribute('target', frameName);
	},
 
	documentLoaded : function(elementID) {

		var frameElement = document.getElementById(elementID);
		if (frameElement.contentDocument) {
			var documentElement = frameElement.contentDocument;
		} else if (frameElement.contentWindow) {

			var documentElement = frameElement.contentWindow.document;
		} else {
			var documentElement = window.frames[elementID].document;
		}

		if (documentElement.location.href == "about:blank") {
			return;
        }
		if (typeof(frameElement.completeCallback) == 'function') {

			frameElement.completeCallback(documentElement.body.innerHTML);
		}
	},
 
	submitForm : function(formElement, startCallback, completeCallback) {

		AsyncUpload.createFrame(formElement, completeCallback);
		if (startCallback && typeof(startCallback) == 'function') {
			return startCallback();
		} else {

			return true;
		}
	}
 
}

Now write your xHTML document (index.html). Let say it will look like this:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US" lang="en-US">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

    <title>Asynchronous Upload</title>
    <script type="text/javascript" src="ajaxupload.js"></script>

    <script type="text/javascript">
        function startCallback() {
            return true;
        }
 
        function completeCallback(response) {
            obj = eval('('+response+')');
            alert(obj.firstname);
            document.getElementById('r').innerHTML = response;
        }
    </script>
</head>
 

<body>
 
    <form action="index.php" method="post" enctype="multipart/form-data" onsubmit="return AsyncUpload.submitForm(this, startCallback, completeCallback)">

        <div><label>First name:</label> <input type="text" name="firstname" /></div>

        <div><label>Last name:</label> <input type="text" name="lastname" /></div>

        <div><label>CV:</label> <input type="file" name="cv" /></div>

        <div><input type="submit" value="SUBMIT" /></div>
    </form>

 
    <p>Response: <span id="r"></span></p>
 
</body>
</html>

On backend (web server) i wrote this PHP script (index.php):

<?php
echo json_encode(
	array_merge(
		$_REQUEST,
		$_FILES

	)
);
?>

Now You must fill the form (firstname, lastname and attach CV file) to test it. When You submit the form, the current page won’t reload. This script will load the index.php file in the background (CV file will be sent in the background too). PHP script will output JSON (about this technology maybe some other time) encoded string.

In the index.html file function completeCallback will handle the index.php response without reloading the page. Voila! Now You only need to figure it out where You can use this JavaScript Asynchronous File Upload Object.

You can read the full post here.

You can download the full source code here.

This is a very interesting use of sending data asynchronously. I never would have thought to use frames in the way that the code does in order to upload the file. I would love to hear if you find any good uses for this code. You can leave them in the comments or write a complete blog post on this blog using your free Ajaxonomy account.

The initial source code was originally posted on webtoolkit.info

Creating a Simple JavaScript Game Board

Over at the Web Cash blog they have posted two tutorials on Game development in JavaScript, Ajax and PHP. The first tutorial explains the concept and describes how to make a game board.

Below is an excerpt from the first tutorial.

Game Development with JS, AJAX, and PHP

How can we use JS and PHP - connected through AJAX - to develop an online game?

Javascript’s main use for us is to create an interface for the game. Through Javascript we can capture user input - i.e. mouse clicks and text. We can also alter the game’s output - changing the HTML of the page, adding images, and moving things around. Javascript will provide a lot of the front end work.

PHP, on the other hand, is a more robust language for dealing with the logic of the game. PHP could be useful for developing an AI and evaluating winning conditions. It also offers a great way to store information for later use through flat files or database integration.

If we’re going to use both Javascript and PHP, we’ll need to use AJAX. This is the glue that holds the whole thing together. It will send input from the main Javascript to the PHP processing scripts. The PHP script will then send info back to the Javascript and it will alter the page’s layout accordingly.

Read the full first tutorial here.

The second tutorial goes into more detail as to how you would start creating a simple game. By the end of the tutorial you have a complete simple tic-tac-toe game (the game needs more logic added to be finished, but the concept is there).

Below is an excerpt from the second tutorial.

Creating Graphics

Tic Tac Toe Circle ImageI created two images in Inkscape to use for this board. Each is a 50×50 png file - with a gray background and a black border. The actual token (the circle or cross) is red and laid on top of the gray background.

Tic Tac Toe Cross ImageI’m no great artist, but these should work for a functional demo. We can worry about making nice circle and cross tokens later. I think getting the game working is more important than making it pretty from the get-go.

Turning Our .js Script into a Class

In making this a functional board, I also converted the script into an actual class. The script may end up being somewhat large and unwieldy - and an object oriented approach may help us keep it tidy and clean. Or it may add a lot of overhead… but I like objects.

In our HTML file, we’ll create the object like this.

<script type="text/javascript">
var tictactoe = new game();
</script>

In the attached .js file, we actually define the game object. Here’s part of the object definition.

function game() {
  //  Array to hold the bgImgs
  this.bgImgs = new Array();
    this.bgImgs[0] = 'tttcircle.png';
    this.bgImgs[1] = 'tttcross.png';

 
  //  Player information			
  this.currentPlayer = 0;
  this.players = new Array();
    this.players[0] = "Player One";
    this.players[1] = "Player Two";

 
   return true;

This class constructor does some of the initialization for us.

First, it creates an array with background images. At the moment we’re only using two images. However, this technique would be useful if you had a more complex map - with 10-15 images you could lay over a div.

Second, we create some player information variables. The ‘currentPlayer’ property is going to track whether the ‘cross’ or ‘circle’ player is currently taking a turn. The ‘players’ array will just hold the names of those players for now.

The Background Image Changing Function

One of the major methods of this class will be changeBackground(). Just like in the previous example, this method will change the background style of a given div tag. This way we can change it from an open square to a circle or cross token.

  this.changeBackground = function (boxId) {
    var box = document.getElementById('box-' + boxId);
    box.style.background = 'transparent url(' + 
      this.bgImgs[this.currentPlayer] + ') top left no-repeat';

 
    box.removeAttribute('onClick');
 
    this.changePlayer();
  }

This should be pretty straightforward. We’re storing the ‘div’ element in the ‘box’ variable. We’re then setting the ‘background’ style as we would in a css style. Remember that we stored the background images in an array (this.bgImgs) and this.currentPlayer corresponds to a key in the this.bgImgs array (either 0 or 1).

The ‘box.removeAttribute()’ method is removing ‘onClick’ from that div. We can’t use a square a second time, so we might as well eliminate the onClick handler altogether.

Finally, this.changePlayer() is calling a new method. This is going to help us switch from Player One’s turn to Player Two’s turn.

One Turn to Another - this.changePlayer()

The last method we need to declare for this class at the moment is changePlayer.

This will toggle the active player - which in turn affects whether a circle or cross is placed on the board. For some added effect, we’ll also create a new html element to display a message that says who’s turn it is.

  this.changePlayer = function () {
    //  Switch the active player

    if (this.currentPlayer == 0) {
      this.currentPlayer = 1;
    } else {

      this.currentPlayer = 0;
    }
 
    //  Get a reference to our 'message' element and create the message
    var box = document.getElementById('message');
    var msg = "It is " + this.players[this.currentPlayer] + "'s turn.";
    var txt = document.createTextNode(msg);

 
    //  Erase any existing text
    while (box.hasChildNodes()) {
      box.removeChild(box.lastChild);
    }

 
    //  Add the text node (our message) to our element
    box.appendChild(txt);
  }

Again, this is pretty straightforward. The DOM functions are amazingly simple - once you see how they work.

‘box’ is a reference to our element (id = message). The msg variable is a temp variable I created to hold the string. The ‘createTextNode’ method creates a new block of text (with our msg) that we can then insert into an HTML element.

The while() loop is simply there to erase any old text. As long as our ‘box’ element has any child nodes inside of it (text or other HTML tags), the loop will execute and delete one of those child nodes each time. This way we have a clean slate on which to write down who’s turn it is.

Read the full second tutorial here.

Although the tutorial only shows a simplistic tic-tac-toe game you could use the concepts as a starting point to build your own web games. As always if you have made any cool games we would love to hear about them either in the comments or you can write a blog post about it using your free Ajaxonomy account.

Help Your Site Users with a Step By Step Tour

Tagged:  

Have you ever made an incredible web application that you think is very intuitive to users, just to be told by a friend or user that they couldn't figure it out? Often our knowledge of our applications blinds us to the fact that everything may not be as simple to use as we thought.

Because of this common problem Christian Heilmann has written a good solution to the problem called Step by Step. The script displays a sort of tool tip that walks you through a site step by step.

Below is how the script is explained by Chris.

You might have encountered interactive demos created with screencasting and screengrabbing software that explain an interface to users in a step-by-step manner. This is exactly what this script does for web sites.

When you loaded this page and all went well you'll have seen the examples, download and first paragraph section being highlighted and a small panel with information showing up in succession. This is done with this script.

The script uses the Yahoo! User Interface (yet another good example of the library) for the effects, so it does have that dependency.

You can go to the official website here and you can download the code and examples here. To view the examples click here.

If you use this or any other similar script I would love to hear about them. You can leave them in the comments or write a post about them on this blog using your free Ajaxonomy account.

Ajax Security

Tagged:  

Over at Reg Developer they have posted a good article regarding Ajax security. The article takes a 1-2-3 approach to security and covers topics like cross site scripting and SQL injection.

Below is an excerpt from the article.

Know what runs where

AJAX is making it increasingly difficult to be sure where your code is going to run. Take the Google Web Toolkit (GWT) for example. You program in Java and the environment takes some of that code and compiles it to JavaScript that runs on the client. If you make a mistake and implement authentication, access control, validation, or other security checks in the code that runs on the client, an attacker can simply bypass them with Firebug.

Imagine you've carefully coded rules to be sure that administrative functions are never shown to ordinary users. This sounds good, but you forgot that the user interface code is running on the client. So the attacker uses Firebug to invoke the administrative functions. If the proper checks aren't in place on the server side, the attacker just gained administrative rights. Many Rich Internet Application (RIA) frameworks also have this issue.

The solution is to be very careful about making the boundary between the client and the server very clear.

Keep data separate from code

Hackers frequently use a technique called "injection" to bury commands inside innocent-looking data and get interpreters to execute their commands for them. This simple trick is at the heart of many security attacks including SQL injection, command injection, LDAP injection, XSS, and buffer overflows. Preventing injection in a target-rich environment like the modern browser takes discipline.

The key to stopping injection attacks is never executing data that might contain code. But with AJAX, lots of data and code get passed around and mashed together in the DOM. There has never been a data structure that mixes together code and data more than modern HTML.

So be very careful with data that might include user input. Assume it's an attack unless you've carefully canonicalized, validated, and properly encoded. Imagine you're invoking a REST interface and the request contains user data. The response you receive is a JSON string that includes that user data. Don't evaluate that string until you're sure that there can't be anything but safe data in there. Even just adding that data to the DOM might be enough to get it to execute if there's JavaScript code buried in there.

Beware encoding

Encoding makes everything complicated. Attackers can hide their attacks inside innocent-looking data by encoding it. Back-end systems may recognize the encoding used and execute the attack. Or they may decode the attack and pass it on to a system that's vulnerable to it.

Attackers may use multiple different encoding schemes, or even double encode to tunnel their attacks through innocent systems. There are dozens and dozens of encoding schemes and no way to tell which schemes will be recognized by the interpreters you're using. This makes recognizing attacks very difficult, if not impossible.

Every time you send or receive data both sides have to know the intended encoding. Never try to make a "best effort" attempt to guess the right encoding. You can't prevent an attacker from sending data with some other encoding through the channel, but you don't have to execute it. Here are a few examples:

Set HTTP encoding in the header:

 
   Content-Type: text/xml, charset=utf-8

Use a meta tag in the HTML:


Set XML encoding in the first line of XML documents:

<?xml version="1.0" encoding="utf-8"?>

You can read the full post here.

Ajax security is very important in developing your Ajax applications and it is something that many developers overlook.

Online Presentation Applications

Tagged:  

Over at Mashable they have posted a run down of 13 Online Presentation Applications. So get your favorite Business Analyst and show them how they can use the web for their next presentation (although it may take some work as they may be lost outside of the Microsoft PowerPoint world).

Below are the first five listed in the post.

http://us.ajax13.com/en/ajaxpresents/index.jsp

AjaxPresents - Presentation software portion of the Ajax13 office suite. Works with Firefox 1.5 and higher, free, and can import & export from PowerPoint and OpenOffice.

http://www.brinkpad.com

BrinkPad.com - A Java based presentation tool that allows you to create online and then download to your system to save it.

http://www.empressr.com/

Empressr.com - A tool for creating media rich presentations online with Flash and Ajax. You can share them with the public and allow them to be voted on.

Presentation Editor

Google Documents - Google made their intentions to take on Microsoft Office fairly obvious when they finally added an online presentation tool to take on PowerPoint.

http://preezo.com/

Preezo.com - Uses an Ajax-based interface for quick editing. Allows collaboration and easy sharing with clients and colleagues.

You can see the full list by clicking here.

Some of these tools look very good although I don't think that they will replace PowerPoint quite yet.

Syndicate content