On this page, we'll look at adding more functionality to the sliding photo map application discussed here. The first improvement to make to the application is to show a visual indication of which control was selected, as described on the Group of Buttons page. We'll keep things simple to start with and show the currently selected control (button) in a different color.
As we did on the "group of buttons" page, we'll use a variable on the main timeline (so it's available to everything in the movie) to keep track of the currently selected control. This variable is of type MovieClip and will contain a reference (pointer) to whichever control movieclip the user last clicked. That variable will then be checked by the routines which handle onRollOver, onRollOut and onRelease events for the controls and used to disable such events on rollover and rollout and set the color of the selected clip on the onRelease event. This is the code added to the movie (frame 1, main timeline) to do that (function slideToPhoto was renamed to doClick, since it now affects the control movieclip itself in addition to the slider):
// create a variable to track the currently selected button
var activebtn:MovieClip;
function doRollOver() {
if (this != activebtn) {
// [same rollover code as before]
}
}
function doRollOut() {
if (this != activebtn) {
// [same rollout code as before]
}
}
function doClick() {
new Color(activebtn).setRGB(0xFFCC00); // return previously selected to normal
this._xscale = this._yscale = 100; // set scale of current selection to 100% and
delete this.onEnterFrame; // stop it pulsing
new Color(this).setRGB(0xC12709); // change color of selected mc
activebtn = this; // update pointer to currently selected control
caption.text = ""; // clear caption while next photo is tweening
// [same slide-to-photo code as before]
}
function init() {
for (var i:Number=0; i < 5; i++) {
// [code to assign myphoto property]
// assign handler functions to each event property of the control
this["p" + i].onRollOver = doRollOver;
this["p" + i].onRollOut = doRollOut;
this["p" + i].onRelease = doClick;
}
}
A complete working example of the code to produce the movie at this stage may be found in oahumap_slider2a.as, available by subscription from the link at right.
In addition to changing the behavior of the controls, we've added a caption that displays under the photo after it has slide into place. Obviously this same idea could be extended to showing a text box of information, a video, a list of hotels, or anything other additional information about the place.
Since each control now needs to know not only which photo to show, but what caption to go under it, we'll use a groupinfo array, as described on the group of buttons page, to store that information in one place (within the program itself for now, but we'll be making this external eventually) and assign it to each control in the init routine. This is the new code (added to the variable declaration section) to store the information:
// create an array of information for all nav buttons (controls) in group
var groupinfo:Array = [
{placename:"Sunset Beach", myphoto:slider_mc.pic0},
{placename:"Kailua", myphoto:slider_mc.pic1},
{placename:"Hanauma Bay", myphoto:slider_mc.pic2},
{placename:"Waikiki", myphoto:slider_mc.pic3},
{placename:"Pearl Harbor", myphoto:slider_mc.pic4}
];
And following is the code that will assign a property to save a pointer to that information to each control. Notice that the number of elements in the loop is now determined by the size of the groupinfo array, so we can get rid of the hardcoded value (5) or constant (NPICS) we used to specify the length previously. Here is the code to assign the properties we'll need:
function init() {
for (var i:Number=0; i < groupinfo.length; i++) {
this["p" + i].myphoto = groupinfo[i].myphoto;
this["p" + i].placename = groupinfo[i].placename;
// [assignment of handlers to event properties as before]
}
}
We'll take a look below at how that property, i, is used to retrieve information when the control is clicked.
To show a caption under the photo, you'll first need to add a dynamic textfield named caption to show it in:

To make sure the caption appears only when the photo has slid into place, we need to create and assign an instance of the Tween class and use its onMotionFinished method to do something when the tween is complete. The code to do that (in the onClick function) will look something like this:
var tw:Tween = new Tween(slider_mc, "_x", Strong.easeOut, slider_mc._x, newpos, 2, true); tw.onMotionFinished = showName;
where showName is the name of a function that we've set up to show the caption. But there's a problem with this. When we assign a function to the event property of another instance (tw), the scope of code within that function is that instance. Thus, if we refer to "this" inside showName and use the code above, "this" will refer to tw inside showName. But we really need it to refer to the control that was just clicked, so we can retrieve information for that control. So instead of the above, we'll use the Delegate class to change the scope of showName from tw to the selected control. To do that, we also need to import the Delegate class code. The complete change to the code is:
import mx.utils.Delegate;
function onClick() {
caption.text = ""; // hide the caption til tween is done
// [code to set activebtn and set control's color, as in the example above]
var newpos:Number = SLIDERSTART - this.myphoto._x + MARGIN;
var tw:Tween = new Tween(slider_mc, "_x", Strong.easeOut, slider_mc._x, newpos, 2, true);
tw.onMotionFinished = Delegate.create(this, showName);
}
Now, with the last statement, showName has been assigned to the event property onMotionFinished of instance tw but still retains the scope we want it to have ("this" = selected control). The first parameter specifies the scope, the second is the function name. All we need to finish up is the actual showName function, which will retrieve information from groupinfo and use it to display the caption:
// display name of selected place under picture
function showName() {
caption.text = this.placename;
}
Those are all the changes to produce the example shown above. For the complete code, get oahumap_slider2.fla and oahumap_slider2.as from the zip file link at right.
In the code above, we used an actual pointer to a movieclip (that is, a property of type MovieClip) to save the information about which photo goes with which control. An alternate way to store the information would be with the string name of the movieclip (that is, a property of type String). In that case, the array would look like this:
var groupinfo:Array = [
{placename:"Sunset Beach", myphoto:"pic0"},
{placename:"Kailua", myphoto:"pic1"},
{placename:"Hanauma Bay", myphoto:"pic2"},
{placename:"Waikiki", myphoto:"pic3"},
{placename:"Pearl Harbor", myphoto:"pic4"}
];
and the onClick function like this:
function doClick() {
// ...
var newpos:Number = SLIDERSTART - slider_mc[this.myphoto]._x + MARGIN;
var tw:Tween = new Tween(slider_mc, "_x", Strong.easeOut, slider_mc._x, newpos, 2, true);
tw.onMotionFinished = Delegate.create(this, showName);
}
To continue on with the same example and see how to attach movieclips dynamically, see this page.
last update: 24 Mar 2006
Discussed on this page:
example of using a group of buttons with an information array to show a visual indication of which control was selected, and track information related to each control, Tween onMotionFinished method, use of Delegate to change scope
Files:
oahumap_start.fla
(free download)
oahumap_slider2.fla
oahumap_slider2a.as
oahumap_slider2.as
In oahumap.zip, password required
Subscription:
A password may be obtained by subscription
An access password will be emailed to the address you specify within 24 hours of receipt of payment, and will remain active for 30 days thereafter. A list of all files currently available at the site may be viewed here.