# Build a Dynamic Flash Gallery with Slider Control

##### Tutorial Details
• Program: Flash

In this tutorial, we’ll create a gallery which displays all image files in a given directory. A slider is used to browse easily through the images.

## Step 1

Set up a new Flash AS3 document and a blank ActionScript file. We’ll create the main class first; name it “Gallery” and save it as “Gallery.as”. Below is the code to set up the first class:

package
{
public class Gallery
{
public function Gallery() : void
{
}
}
}

In Flash we can now set this as the base class by entering the name in the input box under the Publish settings of the document. You can try a “trace(‘hello world’)” in the Gallery function to test if it’s working.

## Step 2

Before we continue with the main class, it’s best to start off with the slider. The code is fairly easy to understand and might shine some light on how things are done in AS3.

Create two new movieclips: a slider and a handle for the slider. The slider or seeker doesn’t need to be exported for ActionScript as we only need to apply some functions to the handle. Set the class for the handle as “Handle”. We can now create a new class called “Handle” and, if saved in the same directory, Flash will automatically use this class for the handle. Give both an instance name such as “slider” and “theHandle”.

## Step 3

The following is the full code for the handle which I will explain in steps. It should be saved as “Handle.as” in the same directory as your .fla. This way, Flash will execute the code once an instance with a class name “Handle” is used.

package
{
import flash.display.MovieClip;
import flash.events.MouseEvent;
import flash.events.Event;

public class Handle extends MovieClip
{
public var goToX : Number = x;
private var slider : MovieClip = MovieClip(parent).slider;
private var mousePos : Number = 0;

public function Handle() : void
{
buttonMode = true;
}

private function moveHandle( _e : MouseEvent ) : void
{
mousePos = mouseX;
}

private function stopHandle( _e : MouseEvent ) : void
{
stage.removeEventListener( MouseEvent.MOUSE_MOVE, followHandle );
}

private function followHandle( _e : MouseEvent ) : void
{
var newPos : Number = stage.mouseX - mousePos;
var orgX : Number = x;
if ( newPos < slider.x )
goToX = slider.x;
else if ( newPos > (slider.x + slider.width) - width )
goToX = (slider.x + slider.width) - width;
else
goToX = newPos;
x = goToX;
if( goToX != orgX ) dispatchEvent( new Event( "sliding", true ) );
}

}

}

In the first few lines we create a few variables to hold data we can use in every function in this class. The slider variable holds a reference to the instance called “slider” on the parent. We need it to correctly calculate the x position to which the handle should be moved. In the constructor we set “buttonMode” to true so a hand cursor shows up when hovering over the handle. Additionally, we add two eventlisteners to listen for mouse events.

public class Handle extends MovieClip
{
public var goToX : Number = x;
private var slider : MovieClip = MovieClip(parent).slider;
private var mousePos : Number = 0;

public function Handle() : void
{
buttonMode = true;
}

Once a mouse down event occurs, an extra listener is added. This listener stays active as long as the drag movement isn’t stopped and calls the “followHandle” function. It’s removed again when the mouse click is over.

private function moveHandle( _e : MouseEvent ) : void
{
mousePos = mouseX;
}

private function stopHandle( _e : MouseEvent ) : void
{
stage.removeEventListener( MouseEvent.MOUSE_MOVE, followHandle );
}

This last function actually moves the handle around. The variable “newPos” stores the new position to which the handle should move. If, however, this position is further than the far left or right of the slider, the position should be set to the maximum possible value. If the handle is moved, we dispatch a new custom event called “sliding”, which we can later use to move around the images.

private function followHandle( _e : MouseEvent ) : void
{
var newPos : Number = stage.mouseX - mousePos;
var orgX : Number = x;
if ( newPos < slider.x )
goToX = slider.x;
else if ( newPos > (slider.x + slider.width) - width )
goToX = (slider.x + slider.width) - width;
else
goToX = newPos;
x = goToX;
if( goToX != orgX ) dispatchEvent( new Event( "sliding", true ) );
}

## Step 4

If everything’s gone well until now, you should have a nice functional slider like the one below. Add a dynamic textfield underneath it which will hold the image number. Give it an instance name like “countTxt” so we can address it later in ActionScript. Because there’s nothing to display yet I filled it with the text “Loading” which will also display while the script loads the first image.

## Step 5

Next we’ll create the php backend script. Flash can’t read the contents of a local directory, so we need to pass the information from php to Flash. We’ll use XML since it’s easy to output with php and even easier to read again in AS3.

The following is the php backend code, save it as “backend.php”. The code loops through the directory “img” and writes a line of XML for each file in there. Before printing we need to filter out the “.” and “..” directories. As the directory only contains images there’s no further checking necessary.

<xml>
<?php
$od = opendir('img'); while ($filename = readdir($od) ) if($filename != "." && $filename != ".." ) echo "<img>" .$filename . "</img>\n";
?>
</xml>

This will output for example:

<xml>
<img>file1.jpg</img>
<img>file2.jpg</img>
<img>file3.jpg</img>
</xml>

## Step 6

Before we load this into Flash, let’s create a class to hold our images individually. In the same way we created the Handle class we can now create an Img class. Start off with creating a movieclip about the size you want your images to be displayed. Give it a margin of a few pixels and save some space on the bottom for the description text. Add a dynamic text field for the description and give it an instance name of “descr”. Make sure to set the registration point of the movieclip to the center so we can easily scale it later. Export it for ActionScript under the class name “Img”. Now delete the instance from the stage as we’ll call it directly from the library.

## Step 7

Next we’ll load the information the php file returns into our Flash project using ActionScript. Open up the Gallery class again. The following code adds two functionalities to our project. First off, it creates “imagesClip”, an empty movieclip in which we’ll store the actual images later. Using “addChild” here adds the movieclip to the stage. Anything added to imagesClip later will also appear on the stage. To actually load the xml data, we create a “URLLoader”. This class can fetch the results and run a function when the results are in.

package
{
import flash.display.MovieClip;
import flash.events.Event;
import flash.net.URLRequest;

public class Gallery extends MovieClip
{
private var backend : String = 'http://localhost/.../backend.php';

private var xdata : XML;
public var images : Array = new Array();

public var imagesClip : MovieClip = new MovieClip;

public function Gallery() : void
{
imagesClip.y = 180;

}

private function loadImages( _e : Event ) : void
{
xdata = new XML( _e.target.data );
var i : Number = 0;
for each( var img:XML in xdata.img )
{
images[i] = new Img();
i++;
}
}
}
}

Here we use the load function of the URLLoader class. To prevent caching of the results we can add a simple date to the end of the url. The eventlistener checks when the URLLoader is finished and then runs the loadImages function.

xmlLoader.load( new URLRequest( backend + "?" + new Date().valueOf() ) );


This next function loops through all the <img> instances in the xml. For each of these it creates a new instance of the Img class. Next we add it to the imagesClip (this is just for testing as later on we only want the active images to be displayed).

private function loadImages( _e : Event ) : void
{
xdata = new XML( _e.target.data );
var i : Number = 0;
for each( var img:XML in xdata.img )
{
images[i] = new Img();
i++;
}
}

## Step 8

To give our Img instances more functionality, create an Img class and save it as “Img.as”. In a similar way to loading the XML we can load the image itself and display it inside the Img movieclip. The loading should not occur in the constructor or all images would try to load at the same time; we’ll create a separate function for doing this.


public class Img extends MovieClip
{
public var id : Number;
private var src : String;
private var main : Gallery;
private var orgWidth:Number = 0;
private var orgHeight:Number = 0;


In the constructor, we set a reference to the main Gallery class so we can later access elements on the stage or public variables and functions of the main class. The string “load” will contain the path to the image which php returned, we’ll save it to a variable so we can access it later.


public function Img( load : String, m : Gallery ) : void
{
orgWidth = width;
orgHeight = height;
main = m;
}

The “loadImage” function loads the image and when finished runs the “displayImage” function.


{
}

The displayImage function checks the images array we created and loads the next image. It sets the smoothing to true on the Loader (by default, smoothing is set to false on dynamically loaded images). Once you start scaling or rotating an image it’s important to set the smoothing so the image remains its quality. As the registration point of the Img movieclip is in the center we need to calculate the x and y position of where to place the image itself. In my example I’ve used a directory of images with the same width and height. If the width and height of the loaded image are variable this is the place to resize it on the fly. Just before adding it as a child we set the description text to “src”, which holds the name of the image.


private function displayImage( _e : Event ) : void
{
if ( main.images[id + 1] != null && !main.images[id + 1].parent ) main.images[id + 1].loadImage();
imageLoader.x = main.spaceBetween/2 - ( orgWidth /2 );
imageLoader.y = main.spaceBetween/2 - ( orgHeight /2 );
descr.text = src;
}
}

## Step 9

After the changes we made to the Img class we need to update the way the instances are called in the loadImages function of the Gallery class. We now need to pass two arguments when calling new Img().

The first is the path name of the image that needs to be loaded, we get this from the xml. The second is a reference to the main Gallery class; we can use “this” which points to the class we’re currently working in. Instead of adding the images with addChild to the imagesClip container we’ll create a new function “goTo”. This function will work out which images to place on the screen. The argument we need to pass is the id number of the image, the same number as the index key in the images array. When the images are loaded for the first time, we’ll set the focus on the first image, of which the id number is zero.


private function loadImages( _e : Event ) : void
{
xdata = new XML( _e.target.data );
var i : Number = 0;
for each( var img:XML in xdata.img )
{
images[i] = new Img( img, this );
images[i].x = 200 * i;
images[i].id = i;
i++;
}
goTo( 0 );
}

## Step 10

To use the goTo function we need to declare a variable “imagesToShow” first. This will set the amount of images we want to load at once on screen. To determine the direction in which the user is scrolling, we simply check if the image we’re going to had a higher or lower id number than the last one.

private function goTo( imgId : Number ) : void
{
var direction : Number;
if ( orgImgId != imgId )
{
if ( imgId > orgImgId  ) direction = 1;
else direction = -1;

The next “for loop” loops all images needed on screen. For example: if we set imagesToShow to 5, it will loop from -2 to 2. This means that if we pass the value of i to the Img class we can determine where on the screen it should be positioned (-2 being far left, 0 center and 2 the far right). Therefore, we can scale the images larger the more centrally they are positioned.

There’s an additional check included so we don’t activate non-existing images (it stops at the first and the last one). For each of the active images we’ll run the “makeActive” function, which we’ll create later on.

		for ( var i : Number = - Math.floor(imagesToShow/2); i <= Math.floor(imagesToShow/2); i++ )
{
if( imgId + i < images.length && imgId + i >= 0 ) images[imgId + i].makeActive( i, direction );
}

Right after placing the images we need on screen, we’ll check which ones shouldn’t be there any more and get those off the stage. Since all images are added to the imagesClip container, we can easily loop through all children of that movieclip. If their id is not within those that should be active, we run the “deActive”.

		for( var j : Number = 0; j < imagesClip.numChildren; j++ )
{
var tile : Img = imagesClip.getChildAt(j) as Img;
if ( tile.id < imgId - Math.floor(imagesToShow/2) || tile.id >  imgId + Math.floor(imagesToShow/2) ) tile.deActive( direction );
}

The next line updates the text of the dynamic textfield we created earlier. Since the ids of the images start their count at 0 we add + 1 to the imgId so the first image is actually number 1 etc. We can get the total number of images from accessing the length of the images array.

		countTxt.text = imgId + 1 + "/" + images.length;
}

Finally, we’ll set “orgImgId” so the next time the function is run, the direction being scrolled can be determined.

	orgImgId = imgId;
}

## Step 11

We now need the “makeActive” and “deActive” functions in the Img class. These will either add the image to the stage, or take it off. For now we’ll just add them and place them correctly. Later on we’ll also tween them to their correct place.

The makeActive function first checks if it is added to the imagesClip already. If there is no parent found, it adds itself to to imagesClip container. The parent is then the imagesClip. Next we set the visible property to true. When deactivating, we set it to false so it’s only normal we want our image to show again when it’s made active.

public function makeActive( position : Number, direction : Number ) : void
{
if ( parent == null )
{
}
visible = true;

There’s a chance that the image itself hasn’t yet loaded. To check this, I check if the amount of children is smaller than 3. This number can depend on the amount of shapes or other movieclips in your Img. If you feel uncertain about this method, a safer option would be to declare a boolean at the start and set it to true in the displayImage function.


if ( numChildren < 3 ) loadImage();

There’s no depth in AS3, but once we start scaling and rotating our images we need to make sure the image in the center is on top of the others. Because we passed the position as an argument in the goTo function we can now use it to set the index of the image in the imagesClip. The index of a child can be compared to a depth, but there won’t be any issues when changing it since the other movieclips will move an index up or down. This step is unnecessary if you don’t plan to overlap the images.


parent.setChildIndex( this, ( parent.numChildren-1 ) - Math.abs( position ) );

Lastly, we determine the position of the image. The “extra” variable is used here to find out by how much the current image is away from the center. “DefaultWidth” and “spaceBetween” are public variables set in the main Gallery class so we can access them from anywhere. Since all the images in my directory have the same width, I set defaultWidth at 195 and spaceBetween to 20. To actually move the image to the new position we set the x property to the newly found x value.

	var extra : Number =  Math.round( position * ( main.defaultWidth + main.spaceBetween ) );
var newX : Number = Math.round( ( main.stageWidth / 2 ) ) + extra;
x = newX;
}

## Step 12

The deActive function is pretty straight forward, it changes the visibility to false. The direction is already set as an argument since we’ll need it later to know in which direction to send the image when taking it off the stage.

public function deActive( direction : Number ) : void
{
visible = false;
}


## Step 13

By now, the first few images should appear on stage. There’s only one functionality still missing. The slider is not connected to the goTo function yet. However, since we already dispatch a custom event once the handle is dragged, it’s not very hard to connect the two.

Add the following line to the Gallery constructor function. This eventlistener will run the slide function every time the “sliding” event is called by the handle.

theHandle.addEventListener( "sliding", slide );


All we need the slide function to do is to calculate which image should be shown in the center depending on where the handle is. In the function “slider” and “theHandle” are the instance names we set earlier on the movieclips on the stage. To find out which image to go to we first determine the percentage of the handle’s position over the slider’s length. Then, multiplying that by the total of images brings us to the right image id.

private function slide( _e : Event ) : void
{
var percent : Number = ( theHandle.goToX - slider.x ) / ( slider.width - theHandle.width );
var imgId : Number = Math.round( percent * ( images.length - 1 ) );

goTo( imgId );
}


## Step 14

If you’ve managed to follow this far and kept track of which classes to import and which variables to declare (or followed the source files) you should by now have a working example.

## Step 15

To finish this tutorial we’ll add tweening to the images using TweenLite, a free and lightweight tweening engine. The standard tweening classes provided by Adobe do not perform well when there’s a lot going on. When trying those out they used to crash or freeze a lot, while I have yet to discover such problems with TweenLite. The syntax of TweenLite is very easy. I’ll demonstrate this by comparing it to a normal Flash tween; tweening an object from its current x to 100 and changing the alpha to 0:

new Tween( object, 'x', Linear.easeOut, object.x, 100, 2, true );
new Tween( object, 'alpha', Linear.easeOut, object.alpha, 0, 2, true );

Now here’s the TweenLite alternative syntax:

TweenLite.to( object, 2, { x:100, alpha:0, easing:Linear.easeOut } );


## Step 16

Let’s create a new function in which we can place all of the tweening actions. Name it “flyTo” and place it in the Img class.

private function flyTo( newX : Number, removeAfter : Boolean, scale : Number = 1 ) : void
{
var tweeningOptions : Object = new Object;
tweeningOptions.x = newX;

if ( removeAfter )
{
tweeningOptions.ease = Linear.easeIn;
tweeningOptions.alpha = 0;
tweeningOptions.scaleX = tweeningOptions.scaleY = 0.3;
tweeningOptions.visible = false;
}
else
{
tweeningOptions.ease = Back.easeOut;
tweeningOptions.alpha = 1;
tweeningOptions.scaleX = tweeningOptions.scaleY = scale;
tweeningOptions.rotation = (Math.random() * 20) - 10;
}
TweenLite.to ( this, 0.4, tweeningOptions );
}

There are 3 arguments needed for this function: the x value we calculated earlier, whether it should be removed after the tween and the scale. The “removedAfter” parameter will be used in the deActive function, so the visibility of the image can be set to false once it’s reached the end of the stage. The scaling parameter is only used for the center image; we’ll display it slightly larger than the rest.

Let’s check out the tweening options for when the image is removed from the stage. First we choose an easing option, in this case “Linear.easeIn” which gives normal, linear movement. Secondly, we fade the alpha value to zero so the image fades away. Then we scale it to only a small percentage of its width and height so it becomes smaller as it reaches the end. Lastly, when the tween is completed, we set the visibility to false.

tweeningOptions.ease = Linear.easeIn;
tweeningOptions.alpha = 0;
tweeningOptions.scaleX = tweeningOptions.scaleY = 0.3;
tweeningOptions.visible = false;

When an image is made active, the tweening options are different. We set the easing to “Back.easeOut” so the images seem to fly slightly too far and then bounce back; a very subtle effect. Next we change the alpha back to 1 and scale the image to the scale value we passed to the function. Lastly, we set a random rotation of -10 to 10 degrees. If your description text fails to load after this action you need to make sure the font is embedded.

tweeningOptions.ease = Back.easeOut;
tweeningOptions.alpha = 1;
tweeningOptions.scaleX = tweeningOptions.scaleY = scale;
tweeningOptions.rotation = Math.round( (Math.random() * 20) - 10 );

## Step 17

Now we need to update the makeActive and deActive functions so they make use of the new flyTo function.

In the makeActive function we need to add an x value to the image so it can be tweened from that original value. The defaultWidth needs to be set in the main Gallery class and contains the width of the stage.

public function makeActive( position : Number, direction : Number ) : void
{
deactivating = false;
if ( parent == null )
{
x = ( direction == 1 ? main.stageWidth + main.defaultWidth * 2 : - main.defaultWidth * 2 );
alpha = 0;
}
visible = true;
if ( numChildren < 3 ) loadImage();
parent.setChildIndex(this, ( parent.numChildren-1 ) - Math.abs( position ) );

var extra : Number =  Math.round( position * ( main.defaultWidth + main.spaceBetween ) );
var newX : Number = ( Math.round( ( main.stageWidth / 2 ) /* - ( main.defaultWidth / 2 )*/ ) + extra );
flyTo( newX, false, ( position == 0 ? 1.2 : 1 )  );
}

In the deActive function all we need to add is a moveTo value which contains the x value to which the image should tween. If we locate this to outside the stage width, the image will disappear just outside the stage.

public function deActive( direction : Number ) : void
{
if ( ! deactivating )
{
active = false;
var moveTo : Number = ( direction != 1 ? main.stageWidth + main.defaultWidth * 2 : parent.x - main.defaultWidth * 2 );
flyTo( moveTo, true );
deactivating = true;
}
}

## Step 18

After updating everything, we now have a functional gallery. To see the movieclips disappearing from the stage check out the full version.

## Conclusion

The final version is still low on functionality. The loaded images all need to be the same size and do not have a larger preview. You could add a resizing function and an option to view a larger preview of the image when clicked. Furthermore, an option to browse left or right with buttons or with a keyboard event could be added.

Once you understand the concept of using classes to separate and structure your code it will help in development and make things easier in the long run. I hope you enjoyed following along!

• http://www.cassrina.com Cassrina

Thanks for the tutorial! however, it seems the source file is a corrupted format for my CS3, or maybe unsupported format.

I have follow through the tutorial and almost able to replicate the working file, but one thing, the wording “loading” is forever there, until I start scrolling with the slider everything gets normal then. This is different from the demo file, is it because of the xmlLoader.addEventListener( Event.COMPLETE, loadImages ); that is wrongly used? or preloader issue?

Would you consider sending me your source file for CS3 so I can find out the course of the problem.

Cassrina.

• Chris

Hard and a bit confusing – ?

• davidscott

Wow dude. Likeing this alot!

• John

Wondering if you could use this for other file formats? images png, etc or movies flv, swf?

• http://123doing.com 123doing

It’s very good.
I like this.
Thanks for share.
And I wrote something to introduce this project for my readers.
If something is wrong,pls figure it out.thanks.

• hendrik

• Ian

I was wondering if there’s a way to set what the starting image is? So instead of starting at 1 or 0, you can start at the 5 for 6th image?

• Edis

This is a great example, and i really like it.
The demo works, but the source seems damaged.

nice slider thank you man

• Ruben

I have a problem… when I am trying in wamp, everything is like 5 times bigger than the example and the pictures become like 10 times bigger than the space to put them!!!

• gsynuh

Thank you very much.
I was starting to teach myself some AS3.
Came across this yesterday and modified it for my needs, help me a lot to refamiliarize myself to flash and its syntax. you can see the gallery right there its only experimental :
http://www.marianneaspairt.com/gallery.html

- keyboard navigation (not a pain in the ass once you understand events)
- thumbnails are generated via phpThumb with a max width and height of 200 (if i remember correctly)
- once the images are loaded they are centered.

there’s no “loading” text, and there’s a lot more i want to add to this. But in few times i’ve managed to get this up and working so i truly thank you for this inspiring tutorial.

• Ruben

Hey !! I need some help to manipulate this gallery… I am having the problem that the images are not getting the size

• gsynuh

The images are not getting any size whatsoever you’d have to program that function to your needs, i myself did not program something to resize them but used an external php script http://phpthumb.sourceforge.net/
that resizes images , changed only that the loaded content be centered on load so all images are centered and pre-thumbnailed.
that’s one method to do it. and it all depends on what you want i guess, or what other functionality you want next, i did stop here but i need the full sized images too but didn’t do something to see them fullsize yet.

Well maybe you could explain further what you want, what your projects are

• Jack

Hi, gsynuh can you show me how did you do your ?

• Ruben

I just wanna know, how you do to make the images fit, cause my images become so big that even them can’t be seeing

• http://www.creobyte.com Creobyte

where exactly did you call the resizing PHP ?? i tried to call it in the loadImage function in the Gallery.as but doesnt seem to work..

• http://www.ajaxshake.com Lucas

Great, very nice gallery, i added to my personal list
http://www.ajaxshake.com
thanks

• victorF

Hi, thanks a lot for this tutorial.
I have a problem with my slider : when i first click on the handler, he goes to the center of the slider and then he doesn’t want to come back to the original slider x position.
Did you have this problem and how to fix it ?

• Jingga

can i know what cs version you used in this??
cause my cs3 can’t open the .fla file..,

• Joepiooo

I got it to work fine but my pictures are comming up very big…

Very Diffecult method yar seo website designer

• Sagar

Hi All,

For all those who couldn’t get this awesome stuff to work check below info…

1. After extracting all files -> go to classes folder and cut all files from there and delete the classes folder -> then paste all files back to main folder where fla is kept.

2. In the gallery.as -> go to -> public function Gallery() : void -> replace

below line
————-

with this line
—————-

AND

below line
—————-
private var backend : String = ‘backend.php’;

with this one
—————-
private var backend : String = ‘backend.xml’;

3. Now create backend.xml
example:
———–

img_1.png
img_2.png

4. Lastly, create a folder img and keep images with names same as you have given in xml
example images names
——————————
img_1.png
img_2.png

And thats it ! You have your working gallery Enjoy!

• Carl

Thanks, but still does not fix it

yep, demo does not work

• http://semtik.pl KaterPikller

Source files works just fine so dwl them and you have your demo!

• Carl

This might be cool if it actually worked. Thanks for trying though!!

• tom nesta

i love this be updating me every time in new things.congrats

• http://www.sammedya.com Ankara Web Tasarım

thanx a lot… useful information

• http://www.24hourswebdesign.com/ รับทำเว็บไซต์

Cool Stuff!

Great, very nice gallery, i added to my personal list

• John

Hi,

I really appreciate your efforts to provide all these steps for free. I myself tried to make use of them and create my own gallery, but unfortunately I couldn’t get it work, and to be honest I just gave up. I ended up using this image slider from this webpage: http://www.flashxml.net/image-slider.html which it proved very easy to install thanks to the support guys who helped me a lot.

• Ben

How do i change the position of the images and also stop the rotation? ty

• Ben

Sorry was being stupid got it sorted

• lock

I don’t understand how this works?!

The loadImage() method in the Img class never gets called. Therefore how do the images load.

Am I missing something here?

• robert

well, haha, I have found this tutorial in many other sites, but, tadadadaaaaa every each with the same issue : DOES NOT WORK! thx anyway for try :)

• http://n/a gabriel

hei robert,

I understand your pain. I banged my head against the monitor for hours on end before I gave up trying to make this script happen. Frustrated I started googling left and right. Managed to find a kick-ass looking Gallery in Flash. It works straight with XML files – you can control everything with the XML, slideshow duration, colors, speeds, transitions, sizes, text colors, animation behavior….everything.
Gave up on trying to make this code work, became hooked on my Dock Gallery! If you are interested, you can check out http://www.flashxml.net/dock-gallery.html

• Richer

Thank you Gabriel, I had the same problem as Robert but I followed your advice and now I am addicted of flashxml.net every product is clearly made with professionalism and passion. Thank you again for the post, it really help me in my activity. Respect!